svelte-origin 1.0.0-next.22 → 1.0.0-next.24

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of svelte-origin might be problematic. Click here for more details.

@@ -3473,34 +3473,22 @@ function __attrsFor(factory, rawAttrs) {
3473
3473
  const factoryWithSchema = factory;
3474
3474
  const schema = getMergedAttrSchema(factoryWithSchema);
3475
3475
  const wrapper = {};
3476
- const localValues = {};
3477
- const hasLocalValue = {};
3478
3476
  const defineExposedProp = (key2, info) => {
3479
3477
  if (Object.prototype.hasOwnProperty.call(wrapper, key2))
3480
3478
  return;
3481
- const base = {
3479
+ const descriptor = {
3482
3480
  get() {
3483
- if (hasLocalValue[key2])
3484
- return localValues[key2];
3485
3481
  return rawAttrs[key2];
3486
3482
  },
3487
3483
  enumerable: true,
3488
3484
  configurable: true
3489
3485
  };
3490
3486
  if (info.bindable) {
3491
- Object.defineProperty(wrapper, key2, {
3492
- ...base,
3493
- set(value) {
3494
- localValues[key2] = value;
3495
- hasLocalValue[key2] = true;
3496
- try {
3497
- rawAttrs[key2] = value;
3498
- } catch {}
3499
- }
3500
- });
3501
- } else {
3502
- Object.defineProperty(wrapper, key2, base);
3487
+ descriptor.set = function(value) {
3488
+ rawAttrs[key2] = value;
3489
+ };
3503
3490
  }
3491
+ Object.defineProperty(wrapper, key2, descriptor);
3504
3492
  };
3505
3493
  for (const [key2, info] of Object.entries(schema)) {
3506
3494
  const parentValue = rawAttrs[key2];
@@ -3521,8 +3509,6 @@ function __attrsFor(factory, rawAttrs) {
3521
3509
  return new Proxy(wrapper, {
3522
3510
  get(target, prop2) {
3523
3511
  if (typeof prop2 === "string" && prop2 in schema) {
3524
- if (hasLocalValue[prop2])
3525
- return localValues[prop2];
3526
3512
  return rawAttrs[prop2];
3527
3513
  }
3528
3514
  if (prop2 in target)
@@ -3531,15 +3517,11 @@ function __attrsFor(factory, rawAttrs) {
3531
3517
  },
3532
3518
  set(target, prop2, value) {
3533
3519
  if (typeof prop2 === "string" && prop2 in schema) {
3534
- localValues[prop2] = value;
3535
- hasLocalValue[prop2] = true;
3536
3520
  if (!Object.prototype.hasOwnProperty.call(wrapper, prop2)) {
3537
3521
  defineExposedProp(prop2, schema[prop2]);
3538
3522
  }
3539
3523
  if (schema[prop2].bindable) {
3540
- try {
3541
- rawAttrs[prop2] = value;
3542
- } catch {}
3524
+ rawAttrs[prop2] = value;
3543
3525
  }
3544
3526
  return true;
3545
3527
  }
@@ -3551,18 +3533,10 @@ function __attrsFor(factory, rawAttrs) {
3551
3533
  }
3552
3534
  try {
3553
3535
  rawAttrs[prop2] = value;
3554
- } catch {
3555
- if (typeof prop2 === "string") {
3556
- localValues[prop2] = value;
3557
- hasLocalValue[prop2] = true;
3558
- }
3559
- }
3536
+ } catch {}
3560
3537
  return true;
3561
3538
  },
3562
3539
  has(target, prop2) {
3563
- if (typeof prop2 === "string" && prop2 in schema) {
3564
- return prop2 in target || hasLocalValue[prop2];
3565
- }
3566
3540
  return prop2 in target || prop2 in rawAttrs;
3567
3541
  },
3568
3542
  ownKeys() {
@@ -6,12 +6,13 @@
6
6
  * - $attrs.for('input') - get typed element attrs
7
7
  */
8
8
  import type MagicString from 'magic-string';
9
+ import { type SchemaResolver } from './schema';
9
10
  /**
10
- * Transform $attrs.for(X) calls.
11
- * Handles both origin factories ($attrs.for(OriginFactory)) and element names ($attrs.for('input'))
11
+ * Transform $attrs.for(X) calls (sync fallback version).
12
12
  *
13
- * If $props() already exists, we extend the existing destructuring with rest syntax.
14
- * Otherwise, we generate a new $props() call.
13
+ * This version always uses the fallback approach since no schema resolver is provided.
14
+ * Fallback generates a raw $props() proxy which does NOT support two-way binding
15
+ * through parent components (the props proxy is read-only for non-destructured props).
15
16
  *
16
17
  * Supports all TypeScript declaration patterns:
17
18
  * - let x = $attrs.for(Factory)
@@ -21,4 +22,34 @@ import type MagicString from 'magic-string';
21
22
  * - export let x = $attrs.for(Factory)
22
23
  * - export const x: Type = $attrs.for('input')
23
24
  */
24
- export declare function transformAttrsForCalls(s: MagicString, source: string, neededImports: Set<string>): boolean;
25
+ export declare function transformAttrsForCallsSync(s: MagicString, source: string, neededImports: Set<string>): boolean;
26
+ /**
27
+ * Transform $attrs.for(X) calls (async version with schema resolution).
28
+ *
29
+ * When schema is available via static resolution:
30
+ * ```svelte
31
+ * let childAttrs = $attrs.for(Counter)
32
+ * ```
33
+ * Becomes:
34
+ * ```svelte
35
+ * let { label = 'Counter', count = $bindable(0), step = 1 }: $attrs.Of<typeof Counter> = $props()
36
+ * let childAttrs = __attrsFor(Counter, { get label() { return label }, get count() { return count }, set count(v) { count = v }, get step() { return step } })
37
+ * ```
38
+ *
39
+ * This approach works because:
40
+ * 1. Props are destructured with $bindable(), making them writable
41
+ * 2. The getter/setter wrapper passes reactive accessors to __attrsFor
42
+ * 3. When child components update bindable props, the setters propagate changes back
43
+ *
44
+ * Fallback (when schema isn't statically known):
45
+ * ```svelte
46
+ * let ___attrs: $attrs.Of<typeof Counter> = $props()
47
+ * let childAttrs = __attrsFor(Counter, ___attrs)
48
+ * ```
49
+ *
50
+ * @param s MagicString instance for source manipulation
51
+ * @param source Original source code
52
+ * @param neededImports Set to track required runtime imports
53
+ * @param schemaResolver Optional resolver for static schema extraction
54
+ */
55
+ export declare function transformAttrsForCalls(s: MagicString, source: string, neededImports: Set<string>, schemaResolver?: SchemaResolver): Promise<boolean>;
@@ -6,12 +6,27 @@
6
6
  */
7
7
  import type MagicString from 'magic-string';
8
8
  import { type SchemaResolver } from './schema';
9
+ /**
10
+ * Information about a tracked origin instance (for destructuring transform)
11
+ */
12
+ export interface TrackedOriginInstance {
13
+ /** Variable name holding the origin instance */
14
+ varName: string;
15
+ /** The factory name/expression used to create it */
16
+ factoryExpr: string;
17
+ /** Start position in source */
18
+ startPos: number;
19
+ /** End position in source */
20
+ endPos: number;
21
+ }
9
22
  /**
10
23
  * Result from transformAttrsOriginCalls including $$Props info for later injection
11
24
  */
12
25
  export interface AttrsOriginTransformResult {
13
26
  changed: boolean;
14
27
  propsTypeDeclaration: string | null;
28
+ /** Tracked origin instances for destructuring transform */
29
+ originInstances: Map<string, TrackedOriginInstance>;
15
30
  }
16
31
  /**
17
32
  * Transform $attrs.origin(X) calls in component scripts (sync fallback version).
@@ -0,0 +1,62 @@
1
+ /**
2
+ * Origin destructuring transformation logic.
3
+ *
4
+ * Handles patterns like:
5
+ * - `let { increment } = counter` - destructure methods with this-binding
6
+ * - `let { value } = counter.props` - destructure props directly
7
+ * - `let { props: { value } } = counter` - nested props destructuring
8
+ * - `let { value = $bindable(0) } = counter.props` - override with bindable
9
+ *
10
+ * Methods are bound to preserve `this` context.
11
+ * Props are converted to reactive $derived values.
12
+ */
13
+ import type MagicString from 'magic-string';
14
+ import type { TrackedOriginInstance } from './attrs-origin-transform';
15
+ /**
16
+ * Parsed destructuring pattern from origin
17
+ */
18
+ export interface OriginDestructure {
19
+ /** Full match start position */
20
+ startPos: number;
21
+ /** Full match end position */
22
+ endPos: number;
23
+ /** The source variable being destructured from */
24
+ sourceVar: string;
25
+ /** Whether destructuring from .props (e.g., counter.props) */
26
+ isPropsAccess: boolean;
27
+ /** Destructured method names (need this binding) */
28
+ methods: DestructuredItem[];
29
+ /** Destructured props (need reactive access) */
30
+ props: DestructuredProp[];
31
+ /** Props pattern within nested `props: { ... }` */
32
+ nestedPropsPattern: NestedPropsPattern | null;
33
+ }
34
+ export interface DestructuredItem {
35
+ /** Original key in the origin */
36
+ key: string;
37
+ /** Alias if renamed (e.g., `increment: inc`) */
38
+ alias: string | null;
39
+ /** Default value if provided */
40
+ defaultValue: string | null;
41
+ }
42
+ export interface DestructuredProp extends DestructuredItem {
43
+ /** Whether $bindable() was used in the default */
44
+ isBindable: boolean;
45
+ /** The value inside $bindable() if bindable */
46
+ bindableDefault: string | null;
47
+ }
48
+ export interface NestedPropsPattern {
49
+ /** Start of the `props: { ... }` pattern */
50
+ startPos: number;
51
+ /** End of the `props: { ... }` pattern */
52
+ endPos: number;
53
+ /** Props within the nested pattern */
54
+ props: DestructuredProp[];
55
+ }
56
+ /**
57
+ * Transform origin destructuring patterns in the source.
58
+ *
59
+ * Tracks origin instances created via $attrs.origin() or direct factory calls,
60
+ * then transforms destructuring patterns that reference them.
61
+ */
62
+ export declare function transformOriginDestructuring(s: MagicString, source: string, originInstances: Map<string, TrackedOriginInstance>): boolean;
@@ -0,0 +1,87 @@
1
+ /**
2
+ * Reserved keyword handling for generated code.
3
+ *
4
+ * JavaScript/TypeScript reserved keywords cannot be used as bare identifiers
5
+ * in destructuring patterns. When a prop name is a reserved keyword (like 'class'),
6
+ * we need to use a renamed internal variable.
7
+ *
8
+ * Example:
9
+ * ```ts
10
+ * // This is INVALID:
11
+ * let { class = '' } = $props()
12
+ *
13
+ * // This is VALID:
14
+ * let { class: ___class = '' } = $props()
15
+ * ```
16
+ */
17
+ /**
18
+ * Check if a string is a reserved keyword that needs renaming
19
+ */
20
+ export declare function isReservedKeyword(name: string): boolean;
21
+ /**
22
+ * Get the internal variable name for a prop.
23
+ *
24
+ * For reserved keywords and collision prevention, we prefix with `___`.
25
+ * This ensures the generated code is valid JavaScript.
26
+ *
27
+ * @param propName The original prop name
28
+ * @param forcePrefix If true, always add prefix (for collision prevention)
29
+ * @returns The internal variable name to use
30
+ *
31
+ * @example
32
+ * getInternalVarName('class') // '___class'
33
+ * getInternalVarName('value') // '___value'
34
+ * getInternalVarName('count', true) // '___count'
35
+ */
36
+ export declare function getInternalVarName(propName: string, forcePrefix?: boolean): string;
37
+ /**
38
+ * Generate the prop destructuring part for a single prop.
39
+ * Handles reserved keywords by using property renaming.
40
+ *
41
+ * @param propName The original prop name
42
+ * @param defaultValue The default value expression (already formatted)
43
+ * @returns The destructuring part for this prop
44
+ *
45
+ * @example
46
+ * // Reserved keyword
47
+ * generatePropDestructure('class', "''")
48
+ * // Returns: "class: ___class = ''"
49
+ *
50
+ * // Normal prop
51
+ * generatePropDestructure('value', '$bindable()')
52
+ * // Returns: "value: ___value = $bindable()"
53
+ */
54
+ export declare function generatePropDestructure(propName: string, defaultValue: string): string;
55
+ /**
56
+ * Generate the prop destructuring part for a prop without a default value.
57
+ *
58
+ * @param propName The original prop name
59
+ * @returns The destructuring part for this prop
60
+ *
61
+ * @example
62
+ * generatePropDestructureNoDefault('class')
63
+ * // Returns: "class: ___class"
64
+ */
65
+ export declare function generatePropDestructureNoDefault(propName: string): string;
66
+ /**
67
+ * Generate a getter for the reactive attrs wrapper.
68
+ *
69
+ * @param propName The original prop name
70
+ * @returns The getter definition
71
+ *
72
+ * @example
73
+ * generateGetter('class')
74
+ * // Returns: "get class() { return ___class }"
75
+ */
76
+ export declare function generateGetter(propName: string): string;
77
+ /**
78
+ * Generate a setter for the reactive attrs wrapper.
79
+ *
80
+ * @param propName The original prop name
81
+ * @returns The setter definition
82
+ *
83
+ * @example
84
+ * generateSetter('class')
85
+ * // Returns: "set class(v) { ___class = v }"
86
+ */
87
+ export declare function generateSetter(propName: string): string;
@@ -64,12 +64,16 @@ export declare function parseAttrsSchemaFromSource(source: string, exportName: s
64
64
  * to the factory type. This approach is required for svelte-check to properly
65
65
  * infer component props from the origin factory definition.
66
66
  *
67
+ * All props use internal variable names (prefixed with ___) to:
68
+ * 1. Avoid reserved keyword conflicts (e.g., 'class' -> 'class: ___class')
69
+ * 2. Prevent accidental naming collisions with user code
70
+ *
67
71
  * @example
68
72
  * generatePropsDestructuring([
69
- * { key: 'label', defaultValue: "'Counter'", bindable: false, hasDefault: true },
73
+ * { key: 'class', defaultValue: "''", bindable: false, hasDefault: true },
70
74
  * { key: 'count', defaultValue: '0', bindable: true, hasDefault: true }
71
75
  * ], 'Counter')
72
- * // Returns: "let { label = 'Counter', count = $bindable(0) }: $attrs.Of<typeof Counter> = $props()"
76
+ * // Returns: "let { class: ___class = '', count: ___count = $bindable(0) }: $attrs.Of<typeof Counter> = $props()"
73
77
  */
74
78
  export declare function generatePropsDestructuring(attrs: ParsedAttrInfo[], factoryName: string): string;
75
79
  /**
@@ -77,12 +81,15 @@ export declare function generatePropsDestructuring(attrs: ParsedAttrInfo[], fact
77
81
  * For bindable attrs, we create getters AND setters to maintain two-way binding.
78
82
  * For non-bindable attrs, we only create getters.
79
83
  *
84
+ * Getters/setters reference internal variable names (___key) that were
85
+ * destructured from $props().
86
+ *
80
87
  * @example
81
88
  * generateFactoryCallFromAttrs('Counter', [
82
- * { key: 'label', defaultValue: "'Counter'", bindable: false, hasDefault: true },
89
+ * { key: 'class', defaultValue: "''", bindable: false, hasDefault: true },
83
90
  * { key: 'count', defaultValue: '0', bindable: true, hasDefault: true }
84
91
  * ])
85
- * // Returns: "Counter({ get label() { return label }, get count() { return count }, set count(v) { count = v } })"
92
+ * // Returns: "Counter({ get class() { return ___class }, get count() { return ___count }, set count(v) { ___count = v } })"
86
93
  */
87
94
  export declare function generateFactoryCallFromAttrs(factoryName: string, attrs: ParsedAttrInfo[]): string;
88
95
  /**
package/dist/vite-dts.js CHANGED
@@ -200,6 +200,79 @@ function findMatchingBracket(source, openIndex, openChar = "(", closeChar = ")")
200
200
  return -1;
201
201
  }
202
202
 
203
+ // src/transform/reserved-keywords.ts
204
+ var RESERVED_KEYWORDS = new Set([
205
+ "break",
206
+ "case",
207
+ "catch",
208
+ "continue",
209
+ "debugger",
210
+ "default",
211
+ "delete",
212
+ "do",
213
+ "else",
214
+ "finally",
215
+ "for",
216
+ "function",
217
+ "if",
218
+ "in",
219
+ "instanceof",
220
+ "new",
221
+ "return",
222
+ "switch",
223
+ "this",
224
+ "throw",
225
+ "try",
226
+ "typeof",
227
+ "var",
228
+ "void",
229
+ "while",
230
+ "with",
231
+ "class",
232
+ "const",
233
+ "enum",
234
+ "export",
235
+ "extends",
236
+ "import",
237
+ "super",
238
+ "implements",
239
+ "interface",
240
+ "let",
241
+ "package",
242
+ "private",
243
+ "protected",
244
+ "public",
245
+ "static",
246
+ "yield",
247
+ "await",
248
+ "async",
249
+ "true",
250
+ "false",
251
+ "null",
252
+ "undefined",
253
+ "arguments",
254
+ "eval"
255
+ ]);
256
+ function getInternalVarName(propName, forcePrefix = true) {
257
+ return `___${propName}`;
258
+ }
259
+ function generatePropDestructure(propName, defaultValue) {
260
+ const internalName = getInternalVarName(propName);
261
+ return `${propName}: ${internalName} = ${defaultValue}`;
262
+ }
263
+ function generatePropDestructureNoDefault(propName) {
264
+ const internalName = getInternalVarName(propName);
265
+ return `${propName}: ${internalName}`;
266
+ }
267
+ function generateGetter(propName) {
268
+ const internalName = getInternalVarName(propName);
269
+ return `get ${propName}() { return ${internalName} }`;
270
+ }
271
+ function generateSetter(propName) {
272
+ const internalName = getInternalVarName(propName);
273
+ return `set ${propName}(v) { ${internalName} = v }`;
274
+ }
275
+
203
276
  // src/transform/schema.ts
204
277
  function parseOriginSchemaFromSource(source, exportName) {
205
278
  const sourceResult = parseSourceOrigin(source, exportName);
@@ -538,14 +611,14 @@ function generatePropsDestructuring(attrs, factoryName) {
538
611
  for (const attr of attrs) {
539
612
  if (attr.bindable) {
540
613
  if (attr.hasDefault) {
541
- parts.push(`${attr.key} = $bindable(${attr.defaultValue})`);
614
+ parts.push(generatePropDestructure(attr.key, `$bindable(${attr.defaultValue})`));
542
615
  } else {
543
- parts.push(`${attr.key} = $bindable()`);
616
+ parts.push(generatePropDestructure(attr.key, "$bindable()"));
544
617
  }
545
618
  } else if (attr.hasDefault) {
546
- parts.push(`${attr.key} = ${attr.defaultValue}`);
619
+ parts.push(generatePropDestructure(attr.key, attr.defaultValue));
547
620
  } else {
548
- parts.push(attr.key);
621
+ parts.push(generatePropDestructureNoDefault(attr.key));
549
622
  }
550
623
  }
551
624
  return `let { ${parts.join(", ")} }: $attrs.Of<typeof ${factoryName}> = $props()`;
@@ -553,9 +626,9 @@ function generatePropsDestructuring(attrs, factoryName) {
553
626
  function generateFactoryCallFromAttrs(factoryName, attrs) {
554
627
  const parts = [];
555
628
  for (const attr of attrs) {
556
- parts.push(`get ${attr.key}() { return ${attr.key} }`);
629
+ parts.push(generateGetter(attr.key));
557
630
  if (attr.bindable) {
558
- parts.push(`set ${attr.key}(v) { ${attr.key} = v }`);
631
+ parts.push(generateSetter(attr.key));
559
632
  }
560
633
  }
561
634
  return `${factoryName}({ ${parts.join(", ")} })`;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "svelte-origin",
3
- "version": "1.0.0-next.22",
3
+ "version": "1.0.0-next.24",
4
4
  "description": "Compiler-assisted state and prop ergonomics for Svelte 5",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",