Skip to content

Conversation

@jmsjtu
Copy link
Member

@jmsjtu jmsjtu commented Oct 21, 2025

Details

The SSR v2 compiler keeps track of local variables via a stack.

When the local variables are retrieved we don't deduplicate them which can lead to errors, specifically:

LWC1001: Unexpected compilation error: Duplicate argument name "unused":

This PR introduces a fix by deduping the variables before use.

Does this pull request introduce a breaking change?

  • 😮‍💨 No, it does not introduce a breaking change.
  • 💔 Yes, it does introduce a breaking change.

Does this pull request introduce an observable change?

  • 🤞 No, it does not introduce an observable change.
  • 🔬 Yes, it does include an observable change.

GUS work item

W-19971203

@jmsjtu jmsjtu requested a review from a team as a code owner October 21, 2025 23:04
Comment on lines 1 to 11
<template lwc:render-mode="light">
<template for:each={relatedListData} for:item="list" if:true={relatedListData}>
<template for:each={list.recordIds} for:item="recordId">
<template for:each={list.fields} for:item="field" for:index="index">
<x-child key={field}>
<div>{field}</div>
</x-child>
</template>
</template>
</template>
</template> No newline at end of file
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Before the change in this PR the output is this:

const __lwcGenerateShadowSlottedContent_xChild_0 = (list, __unused__, recordId, __unused__, field, index) => function __lwcGenerateShadowSlottedContent_xChild_0

The double __unused__ led to a compilation error.

After this change it now appears as:

const __lwcGenerateShadowSlottedContent_xChild_0 = (list, __unused__, recordId, field, index) => function __lwcGenerateShadowSlottedContent_xChild_0

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's less likely to occur with user-provided variables, but deduping is also correct in that case because re-declared variables are shadowed; there's only one "version" of the variable in the scope where we call this function.

Comment on lines -36 to +39
const getLocalVars = () => localVarStack.flatMap((varsSet) => Array.from(varsSet));
// Unique local variable names across block scopes, we don't care about block scope order
const getLocalVars = () => [
...new Set(localVarStack.flatMap((varsSet) => Array.from(varsSet))),
];
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the main change, essentially we're just deduplicating the list.

Note that based on how we're using the array we don't really care about the order the variables appear in the block scopes.

@@ -0,0 +1,2 @@
<fixture-test>
</fixture-test> No newline at end of file
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this supposed to be empty? 🤔

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like I messed up the data in the array oops, I'll fix it.

Copy link
Contributor

@wjhsf wjhsf left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@nolanlawson would approve of the ratio of test files to lines of production code changed.

Comment on lines 1 to 11
<template lwc:render-mode="light">
<template for:each={relatedListData} for:item="list" if:true={relatedListData}>
<template for:each={list.recordIds} for:item="recordId">
<template for:each={list.fields} for:item="field" for:index="index">
<x-child key={field}>
<div>{field}</div>
</x-child>
</template>
</template>
</template>
</template> No newline at end of file
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's less likely to occur with user-provided variables, but deduping is also correct in that case because re-declared variables are shadowed; there's only one "version" of the variable in the scope where we call this function.

@jmsjtu jmsjtu enabled auto-merge (squash) October 22, 2025 20:31
@jmsjtu jmsjtu merged commit 34d4b76 into master Oct 22, 2025
13 checks passed
@jmsjtu jmsjtu deleted the jtu/ssr-fix-duplicate-local-scope branch October 22, 2025 21:32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants