From eac421840223674a703f6f638973c02faed7bda2 Mon Sep 17 00:00:00 2001 From: Paolo Ricciuti Date: Fri, 19 Apr 2024 11:23:27 +0200 Subject: [PATCH] fix: possible name clash in hoisted functions (#11237) * fix: possible name clash in hoisted functions * chore: add test --- .changeset/stupid-parents-crash.md | 5 +++++ .../phases/3-transform/client/utils.js | 22 ++++++++++++++----- .../samples/name-clash-hoisting/_config.js | 9 ++++++++ .../samples/name-clash-hoisting/main.svelte | 11 ++++++++++ 4 files changed, 41 insertions(+), 6 deletions(-) create mode 100644 .changeset/stupid-parents-crash.md create mode 100644 packages/svelte/tests/runtime-runes/samples/name-clash-hoisting/_config.js create mode 100644 packages/svelte/tests/runtime-runes/samples/name-clash-hoisting/main.svelte diff --git a/.changeset/stupid-parents-crash.md b/.changeset/stupid-parents-crash.md new file mode 100644 index 000000000..2e0c9e887 --- /dev/null +++ b/.changeset/stupid-parents-crash.md @@ -0,0 +1,5 @@ +--- +"svelte": patch +--- + +fix: possible name clash in hoisted functions diff --git a/packages/svelte/src/compiler/phases/3-transform/client/utils.js b/packages/svelte/src/compiler/phases/3-transform/client/utils.js index b6b5d7eca..17e3fedc1 100644 --- a/packages/svelte/src/compiler/phases/3-transform/client/utils.js +++ b/packages/svelte/src/compiler/phases/3-transform/client/utils.js @@ -455,18 +455,28 @@ export const function_visitor = (node, context) => { function get_hoistable_params(node, context) { const scope = context.state.scope; - /** @type {import('estree').Pattern[]} */ + /** @type {import('estree').Identifier[]} */ const params = []; let added_props = false; + /** + * we only want to push if it's not already present to avoid name clashing + * @param {import('estree').Identifier} id + */ + function safe_push(id) { + if (!params.find((param) => param.name === id.name)) { + params.push(id); + } + } + for (const [reference] of scope.references) { const binding = scope.get(reference); if (binding !== null && !scope.declarations.has(reference) && binding.initial !== node) { if (binding.kind === 'store_sub') { // We need both the subscription for getting the value and the store for updating - params.push(b.id(binding.node.name.slice(1))); - params.push(b.id(binding.node.name)); + safe_push(b.id(binding.node.name.slice(1))); + safe_push(b.id(binding.node.name)); } else if ( // If it's a destructured derived binding, then we can extract the derived signal reference and use that. binding.expression !== null && @@ -477,7 +487,7 @@ function get_hoistable_params(node, context) { binding.expression.object.callee.name === '$.get' && binding.expression.object.arguments[0].type === 'Identifier' ) { - params.push(b.id(binding.expression.object.arguments[0].name)); + safe_push(b.id(binding.expression.object.arguments[0].name)); } else if ( // If we are referencing a simple $$props value, then we need to reference the object property instead (binding.kind === 'prop' || binding.kind === 'bindable_prop') && @@ -488,11 +498,11 @@ function get_hoistable_params(node, context) { // Handle $$props.something use-cases if (!added_props) { added_props = true; - params.push(b.id('$$props')); + safe_push(b.id('$$props')); } } else { // create a copy to remove start/end tags which would mess up source maps - params.push(b.id(binding.node.name)); + safe_push(b.id(binding.node.name)); } } } diff --git a/packages/svelte/tests/runtime-runes/samples/name-clash-hoisting/_config.js b/packages/svelte/tests/runtime-runes/samples/name-clash-hoisting/_config.js new file mode 100644 index 000000000..e5e25e85a --- /dev/null +++ b/packages/svelte/tests/runtime-runes/samples/name-clash-hoisting/_config.js @@ -0,0 +1,9 @@ +import { test } from '../../test'; + +export default test({ + compileOptions: { + dev: true + }, + recover: true, + mode: ['client'] +}); diff --git a/packages/svelte/tests/runtime-runes/samples/name-clash-hoisting/main.svelte b/packages/svelte/tests/runtime-runes/samples/name-clash-hoisting/main.svelte new file mode 100644 index 000000000..c4d8ecee5 --- /dev/null +++ b/packages/svelte/tests/runtime-runes/samples/name-clash-hoisting/main.svelte @@ -0,0 +1,11 @@ + + +