@barefootjs/xslate 0.35.2 → 0.35.3

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.
@@ -188214,7 +188214,7 @@ function generateDerivedMemoSeed(ctx, ir) {
188214
188214
  }
188215
188215
 
188216
188216
  // src/adapter/props/prop-classes.ts
188217
- import { collectLoopBoundNames } from "@barefootjs/jsx";
188217
+ import { collectLoopBoundNames, resolveBodyDestructuredPropAliases } from "@barefootjs/jsx";
188218
188218
 
188219
188219
  // src/adapter/value/parsed-literal.ts
188220
188220
  import { evalStringArrayJoin } from "@barefootjs/jsx";
@@ -188246,6 +188246,10 @@ function collectStringValueNames(ir) {
188246
188246
  if (isStringTypeInfo(p.type))
188247
188247
  names.add(p.name);
188248
188248
  }
188249
+ for (const [local, callerKey] of resolveBodyDestructuredPropAliases(ir.metadata.localConstants ?? [], ir.metadata.propsObjectName)) {
188250
+ if (names.has(callerKey))
188251
+ names.add(local);
188252
+ }
188249
188253
  for (const c of ir.metadata.localConstants) {
188250
188254
  if (isStringTypeInfo(c.type ?? undefined) || isBareStringLiteral(c.value))
188251
188255
  names.add(c.name);
@@ -46,6 +46,20 @@ export declare function collectNullableOptionalProps(ir: ComponentIR): Set<strin
46
46
  * elsewhere in the component) but safe: the suppressed case just falls
47
47
  * back to today's numeric `+` — the same, already-accepted residual as an
48
48
  * unresolvable operand — never silently-wrong output.
