Skip to content

Commit 4dd5fc5

Browse files
committed
apply optimisation to raw tags
1 parent 5070219 commit 4dd5fc5

File tree

18 files changed

+203
-68
lines changed

18 files changed

+203
-68
lines changed

src/generators/dom/visitors/RawMustacheTag.ts

Lines changed: 32 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,21 @@ export default function visitRawMustacheTag(
1212
) {
1313
const name = node._state.basename;
1414
const before = node._state.name;
15-
const value = block.getUniqueName(`${name}_value`);
1615
const after = block.getUniqueName(`${name}_after`);
1716

18-
const { snippet } = block.contextualise(node.expression);
17+
const { dependencies, indexes, snippet } = block.contextualise(node.expression);
1918

20-
block.addVariable(value);
19+
const hasChangeableIndex = Array.from(indexes).some(index => block.changeableIndexes.get(index));
20+
21+
const shouldCache = (
22+
node.expression.type !== 'Identifier' ||
23+
block.contexts.has(node.expression.name) ||
24+
hasChangeableIndex
25+
);
26+
27+
const value = shouldCache && block.getUniqueName(`${name}_value`);
28+
const init = shouldCache ? `${value} = ${snippet}` : snippet;
29+
if (shouldCache) block.addVariable(value);
2130

2231
// we would have used comments here, but the `insertAdjacentHTML` api only
2332
// exists for `Element`s.
@@ -38,17 +47,27 @@ export default function visitRawMustacheTag(
3847

3948
const isToplevel = !state.parentNode;
4049

41-
const mountStatement = `${before}.insertAdjacentHTML( 'afterend', ${value} = ${snippet} );`;
42-
const detachStatement = `@detachBetween( ${before}, ${after} );`;
50+
block.builders.mount.addLine(`${before}.insertAdjacentHTML( 'afterend', ${init} );`);
51+
block.builders.detachRaw.addBlock(`@detachBetween( ${before}, ${after} );`);
52+
53+
if (dependencies.length || hasChangeableIndex) {
54+
const changedCheck = (
55+
( block.hasOutroMethod ? `#outroing || ` : '' ) +
56+
dependencies.map(dependency => `'${dependency}' in changed`).join(' || ')
57+
);
4358

44-
block.builders.mount.addLine(mountStatement);
59+
const updateCachedValue = `${value} !== ( ${value} = ${snippet} )`;
4560

46-
block.builders.update.addBlock(deindent`
47-
if ( ${value} !== ( ${value} = ${snippet} ) ) {
48-
${detachStatement}
49-
${mountStatement}
50-
}
51-
`);
61+
const condition = shouldCache ?
62+
( dependencies.length ? `( ${changedCheck} ) && ${updateCachedValue}` : updateCachedValue ) :
63+
changedCheck;
5264

53-
block.builders.detachRaw.addBlock(detachStatement);
65+
block.builders.update.addConditionalLine(
66+
condition,
67+
deindent`
68+
@detachBetween( ${before}, ${after} );
69+
${before}.insertAdjacentHTML( 'afterend', ${shouldCache ? value : snippet} );
70+
`
71+
);
72+
}
5473
}

src/utils/CodeBuilder.ts

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,15 +21,17 @@ export default class CodeBuilder {
2121
this.lastCondition = null;
2222
}
2323

24-
addConditionalLine(condition: string, line: string) {
24+
addConditionalLine(condition: string, body: string) {
25+
body = body.replace(/^/gm, '\t');
26+
2527
if (condition === this.lastCondition) {
26-
this.result += `\n\t${line}`;
28+
this.result += `\n${body}`;
2729
} else {
2830
if (this.lastCondition) {
2931
this.result += `\n}`;
3032
}
3133

32-
this.result += `${this.last === ChunkType.Block ? '\n\n' : '\n'}if ( ${condition} ) {\n\t${line}`;
34+
this.result += `${this.last === ChunkType.Block ? '\n\n' : '\n'}if ( ${condition} ) {\n${body}`;
3335
this.lastCondition = condition;
3436
}
3537

test/helpers.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@ export function normalizeHtml(window, html) {
125125
.replace(/>[\s\r\n]+</g, '><')
126126
.trim();
127127
cleanChildren(node, '');
128-
return node.innerHTML;
128+
return node.innerHTML.replace(/<\/?noscript\/?>/g, '');
129129
}
130130

131131
export function setupHtmlEqual() {

test/js/samples/each-block-changed-check/expected-bundle.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -297,9 +297,9 @@ function create_each_block ( state, each_block_value, comment, i, component ) {
297297
text_4.data = text_4_value;
298298
}
299299

300-
if ( raw_value !== ( raw_value = comment.html ) ) {
300+
if ( ( 'comments' in changed ) && raw_value !== ( raw_value = comment.html ) ) {
301301
detachBetween( raw_before, raw_after );
302-
raw_before.insertAdjacentHTML( 'afterend', raw_value = comment.html );
302+
raw_before.insertAdjacentHTML( 'afterend', raw_value );
303303
}
304304
},
305305

test/js/samples/each-block-changed-check/expected.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -123,9 +123,9 @@ function create_each_block ( state, each_block_value, comment, i, component ) {
123123
text_4.data = text_4_value;
124124
}
125125

126-
if ( raw_value !== ( raw_value = comment.html ) ) {
126+
if ( ( 'comments' in changed ) && raw_value !== ( raw_value = comment.html ) ) {
127127
detachBetween( raw_before, raw_after );
128-
raw_before.insertAdjacentHTML( 'afterend', raw_value = comment.html );
128+
raw_before.insertAdjacentHTML( 'afterend', raw_value );
129129
}
130130
},
131131

test/runtime/samples/helpers-invoked-if-changed/_config.js

Lines changed: 0 additions & 38 deletions
This file was deleted.
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import counter from './counter.js';
2+
3+
export default {
4+
data: {
5+
x: 1,
6+
y: 2
7+
},
8+
9+
html: `
10+
<p>1</p>
11+
<p class='-2-'></p>
12+
`,
13+
14+
test(assert, component) {
15+
counter.count = 0;
16+
17+
component.set({ x: 3 });
18+
assert.equal(counter.count, 0);
19+
20+
component.set({ x: 4, y: 5 });
21+
assert.equal(counter.count, 1);
22+
23+
component.set({ x: 5, y: 5 });
24+
assert.equal(counter.count, 1);
25+
}
26+
};
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
11
export default {
2-
y: 0,
3-
z: 0
2+
count: 0
43
};

test/runtime/samples/helpers-invoked-if-changed/main.html renamed to test/runtime/samples/ignore-unchanged-attribute-compound/main.html

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,13 @@
11
<p>{{x}}</p>
2-
<p class='{{getClass(y)}}'>{{myHelper(z)}}</p>
2+
<p class='-{{myHelper(y)}}-'></p>
33

44
<script>
55
import counter from './counter.js';
66

77
export default {
88
helpers: {
9-
getClass(value) {
10-
counter.y += 1;
11-
return value;
12-
},
13-
149
myHelper(value) {
15-
counter.z += 1;
10+
counter.count += 1;
1611
return value;
1712
}
1813
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import counter from './counter.js';
2+
3+
export default {
4+
data: {
5+
x: 1,
6+
y: 2
7+
},
8+
9+
html: `
10+
<p>1</p>
11+
<p class='2'></p>
12+
`,
13+
14+
test(assert, component) {
15+
counter.count = 0;
16+
17+
component.set({ x: 3 });
18+
assert.equal(counter.count, 0);
19+
20+
component.set({ x: 4, y: 5 });
21+
assert.equal(counter.count, 1);
22+
23+
component.set({ x: 5, y: 5 });
24+
assert.equal(counter.count, 1);
25+
}
26+
};

0 commit comments

Comments
 (0)