Convert src/compiler/compile/render_dom/wrappers/shared/bind_this.ts to JavaScript

pull/8569/head
Simon Holthausen 3 years ago
parent 30595f4ee5
commit 2bb0be68d5

@ -1,103 +1,89 @@
import { b, x } from 'code-red'; import { b, x } from 'code-red';
import Component from '../../../Component'; import { compare_node } from '../../../utils/compare_node.js';
import Block from '../../Block';
import BindingWrapper from '../Element/Binding';
import { Identifier } from 'estree';
import { compare_node } from '../../../utils/compare_node';
export default function bind_this( /**
component: Component, * @param {import('../../../Component.js').default} component
block: Block, * @param {import('../../Block.js').default} block
binding: BindingWrapper, * @param {import('../Element/Binding.js').default} binding
variable: Identifier * @param {import('estree').Identifier} variable
) { */
const fn = component.get_unique_name(`${variable.name}_binding`); export default function bind_this(component, block, binding, variable) {
const fn = component.get_unique_name(`${variable.name}_binding`);
block.renderer.add_to_context(fn.name); block.renderer.add_to_context(fn.name);
const callee = block.renderer.reference(fn.name); const callee = block.renderer.reference(fn.name);
const { contextual_dependencies, mutation } = binding.handler;
const { contextual_dependencies, mutation } = binding.handler; const dependencies = binding.get_update_dependencies();
const dependencies = binding.get_update_dependencies(); const body = b `
const body = b`
${mutation} ${mutation}
${Array.from(dependencies) ${Array.from(dependencies)
.filter((dep) => dep[0] !== '$') .filter((dep) => dep[0] !== '$')
.filter((dep) => !contextual_dependencies.has(dep)) .filter((dep) => !contextual_dependencies.has(dep))
.map((dep) => b`${block.renderer.invalidate(dep)};`)} .map((dep) => b `${block.renderer.invalidate(dep)};`)}
`; `;
if (contextual_dependencies.size) {
if (contextual_dependencies.size) { /** @type {import('estree').Identifier[]} */
const params: Identifier[] = Array.from(contextual_dependencies).map((name) => ({ const params = Array.from(contextual_dependencies).map((name) => ({
type: 'Identifier', type: 'Identifier',
name name
})); }));
component.partly_hoisted.push(b` component.partly_hoisted.push(b `
function ${fn}($$value, ${params}) { function ${fn}($$value, ${params}) {
@binding_callbacks[$$value ? 'unshift' : 'push'](() => { @binding_callbacks[$$value ? 'unshift' : 'push'](() => {
${body} ${body}
}); });
} }
`); `);
const alias_map = new Map();
const alias_map = new Map(); const args = [];
const args = []; for (let id of params) {
for (let id of params) { const value = block.renderer.reference(id.name);
const value = block.renderer.reference(id.name); let found = false;
let found = false; if (block.variables.has(id.name)) {
if (block.variables.has(id.name)) { let alias = id.name;
let alias = id.name; for (let i = 1; block.variables.has(alias) && !compare_node(block.variables.get(alias).init, value); alias = `${id.name}_${i++}`)
for ( ;
let i = 1; alias_map.set(alias, id.name);
block.variables.has(alias) && !compare_node(block.variables.get(alias).init, value); id = { type: 'Identifier', name: alias };
alias = `${id.name}_${i++}` found = block.variables.has(alias);
); }
alias_map.set(alias, id.name); args.push(id);
id = { type: 'Identifier', name: alias }; if (!found) {
found = block.variables.has(alias); block.add_variable(id, value);
} }
args.push(id); }
if (!found) { const assign = block.get_unique_name(`assign_${variable.name}`);
block.add_variable(id, value); const unassign = block.get_unique_name(`unassign_${variable.name}`);
} block.chunks.init.push(b `
}
const assign = block.get_unique_name(`assign_${variable.name}`);
const unassign = block.get_unique_name(`unassign_${variable.name}`);
block.chunks.init.push(b`
const ${assign} = () => ${callee}(${variable}, ${args}); const ${assign} = () => ${callee}(${variable}, ${args});
const ${unassign} = () => ${callee}(null, ${args}); const ${unassign} = () => ${callee}(null, ${args});
`); `);
const condition = Array.from(args)
const condition = Array.from(args) .map((name) => x `${name} !== ${block.renderer.reference(alias_map.get(name.name) || name.name)}`)
.map( .reduce((lhs, rhs) => x `${lhs} || ${rhs}`);
(name) => x`${name} !== ${block.renderer.reference(alias_map.get(name.name) || name.name)}` // we push unassign and unshift assign so that references are
) // nulled out before they're created, to avoid glitches
.reduce((lhs, rhs) => x`${lhs} || ${rhs}`); // with shifting indices
block.chunks.update.push(b `
// we push unassign and unshift assign so that references are
// nulled out before they're created, to avoid glitches
// with shifting indices
block.chunks.update.push(b`
if (${condition}) { if (${condition}) {
${unassign}(); ${unassign}();
${args.map((a) => b`${a} = ${block.renderer.reference(alias_map.get(a.name) || a.name)}`)}; ${args.map((a) => b `${a} = ${block.renderer.reference(alias_map.get(a.name) || a.name)}`)};
${assign}(); ${assign}();
}`); }`);
block.chunks.destroy.push(b `${unassign}();`);
block.chunks.destroy.push(b`${unassign}();`); return b `${assign}();`;
return b`${assign}();`; }
} component.partly_hoisted.push(b `
component.partly_hoisted.push(b`
function ${fn}($$value) { function ${fn}($$value) {
@binding_callbacks[$$value ? 'unshift' : 'push'](() => { @binding_callbacks[$$value ? 'unshift' : 'push'](() => {
${body} ${body}
}); });
} }
`); `);
block.chunks.destroy.push(b `${callee}(null);`);
block.chunks.destroy.push(b`${callee}(null);`); return b `${callee}(${variable});`;
return b`${callee}(${variable});`;
} }

Loading…
Cancel
Save