49
+ *
50
+ * A bare-props-form component's BODY-destructured, RENAMED prop (`const {
51
+ * fallbackLabel: skipLabel } = props`, the #2788 alias family) has no
52
+ * `propsParams` entry of its own — `propsParams` only carries the TYPE-level,
53
+ * caller-facing names, and the local alias never appears there. Without the
54
+ * alias resolved here too, a string-typed prop referenced only under its
55
+ * local rename in a `+` concat (`greeting + skipLabel`) is invisible to this
56
+ * witness, so `isStringConcatBinary` falls through to numeric `+` instead of
57
+ * Kolon's `~` (#2894 sibling gap, surfaced by the `string-concat-plus-
58
+ * renamed-prop` fixture — same bug class as #2883/go-template's fix).
59
+ * `resolveBodyDestructuredPropAliases` already recognizes this exact
60
+ * destructuring shape; reusing it here keeps this one witness the single
61
+ * source of truth `_isStringValueName` reads, rather than growing a second,
62
+ * adapter-local alias lookup.
49
63
  */
50
64
  export declare function collectStringValueNames(ir: ComponentIR): Set<string>;
51
65
  //# sourceMappingURL=prop-classes.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"prop-classes.d.ts","sourceRoot":"","sources":["../../../src/adapter/props/prop-classes.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAyB,KAAK,WAAW,EAAE,MAAM,iBAAiB,CAAA;AAGzE;;;;;GAKG;AACH,wBAAgB,wBAAwB,CAAC,EAAE,EAAE,WAAW,GAAG,GAAG,CAAC,MAAM,CAAC,CAMrE;AAED;;;;;GAKG;AACH,wBAAgB,4BAA4B,CAAC,EAAE,EAAE,WAAW,GAAG,GAAG,CAAC,MAAM,CAAC,CAWzE;AAED;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,wBAAgB,uBAAuB,CAAC,EAAE,EAAE,WAAW,GAAG,GAAG,CAAC,MAAM,CAAC,CAepE"}
1
+ {"version":3,"file":"prop-classes.d.ts","sourceRoot":"","sources":["../../../src/adapter/props/prop-classes.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAA6D,KAAK,WAAW,EAAE,MAAM,iBAAiB,CAAA;AAG7G;;;;;GAKG;AACH,wBAAgB,wBAAwB,CAAC,EAAE,EAAE,WAAW,GAAG,GAAG,CAAC,MAAM,CAAC,CAMrE;AAED;;;;;GAKG;AACH,wBAAgB,4BAA4B,CAAC,EAAE,EAAE,WAAW,GAAG,GAAG,CAAC,MAAM,CAAC,CAWzE;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuCG;AACH,wBAAgB,uBAAuB,CAAC,EAAE,EAAE,WAAW,GAAG,GAAG,CAAC,MAAM,CAAC,CAqBpE"}
package/dist/index.js CHANGED
@@ -188214,7 +188214,7 @@ function generateDerivedMemoSeed(ctx, ir) {
188214
188214
  }
188215
188215
 
188216
188216
  // src/adapter/props/prop-classes.ts
188217
- import { collectLoopBoundNames } from "@barefootjs/jsx";
188217
+ import { collectLoopBoundNames, resolveBodyDestructuredPropAliases } from "@barefootjs/jsx";
188218
188218
 
188219
188219
  // src/adapter/value/parsed-literal.ts
188220
188220
  import { evalStringArrayJoin } from "@barefootjs/jsx";
@@ -188246,6 +188246,10 @@ function collectStringValueNames(ir) {
188246
188246
  if (isStringTypeInfo(p.type))
188247
188247
  names.add(p.name);
188248
188248
  }
188249
+ for (const [local, callerKey] of resolveBodyDestructuredPropAliases(ir.metadata.localConstants ?? [], ir.metadata.propsObjectName)) {
188250
+ if (names.has(callerKey))
188251
+ names.add(local);
188252
+ }
188249
188253
  for (const c of ir.metadata.localConstants) {
188250
188254
  if (isStringTypeInfo(c.type ?? undefined) || isBareStringLiteral(c.value))
188251
188255
  names.add(c.name);
package/dist/vite.js CHANGED
@@ -2175,6 +2175,20 @@ function propsDestructureBinding(p) {
2175
2175
  const binding = callerKey === localName ? localName : `${isIdentifierName(callerKey) ? callerKey : JSON.stringify(callerKey)}: ${localName}`;
2176
2176
  return p.defaultValue ? `${binding} = ${p.defaultValue}` : binding;
2177
2177
  }
2178
+ function resolveBodyDestructuredPropAliases(localConstants, propsObjectName) {
2179
+ const aliases = new Map;
2180
+ if (propsObjectName === null)
2181
+ return aliases;
2182
+ for (const c of localConstants) {
2183
+ if (c.isModule)
2184
+ continue;
2185
+ const m = c.parsed;
2186
+ if (m?.kind === "member" && !m.computed && m.object.kind === "identifier" && m.object.name === propsObjectName) {
2187
+ aliases.set(c.name, m.property);
2188
+ }
2189
+ }
2190
+ return aliases;
2191
+ }
2178
2192
  var EMPTY_SET = new Set;
2179
2193
 
2180
2194
  // ../jsx/src/ir-to-client-js/csr-substitute.ts
@@ -3421,8 +3435,11 @@ function matchSearchParamsMethodCall(callee, args, localNames) {
3421
3435
  // ../jsx/src/ir-to-client-js/prune-unused-prop-extractions.ts
3422
3436
  import ts19 from "typescript";
3423
3437
 
3424
- // ../jsx/src/ir-to-client-js/control-flow/plan/lazy-preamble.ts
3438
+ // ../jsx/src/ir-to-client-js/emit-reactive.ts
3425
3439
  import ts20 from "typescript";
3440
+
3441
+ // ../jsx/src/ir-to-client-js/control-flow/plan/lazy-preamble.ts
3442
+ import ts21 from "typescript";
3426
3443
  var NO_PREAMBLE = {
3427
3444
  lazySafe: true,
3428
3445
  facts: { declaredNames: new Set, freeNames: new Set }
@@ -3471,9 +3488,6 @@ var INERT_BINDING_GLOBALS = new Set([
3471
3488
  "decodeURI"
3472
3489
  ]);
3473
3490
 
3474
- // ../jsx/src/ir-to-client-js/emit-reactive.ts
3475
- import ts21 from "typescript";
3476
-
3477
3491
  // ../jsx/src/ir-to-client-js/control-flow/stringify/event-delegation.ts
3478
3492
  var NON_BUBBLING_EVENTS = new Set([
3479
3493
  "blur",
@@ -6215,6 +6229,10 @@ function collectStringValueNames(ir) {
6215
6229
  if (isStringTypeInfo(p.type))
6216
6230
  names.add(p.name);
6217
6231
  }
6232
+ for (const [local, callerKey] of resolveBodyDestructuredPropAliases(ir.metadata.localConstants ?? [], ir.metadata.propsObjectName)) {
6233
+ if (names.has(callerKey))
6234
+ names.add(local);
6235
+ }
6218
6236
  for (const c of ir.metadata.localConstants) {
6219
6237
  if (isStringTypeInfo(c.type ?? undefined) || isBareStringLiteral(c.value))
6220
6238
  names.add(c.name);
@@ -1,5 +1,5 @@
1
1
  package BarefootJS::Backend::Xslate;
2
- our $VERSION = "0.35.1";
2
+ our $VERSION = "0.35.2";
3
3
  use strict;
4
4
  use warnings;
5
5
  use utf8;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@barefootjs/xslate",
3
- "version": "0.35.2",
3
+ "version": "0.35.3",
4
4
  "description": "Text::Xslate (Kolon) adapter for BarefootJS — compiles IR to .tx templates and ships the Xslate rendering backend; runs under any PSGI/Plack app",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -55,7 +55,7 @@
55
55
  "directory": "packages/adapter-xslate"
56
56
  },
57
57
  "dependencies": {
58
- "@barefootjs/shared": "0.35.2"
58
+ "@barefootjs/shared": "0.35.3"
59
59
  },
60
60
  "peerDependencies": {
61
61
  "@barefootjs/jsx": ">=0.2.0",
@@ -72,9 +72,9 @@
72
72
  },
73
73
  "devDependencies": {
74
74
  "@barefootjs/adapter-tests": "0.1.0",
75
- "@barefootjs/jsx": "0.35.2",
76
- "@barefootjs/vite": "0.35.2",
77
- "@barefootjs/client": "0.35.2",
75
+ "@barefootjs/jsx": "0.35.3",
76
+ "@barefootjs/vite": "0.35.3",
77
+ "@barefootjs/client": "0.35.3",
78
78
  "typescript": "^5.0.0",
79
79
  "vite": "^6.0.0"
80
80
  }
@@ -759,3 +759,33 @@ export function Counter() {
759
759
  expect(template).not.toContain('<link')
760
760
  })
761
761
  })
762
+
763
+ describe('XslateAdapter - collectStringValueNames resolves renamed body-destructured prop aliases (#2894)', () => {
764
+ // Sibling gap to #2883 (Mojolicious) and this same PR's go-template fix:
765
+ // a `+` concat against a bare-props-form BODY-destructured, RENAMED prop
766
+ // (`const { fallbackLabel: skipLabel } = props`, the #2788 alias family)
767
+ // had no witness in `collectStringValueNames`, so `isStringConcatBinary`
768
+ // fell through to Kolon's numeric `+` instead of `~` — Kolon's `+`
769
+ // coerces a non-numeric string operand to `0` (#2176).
770
+ test('a `+` concat against a renamed body-destructured prop lowers to ~, not numeric +', () => {
771
+ const result = compileAndGenerate(`
772
+ 'use client'
773
+ import { createSignal } from '@barefootjs/client'
774
+
775
+ type Todo = { id: number; label: string }
776
+
777
+ export function ConcatRenamedProp(props: { fallbackLabel: string }) {
778
+ const { fallbackLabel: skipLabel } = props
779
+ const [todos] = createSignal<Todo[]>([{ id: 1, label: 'Alpha' }])
780
+ return (
781
+ <ul>
782
+ {todos().map(t => (
783
+ <li key={t.id}>{t.label + skipLabel}</li>
784
+ ))}
785
+ </ul>
786
+ )
787
+ }
788
+ `)
789
+ expect(result.template).toContain('$t.label ~ $skipLabel')
790
+ })
791
+ })
@@ -7,7 +7,7 @@
7
7
  * adapter's `props/prop-types.ts`. No adapter instance state.
8
8
  */
9
9
 
10
- import { collectLoopBoundNames, type ComponentIR } from '@barefootjs/jsx'
10
+ import { collectLoopBoundNames, resolveBodyDestructuredPropAliases, type ComponentIR } from '@barefootjs/jsx'
11
11
  import { isStringTypeInfo, isBareStringLiteral } from '../value/parsed-literal.ts'
12
12
 
13
13
  /**
@@ -68,6 +68,20 @@ export function collectNullableOptionalProps(ir: ComponentIR): Set<string> {
68
68
  * elsewhere in the component) but safe: the suppressed case just falls
69
69
  * back to today's numeric `+` — the same, already-accepted residual as an
70
70
  * unresolvable operand — never silently-wrong output.
71
+ *
72
+ * A bare-props-form component's BODY-destructured, RENAMED prop (`const {
73
+ * fallbackLabel: skipLabel } = props`, the #2788 alias family) has no
74
+ * `propsParams` entry of its own — `propsParams` only carries the TYPE-level,
75
+ * caller-facing names, and the local alias never appears there. Without the
76
+ * alias resolved here too, a string-typed prop referenced only under its
77
+ * local rename in a `+` concat (`greeting + skipLabel`) is invisible to this
78
+ * witness, so `isStringConcatBinary` falls through to numeric `+` instead of
79
+ * Kolon's `~` (#2894 sibling gap, surfaced by the `string-concat-plus-
80
+ * renamed-prop` fixture — same bug class as #2883/go-template's fix).
81
+ * `resolveBodyDestructuredPropAliases` already recognizes this exact
82
+ * destructuring shape; reusing it here keeps this one witness the single
83
+ * source of truth `_isStringValueName` reads, rather than growing a second,
84
+ * adapter-local alias lookup.
71
85
  */
72
86
  export function collectStringValueNames(ir: ComponentIR): Set<string> {
73
87
  const names = new Set<string>()
@@ -79,6 +93,12 @@ export function collectStringValueNames(ir: ComponentIR): Set<string> {
79
93
  for (const p of ir.metadata.propsParams) {
80
94
  if (isStringTypeInfo(p.type)) names.add(p.name)
81
95
  }
96
+ for (const [local, callerKey] of resolveBodyDestructuredPropAliases(
97
+ ir.metadata.localConstants ?? [],
98
+ ir.metadata.propsObjectName,
99
+ )) {
100
+ if (names.has(callerKey)) names.add(local)
101
+ }
82
102
  for (const c of ir.metadata.localConstants) {
83
103
  if (isStringTypeInfo(c.type ?? undefined) || isBareStringLiteral(c.value)) names.add(c.name)
84
104
  }