Skip to content

Commit aba5228

Browse files
committed
wip - current tests pass
1 parent 792c139 commit aba5228

File tree

9 files changed

+55
-30
lines changed

9 files changed

+55
-30
lines changed

src/api/child.js

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,5 @@ exports.$addChild = function (opts, BaseCtor) {
4242
opts._parent = parent
4343
opts._root = parent.$root
4444
var child = new ChildVue(opts)
45-
this._children.push(child)
4645
return child
4746
}

src/compiler/compile.js

Lines changed: 22 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -60,10 +60,13 @@ function compile (el, options, partial, transcluded) {
6060
}
6161
// cache childNodes before linking parent, fix #657
6262
var childNodes = _.toArray(el.childNodes)
63-
// if transcluded, link in parent scope
64-
if (transcluded) vm = vm.$parent
65-
if (nodeLinkFn) nodeLinkFn(vm, el)
66-
if (childLinkFn) childLinkFn(vm, childNodes)
63+
// if this is a transcluded compile, linkers need to be
64+
// called in source scope, and the host needs to be
65+
// passed down.
66+
var source = transcluded ? vm.$parent : vm
67+
var host = transcluded ? vm : undefined
68+
if (nodeLinkFn) nodeLinkFn(source, el, host)
69+
if (childLinkFn) childLinkFn(source, childNodes, host)
6770

6871
/**
6972
* If this is a partial compile, the linker function
@@ -150,7 +153,7 @@ function compileElement (el, options) {
150153
if (!linkFn) {
151154
var dirs = collectDirectives(el, options)
152155
linkFn = dirs.length
153-
? makeDirectivesLinkFn(dirs)
156+
? makeNodeLinkFn(dirs)
154157
: null
155158
}
156159
}
@@ -168,14 +171,14 @@ function compileElement (el, options) {
168171
}
169172

170173
/**
171-
* Build a multi-directive link function.
174+
* Build a link function for all directives on a single node.
172175
*
173176
* @param {Array} directives
174177
* @return {Function} directivesLinkFn
175178
*/
176179

