Lint and format src/compiler/compile/nodes/shared/Context.js

pull/8569/head
Simon Holthausen 3 years ago
parent e197dcb3d7
commit f78ca010f6

@ -15,143 +15,159 @@ import flatten_reference from '../../utils/flatten_reference.js';
* in_rest_element?: boolean; * in_rest_element?: boolean;
* }} * }}
*/ */
export function unpack_destructuring({ contexts, node, modifier = (node) => node, default_modifier = (node) => node, scope, component, context_rest_properties, in_rest_element = false }) { export function unpack_destructuring({
if (!node) contexts,
return; node,
if (node.type === 'Identifier') { modifier = (node) => node,
contexts.push({ default_modifier = (node) => node,
type: 'DestructuredVariable', scope,
key: /** @type {import('estree').Identifier} */ (node), component,
modifier, context_rest_properties,
default_modifier in_rest_element = false
}); }) {
if (in_rest_element) { if (!node) return;
context_rest_properties.set(node.name, node); if (node.type === 'Identifier') {
} contexts.push({
} type: 'DestructuredVariable',
else if (node.type === 'ArrayPattern') { key: /** @type {import('estree').Identifier} */ (node),
node.elements.forEach((element, i) => { modifier,
if (!element) { default_modifier
return; });
} if (in_rest_element) {
else if (element.type === 'RestElement') { context_rest_properties.set(node.name, node);
unpack_destructuring({ }
contexts, } else if (node.type === 'ArrayPattern') {
node: element.argument, node.elements.forEach((element, i) => {
modifier: (node) => /** @type {import('estree').Node} */ (x `${modifier(node)}.slice(${i})`), if (!element) {
default_modifier, return;
scope, } else if (element.type === 'RestElement') {
component, unpack_destructuring({
context_rest_properties, contexts,
in_rest_element: true node: element.argument,
}); modifier: (node) =>
} /** @type {import('estree').Node} */ (x`${modifier(node)}.slice(${i})`),
else if (element.type === 'AssignmentPattern') { default_modifier,
const n = contexts.length; scope,
mark_referenced(element.right, scope, component); component,
unpack_destructuring({ context_rest_properties,
contexts, in_rest_element: true
node: element.left, });
modifier: (node) => x `${modifier(node)}[${i}]`, } else if (element.type === 'AssignmentPattern') {
default_modifier: (node, to_ctx) => const n = contexts.length;
/** @type {import('estree').Node} */ (x `${node} !== undefined ? ${node} : ${update_reference(contexts, n, element.right, to_ctx)}`), mark_referenced(element.right, scope, component);
scope, unpack_destructuring({
component, contexts,
context_rest_properties, node: element.left,
in_rest_element modifier: (node) => x`${modifier(node)}[${i}]`,
}); default_modifier: (node, to_ctx) =>
} /** @type {import('estree').Node} */ (
else { x`${node} !== undefined ? ${node} : ${update_reference(
unpack_destructuring({ contexts,
contexts, n,
node: element, element.right,
modifier: (node) => /** @type {import('estree').Node} */ (x `${modifier(node)}[${i}]`), to_ctx
default_modifier, )}`
scope, ),
component, scope,
context_rest_properties, component,
in_rest_element context_rest_properties,
}); in_rest_element
} });
}); } else {
} unpack_destructuring({
else if (node.type === 'ObjectPattern') { contexts,
const used_properties = []; node: element,
node.properties.forEach((property) => { modifier: (node) => /** @type {import('estree').Node} */ (x`${modifier(node)}[${i}]`),
if (property.type === 'RestElement') { default_modifier,
unpack_destructuring({ scope,
contexts, component,
node: property.argument, context_rest_properties,
modifier: (node) => in_rest_element
/** @type {import('estree').Node} */ (x `@object_without_properties(${modifier(node)}, [${used_properties}])`), });
default_modifier, }
scope, });
component, } else if (node.type === 'ObjectPattern') {
context_rest_properties, const used_properties = [];
in_rest_element: true node.properties.forEach((property) => {
}); if (property.type === 'RestElement') {
} unpack_destructuring({
else if (property.type === 'Property') { contexts,
const key = property.key; node: property.argument,
const value = property.value; modifier: (node) =>
/** @type {import('estree').Node} */ (
x`@object_without_properties(${modifier(node)}, [${used_properties}])`
),
default_modifier,
scope,
component,
context_rest_properties,
in_rest_element: true
});
} else if (property.type === 'Property') {
const key = property.key;
const value = property.value;
/** @type {(node: import('estree').Node) => import('estree').Node} */ /** @type {(node: import('estree').Node) => import('estree').Node} */
let new_modifier; let new_modifier;
if (property.computed) { if (property.computed) {
// e.g { [computedProperty]: ... } // e.g { [computedProperty]: ... }
const property_name = component.get_unique_name('computed_property'); const property_name = component.get_unique_name('computed_property');
contexts.push({ contexts.push({
type: 'ComputedProperty', type: 'ComputedProperty',
property_name, property_name,
key key
}); });
new_modifier = (node) => x `${modifier(node)}[${property_name}]`; new_modifier = (node) => x`${modifier(node)}[${property_name}]`;
used_properties.push(x `${property_name}`); used_properties.push(x`${property_name}`);
} } else if (key.type === 'Identifier') {
else if (key.type === 'Identifier') { // e.g. { someProperty: ... }
// e.g. { someProperty: ... } const property_name = key.name;
const property_name = key.name; new_modifier = (node) => x`${modifier(node)}.${property_name}`;
new_modifier = (node) => x `${modifier(node)}.${property_name}`; used_properties.push(x`"${property_name}"`);
used_properties.push(x `"${property_name}"`); } else if (key.type === 'Literal') {
} // e.g. { "property-in-quotes": ... } or { 14: ... }
else if (key.type === 'Literal') { const property_name = key.value;
// e.g. { "property-in-quotes": ... } or { 14: ... } new_modifier = (node) => x`${modifier(node)}["${property_name}"]`;
const property_name = key.value; used_properties.push(x`"${property_name}"`);
new_modifier = (node) => x `${modifier(node)}["${property_name}"]`; }
used_properties.push(x `"${property_name}"`); if (value.type === 'AssignmentPattern') {
} // e.g. { property = default } or { property: newName = default }
if (value.type === 'AssignmentPattern') { const n = contexts.length;
// e.g. { property = default } or { property: newName = default } mark_referenced(value.right, scope, component);
const n = contexts.length; unpack_destructuring({
mark_referenced(value.right, scope, component); contexts,
unpack_destructuring({ node: value.left,
contexts, modifier: new_modifier,
node: value.left, default_modifier: (node, to_ctx) =>
modifier: new_modifier, /** @type {import('estree').Node} */ (
default_modifier: (node, to_ctx) => x`${node} !== undefined ? ${node} : ${update_reference(
/** @type {import('estree').Node} */ (x `${node} !== undefined ? ${node} : ${update_reference(contexts, n, value.right, to_ctx)}`), contexts,
scope, n,
component, value.right,
context_rest_properties, to_ctx
in_rest_element )}`
}); ),
} scope,
else { component,
// e.g. { property } or { property: newName } context_rest_properties,
unpack_destructuring({ in_rest_element
contexts, });
node: value, } else {
modifier: new_modifier, // e.g. { property } or { property: newName }
default_modifier, unpack_destructuring({
scope, contexts,
component, node: value,
context_rest_properties, modifier: new_modifier,
in_rest_element default_modifier,
}); scope,
} component,
} context_rest_properties,
}); in_rest_element
} });
}
}
});
}
} }
/** /**
@ -162,34 +178,37 @@ export function unpack_destructuring({ contexts, node, modifier = (node) => node
* @returns {import("C:/repos/svelte/svelte/node_modules/.pnpm/@types+estree@1.0.0/node_modules/@types/estree/index").import('estree').Node} * @returns {import("C:/repos/svelte/svelte/node_modules/.pnpm/@types+estree@1.0.0/node_modules/@types/estree/index").import('estree').Node}
*/ */
function update_reference(contexts, n, expression, to_ctx) { function update_reference(contexts, n, expression, to_ctx) {
/** @param {import('estree').Identifier} node */
/** @param {import('estree').Identifier} node */ const find_from_context = (node) => {
const find_from_context = (node) => { for (let i = n; i < contexts.length; i++) {
for (let i = n; i < contexts.length; i++) { const cur_context = contexts[i];
const cur_context = contexts[i]; if (cur_context.type !== 'DestructuredVariable') continue;
if (cur_context.type !== 'DestructuredVariable') const { key } = cur_context;
continue; if (node.name === key.name) {
const { key } = cur_context; throw new Error(`Cannot access '${node.name}' before initialization`);
if (node.name === key.name) { }
throw new Error(`Cannot access '${node.name}' before initialization`); }
} return to_ctx(node.name);
} };
return to_ctx(node.name); if (expression.type === 'Identifier') {
}; return find_from_context(expression);
if (expression.type === 'Identifier') { }
return find_from_context(expression); // NOTE: avoid unnecessary deep clone?
} expression = /** @type {import('estree').Expression} */ (clone(expression));
// NOTE: avoid unnecessary deep clone? walk(expression, {
expression = /** @type {import('estree').Expression} */ (clone(expression)); enter(node, parent) {
walk(expression, { if (
enter(node, parent) { is_reference(
if (is_reference(/** @type {import('is-reference').NodeWithPropertyDefinition} */ (node), /** @type {import('is-reference').NodeWithPropertyDefinition} */ (parent))) { /** @type {import('is-reference').NodeWithPropertyDefinition} */ (node),
this.replace(find_from_context(/** @type {import('estree').Identifier} */ (node))); /** @type {import('is-reference').NodeWithPropertyDefinition} */ (parent)
this.skip(); )
} ) {
} this.replace(find_from_context(/** @type {import('estree').Identifier} */ (node)));
}); this.skip();
return expression; }
}
});
return expression;
} }
/** /**
@ -198,19 +217,18 @@ function update_reference(contexts, n, expression, to_ctx) {
* @param {import('../../Component.js').default} component * @param {import('../../Component.js').default} component
*/ */
function mark_referenced(node, scope, component) { function mark_referenced(node, scope, component) {
walk(node, { walk(node, {
enter(node, parent) { enter(node, parent) {
if (is_reference(node, parent)) { if (is_reference(node, parent)) {
const { name } = flatten_reference(node); const { name } = flatten_reference(node);
if (!scope.is_let(name) && !scope.names.has(name)) { if (!scope.is_let(name) && !scope.names.has(name)) {
component.add_reference(node, name); component.add_reference(node, name);
} }
} }
} }
}); });
} }
/** @typedef {DestructuredVariable | ComputedProperty} Context */ /** @typedef {DestructuredVariable | ComputedProperty} Context */
/** @typedef {Object} ComputedProperty /** @typedef {Object} ComputedProperty

Loading…
Cancel
Save