diff --git a/src/generators/dom/preprocess.ts b/src/generators/dom/preprocess.ts
index 24663d9796..6beca924ff 100644
--- a/src/generators/dom/preprocess.ts
+++ b/src/generators/dom/preprocess.ts
@@ -353,9 +353,7 @@ const preprocessors = {
}
const name = block.getUniqueName(
- node.name === 'slot' ?
- `slot_${getStaticAttributeValue(node, 'name') || 'default'}`:
- node.name.replace(/[^a-zA-Z0-9_$]/g, '_')
+ node.name.replace(/[^a-zA-Z0-9_$]/g, '_')
);
node._state = getChildState(state, {
diff --git a/src/generators/dom/visitors/Slot.ts b/src/generators/dom/visitors/Slot.ts
index 9a059c138e..85f53f2ca3 100644
--- a/src/generators/dom/visitors/Slot.ts
+++ b/src/generators/dom/visitors/Slot.ts
@@ -17,38 +17,14 @@ export default function visitSlot(
const slotName = getStaticAttributeValue(node, 'name') || 'default';
generator.slots.add(slotName);
- const name = node._state.name;
const content_name = block.getUniqueName(`slot_content_${slotName}`);
-
block.addVariable(content_name, `#component._slotted.${slotName}`);
- block.addVariable(name);
- block.addElement(
- name,
- `@createElement('slot')`,
- `@claimElement(${state.parentNodes}, 'slot', {${slotName !== 'default' ? ` name: '${slotName}' ` : ''}})`,
- state.parentNode
- );
-
- if (generator.hydratable) {
- block.builders.claim.addLine(
- `var ${node._state.parentNodes} = @children(${name});`
- );
- }
-
- if (slotName !== 'default') {
- block.builders.hydrate.addBlock(deindent`
- @setAttribute(${name}, 'name', '${slotName}');
- `);
- }
-
- block.builders.mount.addLine(
- `#component.slots.${slotName} = ${name};`
- );
-
- block.builders.unmount.addLine(
- `#component.slots.${slotName} = null;`
- );
+ // TODO use surrounds as anchors where possible, a la if/each blocks
+ const before = block.getUniqueName(`${content_name}_before`);
+ const after = block.getUniqueName(`${content_name}_after`);
+ block.addVariable(before);
+ block.addVariable(after);
block.builders.create.pushCondition(`!${content_name}`);
block.builders.hydrate.pushCondition(`!${content_name}`);
@@ -57,7 +33,7 @@ export default function visitSlot(
block.builders.destroy.pushCondition(`!${content_name}`);
node.children.forEach((child: Node) => {
- visit(generator, block, node._state, child, elementStack.concat(node), componentStack);
+ visit(generator, block, state, child, elementStack, componentStack);
});
block.builders.create.popCondition();
@@ -67,19 +43,34 @@ export default function visitSlot(
block.builders.destroy.popCondition();
// TODO can we use an else here?
- block.builders.mount.addBlock(deindent`
- if (${content_name}) {
- @appendNode(${content_name}, ${name});
- }
- `);
+ if (state.parentNode) {
+ block.builders.mount.addBlock(deindent`
+ if (${content_name}) {
+ @appendNode(${before} || (${before} = @createComment()), ${state.parentNode});
+ @appendNode(${content_name}, ${state.parentNode});
+ @appendNode(${after} || (${after} = @createComment()), ${state.parentNode});
+ }
+ `);
+ } else {
+ block.builders.mount.addBlock(deindent`
+ if (${content_name}) {
+ @insertNode(${before} || (${before} = @createComment()), #target, anchor);
+ @insertNode(${content_name}, #target, anchor);
+ @insertNode(${after} || (${after} = @createComment()), #target, anchor);
+ }
+ `);
+ }
// if the slot is unmounted, move nodes back into the document fragment,
// so that it can be reinserted later
// TODO so that this can work with public API, component._slotted should
// be all fragments, derived from options.slots. Not === options.slots
+ // TODO can we use an else here?
block.builders.unmount.addBlock(deindent`
if (${content_name}) {
- while (${name}.firstChild) @appendNode(${name}.firstChild, ${content_name});
+ @reinsertBetween(${before}, ${after}, ${content_name});
+ @detachNode(${before});
+ @detachNode(${after});
}
`);
}
diff --git a/src/generators/server-side-rendering/visitors/Slot.ts b/src/generators/server-side-rendering/visitors/Slot.ts
index 8288b283fe..3886f8a4d9 100644
--- a/src/generators/server-side-rendering/visitors/Slot.ts
+++ b/src/generators/server-side-rendering/visitors/Slot.ts
@@ -12,7 +12,6 @@ export default function visitSlot(
const name = node.attributes.find((attribute: Node) => attribute.name);
const slotName = name && name.value[0].data || 'default';
- generator.append(``);
generator.append(`\${options && options.slotted && options.slotted.${slotName} ? options.slotted.${slotName}() : '`);
generator.elementDepth += 1;
@@ -23,5 +22,5 @@ export default function visitSlot(
generator.elementDepth -= 1;
- generator.append(`'} `);
+ generator.append(`'}`);
}
diff --git a/src/shared/dom.js b/src/shared/dom.js
index 2ed1173f2d..8408ffd359 100644
--- a/src/shared/dom.js
+++ b/src/shared/dom.js
@@ -16,6 +16,12 @@ export function detachBetween(before, after) {
}
}
+export function reinsertBetween(before, after, target) {
+ while (before.nextSibling && before.nextSibling !== after) {
+ target.appendChild(before.parentNode.removeChild(before.nextSibling));
+ }
+}
+
// TODO this is out of date
export function destroyEach(iterations, detach, start) {
for (var i = start; i < iterations.length; i += 1) {
diff --git a/test/runtime/samples/binding-select-in-yield/_config.js b/test/runtime/samples/binding-select-in-yield/_config.js
index 927a8a14a1..4ff851d33f 100644
--- a/test/runtime/samples/binding-select-in-yield/_config.js
+++ b/test/runtime/samples/binding-select-in-yield/_config.js
@@ -9,15 +9,13 @@ export default {
component.refs.modal.toggle();
assert.htmlEqual(target.innerHTML, `
-
- b
+ b
-
- a
- b
- c
-
-
+
+ a
+ b
+ c
+
`);
const select = target.querySelector('select');
@@ -34,15 +32,13 @@ export default {
]);
assert.htmlEqual(target.innerHTML, `
-
- c
+ c
-
- a
- b
- c
-
-
+
+ a
+ b
+ c
+
`);
component.refs.modal.toggle();
@@ -55,15 +51,13 @@ export default {
]);
assert.htmlEqual(target.innerHTML, `
-
- c
+ c
-
- a
- b
- c
-
-
+
+ a
+ b
+ c
+
`);
}
};
diff --git a/test/runtime/samples/component-binding-blowback-b/_config.js b/test/runtime/samples/component-binding-blowback-b/_config.js
index 9e32ad9a91..7f2bd38d9b 100644
--- a/test/runtime/samples/component-binding-blowback-b/_config.js
+++ b/test/runtime/samples/component-binding-blowback-b/_config.js
@@ -8,9 +8,9 @@ export default {
html: `
- id-0: value is zero
- id-1: value is one
- id-2: value is two
+ id-0: value is zero
+ id-1: value is one
+ id-2: value is two
`,
@@ -23,10 +23,10 @@ export default {
assert.htmlEqual(target.innerHTML, `
- id-0: value is zero
- id-1: value is one
- id-2: value is two
- id-3: value is three
+ id-0: value is zero
+ id-1: value is one
+ id-2: value is two
+ id-3: value is three
`);
}
diff --git a/test/runtime/samples/component-binding-blowback-c/_config.js b/test/runtime/samples/component-binding-blowback-c/_config.js
index 1d2cdbe2b2..78c3e915fd 100644
--- a/test/runtime/samples/component-binding-blowback-c/_config.js
+++ b/test/runtime/samples/component-binding-blowback-c/_config.js
@@ -8,9 +8,9 @@ export default {
html: `
- id-2: value is two
- id-1: value is one
- id-0: value is zero
+ id-2: value is two
+ id-1: value is one
+ id-0: value is zero
`,
@@ -23,10 +23,10 @@ export default {
assert.htmlEqual(target.innerHTML, `
- id-3: value is three
- id-2: value is two
- id-1: value is one
- id-0: value is zero
+ id-3: value is three
+ id-2: value is two
+ id-1: value is one
+ id-0: value is zero
`);
}
diff --git a/test/runtime/samples/component-binding-infinite-loop/_config.js b/test/runtime/samples/component-binding-infinite-loop/_config.js
index 3668227e21..6a379af0a4 100644
--- a/test/runtime/samples/component-binding-infinite-loop/_config.js
+++ b/test/runtime/samples/component-binding-infinite-loop/_config.js
@@ -1,28 +1,28 @@
export default {
html: `
- 1
- 2
- 3
- 2
- 1
+ 1
+ 2
+ 3
+ 2
+ 1
- 1
- 2
- 3
- 2
- 1
+ 1
+ 2
+ 3
+ 2
+ 1
- 1
- 2
- 3
- 2
- 1
+ 1
+ 2
+ 3
+ 2
+ 1
- 1
- 2
- 3
- 2
- 1
+ 1
+ 2
+ 3
+ 2
+ 1
`,
test ( assert, component, target, window ) {
@@ -33,58 +33,58 @@ export default {
assert.equal( component.get( 'currentIdentifier' ), 1 );
assert.htmlEqual( target.innerHTML, `
- 1
- 2
- 3
- 2
- 1
+ 1
+ 2
+ 3
+ 2
+ 1
- 1
- 2
- 3
- 2
- 1
+ 1
+ 2
+ 3
+ 2
+ 1
- 1
- 2
- 3
- 2
- 1
+ 1
+ 2
+ 3
+ 2
+ 1
- 1
- 2
- 3
- 2
- 1
+ 1
+ 2
+ 3
+ 2
+ 1
` );
spans[0].dispatchEvent( click );
assert.equal( component.get( 'currentIdentifier' ), null );
assert.htmlEqual( target.innerHTML, `
- 1
- 2
- 3
- 2
- 1
+ 1
+ 2
+ 3
+ 2
+ 1
- 1
- 2
- 3
- 2
- 1
+ 1
+ 2
+ 3
+ 2
+ 1
- 1
- 2
- 3
- 2
- 1
+ 1
+ 2
+ 3
+ 2
+ 1
- 1
- 2
- 3
- 2
- 1
+ 1
+ 2
+ 3
+ 2
+ 1
` );
}
};
diff --git a/test/runtime/samples/component-not-void/_config.js b/test/runtime/samples/component-not-void/_config.js
index 01d610e458..174d01f1a5 100644
--- a/test/runtime/samples/component-not-void/_config.js
+++ b/test/runtime/samples/component-not-void/_config.js
@@ -1,3 +1,3 @@
export default {
- html: 'Hello
'
+ html: 'Hello
'
};
diff --git a/test/runtime/samples/component-slot-default/_config.js b/test/runtime/samples/component-slot-default/_config.js
index 04ea8d044a..174d01f1a5 100644
--- a/test/runtime/samples/component-slot-default/_config.js
+++ b/test/runtime/samples/component-slot-default/_config.js
@@ -1,7 +1,3 @@
export default {
- html: 'Hello
',
-
- test(assert, component) {
- assert.htmlEqual(component.refs.nested.slots.default.innerHTML, 'Hello');
- }
+ html: 'Hello
'
};
diff --git a/test/runtime/samples/component-slot-fallback/_config.js b/test/runtime/samples/component-slot-fallback/_config.js
index 14e7ad403b..64f770b5a4 100644
--- a/test/runtime/samples/component-slot-fallback/_config.js
+++ b/test/runtime/samples/component-slot-fallback/_config.js
@@ -1,9 +1,9 @@
export default {
html: `
-
not fallback
-
bar fallback content
-
foo fallback content
+
not fallback
+
bar fallback content
+
foo fallback content
`
};
diff --git a/test/runtime/samples/component-slot-named/_config.js b/test/runtime/samples/component-slot-named/_config.js
index 251ded4a65..330e219242 100644
--- a/test/runtime/samples/component-slot-named/_config.js
+++ b/test/runtime/samples/component-slot-named/_config.js
@@ -1,15 +1,9 @@
export default {
html: `
-
Hello
-
bar
-
foo
+ Hello
+
bar
+
foo
- `,
-
- test(assert, component) {
- assert.htmlEqual(component.refs.nested.slots.default.innerHTML, 'Hello');
- assert.htmlEqual(component.refs.nested.slots.foo.innerHTML, `foo
`);
- assert.htmlEqual(component.refs.nested.slots.bar.innerHTML, `bar
`);
- }
+ `
};
diff --git a/test/runtime/samples/component-yield-follows-element/_config.js b/test/runtime/samples/component-yield-follows-element/_config.js
index 390a349ccd..93703c7dab 100644
--- a/test/runtime/samples/component-yield-follows-element/_config.js
+++ b/test/runtime/samples/component-yield-follows-element/_config.js
@@ -1,6 +1,6 @@
export default {
html: `
before
- test
+ test
`
};
diff --git a/test/runtime/samples/component-yield-if/_config.js b/test/runtime/samples/component-yield-if/_config.js
index 8bc6fec66a..a428e4522d 100644
--- a/test/runtime/samples/component-yield-if/_config.js
+++ b/test/runtime/samples/component-yield-if/_config.js
@@ -7,10 +7,10 @@ export default {
assert.equal( widget.get( 'show' ), false );
widget.set({show: true});
- assert.htmlEqual( target.innerHTML, '' );
+ assert.htmlEqual( target.innerHTML, '' );
component.set({data: 'World'});
- assert.htmlEqual( target.innerHTML, '' );
+ assert.htmlEqual( target.innerHTML, '' );
widget.set({show: false});
assert.htmlEqual( target.innerHTML, '' );
@@ -19,6 +19,6 @@ export default {
assert.htmlEqual( target.innerHTML, '' );
widget.set({show: true});
- assert.htmlEqual( target.innerHTML, '' );
+ assert.htmlEqual( target.innerHTML, '' );
}
};
diff --git a/test/runtime/samples/component-yield-multiple-in-each/_config.js b/test/runtime/samples/component-yield-multiple-in-each/_config.js
index dec002f6e9..3669b3f90b 100644
--- a/test/runtime/samples/component-yield-multiple-in-each/_config.js
+++ b/test/runtime/samples/component-yield-multiple-in-each/_config.js
@@ -1,8 +1,8 @@
export default {
html: `
- Hello Alice
- Hello Bob
- Hello Charles
+ Hello Alice
+ Hello Bob
+ Hello Charles
`,
test ( assert, component, target ) {
@@ -11,9 +11,9 @@ export default {
});
assert.htmlEqual( target.innerHTML, `
- Hello Alice
- Hello Charles
- Hello Bob
+ Hello Alice
+ Hello Charles
+ Hello Bob
`);
}
};
diff --git a/test/runtime/samples/component-yield-multiple-in-if/_config.js b/test/runtime/samples/component-yield-multiple-in-if/_config.js
index 15808c86b6..1460962e7a 100644
--- a/test/runtime/samples/component-yield-multiple-in-if/_config.js
+++ b/test/runtime/samples/component-yield-multiple-in-if/_config.js
@@ -1,11 +1,11 @@
export default {
html: `
-
+
`,
test ( assert, component, target ) {
component.set({ arriving: false });
- assert.htmlEqual( target.innerHTML, `` );
+ assert.htmlEqual( target.innerHTML, `` );
component.destroy();
}
diff --git a/test/runtime/samples/component-yield-nested-if/_config.js b/test/runtime/samples/component-yield-nested-if/_config.js
index e623b1875f..44548b2f16 100644
--- a/test/runtime/samples/component-yield-nested-if/_config.js
+++ b/test/runtime/samples/component-yield-nested-if/_config.js
@@ -1,7 +1,7 @@
export default {
html: `
- One
- Inner
+ One
+ Inner
`,
test ( assert, component, target ) {
@@ -9,6 +9,6 @@ export default {
assert.htmlEqual( target.innerHTML, `` );
component.set({ foo: true });
- assert.htmlEqual( target.innerHTML, `One\nInner ` );
+ assert.htmlEqual( target.innerHTML, `One\nInner` );
}
};
diff --git a/test/runtime/samples/component-yield-parent/_config.js b/test/runtime/samples/component-yield-parent/_config.js
index 2aafa0f982..b80ee68bdb 100644
--- a/test/runtime/samples/component-yield-parent/_config.js
+++ b/test/runtime/samples/component-yield-parent/_config.js
@@ -1,6 +1,6 @@
export default {
html: `
-
+
`,
test ( assert, component, target ) {
@@ -9,7 +9,7 @@ export default {
component.set({ data: 'World' });
assert.equal( component.get( 'data' ), 'World' );
assert.htmlEqual( target.innerHTML, `
-
+
` );
}
};
diff --git a/test/runtime/samples/component-yield-placement/_config.js b/test/runtime/samples/component-yield-placement/_config.js
index 6c3b08961a..6e5a7d4b73 100644
--- a/test/runtime/samples/component-yield-placement/_config.js
+++ b/test/runtime/samples/component-yield-placement/_config.js
@@ -7,7 +7,7 @@ export default {
- Hello!
+
Hello!
close modal
`,
diff --git a/test/runtime/samples/component-yield-static/_config.js b/test/runtime/samples/component-yield-static/_config.js
index 05acc4edf7..06bcd82882 100644
--- a/test/runtime/samples/component-yield-static/_config.js
+++ b/test/runtime/samples/component-yield-static/_config.js
@@ -1,12 +1,12 @@
export default {
html: `
- Hello
+ Hello
`,
test ( assert, component, target ) {
component.set( { name: 'World' } );
assert.htmlEqual( target.innerHTML, `
- Hello World
+ Hello World
` );
}
};
diff --git a/test/runtime/samples/component-yield/_config.js b/test/runtime/samples/component-yield/_config.js
index 07459ac8b3..86cb924c9b 100644
--- a/test/runtime/samples/component-yield/_config.js
+++ b/test/runtime/samples/component-yield/_config.js
@@ -1,6 +1,6 @@
export default {
html: `
Hello
-
+
`
};
diff --git a/test/runtime/samples/flush-before-bindings/_config.js b/test/runtime/samples/flush-before-bindings/_config.js
index e28737b19c..1f731d6a34 100644
--- a/test/runtime/samples/flush-before-bindings/_config.js
+++ b/test/runtime/samples/flush-before-bindings/_config.js
@@ -4,8 +4,8 @@ export default {
'skip-ssr': true,
html: `
-
-
+
+
`,
test(assert, component) {
diff --git a/test/server-side-rendering/samples/component-yield/_actual.html b/test/server-side-rendering/samples/component-yield/_actual.html
index b76eab3af6..49139417a2 100644
--- a/test/server-side-rendering/samples/component-yield/_actual.html
+++ b/test/server-side-rendering/samples/component-yield/_actual.html
@@ -1,3 +1,3 @@
\ No newline at end of file
diff --git a/test/server-side-rendering/samples/component-yield/_expected.html b/test/server-side-rendering/samples/component-yield/_expected.html
index b76eab3af6..49139417a2 100644
--- a/test/server-side-rendering/samples/component-yield/_expected.html
+++ b/test/server-side-rendering/samples/component-yield/_expected.html
@@ -1,3 +1,3 @@
\ No newline at end of file