177-
function makeDirectivesLinkFn (directives) {
178-
return function directivesLinkFn (vm, el) {
180+
function makeNodeLinkFn (directives) {
181+
return function nodeLinkFn (vm, el, host) {
179182
// reverse apply because it's sorted low to high
180183
var i = directives.length
181184
var dir, j, k, target
@@ -193,7 +196,7 @@ function makeDirectivesLinkFn (directives) {
193196
k = dir.descriptors.length
194197
for (j = 0; j < k; j++) {
195198
target._bindDir(dir.name, el,
196-
dir.descriptors[j], dir.def)
199+
dir.descriptors[j], dir.def, host)
197200
}
198201
}
199202
}
@@ -465,13 +468,16 @@ function checkTerminalDirectives (el, options) {
465468
for (var i = 0; i < 3; i++) {
466469
dirName = terminalDirectives[i]
467470
if (value = _.attr(el, dirName)) {
468-
return makeTeriminalLinkFn(el, dirName, value, options)
471+
return makeTerminalNodeLinkFn(el, dirName, value, options)
469472
}
470473
}
471474
}
472475

473476
/**
474-
* Build a link function for a terminal directive.
477+
* Build a node link function for a terminal directive.
478+
* A terminal link function terminates the current
479+
* compilation recursion and handles compilation of the
480+
* subtree in the directive.
475481
*
476482
* @param {Element} el
477483
* @param {String} dirName
@@ -480,14 +486,14 @@ function checkTerminalDirectives (el, options) {
480486
* @return {Function} terminalLinkFn
481487
*/
482488

483-
function makeTeriminalLinkFn (el, dirName, value, options) {
489+
function makeTerminalNodeLinkFn (el, dirName, value, options) {
484490
var descriptor = dirParser.parse(value)[0]
485491
var def = options.directives[dirName]
486-
var terminalLinkFn = function (vm, el) {
487-
vm._bindDir(dirName, el, descriptor, def)
492+
var fn = function terminalNodeLinkFn (vm, el, host) {
493+
vm._bindDir(dirName, el, descriptor, def, host)
488494
}
489-
terminalLinkFn.terminal = true
490-
return terminalLinkFn
495+
fn.terminal = true
496+
return fn
491497
}
492498

493499
/**

src/directive.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,11 @@ var expParser = require('./parsers/expression')
1818
* - {String} [arg]
1919
* - {Array<Object>} [filters]
2020
* @param {Object} def - directive definition object
21+
* @param {Vue|undefined} host - transclusion host target
2122
* @constructor
2223
*/
2324

24-
function Directive (name, el, vm, descriptor, def) {
25+
function Directive (name, el, vm, descriptor, def, host) {
2526
// public
2627
this.name = name
2728
this.el = el
@@ -32,6 +33,7 @@ function Directive (name, el, vm, descriptor, def) {
3233
this.arg = descriptor.arg
3334
this.filters = _.resolveFilters(vm, descriptor.filters)
3435
// private
36+
this._host = host
3537
this._locked = false
3638
this._bound = false
3739
// init

src/directives/component.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,8 @@ module.exports = {
8787
var child = vm.$addChild({
8888
el: el,
8989
template: this.template,
90-
_asComponent: true
90+
_asComponent: true,
91+
_host: this._host
9192
}, this.Ctor)
9293
if (this.keepAlive) {
9394
this.cache[this.ctorId] = child

src/directives/repeat.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -297,6 +297,7 @@ module.exports = {
297297
var vm = this.vm.$addChild({
298298
el: templateParser.clone(this.template),
299299
_asComponent: this.asComponent,
300+
_host: this._host,
300301
_linkFn: this._linkFn,
301302
_meta: meta,
302303
data: data,

src/instance/compile.js

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -89,11 +89,12 @@ exports._initElement = function (el) {
8989
* @param {Node} node - target node
9090
* @param {Object} desc - parsed directive descriptor
9191
* @param {Object} def - directive definition object
92+
* @param {Vue|undefined} host - transclusion host component
9293
*/
9394

94-
exports._bindDir = function (name, node, desc, def) {
95+
exports._bindDir = function (name, node, desc, def, host) {
9596
this._directives.push(
96-
new Directive(name, node, this, desc, def)
97+
new Directive(name, node, this, desc, def, host)
9798
)
9899
}
99100

@@ -120,6 +121,12 @@ exports._destroy = function (remove, deferCleanup) {
120121
i = parent._children.indexOf(this)
121122
parent._children.splice(i, 1)
122123
}
124+
// same for transclusion host.
125+
var host = this._host
126+
if (host && !host._isBeingDestroyed) {
127+
i = host._transCpnts.indexOf(this)
128+
host._transCpnts.splice(i, 1)
129+
}
123130
// destroy all children.
124131
i = this._children.length
125132
while (i--) {

src/instance/events.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ exports._initDOMHooks = function () {
8080
function onAttached () {
8181
this._isAttached = true
8282
this._children.forEach(callAttach)
83-
if (this._transCpnts) {
83+
if (this._transCpnts.length) {
8484
this._transCpnts.forEach(callAttach)
8585
}
8686
}
@@ -104,7 +104,7 @@ function callAttach (child) {
104104
function onDetached () {
105105
this._isAttached = false
106106
this._children.forEach(callDetach)
107-
if (this._transCpnts) {
107+
if (this._transCpnts.length) {
108108
this._transCpnts.forEach(callDetach)
109109
}
110110
}

src/instance/init.js

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,16 @@ exports._init = function (options) {
5656
// transcluded components that belong to the parent.
5757
// need to keep track of them so that we can call
5858
// attached/detached hooks on them.
59-
this._transCpnts = null
59+
this._transCpnts = []
60+
this._host = options._host
61+
62+
// push self into parent / transclusion host
63+
if (this.$parent) {
64+
this.$parent._children.push(this)
65+
}
66+
if (this._host) {
67+
this._host._transCpnts.push(this)
68+
}
6069

6170
// props used in v-repeat diffing
6271
this._new = true

test/unit/specs/compiler/compile_spec.js

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -53,10 +53,10 @@ if (_.inBrowser) {
5353
expect(typeof linker).toBe('function')
5454
linker(vm, el)
5555
expect(vm._bindDir.calls.count()).toBe(4)
56-
expect(vm._bindDir).toHaveBeenCalledWith('a', el, descriptorB, defA)
57-
expect(vm._bindDir).toHaveBeenCalledWith('a', el.firstChild, descriptorA, defA)
58-
expect(vm._bindDir).toHaveBeenCalledWith('b', el.firstChild, descriptorB, defB)
59-
expect(vm._bindDir).toHaveBeenCalledWith('b', el.lastChild, descriptorB, defB)
56+
expect(vm._bindDir).toHaveBeenCalledWith('a', el, descriptorB, defA, undefined)
57+
expect(vm._bindDir).toHaveBeenCalledWith('a', el.firstChild, descriptorA, defA, undefined)
58+
expect(vm._bindDir).toHaveBeenCalledWith('b', el.firstChild, descriptorB, defB, undefined)
59+
expect(vm._bindDir).toHaveBeenCalledWith('b', el.lastChild, descriptorB, defB, undefined)
6060
// check the priority sorting
6161
// the "b" on the firstNode should be called first!
6262
expect(vm._bindDir.calls.argsFor(1)[0]).toBe('b')
@@ -116,7 +116,7 @@ if (_.inBrowser) {
116116
// expect 1 call because terminal should return early and let
117117
// the directive handle the rest.
118118
expect(vm._bindDir.calls.count()).toBe(1)
119-
expect(vm._bindDir).toHaveBeenCalledWith('repeat', el.firstChild, descriptor, def)
119+
expect(vm._bindDir).toHaveBeenCalledWith('repeat', el.firstChild, descriptor, def, undefined)
120120
})
121121

122122
it('custom element components', function () {
@@ -131,7 +131,7 @@ if (_.inBrowser) {
131131
var linker = compile(el, options)
132132
linker(vm, el)
133133
expect(vm._bindDir.calls.count()).toBe(1)
134-
expect(vm._bindDir).toHaveBeenCalledWith('component', el.firstChild, descriptor, def)
134+
expect(vm._bindDir).toHaveBeenCalledWith('component', el.firstChild, descriptor, def, undefined)
135135
expect(_.warn).not.toHaveBeenCalled()
136136
})
137137

0 commit comments

Comments
 (0)