|
|
|
@ -153,74 +153,9 @@ export default function visitComponent(
|
|
|
|
|
const statements: string[] = [];
|
|
|
|
|
let name_updating: string;
|
|
|
|
|
let name_initial_data: string;
|
|
|
|
|
let _beforecreate: string = null;
|
|
|
|
|
let bindings = [];
|
|
|
|
|
|
|
|
|
|
if (local.bindings.length) {
|
|
|
|
|
name_updating = block.alias(`${name}_updating`);
|
|
|
|
|
name_initial_data = block.getUniqueName(`${name}_initial_data`);
|
|
|
|
|
|
|
|
|
|
block.addVariable(name_updating, '{}');
|
|
|
|
|
|
|
|
|
|
bindings = local.bindings.map(binding => {
|
|
|
|
|
let setParentFromChild;
|
|
|
|
|
|
|
|
|
|
const { name: key } = getObject(binding.value);
|
|
|
|
|
|
|
|
|
|
if (block.contexts.has(key)) {
|
|
|
|
|
const prop = binding.dependencies[0];
|
|
|
|
|
const computed = isComputed(binding.value);
|
|
|
|
|
const tail = binding.value.type === 'MemberExpression' ? getTailSnippet(binding.value) : '';
|
|
|
|
|
|
|
|
|
|
setParentFromChild = deindent`
|
|
|
|
|
var list = ${name}._context.${block.listNames.get(key)};
|
|
|
|
|
var index = ${name}._context.${block.indexNames.get(key)};
|
|
|
|
|
list[index]${tail} = childState.${binding.name};
|
|
|
|
|
|
|
|
|
|
${binding.dependencies
|
|
|
|
|
.map((prop: string) => `newState.${prop} = state.${prop};`)
|
|
|
|
|
.join('\n')}
|
|
|
|
|
`;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
else if (binding.value.type === 'MemberExpression') {
|
|
|
|
|
setParentFromChild = deindent`
|
|
|
|
|
${binding.snippet} = childState.${binding.name};
|
|
|
|
|
${binding.dependencies.map((prop: string) => `newState.${prop} = state.${prop};`).join('\n')}
|
|
|
|
|
`;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
else {
|
|
|
|
|
setParentFromChild = `newState.${binding.value.name} = childState.${binding.name};`;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return {
|
|
|
|
|
init: deindent`
|
|
|
|
|
if ( ${binding.prop} in ${binding.obj} ) {
|
|
|
|
|
${name_initial_data}.${binding.name} = ${binding.snippet};
|
|
|
|
|
${name_updating}.${binding.name} = true;
|
|
|
|
|
}`,
|
|
|
|
|
bind: deindent`
|
|
|
|
|
if (!${name_updating}.${binding.name} && changed.${binding.name}) {
|
|
|
|
|
${setParentFromChild}
|
|
|
|
|
}
|
|
|
|
|
`,
|
|
|
|
|
setParentFromChild: deindent`
|
|
|
|
|
if (!${name_updating}.${binding.name}) {
|
|
|
|
|
${setParentFromChild}
|
|
|
|
|
}
|
|
|
|
|
`,
|
|
|
|
|
|
|
|
|
|
// TODO could binding.dependencies.length ever be 0?
|
|
|
|
|
update: binding.dependencies.length && deindent`
|
|
|
|
|
if ( !${name_updating}.${binding.name} && ${binding.dependencies.map((dependency: string) => `changed.${dependency}`).join(' || ')} ) {
|
|
|
|
|
${name}_changes.${binding.name} = ${binding.snippet};
|
|
|
|
|
${name_updating}.${binding.name} = true;
|
|
|
|
|
}
|
|
|
|
|
`
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (
|
|
|
|
|
local.staticAttributes.length ||
|
|
|
|
|
local.dynamicAttributes.length ||
|
|
|
|
@ -232,9 +167,90 @@ export default function visitComponent(
|
|
|
|
|
|
|
|
|
|
const initialPropString = stringifyProps(initialProps);
|
|
|
|
|
|
|
|
|
|
const updates: string[] = [];
|
|
|
|
|
|
|
|
|
|
local.dynamicAttributes.forEach(attribute => {
|
|
|
|
|
if (attribute.dependencies.length) {
|
|
|
|
|
updates.push(deindent`
|
|
|
|
|
if ( ${attribute.dependencies
|
|
|
|
|
.map(dependency => `changed.${dependency}`)
|
|
|
|
|
.join(' || ')} ) ${name}_changes.${attribute.name} = ${attribute.value};
|
|
|
|
|
`);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
else {
|
|
|
|
|
// TODO this is an odd situation to encounter – I *think* it should only happen with
|
|
|
|
|
// each block indices, in which case it may be possible to optimise this
|
|
|
|
|
updates.push(`${name}_changes.${attribute.name} = ${attribute.value};`);
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
if (local.bindings.length) {
|
|
|
|
|
name_updating = block.alias(`${name}_updating`);
|
|
|
|
|
name_initial_data = block.getUniqueName(`${name}_initial_data`);
|
|
|
|
|
|
|
|
|
|
block.addVariable(name_updating, '{}');
|
|
|
|
|
statements.push(`var ${name_initial_data} = ${initialPropString};`);
|
|
|
|
|
|
|
|
|
|
bindings = local.bindings.map(binding => {
|
|
|
|
|
let setParentFromChild;
|
|
|
|
|
|
|
|
|
|
const { name: key } = getObject(binding.value);
|
|
|
|
|
|
|
|
|
|
if (block.contexts.has(key)) {
|
|
|
|
|
const prop = binding.dependencies[0];
|
|
|
|
|
const computed = isComputed(binding.value);
|
|
|
|
|
const tail = binding.value.type === 'MemberExpression' ? getTailSnippet(binding.value) : '';
|
|
|
|
|
|
|
|
|
|
setParentFromChild = deindent`
|
|
|
|
|
var list = ${name}._context.${block.listNames.get(key)};
|
|
|
|
|
var index = ${name}._context.${block.indexNames.get(key)};
|
|
|
|
|
list[index]${tail} = childState.${binding.name};
|
|
|
|
|
|
|
|
|
|
${binding.dependencies
|
|
|
|
|
.map((prop: string) => `newState.${prop} = state.${prop};`)
|
|
|
|
|
.join('\n')}
|
|
|
|
|
`;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
else if (binding.value.type === 'MemberExpression') {
|
|
|
|
|
setParentFromChild = deindent`
|
|
|
|
|
${binding.snippet} = childState.${binding.name};
|
|
|
|
|
${binding.dependencies.map((prop: string) => `newState.${prop} = state.${prop};`).join('\n')}
|
|
|
|
|
`;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
else {
|
|
|
|
|
setParentFromChild = `newState.${binding.value.name} = childState.${binding.name};`;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return {
|
|
|
|
|
init: deindent`
|
|
|
|
|
if ( ${binding.prop} in ${binding.obj} ) {
|
|
|
|
|
${name_initial_data}.${binding.name} = ${binding.snippet};
|
|
|
|
|
${name_updating}.${binding.name} = true;
|
|
|
|
|
}`,
|
|
|
|
|
bind: deindent`
|
|
|
|
|
if (!${name_updating}.${binding.name} && changed.${binding.name}) {
|
|
|
|
|
${setParentFromChild}
|
|
|
|
|
}
|
|
|
|
|
`,
|
|
|
|
|
setParentFromChild: deindent`
|
|
|
|
|
if (!${name_updating}.${binding.name}) {
|
|
|
|
|
${setParentFromChild}
|
|
|
|
|
}
|
|
|
|
|
`,
|
|
|
|
|
|
|
|
|
|
// TODO could binding.dependencies.length ever be 0?
|
|
|
|
|
update: binding.dependencies.length && deindent`
|
|
|
|
|
if ( !${name_updating}.${binding.name} && ${binding.dependencies.map((dependency: string) => `changed.${dependency}`).join(' || ')} ) {
|
|
|
|
|
${name}_changes.${binding.name} = ${binding.snippet};
|
|
|
|
|
${name_updating}.${binding.name} = true;
|
|
|
|
|
}
|
|
|
|
|
`
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
bindings.forEach(binding => {
|
|
|
|
|
statements.push(binding.init);
|
|
|
|
|
});
|
|
|
|
@ -250,9 +266,31 @@ export default function visitComponent(
|
|
|
|
|
${name_updating} = {};
|
|
|
|
|
}
|
|
|
|
|
`);
|
|
|
|
|
|
|
|
|
|
bindings.forEach(binding => {
|
|
|
|
|
if (binding.update) updates.push(binding.update);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
_beforecreate = deindent`
|
|
|
|
|
#component._root._beforecreate.push(function () {
|
|
|
|
|
var state = #component.get(), childState = ${name}.get(), newState = {};
|
|
|
|
|
if (!childState) return;
|
|
|
|
|
${bindings.map(binding => binding.setParentFromChild).join('\n')}
|
|
|
|
|
${name_updating} = { ${local.bindings.map(binding => `${binding.name}: true`).join(', ')} };
|
|
|
|
|
#component._set(newState);
|
|
|
|
|
${name_updating} = {};
|
|
|
|
|
});
|
|
|
|
|
`;
|
|
|
|
|
} else if (initialProps.length) {
|
|
|
|
|
componentInitProperties.push(`data: ${initialPropString}`);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
local.update.addBlock(deindent`
|
|
|
|
|
var ${name}_changes = {};
|
|
|
|
|
${updates.join('\n')}
|
|
|
|
|
${name}._set( ${name}_changes );
|
|
|
|
|
${bindings.length && `${name_updating} = {};`}
|
|
|
|
|
`);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const expression = node.name === ':Self'
|
|
|
|
@ -265,51 +303,9 @@ export default function visitComponent(
|
|
|
|
|
var ${name} = new ${expression}({
|
|
|
|
|
${componentInitProperties.join(',\n')}
|
|
|
|
|
});
|
|
|
|
|
`);
|
|
|
|
|
|
|
|
|
|
if (bindings.length) {
|
|
|
|
|
local.create.addBlock(deindent`
|
|
|
|
|
#component._root._beforecreate.push(function () {
|
|
|
|
|
var state = #component.get(), childState = ${name}.get(), newState = {};
|
|
|
|
|
if (!childState) return;
|
|
|
|
|
${bindings.map(binding => binding.setParentFromChild).join('\n')}
|
|
|
|
|
${name_updating} = { ${local.bindings.map(binding => `${binding.name}: true`).join(', ')} };
|
|
|
|
|
#component._set(newState);
|
|
|
|
|
${name_updating} = {};
|
|
|
|
|
});
|
|
|
|
|
`);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (local.dynamicAttributes.length || local.bindings.length) {
|
|
|
|
|
const updates: string[] = [];
|
|
|
|
|
|
|
|
|
|
local.dynamicAttributes.forEach(attribute => {
|
|
|
|
|
if (attribute.dependencies.length) {
|
|
|
|
|
updates.push(deindent`
|
|
|
|
|
if ( ${attribute.dependencies
|
|
|
|
|
.map(dependency => `changed.${dependency}`)
|
|
|
|
|
.join(' || ')} ) ${name}_changes.${attribute.name} = ${attribute.value};
|
|
|
|
|
`);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
else {
|
|
|
|
|
// TODO this is an odd situation to encounter – I *think* it should only happen with
|
|
|
|
|
// each block indices, in which case it may be possible to optimise this
|
|
|
|
|
updates.push(`${name}_changes.${attribute.name} = ${attribute.value};`);
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
bindings.forEach(binding => {
|
|
|
|
|
if (binding.update) updates.push(binding.update);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
local.update.addBlock(deindent`
|
|
|
|
|
var ${name}_changes = {};
|
|
|
|
|
${updates.join('\n')}
|
|
|
|
|
${name}._set( ${name}_changes );
|
|
|
|
|
${bindings.length && `${name_updating} = {};`}
|
|
|
|
|
`);
|
|
|
|
|
}
|
|
|
|
|
${_beforecreate}
|
|
|
|
|
`);
|
|
|
|
|
|
|
|
|
|
if (isTopLevel)
|
|
|
|
|
block.builders.unmount.addLine(`${name}._fragment.unmount();`);
|
|
|
|
|