wrap fallback hydration code in conditional

pull/787/head
Rich Harris 8 years ago
parent a023346c91
commit 361a19df17

@ -51,6 +51,7 @@ export default function visitSlot(
); );
block.builders.create.pushCondition(`!${content_name}`); block.builders.create.pushCondition(`!${content_name}`);
block.builders.hydrate.pushCondition(`!${content_name}`);
block.builders.mount.pushCondition(`!${content_name}`); block.builders.mount.pushCondition(`!${content_name}`);
block.builders.unmount.pushCondition(`!${content_name}`); block.builders.unmount.pushCondition(`!${content_name}`);
block.builders.destroy.pushCondition(`!${content_name}`); block.builders.destroy.pushCondition(`!${content_name}`);
@ -60,6 +61,7 @@ export default function visitSlot(
}); });
block.builders.create.popCondition(); block.builders.create.popCondition();
block.builders.hydrate.popCondition();
block.builders.mount.popCondition(); block.builders.mount.popCondition();
block.builders.unmount.popCondition(); block.builders.unmount.popCondition();
block.builders.destroy.popCondition(); block.builders.destroy.popCondition();

@ -5,12 +5,17 @@ enum ChunkType {
Block Block
} }
interface Condition {
condition: string;
used: boolean;
}
export default class CodeBuilder { export default class CodeBuilder {
result: string; result: string;
first: ChunkType; first: ChunkType;
last: ChunkType; last: ChunkType;
lastCondition: string; lastCondition: string;
conditionStack: string[]; conditionStack: Condition[];
indent: string; indent: string;
constructor(str = '') { constructor(str = '') {
@ -28,6 +33,8 @@ export default class CodeBuilder {
} }
addConditional(condition: string, body: string) { addConditional(condition: string, body: string) {
this.reifyConditions();
body = body.replace(/^/gm, `${this.indent}\t`); body = body.replace(/^/gm, `${this.indent}\t`);
if (condition === this.lastCondition) { if (condition === this.lastCondition) {
@ -45,6 +52,8 @@ export default class CodeBuilder {
} }
addLine(line: string) { addLine(line: string) {
this.reifyConditions();
if (this.lastCondition) { if (this.lastCondition) {
this.result += `\n${this.indent}}`; this.result += `\n${this.indent}}`;
this.lastCondition = null; this.lastCondition = null;
@ -63,6 +72,8 @@ export default class CodeBuilder {
} }
addLineAtStart(line: string) { addLineAtStart(line: string) {
this.reifyConditions();
if (this.first === ChunkType.Block) { if (this.first === ChunkType.Block) {
this.result = `${line}\n\n${this.indent}${this.result}`; this.result = `${line}\n\n${this.indent}${this.result}`;
} else if (this.first === ChunkType.Line) { } else if (this.first === ChunkType.Line) {
@ -76,6 +87,8 @@ export default class CodeBuilder {
} }
addBlock(block: string) { addBlock(block: string) {
this.reifyConditions();
if (this.indent) block = block.replace(/^/gm, `${this.indent}`); if (this.indent) block = block.replace(/^/gm, `${this.indent}`);
if (this.lastCondition) { if (this.lastCondition) {
@ -94,6 +107,8 @@ export default class CodeBuilder {
} }
addBlockAtStart(block: string) { addBlockAtStart(block: string) {
this.reifyConditions();
if (this.result) { if (this.result) {
this.result = `${block}\n\n${this.indent}${this.result}`; this.result = `${block}\n\n${this.indent}${this.result}`;
} else { } else {
@ -109,15 +124,37 @@ export default class CodeBuilder {
} }
pushCondition(condition: string) { pushCondition(condition: string) {
this.conditionStack.push(condition); this.conditionStack.push({ condition, used: false });
this.addLine(`if (${condition}) {`);
this.indent = repeat('\t', this.conditionStack.length);
} }
popCondition() { popCondition() {
this.conditionStack.pop(); const { used } = this.conditionStack.pop();
this.indent = repeat('\t', this.conditionStack.length);
if (used) this.addLine('}');
}
reifyConditions() {
for (let i = 0; i < this.conditionStack.length; i += 1) {
const condition = this.conditionStack[i];
if (!condition.used) {
const line = `if (${condition.condition}) {`;
if (this.last === ChunkType.Block) {
this.result += `\n\n${this.indent}${line}`;
} else if (this.last === ChunkType.Line) {
this.result += `\n${this.indent}${line}`;
} else {
this.result += line;
}
this.last = ChunkType.Line;
if (!this.first) this.first = ChunkType.Line;
this.indent = repeat('\t', this.conditionStack.length); this.indent = repeat('\t', this.conditionStack.length);
this.addLine('}'); condition.used = true;
}
}
} }
toString() { toString() {

@ -120,12 +120,16 @@ function cleanChildren(node) {
} }
export function normalizeHtml(window, html) { export function normalizeHtml(window, html) {
try {
const node = window.document.createElement('div'); const node = window.document.createElement('div');
node.innerHTML = html node.innerHTML = html
.replace(/>[\s\r\n]+</g, '><') .replace(/>[\s\r\n]+</g, '><')
.trim(); .trim();
cleanChildren(node, ''); cleanChildren(node, '');
return node.innerHTML.replace(/<\/?noscript\/?>/g, ''); return node.innerHTML.replace(/<\/?noscript\/?>/g, '');
} catch (err) {
throw new Error(`Failed to normalize HTML:\n${html}`);
}
} }
export function setupHtmlEqual() { export function setupHtmlEqual() {

@ -1,5 +1,5 @@
<div> <div>
<slot>default fallback content</slot> <slot><p class='default'>default fallback content</p></slot>
<slot name='bar'>bar fallback content</slot> <slot name='bar'><p class='default'>bar fallback content</p></slot>
<slot name='foo'>foo fallback content</slot> <slot name='foo'><p class='default'>foo fallback content</p></slot>
</div> </div>

@ -1,9 +1,9 @@
export default { export default {
html: ` html: `
<div> <div>
<slot>default fallback content</slot> <slot><p>not fallback</p></slot>
<slot name='bar'>bar fallback content</slot> <slot name='bar'><p class='default'>bar fallback content</p></slot>
<slot name='foo'>foo fallback content</slot> <slot name='foo'><p class='default'>foo fallback content</p></slot>
</div> </div>
` `
}; };

@ -1,4 +1,6 @@
<Nested ref:nested></Nested> <Nested ref:nested>
<p>not fallback</p>
</Nested>
<script> <script>
import Nested from './Nested.html'; import Nested from './Nested.html';

Loading…
Cancel
Save