apply optimisation to raw tags

pull/769/head
Rich Harris 8 years ago
parent 5070219218
commit 4dd5fc5594

@ -12,12 +12,21 @@ export default function visitRawMustacheTag(
) {
const name = node._state.basename;
const before = node._state.name;
const value = block.getUniqueName(`${name}_value`);
const after = block.getUniqueName(`${name}_after`);
const { snippet } = block.contextualise(node.expression);
const { dependencies, indexes, snippet } = block.contextualise(node.expression);
block.addVariable(value);
const hasChangeableIndex = Array.from(indexes).some(index => block.changeableIndexes.get(index));
const shouldCache = (
node.expression.type !== 'Identifier' ||
block.contexts.has(node.expression.name) ||
hasChangeableIndex
);
const value = shouldCache && block.getUniqueName(`${name}_value`);
const init = shouldCache ? `${value} = ${snippet}` : snippet;
if (shouldCache) block.addVariable(value);
// we would have used comments here, but the `insertAdjacentHTML` api only
// exists for `Element`s.
@ -38,17 +47,27 @@ export default function visitRawMustacheTag(
const isToplevel = !state.parentNode;
const mountStatement = `${before}.insertAdjacentHTML( 'afterend', ${value} = ${snippet} );`;
const detachStatement = `@detachBetween( ${before}, ${after} );`;
block.builders.mount.addLine(`${before}.insertAdjacentHTML( 'afterend', ${init} );`);
block.builders.detachRaw.addBlock(`@detachBetween( ${before}, ${after} );`);
if (dependencies.length || hasChangeableIndex) {
const changedCheck = (
( block.hasOutroMethod ? `#outroing || ` : '' ) +
dependencies.map(dependency => `'${dependency}' in changed`).join(' || ')
);
block.builders.mount.addLine(mountStatement);
const updateCachedValue = `${value} !== ( ${value} = ${snippet} )`;
block.builders.update.addBlock(deindent`
if ( ${value} !== ( ${value} = ${snippet} ) ) {
${detachStatement}
${mountStatement}
}
`);
const condition = shouldCache ?
( dependencies.length ? `( ${changedCheck} ) && ${updateCachedValue}` : updateCachedValue ) :
changedCheck;
block.builders.detachRaw.addBlock(detachStatement);
block.builders.update.addConditionalLine(
condition,
deindent`
@detachBetween( ${before}, ${after} );
${before}.insertAdjacentHTML( 'afterend', ${shouldCache ? value : snippet} );
`
);
}
}

@ -21,15 +21,17 @@ export default class CodeBuilder {
this.lastCondition = null;
}
addConditionalLine(condition: string, line: string) {
addConditionalLine(condition: string, body: string) {
body = body.replace(/^/gm, '\t');
if (condition === this.lastCondition) {
this.result += `\n\t${line}`;
this.result += `\n${body}`;
} else {
if (this.lastCondition) {
this.result += `\n}`;
}
this.result += `${this.last === ChunkType.Block ? '\n\n' : '\n'}if ( ${condition} ) {\n\t${line}`;
this.result += `${this.last === ChunkType.Block ? '\n\n' : '\n'}if ( ${condition} ) {\n${body}`;
this.lastCondition = condition;
}

@ -125,7 +125,7 @@ export function normalizeHtml(window, html) {
.replace(/>[\s\r\n]+</g, '><')
.trim();
cleanChildren(node, '');
return node.innerHTML;
return node.innerHTML.replace(/<\/?noscript\/?>/g, '');
}
export function setupHtmlEqual() {

@ -297,9 +297,9 @@ function create_each_block ( state, each_block_value, comment, i, component ) {
text_4.data = text_4_value;
}
if ( raw_value !== ( raw_value = comment.html ) ) {
if ( ( 'comments' in changed ) && raw_value !== ( raw_value = comment.html ) ) {
detachBetween( raw_before, raw_after );
raw_before.insertAdjacentHTML( 'afterend', raw_value = comment.html );
raw_before.insertAdjacentHTML( 'afterend', raw_value );
}
},

@ -123,9 +123,9 @@ function create_each_block ( state, each_block_value, comment, i, component ) {
text_4.data = text_4_value;
}
if ( raw_value !== ( raw_value = comment.html ) ) {
if ( ( 'comments' in changed ) && raw_value !== ( raw_value = comment.html ) ) {
detachBetween( raw_before, raw_after );
raw_before.insertAdjacentHTML( 'afterend', raw_value = comment.html );
raw_before.insertAdjacentHTML( 'afterend', raw_value );
}
},

@ -1,38 +0,0 @@
import counter from './counter.js';
export default {
data: {
x: 1,
y: 2,
z: 3
},
html: `
<p>1</p>
<p class='2'>3</p>
`,
test(assert, component) {
counter.y = counter.z = 0;
component.set({ x: 4 });
assert.equal(counter.y, 0);
assert.equal(counter.z, 0);
component.set({ x: 5, y: 6 });
assert.equal(counter.y, 1);
assert.equal(counter.z, 0);
component.set({ x: 6, y: 6 });
assert.equal(counter.y, 1);
assert.equal(counter.z, 0);
component.set({ z: 7 });
assert.equal(counter.y, 1);
assert.equal(counter.z, 1);
component.set({ x: 8, z: 7 });
assert.equal(counter.y, 1);
assert.equal(counter.z, 1);
}
};

@ -0,0 +1,26 @@
import counter from './counter.js';
export default {
data: {
x: 1,
y: 2
},
html: `
<p>1</p>
<p class='-2-'></p>
`,
test(assert, component) {
counter.count = 0;
component.set({ x: 3 });
assert.equal(counter.count, 0);
component.set({ x: 4, y: 5 });
assert.equal(counter.count, 1);
component.set({ x: 5, y: 5 });
assert.equal(counter.count, 1);
}
};

@ -1,18 +1,13 @@
<p>{{x}}</p>
<p class='{{getClass(y)}}'>{{myHelper(z)}}</p>
<p class='-{{myHelper(y)}}-'></p>
<script>
import counter from './counter.js';
export default {
helpers: {
getClass(value) {
counter.y += 1;
return value;
},
myHelper(value) {
counter.z += 1;
counter.count += 1;
return value;
}
}

@ -0,0 +1,26 @@
import counter from './counter.js';
export default {
data: {
x: 1,
y: 2
},
html: `
<p>1</p>
<p class='2'></p>
`,
test(assert, component) {
counter.count = 0;
component.set({ x: 3 });
assert.equal(counter.count, 0);
component.set({ x: 4, y: 5 });
assert.equal(counter.count, 1);
component.set({ x: 5, y: 5 });
assert.equal(counter.count, 1);
}
};

@ -0,0 +1,15 @@
<p>{{x}}</p>
<p class='{{myHelper(y)}}'></p>
<script>
import counter from './counter.js';
export default {
helpers: {
myHelper(value) {
counter.count += 1;
return value;
}
}
};
</script>

@ -0,0 +1,26 @@
import counter from './counter.js';
export default {
data: {
x: 1,
y: 2
},
html: `
<p>1</p>
<p>2</p>
`,
test(assert, component) {
counter.count = 0;
component.set({ x: 3 });
assert.equal(counter.count, 0);
component.set({ x: 4, y: 5 });
assert.equal(counter.count, 1);
component.set({ x: 5, y: 5 });
assert.equal(counter.count, 1);
}
};

@ -0,0 +1,15 @@
<p>{{x}}</p>
<p>{{{myHelper(y)}}}</p>
<script>
import counter from './counter.js';
export default {
helpers: {
myHelper(value) {
counter.count += 1;
return value;
}
}
};
</script>

@ -0,0 +1,26 @@
import counter from './counter.js';
export default {
data: {
x: 1,
y: 2
},
html: `
<p>1</p>
<p>2</p>
`,
test(assert, component) {
counter.count = 0;
component.set({ x: 3 });
assert.equal(counter.count, 0);
component.set({ x: 4, y: 5 });
assert.equal(counter.count, 1);
component.set({ x: 5, y: 5 });
assert.equal(counter.count, 1);
}
};

@ -0,0 +1,15 @@
<p>{{x}}</p>
<p>{{myHelper(y)}}</p>
<script>
import counter from './counter.js';
export default {
helpers: {
myHelper(value) {
counter.count += 1;
return value;
}
}
};
</script>
Loading…
Cancel
Save