only add list/index to each block context if necessary

pull/1383/head
Rich Harris 6 years ago
parent 681de7d220
commit e7c62e9182

@ -3,6 +3,7 @@ import deindent from '../../utils/deindent';
import { escape } from '../../utils/stringify'; import { escape } from '../../utils/stringify';
import Renderer from './Renderer'; import Renderer from './Renderer';
import Wrapper from './wrappers/shared/Wrapper'; import Wrapper from './wrappers/shared/Wrapper';
import EachBlockWrapper from './wrappers/EachBlock';
export interface BlockOptions { export interface BlockOptions {
parent?: Block; parent?: Block;
@ -11,6 +12,7 @@ export interface BlockOptions {
comment?: string; comment?: string;
key?: string; key?: string;
bindings?: Map<string, () => string>; bindings?: Map<string, () => string>;
contextOwners?: Map<string, EachBlockWrapper>;
dependencies?: Set<string>; dependencies?: Set<string>;
} }
@ -28,6 +30,7 @@ export default class Block {
dependencies: Set<string>; dependencies: Set<string>;
bindings: Map<string, () => string>; bindings: Map<string, () => string>;
contextOwners: Map<string, EachBlockWrapper>;
builders: { builders: {
init: CodeBuilder; init: CodeBuilder;
@ -74,6 +77,7 @@ export default class Block {
this.dependencies = new Set(); this.dependencies = new Set();
this.bindings = options.bindings; this.bindings = options.bindings;
this.contextOwners = options.contextOwners;
this.builders = { this.builders = {
init: new CodeBuilder(), init: new CodeBuilder(),

@ -47,6 +47,7 @@ export default class Renderer {
key: null, key: null,
bindings: new Map(), bindings: new Map(),
contextOwners: new Map(),
dependencies: new Set(), dependencies: new Set(),
}); });

@ -53,7 +53,6 @@ export default class EachBlockWrapper extends Wrapper {
node: EachBlock; node: EachBlock;
fragment: FragmentWrapper; fragment: FragmentWrapper;
else?: ElseBlockWrapper; else?: ElseBlockWrapper;
var: string;
vars: { vars: {
anchor: string; anchor: string;
create_each_block: string; create_each_block: string;
@ -64,6 +63,12 @@ export default class EachBlockWrapper extends Wrapper {
mountOrIntro: string; mountOrIntro: string;
} }
contextProps: string[];
indexName: string;
var = 'each';
hasBinding = false;
constructor( constructor(
renderer: Renderer, renderer: Renderer,
block: Block, block: Block,
@ -75,8 +80,6 @@ export default class EachBlockWrapper extends Wrapper {
super(renderer, block, parent, node); super(renderer, block, parent, node);
this.cannotUseInnerHTML(); this.cannotUseInnerHTML();
this.var = 'each';
const { dependencies } = node.expression; const { dependencies } = node.expression;
block.addDependencies(dependencies); block.addDependencies(dependencies);
@ -85,7 +88,8 @@ export default class EachBlockWrapper extends Wrapper {
name: renderer.component.getUniqueName('create_each_block'), name: renderer.component.getUniqueName('create_each_block'),
key: <string>node.key, // TODO... key: <string>node.key, // TODO...
bindings: new Map(block.bindings) bindings: new Map(block.bindings),
contextOwners: new Map(block.contextOwners)
}); });
// TODO this seems messy // TODO this seems messy
@ -94,6 +98,8 @@ export default class EachBlockWrapper extends Wrapper {
this.indexName = this.node.index || renderer.component.getUniqueName(`${this.node.context}_index`); this.indexName = this.node.index || renderer.component.getUniqueName(`${this.node.context}_index`);
node.contexts.forEach(prop => { node.contexts.forEach(prop => {
this.block.contextOwners.set(prop.key.name, this);
// TODO this doesn't feel great // TODO this doesn't feel great
this.block.bindings.set(prop.key.name, () => `ctx.${this.vars.each_block_value}[ctx.${this.indexName}]${prop.tail}`); this.block.bindings.set(prop.key.name, () => `ctx.${this.vars.each_block_value}[ctx.${this.indexName}]${prop.tail}`);
}); });
@ -164,11 +170,8 @@ export default class EachBlockWrapper extends Wrapper {
this.contextProps = this.node.contexts.map(prop => `child_ctx.${prop.key.name} = list[i]${prop.tail};`); this.contextProps = this.node.contexts.map(prop => `child_ctx.${prop.key.name} = list[i]${prop.tail};`);
// TODO only add these if necessary if (this.hasBinding) this.contextProps.push(`child_ctx.${this.vars.each_block_value} = list;`);
this.contextProps.push( if (this.hasBinding || this.node.index) this.contextProps.push(`child_ctx.${this.indexName} = i;`);
`child_ctx.${this.vars.each_block_value} = list;`,
`child_ctx.${this.indexName} = i;`
);
const { snippet } = this.node.expression; const { snippet } = this.node.expression;

@ -42,6 +42,15 @@ export default class BindingWrapper {
parent.renderer.component.indirectDependencies.set(prop, new Set()); parent.renderer.component.indirectDependencies.set(prop, new Set());
}); });
} }
if (node.isContextual) {
// we need to ensure that the each block creates a context including
// the list and the index, if they're not otherwise referenced
const { name } = getObject(this.node.value.node);
const eachBlock = block.contextOwners.get(name);
eachBlock.hasBinding = true;
}
} }
isReadOnlyMediaAttribute() { isReadOnlyMediaAttribute() {

@ -41,6 +41,15 @@ export default class InlineComponentWrapper extends Wrapper {
}); });
this.node.bindings.forEach(binding => { this.node.bindings.forEach(binding => {
if (binding.isContextual) {
// we need to ensure that the each block creates a context including
// the list and the index, if they're not otherwise referenced
const { name } = getObject(binding.value.node);
const eachBlock = block.contextOwners.get(name);
eachBlock.hasBinding = true;
}
block.addDependencies(binding.value.dependencies); block.addDependencies(binding.value.dependencies);
}); });

