start implementing context

pull/1173/head
Rich Harris 7 years ago
parent 173792fd90
commit 0b39cafc67

@ -242,24 +242,26 @@ export default class Generator {
if (name === 'event' && isEventHandler) {
// noop
} else if (contexts.has(name)) {
const contextName = contexts.get(name);
if (contextName !== name) {
// this is true for 'reserved' names like `state` and `component`,
// also destructured contexts
code.overwrite(
node.start,
node.start + name.length,
contextName,
{ storeName: true, contentOnly: false }
);
const destructuredName = contextName.replace(/\[\d+\]/, '');
if (destructuredName !== contextName) {
// so that hoisting the context works correctly
usedContexts.add(destructuredName);
}
}
// const contextName = contexts.get(name);
// if (contextName !== name) {
// // this is true for 'reserved' names like `state` and `component`,
// // also destructured contexts
// code.overwrite(
// node.start,
// node.start + name.length,
// contextName,
// { storeName: true, contentOnly: false }
// );
// const destructuredName = contextName.replace(/\[\d+\]/, '');
// if (destructuredName !== contextName) {
// // so that hoisting the context works correctly
// usedContexts.add(destructuredName);
// }
// }
// TODO filthy, temporary hack
if (self.constructor.name === 'DomGenerator') code.prependRight(node.start, `state.`);
usedContexts.add(name);
} else if (helpers.has(name)) {
let object = node;
@ -268,6 +270,8 @@ export default class Generator {
const alias = self.templateVars.get(`helpers-${name}`);
if (alias !== name) code.overwrite(object.start, object.end, alias);
} else if (indexes.has(name)) {
if (self.constructor.name === 'DomGenerator') code.prependRight(node.start, `state.`);
const context = indexes.get(name);
usedContexts.add(context); // TODO is this right?
usedIndexes.add(name);

@ -17,7 +17,6 @@ export interface BlockOptions {
contextTypes?: Map<string, string>;
indexes?: Map<string, string>;
changeableIndexes?: Map<string, boolean>;
params?: string[];
indexNames?: Map<string, string>;
listNames?: Map<string, string>;
indexName?: string;
@ -41,7 +40,6 @@ export default class Block {
indexes: Map<string, string>;
changeableIndexes: Map<string, boolean>;
dependencies: Set<string>;
params: string[];
indexNames: Map<string, string>;
listNames: Map<string, string>;
indexName: string;
@ -90,10 +88,10 @@ export default class Block {
this.changeableIndexes = options.changeableIndexes;
this.dependencies = new Set();
this.params = options.params;
this.indexNames = options.indexNames;
this.listNames = options.listNames;
this.indexName = options.indexName;
this.listName = options.listName;
this.builders = {
@ -116,7 +114,7 @@ export default class Block {
this.aliases = new Map();
this.variables = new Map();
this.getUniqueName = this.generator.getUniqueNameMaker(options.params);
this.getUniqueName = this.generator.getUniqueNameMaker([]); // TODO this is wrong... we probably don't need this any more
this.hasUpdateMethod = false; // determined later
}
@ -254,7 +252,7 @@ export default class Block {
properties.addBlock(`p: @noop,`);
} else {
properties.addBlock(deindent`
p: function update(changed, ${this.params.join(', ')}) {
p: function update(changed, state) {
${this.builders.update}
},
`);
@ -328,7 +326,7 @@ export default class Block {
return deindent`
${this.comment && `// ${escape(this.comment)}`}
function ${this.name}(${this.params.join(', ')}, #component${this.key ? `, ${localKey}` : ''}) {
function ${this.name}(#component, state${this.key ? `, ${localKey}` : ''}) {
${this.variables.size > 0 &&
`var ${Array.from(this.variables.keys())
.map(key => {

@ -50,7 +50,7 @@ export class DomGenerator extends Generator {
}
getUniqueNameMaker(params: string[]) {
const localUsedNames = new Set(params);
const localUsedNames = new Set(params); // TODO is this ever called with params?
function add(name: string) {
localUsedNames.add(name);
@ -257,7 +257,7 @@ export default function dom(
${generator.slots.size && `this.slots = {};`}
this._fragment = @create_main_fragment(this._state, this);
this._fragment = @create_main_fragment(this, this._state);
${(templateProperties.oncreate) && deindent`
this.root._oncreate.push(_oncreate);

@ -45,7 +45,6 @@ export default class AwaitBlock extends Node {
child.block = block.child({
comment: createDebuggingComment(child, this.generator),
name: this.generator.getUniqueName(`create_${status}_block`),
params: block.params.concat(context),
context,
contexts,
contextTypes
@ -75,8 +74,6 @@ export default class AwaitBlock extends Node {
const anchor = this.getOrCreateAnchor(block, parentNode, parentNodes);
const updateMountNode = this.getUpdateMountNode(anchor);
const params = block.params.join(', ');
block.contextualise(this.expression);
const { snippet } = this.metadata;
@ -106,11 +103,11 @@ export default class AwaitBlock extends Node {
// but it's probably not worth it
block.builders.init.addBlock(deindent`
function ${replace_await_block}(${token}, type, ${value}, ${params}) {
function ${replace_await_block}(${token}, type, ${value}, state) {
if (${token} !== ${await_token}) return;
var ${old_block} = ${await_block};
${await_block} = (${await_block_type} = type)(${params}, ${resolved} = ${value}, #component);
${await_block} = (${await_block_type} = type)(state, ${resolved} = ${value}, #component);
if (${old_block}) {
${old_block}.u();
@ -122,33 +119,33 @@ export default class AwaitBlock extends Node {
}
}
function ${handle_promise}(${promise}, ${params}) {
function ${handle_promise}(${promise}, state) {
var ${token} = ${await_token} = {};
if (@isPromise(${promise})) {
${promise}.then(function(${value}) {
var state = #component.get();
${replace_await_block}(${token}, ${create_then_block}, ${value}, ${params});
${replace_await_block}(${token}, ${create_then_block}, ${value}, state);
}, function (${error}) {
var state = #component.get();
${replace_await_block}(${token}, ${create_catch_block}, ${error}, ${params});
${replace_await_block}(${token}, ${create_catch_block}, ${error}, state);
});
// if we previously had a then/catch block, destroy it
if (${await_block_type} !== ${create_pending_block}) {
${replace_await_block}(${token}, ${create_pending_block}, null, ${params});
${replace_await_block}(${token}, ${create_pending_block}, null, state);
return true;
}
} else {
${resolved} = ${promise};
if (${await_block_type} !== ${create_then_block}) {
${replace_await_block}(${token}, ${create_then_block}, ${resolved}, ${params});
${replace_await_block}(${token}, ${create_then_block}, ${resolved}, state);
return true;
}
}
}
${handle_promise}(${promise} = ${snippet}, ${params});
${handle_promise}(${promise} = ${snippet}, state);
`);
block.builders.create.addBlock(deindent`
@ -177,7 +174,7 @@ export default class AwaitBlock extends Node {
conditions.push(
`${promise} !== (${promise} = ${snippet})`,
`${handle_promise}(${promise}, ${params})`
`${handle_promise}(${promise}, state)`
);
if (this.pending.block.hasUpdateMethod) {
@ -185,7 +182,7 @@ export default class AwaitBlock extends Node {
if (${conditions.join(' && ')}) {
// nothing
} else {
${await_block}.p(changed, ${params}, ${resolved});
${await_block}.p(changed, state, ${resolved});
}
`);
} else {

@ -279,12 +279,10 @@ export default class Component extends Node {
const anchor = this.getOrCreateAnchor(block, parentNode, parentNodes);
const params = block.params.join(', ');
block.builders.init.addBlock(deindent`
var ${switch_vars.value} = ${snippet};
function ${switch_vars.props}(${params}) {
function ${switch_vars.props}(state) {
${statements.length > 0 && statements.join('\n')}
return {
${componentInitProperties.join(',\n')}
@ -292,7 +290,7 @@ export default class Component extends Node {
}
if (${switch_vars.value}) {
var ${name} = new ${expression}(${switch_vars.props}(${params}));
var ${name} = new ${expression}(${switch_vars.props}(state));
${beforecreate}
}
@ -327,7 +325,7 @@ export default class Component extends Node {
if (${name}) ${name}.destroy();
if (${switch_vars.value}) {
${name} = new ${switch_vars.value}(${switch_vars.props}(${params}));
${name} = new ${switch_vars.value}(${switch_vars.props}(state));
${name}._fragment.c();
${this.children.map(child => remount(generator, child, name))}

@ -29,6 +29,7 @@ export default class EachBlock extends Node {
this.var = block.getUniqueName(`each`);
this.iterations = block.getUniqueName(`${this.var}_blocks`);
this.each_context = block.getUniqueName(`${this.var}_context`);
const { dependencies } = this.metadata;
block.addDependencies(dependencies);
@ -80,8 +81,7 @@ export default class EachBlock extends Node {
indexName,
indexNames,
listNames,
params: block.params.concat(listName, context, indexName),
listNames
});
this.generator.blocks.push(this.block);
@ -117,7 +117,6 @@ export default class EachBlock extends Node {
const create_each_block = this.block.name;
const each_block_value = this.block.listName;
const iterations = this.iterations;
const params = block.params.join(', ');
const needsAnchor = this.next ? !this.next.isDomNode() : !parentNode || !this.parent.isDomNode();
const anchor = needsAnchor
@ -138,7 +137,6 @@ export default class EachBlock extends Node {
each_block_value,
length,
iterations,
params,
anchor,
mountOrIntro,
};
@ -171,7 +169,7 @@ export default class EachBlock extends Node {
// TODO neaten this up... will end up with an empty line in the block
block.builders.init.addBlock(deindent`
if (!${each_block_value}.${length}) {
${each_block_else} = ${this.else.block.name}(${params}, #component);
${each_block_else} = ${this.else.block.name}(#component, state);
${each_block_else}.c();
}
`);
@ -187,9 +185,9 @@ export default class EachBlock extends Node {
if (this.else.block.hasUpdateMethod) {
block.builders.update.addBlock(deindent`
if (!${each_block_value}.${length} && ${each_block_else}) {
${each_block_else}.p( changed, ${params} );
${each_block_else}.p(changed, state);
} else if (!${each_block_value}.${length}) {
${each_block_else} = ${this.else.block.name}(${params}, #component);
${each_block_else} = ${this.else.block.name}(#component, state);
${each_block_else}.c();
${each_block_else}.${mountOrIntro}(${initialMountNode}, ${anchor});
} else if (${each_block_else}) {
@ -207,7 +205,7 @@ export default class EachBlock extends Node {
${each_block_else} = null;
}
} else if (!${each_block_else}) {
${each_block_else} = ${this.else.block.name}(${params}, #component);
${each_block_else} = ${this.else.block.name}(#component, state);
${each_block_else}.c();
${each_block_else}.${mountOrIntro}(${initialMountNode}, ${anchor});
}
@ -244,7 +242,6 @@ export default class EachBlock extends Node {
create_each_block,
each_block_value,
length,
params,
anchor,
mountOrIntro,
}
@ -275,7 +272,7 @@ export default class EachBlock extends Node {
block.builders.init.addBlock(deindent`
for (var #i = 0; #i < ${each_block_value}.${length}; #i += 1) {
var ${key} = ${each_block_value}[#i].${this.key};
var ${iteration} = ${lookup}[${key}] = ${create_each_block}(${params}, ${each_block_value}, ${each_block_value}[#i], #i, #component, ${key});
var ${iteration} = ${lookup}[${key}] = ${create_each_block}(#component, state, ${key});
if (${last}) ${last}.next = ${iteration};
${iteration}.last = ${last};
@ -380,7 +377,7 @@ export default class EachBlock extends Node {
var ${iteration} = ${lookup}[${key}];
${dynamic &&
`if (${iteration}) ${iteration}.p(changed, ${params}, ${each_block_value}, ${each_block_value}[#i], #i);`}
`if (${iteration}) ${iteration}.p(changed, state);`}
if (${expected}) {
if (${key} === ${expected}.key) {
@ -401,7 +398,7 @@ export default class EachBlock extends Node {
if (!${expected}) ${iteration}.m(${updateMountNode}, ${anchor});
} else {
// key is being inserted
${iteration} = ${lookup}[${key}] = ${create_each_block}(${params}, ${each_block_value}, ${each_block_value}[#i], #i, #component, ${key});
${iteration} = ${lookup}[${key}] = ${create_each_block}(#component, state, ${key});
${iteration}.c();
${iteration}.${mountOrIntro}(${updateMountNode}, ${expected}.first);
@ -416,7 +413,7 @@ export default class EachBlock extends Node {
${iteration}.next = null;
${iteration}.m(${updateMountNode}, ${anchor});
} else {
${iteration} = ${lookup}[${key}] = ${create_each_block}(${params}, ${each_block_value}, ${each_block_value}[#i], #i, #component, ${key});
${iteration} = ${lookup}[${key}] = ${create_each_block}(#component, state, ${key});
${iteration}.c();
${iteration}.${mountOrIntro}(${updateMountNode}, ${anchor});
}
@ -464,7 +461,6 @@ export default class EachBlock extends Node {
each_block_value,
length,
iterations,
params,
anchor,
mountOrIntro,
}
@ -473,7 +469,10 @@ export default class EachBlock extends Node {
var ${iterations} = [];
for (var #i = 0; #i < ${each_block_value}.${length}; #i += 1) {
${iterations}[#i] = ${create_each_block}(${params}, ${each_block_value}, ${each_block_value}[#i], #i, #component);
${iterations}[#i] = ${create_each_block}(#component, @assign({}, state, {
${this.context}: ${each_block_value}[#i],
${this.block.indexName}: #i
}));
}
`);
@ -517,24 +516,24 @@ export default class EachBlock extends Node {
? this.block.hasIntroMethod
? deindent`
if (${iterations}[#i]) {
${iterations}[#i].p(changed, ${params}, ${each_block_value}, ${each_block_value}[#i], #i);
${iterations}[#i].p(changed, ${this.each_context});
} else {
${iterations}[#i] = ${create_each_block}(${params}, ${each_block_value}, ${each_block_value}[#i], #i, #component);
${iterations}[#i] = ${create_each_block}(#component, ${this.each_context});
${iterations}[#i].c();
}
${iterations}[#i].i(${updateMountNode}, ${anchor});
`
: deindent`
if (${iterations}[#i]) {
${iterations}[#i].p(changed, ${params}, ${each_block_value}, ${each_block_value}[#i], #i);
${iterations}[#i].p(changed, ${this.each_context});
} else {
${iterations}[#i] = ${create_each_block}(${params}, ${each_block_value}, ${each_block_value}[#i], #i, #component);
${iterations}[#i] = ${create_each_block}(#component, ${this.each_context});
${iterations}[#i].c();
${iterations}[#i].m(${updateMountNode}, ${anchor});
}
`
: deindent`
${iterations}[#i] = ${create_each_block}(${params}, ${each_block_value}, ${each_block_value}[#i], #i, #component);
${iterations}[#i] = ${create_each_block}(#component, ${this.each_context});
${iterations}[#i].c();
${iterations}[#i].${mountOrIntro}(${updateMountNode}, ${anchor});
`;
@ -569,6 +568,11 @@ export default class EachBlock extends Node {
if (${condition}) {
for (var #i = ${start}; #i < ${each_block_value}.${length}; #i += 1) {
var ${this.each_context} = @assign({}, state, {
${this.context}: ${each_block_value}[#i],
${this.block.indexName}: #i
});
${forLoopBody}
}

@ -16,7 +16,6 @@ export default class Fragment extends Node {
indexes: new Map(),
changeableIndexes: new Map(),
params: ['state'],
indexNames: new Map(),
listNames: new Map(),

@ -100,7 +100,6 @@ export default class IfBlock extends Node {
const anchor = needsAnchor
? block.getUniqueName(`${name}_anchor`)
: (this.next && this.next.var) || 'null';
const params = block.params.join(', ');
const branches = getBranches(this.generator, block, parentNode, parentNodes, this);
@ -110,7 +109,7 @@ export default class IfBlock extends Node {
const dynamic = branches[0].hasUpdateMethod; // can use [0] as proxy for all, since they necessarily have the same value
const hasOutros = branches[0].hasOutroMethod;
const vars = { name, anchor, params, if_name, hasElse };
const vars = { name, anchor, if_name, hasElse };
if (this.else) {
if (hasOutros) {
@ -218,10 +217,10 @@ function simple(
node: Node,
branch,
dynamic,
{ name, anchor, params, if_name }
{ name, anchor, if_name }
) {
block.builders.init.addBlock(deindent`
var ${name} = (${branch.condition}) && ${branch.block}(${params}, #component);
var ${name} = (${branch.condition}) && ${branch.block}(#component, state);
`);
const mountOrIntro = branch.hasIntroMethod ? 'i' : 'm';
@ -238,9 +237,9 @@ function simple(
? branch.hasIntroMethod
? deindent`
if (${name}) {
${name}.p(changed, ${params});
${name}.p(changed, state);
} else {
${name} = ${branch.block}(${params}, #component);
${name} = ${branch.block}(#component, state);
if (${name}) ${name}.c();
}
@ -248,9 +247,9 @@ function simple(
`
: deindent`
if (${name}) {
${name}.p(changed, ${params});
${name}.p(changed, state);
} else {
${name} = ${branch.block}(${params}, #component);
${name} = ${branch.block}(#component, state);
${name}.c();
${name}.m(${updateMountNode}, ${anchor});
}
@ -258,14 +257,14 @@ function simple(
: branch.hasIntroMethod
? deindent`
if (!${name}) {
${name} = ${branch.block}(${params}, #component);
${name} = ${branch.block}(#component, state);
${name}.c();
}
${name}.i(${updateMountNode}, ${anchor});
`
: deindent`
if (!${name}) {
${name} = ${branch.block}(${params}, #component);
${name} = ${branch.block}(#component, state);
${name}.c();
${name}.m(${updateMountNode}, ${anchor});
}
@ -308,14 +307,14 @@ function compound(
node: Node,
branches,
dynamic,
{ name, anchor, params, hasElse, if_name }
{ name, anchor, hasElse, if_name }
) {
const select_block_type = generator.getUniqueName(`select_block_type`);
const current_block_type = block.getUniqueName(`current_block_type`);
const current_block_type_and = hasElse ? '' : `${current_block_type} && `;
generator.blocks.push(deindent`
function ${select_block_type}(${params}) {
function ${select_block_type}(state) {
${branches
.map(({ condition, block }) => `${condition ? `if (${condition}) ` : ''}return ${block};`)
.join('\n')}
@ -323,8 +322,8 @@ function compound(
`);
block.builders.init.addBlock(deindent`
var ${current_block_type} = ${select_block_type}(${params});
var ${name} = ${current_block_type_and}${current_block_type}(${params}, #component);
var ${current_block_type} = ${select_block_type}(state);
var ${name} = ${current_block_type_and}${current_block_type}(#component, state);
`);
const mountOrIntro = branches[0].hasIntroMethod ? 'i' : 'm';
@ -348,22 +347,22 @@ function compound(
${name}.u();
${name}.d();
}`}
${name} = ${current_block_type_and}${current_block_type}(${params}, #component);
${name} = ${current_block_type_and}${current_block_type}(#component, state);
${if_name}${name}.c();
${if_name}${name}.${mountOrIntro}(${updateMountNode}, ${anchor});
`;
if (dynamic) {
block.builders.update.addBlock(deindent`
if (${current_block_type} === (${current_block_type} = ${select_block_type}(${params})) && ${name}) {
${name}.p(changed, ${params});
if (${current_block_type} === (${current_block_type} = ${select_block_type}(state)) && ${name}) {
${name}.p(changed, state);
} else {
${changeBlock}
}
`);
} else {
block.builders.update.addBlock(deindent`
if (${current_block_type} !== (${current_block_type} = ${select_block_type}(${params}))) {
if (${current_block_type} !== (${current_block_type} = ${select_block_type}(state))) {
${changeBlock}
}
`);
@ -384,7 +383,7 @@ function compoundWithOutros(
node: Node,
branches,
dynamic,
{ name, anchor, params, hasElse }
{ name, anchor, hasElse }
) {
const select_block_type = block.getUniqueName(`select_block_type`);
const current_block_type_index = block.getUniqueName(`current_block_type_index`);
@ -406,7 +405,7 @@ function compoundWithOutros(
var ${if_blocks} = [];
function ${select_block_type}(${params}) {
function ${select_block_type}(state) {
${branches
.map(({ condition, block }, i) => `${condition ? `if (${condition}) ` : ''}return ${block ? i : -1};`)
.join('\n')}
@ -415,13 +414,13 @@ function compoundWithOutros(
if (hasElse) {
block.builders.init.addBlock(deindent`
${current_block_type_index} = ${select_block_type}(${params});
${name} = ${if_blocks}[${current_block_type_index}] = ${if_block_creators}[${current_block_type_index}](${params}, #component);
${current_block_type_index} = ${select_block_type}(state);
${name} = ${if_blocks}[${current_block_type_index}] = ${if_block_creators}[${current_block_type_index}](#component, state);
`);
} else {
block.builders.init.addBlock(deindent`
if (~(${current_block_type_index} = ${select_block_type}(${params}))) {
${name} = ${if_blocks}[${current_block_type_index}] = ${if_block_creators}[${current_block_type_index}](${params}, #component);
if (~(${current_block_type_index} = ${select_block_type}(state))) {
${name} = ${if_blocks}[${current_block_type_index}] = ${if_block_creators}[${current_block_type_index}](#component, state);
}
`);
}
@ -447,7 +446,7 @@ function compoundWithOutros(
const createNewBlock = deindent`
${name} = ${if_blocks}[${current_block_type_index}];
if (!${name}) {
${name} = ${if_blocks}[${current_block_type_index}] = ${if_block_creators}[${current_block_type_index}](${params}, #component);
${name} = ${if_blocks}[${current_block_type_index}] = ${if_block_creators}[${current_block_type_index}](#component, state);
${name}.c();
}
${name}.${mountOrIntro}(${updateMountNode}, ${anchor});
@ -474,9 +473,9 @@ function compoundWithOutros(
if (dynamic) {
block.builders.update.addBlock(deindent`
var ${previous_block_index} = ${current_block_type_index};
${current_block_type_index} = ${select_block_type}(${params});
${current_block_type_index} = ${select_block_type}(state);
if (${current_block_type_index} === ${previous_block_index}) {
${if_current_block_type_index}${if_blocks}[${current_block_type_index}].p(changed, ${params});
${if_current_block_type_index}${if_blocks}[${current_block_type_index}].p(changed, state);
} else {
${changeBlock}
}
@ -484,7 +483,7 @@ function compoundWithOutros(
} else {
block.builders.update.addBlock(deindent`
var ${previous_block_index} = ${current_block_type_index};
${current_block_type_index} = ${select_block_type}(${params});
${current_block_type_index} = ${select_block_type}(state);
if (${current_block_type_index} !== ${previous_block_index}) {
${changeBlock}
}

Loading…
Cancel
Save