diff --git a/packages/svelte2tsx/src/svelte2tsx/processInstanceScriptContent.ts b/packages/svelte2tsx/src/svelte2tsx/processInstanceScriptContent.ts
index 4790739cb..d6f0ebdf6 100644
--- a/packages/svelte2tsx/src/svelte2tsx/processInstanceScriptContent.ts
+++ b/packages/svelte2tsx/src/svelte2tsx/processInstanceScriptContent.ts
@@ -1,6 +1,6 @@
import MagicString from 'magic-string';
import { Node } from 'estree-walker';
-import ts from 'typescript';
+import ts, { VariableDeclaration } from 'typescript';
import { getBinaryAssignmentExpr, isNotPropertyNameOfImport, moveNode } from './utils/tsAst';
import { ExportedNames, is$$PropsDeclaration } from './nodes/ExportedNames';
import { ImplicitTopLevelNames } from './nodes/ImplicitTopLevelNames';
@@ -32,6 +32,7 @@ interface PendingStoreResolution {
node: ts.Identifier;
parent: ts.Node;
scope: Scope;
+ isPropsId: boolean;
}
export function processInstanceScriptContent(
@@ -82,13 +83,19 @@ export function processInstanceScriptContent(
//track if we are in a declaration scope
let isDeclaration = false;
+ //track the variable declaration node
+ let variableDeclarationNode: VariableDeclaration | null = null;
+
//track $store variables since we are only supposed to give top level scopes special treatment, and users can declare $blah variables at higher scopes
//which prevents us just changing all instances of Identity that start with $
- const pendingStoreResolutions: PendingStoreResolution[] = [];
+ let pendingStoreResolutions: PendingStoreResolution[] = [];
let scope = new Scope();
const rootScope = scope;
+ //track is the variable declared as `props` comes from `$props()`
+ let isPropsDeclarationRune = false;
+
const pushScope = () => (scope = new Scope(scope));
const popScope = () => (scope = scope.parent);
@@ -124,6 +131,17 @@ export function processInstanceScriptContent(
return;
}
+ //if we are in a variable declaration and the identifier is `props` we check the initializer
+ if (
+ ident.text === 'props' &&
+ variableDeclarationNode &&
+ variableDeclarationNode.initializer &&
+ ts.isCallExpression(variableDeclarationNode.initializer) &&
+ variableDeclarationNode.initializer.getText() === '$props()'
+ ) {
+ isPropsDeclarationRune = true;
+ }
+
if (isDeclaration || ts.isParameter(parent)) {
if (
isNotPropertyNameOfImport(ident) &&
@@ -148,6 +166,17 @@ export function processInstanceScriptContent(
!ts.isTypeAliasDeclaration(parent) &&
!ts.isInterfaceDeclaration(parent)
) {
+ let isPropsId = false;
+ if (
+ text === '$props' &&
+ ts.isPropertyAccessExpression(parent) &&
+ parent.parent &&
+ ts.isCallExpression(parent.parent) &&
+ parent.parent.arguments.length === 0
+ ) {
+ const text = parent.getText();
+ isPropsId = text === '$props.id';
+ }
// Handle the const { ...props } = $props() case
const is_rune =
(text === '$props' || text === '$derived' || text === '$state') &&
@@ -155,7 +184,7 @@ export function processInstanceScriptContent(
ts.isVariableDeclaration(parent.parent) &&
parent.parent.name.getText().includes(text.slice(1));
if (!is_rune) {
- pendingStoreResolutions.push({ node: ident, parent, scope });
+ pendingStoreResolutions.push({ node: ident, parent, scope, isPropsId });
}
}
}
@@ -234,7 +263,11 @@ export function processInstanceScriptContent(
if (ts.isVariableDeclaration(parent) && parent.name == node) {
isDeclaration = true;
- onLeaveCallbacks.push(() => (isDeclaration = false));
+ variableDeclarationNode = parent;
+ onLeaveCallbacks.push(() => {
+ isDeclaration = false;
+ variableDeclarationNode = null;
+ });
}
if (ts.isBindingElement(parent) && parent.name == node) {
@@ -295,6 +328,10 @@ export function processInstanceScriptContent(
tsAst.forEachChild((n) => walk(n, tsAst));
//resolve stores
+ if (isPropsDeclarationRune) {
+ //we filter out every pendingStore resolution that `isPropsId` if the variable names `props` comes from `$props()`
+ pendingStoreResolutions = pendingStoreResolutions.filter(({ isPropsId }) => !isPropsId);
+ }
pendingStoreResolutions.map(resolveStore);
// declare implicit reactive variables we found in the script
diff --git a/packages/svelte2tsx/test/svelte2tsx/samples/props-variable-and-$props.id-destructured.v5/expectedv2.ts b/packages/svelte2tsx/test/svelte2tsx/samples/props-variable-and-$props.id-destructured.v5/expectedv2.ts
new file mode 100644
index 000000000..2cab6b0ed
--- /dev/null
+++ b/packages/svelte2tsx/test/svelte2tsx/samples/props-variable-and-$props.id-destructured.v5/expectedv2.ts
@@ -0,0 +1,13 @@
+///
+;function $$render() {
+
+ let/** @typedef {{ props: any }} $$ComponentProps *//** @type {$$ComponentProps} */ { props } = $props();
+ let id = $props.id();
+;
+async () => {
+
+id; props;};
+return { props: /** @type {$$ComponentProps} */({}), exports: {}, bindings: __sveltets_$$bindings(''), slots: {}, events: {} }}
+const Input__SvelteComponent_ = __sveltets_2_fn_component($$render());
+type Input__SvelteComponent_ = ReturnType;
+export default Input__SvelteComponent_;
\ No newline at end of file
diff --git a/packages/svelte2tsx/test/svelte2tsx/samples/props-variable-and-$props.id-destructured.v5/input.svelte b/packages/svelte2tsx/test/svelte2tsx/samples/props-variable-and-$props.id-destructured.v5/input.svelte
new file mode 100644
index 000000000..99067a438
--- /dev/null
+++ b/packages/svelte2tsx/test/svelte2tsx/samples/props-variable-and-$props.id-destructured.v5/input.svelte
@@ -0,0 +1,6 @@
+
+
+{id} {props}
diff --git a/packages/svelte2tsx/test/svelte2tsx/samples/props-variable-and-$props.id-not-$props-init.v5/expectedv2.ts b/packages/svelte2tsx/test/svelte2tsx/samples/props-variable-and-$props.id-not-$props-init.v5/expectedv2.ts
new file mode 100644
index 000000000..4ca5bbfd3
--- /dev/null
+++ b/packages/svelte2tsx/test/svelte2tsx/samples/props-variable-and-$props.id-not-$props-init.v5/expectedv2.ts
@@ -0,0 +1,13 @@
+///
+;function $$render() {
+
+ let props = {}/*Ωignore_startΩ*/;let $props = __sveltets_2_store_get(props);/*Ωignore_endΩ*/;
+ let id = $props.id();
+;
+async () => {
+
+id; props;};
+return { props: /** @type {Record} */ ({}), exports: {}, bindings: "", slots: {}, events: {} }}
+const Input__SvelteComponent_ = __sveltets_2_isomorphic_component(__sveltets_2_partial(__sveltets_2_with_any_event($$render())));
+/*Ωignore_startΩ*/type Input__SvelteComponent_ = InstanceType;
+/*Ωignore_endΩ*/export default Input__SvelteComponent_;
\ No newline at end of file
diff --git a/packages/svelte2tsx/test/svelte2tsx/samples/props-variable-and-$props.id-not-$props-init.v5/input.svelte b/packages/svelte2tsx/test/svelte2tsx/samples/props-variable-and-$props.id-not-$props-init.v5/input.svelte
new file mode 100644
index 000000000..bbda4b80b
--- /dev/null
+++ b/packages/svelte2tsx/test/svelte2tsx/samples/props-variable-and-$props.id-not-$props-init.v5/input.svelte
@@ -0,0 +1,6 @@
+
+
+{id} {props}
diff --git a/packages/svelte2tsx/test/svelte2tsx/samples/props-variable-and-$props.id-spread.v5/expectedv2.ts b/packages/svelte2tsx/test/svelte2tsx/samples/props-variable-and-$props.id-spread.v5/expectedv2.ts
new file mode 100644
index 000000000..7016df35d
--- /dev/null
+++ b/packages/svelte2tsx/test/svelte2tsx/samples/props-variable-and-$props.id-spread.v5/expectedv2.ts
@@ -0,0 +1,13 @@
+///
+;function $$render() {
+
+ let/** @typedef {Record} $$ComponentProps *//** @type {$$ComponentProps} */ {...props} = $props();
+ let id = $props.id();
+;
+async () => {
+
+id; props;};
+return { props: /** @type {$$ComponentProps} */({}), exports: {}, bindings: __sveltets_$$bindings(''), slots: {}, events: {} }}
+const Input__SvelteComponent_ = __sveltets_2_fn_component($$render());
+type Input__SvelteComponent_ = ReturnType;
+export default Input__SvelteComponent_;
\ No newline at end of file
diff --git a/packages/svelte2tsx/test/svelte2tsx/samples/props-variable-and-$props.id-spread.v5/input.svelte b/packages/svelte2tsx/test/svelte2tsx/samples/props-variable-and-$props.id-spread.v5/input.svelte
new file mode 100644
index 000000000..754e52c42
--- /dev/null
+++ b/packages/svelte2tsx/test/svelte2tsx/samples/props-variable-and-$props.id-spread.v5/input.svelte
@@ -0,0 +1,6 @@
+
+
+{id} {props}
diff --git a/packages/svelte2tsx/test/svelte2tsx/samples/props-variable-and-$props.id.v5/expectedv2.ts b/packages/svelte2tsx/test/svelte2tsx/samples/props-variable-and-$props.id.v5/expectedv2.ts
new file mode 100644
index 000000000..c897e5063
--- /dev/null
+++ b/packages/svelte2tsx/test/svelte2tsx/samples/props-variable-and-$props.id.v5/expectedv2.ts
@@ -0,0 +1,13 @@
+///
+;function $$render() {
+
+ let props = $props();
+ let id = $props.id();
+;
+async () => {
+
+id; props;};
+return { props: /** @type {$$ComponentProps} */({}), exports: {}, bindings: __sveltets_$$bindings(''), slots: {}, events: {} }}
+const Input__SvelteComponent_ = __sveltets_2_fn_component($$render());
+type Input__SvelteComponent_ = ReturnType;
+export default Input__SvelteComponent_;
\ No newline at end of file
diff --git a/packages/svelte2tsx/test/svelte2tsx/samples/props-variable-and-$props.id.v5/input.svelte b/packages/svelte2tsx/test/svelte2tsx/samples/props-variable-and-$props.id.v5/input.svelte
new file mode 100644
index 000000000..8a93516e4
--- /dev/null
+++ b/packages/svelte2tsx/test/svelte2tsx/samples/props-variable-and-$props.id.v5/input.svelte
@@ -0,0 +1,6 @@
+
+
+{id} {props}