@ -6,8 +6,6 @@ const file = undefined;
function get_each_context(ctx, list, i) { function get_each_context(ctx, list, i) {
const child_ctx = Object.create(ctx); const child_ctx = Object.create(ctx);
child_ctx.thing = list[i]; child_ctx.thing = list[i];
child_ctx.each_value = list;
child_ctx.thing_index = i;
return child_ctx; return child_ctx;
} }

@ -6,8 +6,6 @@ const file = undefined;
function get_each_context(ctx, list, i) { function get_each_context(ctx, list, i) {
const child_ctx = Object.create(ctx); const child_ctx = Object.create(ctx);
child_ctx.thing = list[i]; child_ctx.thing = list[i];
child_ctx.each_value = list;
child_ctx.thing_index = i;
return child_ctx; return child_ctx;
} }

@ -4,7 +4,6 @@ import { append, assign, createElement, createText, destroyEach, detachAfter, de
function get_each_context(ctx, list, i) { function get_each_context(ctx, list, i) {
const child_ctx = Object.create(ctx); const child_ctx = Object.create(ctx);
child_ctx.comment = list[i]; child_ctx.comment = list[i];
child_ctx.each_value = list;
child_ctx.i = i; child_ctx.i = i;
return child_ctx; return child_ctx;
} }

@ -18,8 +18,6 @@ function foo(node, animation, params) {
function get_each_context(ctx, list, i) { function get_each_context(ctx, list, i) {
const child_ctx = Object.create(ctx); const child_ctx = Object.create(ctx);
child_ctx.thing = list[i]; child_ctx.thing = list[i];
child_ctx.each_value = list;
child_ctx.thing_index = i;
return child_ctx; return child_ctx;
} }

@ -4,8 +4,6 @@ import { append, assign, blankObject, createComment, createElement, createText,
function get_each_context(ctx, list, i) { function get_each_context(ctx, list, i) {
const child_ctx = Object.create(ctx); const child_ctx = Object.create(ctx);
child_ctx.thing = list[i]; child_ctx.thing = list[i];
child_ctx.each_value = list;
child_ctx.thing_index = i;
return child_ctx; return child_ctx;
} }

Loading…
Cancel
Save