Skip to content

Commit f00d084

Browse files
committed
Merge branch 'master' into gh-984
2 parents 2866b11 + 1130556 commit f00d084

File tree

25 files changed

+346
-125
lines changed

25 files changed

+346
-125
lines changed

src/compile/dom/Block.ts

+4-6
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,7 @@ export interface BlockOptions {
99
compiler?: Compiler;
1010
comment?: string;
1111
key?: string;
12-
indexNames?: Map<string, string>;
13-
listNames?: Map<string, string>;
12+
bindings?: Map<string, string>;
1413
dependencies?: Set<string>;
1514
}
1615

@@ -23,8 +22,8 @@ export default class Block {
2322
first: string;
2423

2524
dependencies: Set<string>;
26-
indexNames: Map<string, string>;
27-
listNames: Map<string, string>;
25+
26+
bindings: Map<string, string>;
2827

2928
builders: {
3029
init: CodeBuilder;
@@ -62,8 +61,7 @@ export default class Block {
6261

6362
this.dependencies = new Set();
6463

65-
this.indexNames = options.indexNames;
66-
this.listNames = options.listNames;
64+
this.bindings = options.bindings;
6765

6866
this.builders = {
6967
init: new CodeBuilder(),

src/compile/nodes/Binding.ts

+2-3
Original file line numberDiff line numberDiff line change
@@ -206,14 +206,13 @@ function getEventHandler(
206206
? getTailSnippet(binding.value.node)
207207
: '';
208208

209-
const list = `ctx.${block.listNames.get(name)}`;
210-
const index = `ctx.${block.indexNames.get(name)}`;
209+
const head = block.bindings.get(name);
211210

212211
return {
213212
usesContext: true,
214213
usesState: true,
215214
usesStore: storeDependencies.length > 0,
216-
mutation: `${list}[${index}]${tail} = ${value};`,
215+
mutation: `${head}${tail} = ${value};`,
217216
props: dependencies.map(prop => `${prop}: ctx.${prop}`),
218217
storeProps: storeDependencies.map(prop => `${prop}: $.${prop}`)
219218
};

src/compile/nodes/Component.ts

+2-3
Original file line numberDiff line numberDiff line change
@@ -239,12 +239,11 @@ export default class Component extends Node {
239239
const computed = isComputed(binding.value.node);
240240
const tail = binding.value.node.type === 'MemberExpression' ? getTailSnippet(binding.value.node) : '';
241241

242-
const list = block.listNames.get(key);
243-
const index = block.indexNames.get(key);
242+
const head = block.bindings.get(key);
244243

245244
const lhs = binding.value.node.type === 'MemberExpression'
246245
? binding.value.snippet
247-
: `ctx.${list}[ctx.${index}]${tail} = childState.${binding.name}`;
246+
: `${head}${tail} = childState.${binding.name}`;
248247

249248
setFromChild = deindent`
250249
${lhs} = childState.${binding.name};

src/compile/nodes/EachBlock.ts

+37-45
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import createDebuggingComment from '../../utils/createDebuggingComment';
66
import Expression from './shared/Expression';
77
import mapChildren from './shared/mapChildren';
88
import TemplateScope from './shared/TemplateScope';
9+
import unpackDestructuring from '../../utils/unpackDestructuring';
910

1011
export default class EachBlock extends Node {
1112
type: 'EachBlock';
@@ -18,7 +19,7 @@ export default class EachBlock extends Node {
1819
context: string;
1920
key: Expression;
2021
scope: TemplateScope;
21-
destructuredContexts: string[];
22+
contexts: Array<{ name: string, tail: string }>;
2223

2324
children: Node[];
2425
else?: ElseBlock;
@@ -27,7 +28,7 @@ export default class EachBlock extends Node {
2728
super(compiler, parent, scope, info);
2829

2930
this.expression = new Expression(compiler, this, scope, info.expression);
30-
this.context = info.context;
31+
this.context = info.context.name || 'each'; // TODO this is used to facilitate binding; currently fails with destructuring
3132
this.index = info.index;
3233

3334
this.key = info.key
@@ -36,20 +37,19 @@ export default class EachBlock extends Node {
3637

3738
this.scope = scope.child();
3839

39-
this.scope.add(this.context, this.expression.dependencies);
40+
this.contexts = [];
41+
unpackDestructuring(this.contexts, info.context, '');
42+
43+
this.contexts.forEach(context => {
44+
this.scope.add(context.key.name, this.expression.dependencies);
45+
});
4046

4147
if (this.index) {
4248
// index can only change if this is a keyed each block
4349
const dependencies = this.key ? this.expression.dependencies : [];
4450
this.scope.add(this.index, dependencies);
4551
}
4652

47-
// TODO more general approach to destructuring
48-
this.destructuredContexts = info.destructuredContexts || [];
49-
this.destructuredContexts.forEach(name => {
50-
this.scope.add(name, this.expression.dependencies);
51-
});
52-
5353
this.children = mapChildren(compiler, this, this.scope, info.children);
5454

5555
this.else = info.else
@@ -76,31 +76,28 @@ export default class EachBlock extends Node {
7676
name: this.compiler.getUniqueName('create_each_block'),
7777
key: this.key,
7878

79-
indexNames: new Map(block.indexNames),
80-
listNames: new Map(block.listNames)
79+
bindings: new Map(block.bindings)
8180
});
8281

83-
const listName = this.compiler.getUniqueName('each_value');
82+
this.each_block_value = this.compiler.getUniqueName('each_value');
83+
8484
const indexName = this.index || this.compiler.getUniqueName(`${this.context}_index`);
8585

86-
this.block.indexNames.set(this.context, indexName);
87-
this.block.listNames.set(this.context, listName);
86+
this.contexts.forEach(prop => {
87+
this.block.bindings.set(prop.key.name, `ctx.${this.each_block_value}[ctx.${indexName}]${prop.tail}`);
88+
});
8889

8990
if (this.index) {
9091
this.block.getUniqueName(this.index); // this prevents name collisions (#1254)
9192
}
9293

93-
this.contextProps = [
94-
`${listName}: list`,
95-
`${this.context}: list[i]`,
96-
`${indexName}: i`
97-
];
94+
this.contextProps = this.contexts.map(prop => `${prop.key.name}: list[i]${prop.tail}`);
9895

99-
if (this.destructuredContexts) {
100-
for (let i = 0; i < this.destructuredContexts.length; i += 1) {
101-
this.contextProps.push(`${this.destructuredContexts[i]}: list[i][${i}]`);
102-
}
103-
}
96+
// TODO only add these if necessary
97+
this.contextProps.push(
98+
`${this.each_block_value}: list`,
99+
`${indexName}: i`
100+
);
104101

105102
this.compiler.target.blocks.push(this.block);
106103
this.initChildren(this.block, stripWhitespace, nextSibling);
@@ -135,7 +132,6 @@ export default class EachBlock extends Node {
135132
const each = this.var;
136133

137134
const create_each_block = this.block.name;
138-
const each_block_value = this.block.listNames.get(this.context);
139135
const iterations = this.iterations;
140136

141137
const needsAnchor = this.next ? !this.next.isDomNode() : !parentNode || !this.parent.isDomNode();
@@ -154,7 +150,6 @@ export default class EachBlock extends Node {
154150
const vars = {
155151
each,
156152
create_each_block,
157-
each_block_value,
158153
length,
159154
iterations,
160155
anchor,
@@ -163,7 +158,7 @@ export default class EachBlock extends Node {
163158

164159
const { snippet } = this.expression;
165160

166-
block.builders.init.addLine(`var ${each_block_value} = ${snippet};`);
161+
block.builders.init.addLine(`var ${this.each_block_value} = ${snippet};`);
167162

168163
this.compiler.target.blocks.push(deindent`
169164
function ${this.get_each_context}(ctx, list, i) {
@@ -195,7 +190,7 @@ export default class EachBlock extends Node {
195190

196191
// TODO neaten this up... will end up with an empty line in the block
197192
block.builders.init.addBlock(deindent`
198-
if (!${each_block_value}.${length}) {
193+
if (!${this.each_block_value}.${length}) {
199194
${each_block_else} = ${this.else.block.name}(#component, ctx);
200195
${each_block_else}.c();
201196
}
@@ -211,9 +206,9 @@ export default class EachBlock extends Node {
211206

212207
if (this.else.block.hasUpdateMethod) {
213208
block.builders.update.addBlock(deindent`
214-
if (!${each_block_value}.${length} && ${each_block_else}) {
209+
if (!${this.each_block_value}.${length} && ${each_block_else}) {
215210
${each_block_else}.p(changed, ctx);
216-
} else if (!${each_block_value}.${length}) {
211+
} else if (!${this.each_block_value}.${length}) {
217212
${each_block_else} = ${this.else.block.name}(#component, ctx);
218213
${each_block_else}.c();
219214
${each_block_else}.${mountOrIntro}(${initialMountNode}, ${anchor});
@@ -225,7 +220,7 @@ export default class EachBlock extends Node {
225220
`);
226221
} else {
227222
block.builders.update.addBlock(deindent`
228-
if (${each_block_value}.${length}) {
223+
if (${this.each_block_value}.${length}) {
229224
if (${each_block_else}) {
230225
${each_block_else}.u();
231226
${each_block_else}.d();
@@ -267,7 +262,6 @@ export default class EachBlock extends Node {
267262
{
268263
each,
269264
create_each_block,
270-
each_block_value,
271265
length,
272266
anchor,
273267
mountOrIntro,
@@ -295,8 +289,8 @@ export default class EachBlock extends Node {
295289
block.builders.init.addBlock(deindent`
296290
const ${get_key} = ctx => ${this.key.snippet};
297291
298-
for (var #i = 0; #i < ${each_block_value}.${length}; #i += 1) {
299-
let child_ctx = ${this.get_each_context}(ctx, ${each_block_value}, #i);
292+
for (var #i = 0; #i < ${this.each_block_value}.${length}; #i += 1) {
293+
let child_ctx = ${this.get_each_context}(ctx, ${this.each_block_value}, #i);
300294
let key = ${get_key}(child_ctx);
301295
${blocks}[#i] = ${lookup}[key] = ${create_each_block}(#component, key, child_ctx);
302296
}
@@ -323,9 +317,9 @@ export default class EachBlock extends Node {
323317
const dynamic = this.block.hasUpdateMethod;
324318

325319
block.builders.update.addBlock(deindent`
326-
var ${each_block_value} = ${snippet};
320+
var ${this.each_block_value} = ${snippet};
327321
328-
${blocks} = @updateKeyedEach(${blocks}, #component, changed, ${get_key}, ${dynamic ? '1' : '0'}, ctx, ${each_block_value}, ${lookup}, ${updateMountNode}, ${String(this.block.hasOutroMethod)}, ${create_each_block}, "${mountOrIntro}", ${anchor}, ${this.get_each_context});
322+
${blocks} = @updateKeyedEach(${blocks}, #component, changed, ${get_key}, ${dynamic ? '1' : '0'}, ctx, ${this.each_block_value}, ${lookup}, ${updateMountNode}, ${String(this.block.hasOutroMethod)}, ${create_each_block}, "${mountOrIntro}", ${anchor}, ${this.get_each_context});
329323
`);
330324

331325
if (!parentNode) {
@@ -346,7 +340,6 @@ export default class EachBlock extends Node {
346340
snippet: string,
347341
{
348342
create_each_block,
349-
each_block_value,
350343
length,
351344
iterations,
352345
anchor,
@@ -356,8 +349,8 @@ export default class EachBlock extends Node {
356349
block.builders.init.addBlock(deindent`
357350
var ${iterations} = [];
358351
359-
for (var #i = 0; #i < ${each_block_value}.${length}; #i += 1) {
360-
${iterations}[#i] = ${create_each_block}(#component, ${this.get_each_context}(ctx, ${each_block_value}, #i));
352+
for (var #i = 0; #i < ${this.each_block_value}.${length}; #i += 1) {
353+
${iterations}[#i] = ${create_each_block}(#component, ${this.get_each_context}(ctx, ${this.each_block_value}, #i));
361354
}
362355
`);
363356

@@ -445,15 +438,15 @@ export default class EachBlock extends Node {
445438
${iterations}[#i].u();
446439
${iterations}[#i].d();
447440
}
448-
${iterations}.length = ${each_block_value}.${length};
441+
${iterations}.length = ${this.each_block_value}.${length};
449442
`;
450443

451444
block.builders.update.addBlock(deindent`
452445
if (${condition}) {
453-
${each_block_value} = ${snippet};
446+
${this.each_block_value} = ${snippet};
454447
455-
for (var #i = ${start}; #i < ${each_block_value}.${length}; #i += 1) {
456-
const child_ctx = ${this.get_each_context}(ctx, ${each_block_value}, #i);
448+
for (var #i = ${start}; #i < ${this.each_block_value}.${length}; #i += 1) {
449+
const child_ctx = ${this.get_each_context}(ctx, ${this.each_block_value}, #i);
457450
458451
${forLoopBody}
459452
}
@@ -481,8 +474,7 @@ export default class EachBlock extends Node {
481474
const { compiler } = this;
482475
const { snippet } = this.expression;
483476

484-
const props = [`${this.context}: item`]
485-
.concat(this.destructuredContexts.map((name, i) => `${name}: item[${i}]`));
477+
const props = this.contexts.map(prop => `${prop.key.name}: item${prop.tail}`);
486478

487479
const getContext = this.index
488480
? `(item, i) => Object.assign({}, ctx, { ${props.join(', ')}, ${this.index}: i })`

src/compile/nodes/Fragment.ts

+1-2
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,7 @@ export default class Fragment extends Node {
2323
name: '@create_main_fragment',
2424
key: null,
2525

26-
indexNames: new Map(),
27-
listNames: new Map(),
26+
bindings: new Map(),
2827

2928
dependencies: new Set(),
3029
});

0 commit comments

Comments
 (0)