@barefootjs/jsx 0.18.5 → 0.18.7
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.
- package/dist/adapters/dangerous-inner-html.d.ts +77 -0
- package/dist/adapters/dangerous-inner-html.d.ts.map +1 -0
- package/dist/adapters/loop-bound-names.d.ts +22 -0
- package/dist/adapters/loop-bound-names.d.ts.map +1 -0
- package/dist/adapters/parsed-expr-emitter.d.ts.map +1 -1
- package/dist/analyzer.d.ts.map +1 -1
- package/dist/index.d.ts +14 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +977 -273
- package/dist/ir-to-client-js/collect-elements.d.ts.map +1 -1
- package/dist/ir-to-client-js/control-flow/plan/build-inner-loop.d.ts.map +1 -1
- package/dist/ir-to-client-js/control-flow/plan/build-loop-child-arm.d.ts.map +1 -1
- package/dist/ir-to-client-js/control-flow/plan/build-loop.d.ts.map +1 -1
- package/dist/ir-to-client-js/control-flow/plan/loop-child-arm.d.ts +9 -0
- package/dist/ir-to-client-js/control-flow/plan/loop-child-arm.d.ts.map +1 -1
- package/dist/ir-to-client-js/control-flow/plan/loop.d.ts +9 -0
- package/dist/ir-to-client-js/control-flow/plan/loop.d.ts.map +1 -1
- package/dist/ir-to-client-js/control-flow/shared.d.ts +45 -3
- package/dist/ir-to-client-js/control-flow/shared.d.ts.map +1 -1
- package/dist/ir-to-client-js/control-flow/stringify/loop-child-arm.d.ts.map +1 -1
- package/dist/ir-to-client-js/control-flow/stringify/loop.d.ts +1 -0
- package/dist/ir-to-client-js/control-flow/stringify/loop.d.ts.map +1 -1
- package/dist/ir-to-client-js/control-flow/stringify/reactive-effects.d.ts +10 -0
- package/dist/ir-to-client-js/control-flow/stringify/reactive-effects.d.ts.map +1 -1
- package/dist/ir-to-client-js/control-flow/stringify/skeleton-paths.d.ts +38 -0
- package/dist/ir-to-client-js/control-flow/stringify/skeleton-paths.d.ts.map +1 -0
- package/dist/ir-to-client-js/control-flow/stringify/template-parse.d.ts +19 -0
- package/dist/ir-to-client-js/control-flow/stringify/template-parse.d.ts.map +1 -1
- package/dist/ir-to-client-js/csr-substitute.d.ts +23 -0
- package/dist/ir-to-client-js/csr-substitute.d.ts.map +1 -1
- package/dist/ir-to-client-js/html-template.d.ts +42 -0
- package/dist/ir-to-client-js/html-template.d.ts.map +1 -1
- package/dist/ir-to-client-js/imports.d.ts +2 -2
- package/dist/ir-to-client-js/imports.d.ts.map +1 -1
- package/dist/ir-to-client-js/plan/static-array-child-init.d.ts +20 -1
- package/dist/ir-to-client-js/plan/static-array-child-init.d.ts.map +1 -1
- package/dist/ir-to-client-js/reactivity.d.ts.map +1 -1
- package/dist/ir-to-client-js/stringify/static-array-child-init.d.ts +1 -1
- package/dist/ir-to-client-js/types.d.ts +21 -0
- package/dist/ir-to-client-js/types.d.ts.map +1 -1
- package/dist/jsx-to-ir.d.ts.map +1 -1
- package/dist/signal-init-eval.d.ts +82 -0
- package/dist/signal-init-eval.d.ts.map +1 -0
- package/dist/static-literal.d.ts +45 -0
- package/dist/static-literal.d.ts.map +1 -0
- package/package.json +2 -2
- package/src/__tests__/__snapshots__/doc-examples.test.ts.snap +19 -13
- package/src/__tests__/create-selector.test.ts +110 -0
- package/src/__tests__/csr-template-loop-shadowing.test.ts +214 -0
- package/src/__tests__/dangerous-inner-html-resolver.test.ts +197 -0
- package/src/__tests__/inner-loop-svg-namespace.test.ts +245 -0
- package/src/__tests__/loop-bound-names.test.ts +102 -0
- package/src/__tests__/loop-plan-classification.test.ts +2 -0
- package/src/__tests__/map-function-reference.test.ts +303 -0
- package/src/__tests__/nested-loop-index-param.test.ts +285 -0
- package/src/__tests__/signal-init-eval.test.ts +138 -0
- package/src/__tests__/static-array-inner-loop-index-param.test.ts +180 -0
- package/src/__tests__/static-literal.test.ts +126 -0
- package/src/__tests__/string-concat-identifier.test.ts +55 -0
- package/src/adapters/dangerous-inner-html.ts +186 -0
- package/src/adapters/loop-bound-names.ts +80 -0
- package/src/adapters/parsed-expr-emitter.ts +9 -0
- package/src/analyzer.ts +6 -0
- package/src/index.ts +19 -3
- package/src/ir-to-client-js/collect-elements.ts +15 -3
- package/src/ir-to-client-js/control-flow/plan/build-inner-loop.ts +21 -4
- package/src/ir-to-client-js/control-flow/plan/build-loop-child-arm.ts +13 -1
- package/src/ir-to-client-js/control-flow/plan/build-loop.ts +1 -0
- package/src/ir-to-client-js/control-flow/plan/loop-child-arm.ts +9 -0
- package/src/ir-to-client-js/control-flow/plan/loop.ts +9 -0
- package/src/ir-to-client-js/control-flow/shared.ts +103 -6
- package/src/ir-to-client-js/control-flow/stringify/inner-loop.ts +11 -2
- package/src/ir-to-client-js/control-flow/stringify/loop-child-arm.ts +5 -0
- package/src/ir-to-client-js/control-flow/stringify/loop.ts +53 -10
- package/src/ir-to-client-js/control-flow/stringify/reactive-effects.ts +25 -4
- package/src/ir-to-client-js/control-flow/stringify/skeleton-paths.ts +70 -0
- package/src/ir-to-client-js/control-flow/stringify/template-parse.ts +25 -1
- package/src/ir-to-client-js/csr-substitute.ts +53 -0
- package/src/ir-to-client-js/html-template.ts +235 -2
- package/src/ir-to-client-js/imports.ts +1 -0
- package/src/ir-to-client-js/plan/build-static-array-child-init.ts +12 -1
- package/src/ir-to-client-js/plan/static-array-child-init.ts +20 -1
- package/src/ir-to-client-js/reactivity.ts +6 -0
- package/src/ir-to-client-js/stringify/static-array-child-init.ts +11 -6
- package/src/ir-to-client-js/types.ts +21 -0
- package/src/jsx-to-ir.ts +230 -39
- package/src/signal-init-eval.ts +165 -0
- package/src/static-literal.ts +128 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/ir-to-client-js/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EACV,yBAAyB,EACzB,oBAAoB,EACrB,MAAM,0BAA0B,CAAA;AACjC,OAAO,KAAK,EACV,QAAQ,EACR,OAAO,EACP,oBAAoB,EACpB,UAAU,EACV,QAAQ,EACR,UAAU,EACV,WAAW,EACX,iBAAiB,EACjB,YAAY,EACZ,YAAY,EACZ,SAAS,EACT,aAAa,EACb,UAAU,EACX,MAAM,aAAa,CAAA;AACpB,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAA;
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/ir-to-client-js/types.ts"],"names":[],"mappings":"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"}
|
package/dist/jsx-to-ir.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"jsx-to-ir.d.ts","sourceRoot":"","sources":["../src/jsx-to-ir.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,EACL,KAAK,MAAM,EA0BZ,MAAM,YAAY,CAAA;AACnB,OAAO,EAAE,KAAK,eAAe,EAA0E,MAAM,uBAAuB,CAAA;
|
|
1
|
+
{"version":3,"file":"jsx-to-ir.d.ts","sourceRoot":"","sources":["../src/jsx-to-ir.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,EACL,KAAK,MAAM,EA0BZ,MAAM,YAAY,CAAA;AACnB,OAAO,EAAE,KAAK,eAAe,EAA0E,MAAM,uBAAuB,CAAA;AAsqBpI,wBAAgB,OAAO,CAAC,QAAQ,EAAE,eAAe,GAAG,MAAM,GAAG,IAAI,CAIhE"}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TEST-HARNESS ONLY. Evaluate a signal initializer / prop-default source
|
|
3
|
+
* expression against a mock `props` object by EXECUTING it (`new
|
|
4
|
+
* Function`, with `undefined` shadowing the globals listed below), the
|
|
5
|
+
* same way the Hono/CSR conformance reference produces its value — by
|
|
6
|
+
* actually running the component. Never call this from a build path (`bf
|
|
7
|
+
* build`, `compileJSX`, any adapter's `generate`); it exists only so each
|
|
8
|
+
* adapter's `test-render.ts` conformance harness can seed a signal/
|
|
9
|
+
* prop-default for a non-JS-runtime SSR render (PHP/Ruby/Python/Perl/Go)
|
|
10
|
+
* that matches what Hono would compute. (#2209)
|
|
11
|
+
*
|
|
12
|
+
* NOT a security sandbox — the global shadowing below is a determinism
|
|
13
|
+
* tripwire (catches the common accidental-nondeterminism case, e.g.
|
|
14
|
+
* `Date.now()`), not containment: a sufficiently creative expression can
|
|
15
|
+
* still reach the real global scope (`new Function` bodies execute
|
|
16
|
+
* unlexically-scoped, so e.g. `[].constructor.constructor('return
|
|
17
|
+
* Date')()` recovers `Date` even though the bare name is shadowed, and
|
|
18
|
+
* `eval` can't be shadowed at all — JS forbids declaring or binding a
|
|
19
|
+
* parameter literally named `eval` in strict-mode code). Do not widen this
|
|
20
|
+
* module's use to anything but first-party fixture source. The actual
|
|
21
|
+
* trust boundary is that the evaluated text is first-party fixture
|
|
22
|
+
* source, already compiled by this same process — the conformance harness
|
|
23
|
+
* already executes fixture-derived code far more invasively (spawning
|
|
24
|
+
* `ruby`/`php`/`perl`/`go run` on generated programs). This module is
|
|
25
|
+
* never reachable from anything a real end user's untrusted input could
|
|
26
|
+
* influence.
|
|
27
|
+
*
|
|
28
|
+
* Why real execution instead of a hand-rolled evaluator: the initializer
|
|
29
|
+
* source is an arbitrary JS-subset expression over `props` (e.g. `(props.x
|
|
30
|
+
* ?? []).map(t => ({ ...t, editing: false }))`, #2209's actual repro) —
|
|
31
|
+
* every previous approach here was a regex/pattern-match over a small
|
|
32
|
+
* catalogue of recognized shapes (`props.x`, `props.x ?? default`, a bare
|
|
33
|
+
* literal), and #2209 is literally "the catalogue missed a shape" (the
|
|
34
|
+
* THIRD such miss on this codebase, per the superseded
|
|
35
|
+
* `evaluate-signal-init.test.ts`'s own #1672 pins). A hand-written
|
|
36
|
+
* evaluator over `ParsedExpr` would face the same drift, and can't
|
|
37
|
+
* represent object spread (`{ ...t, editing: false }`) without extending
|
|
38
|
+
* `ParsedExpr` — a production-compiler change that ripples into every
|
|
39
|
+
* adapter's exhaustive switch, disproportionate for a test-only need.
|
|
40
|
+
* `new Function` delegates parsing to the JS engine itself — CLAUDE.md's
|
|
41
|
+
* regex-parsing ban exists precisely to avoid the false-match/missed-shape
|
|
42
|
+
* failure mode this replaces.
|
|
43
|
+
*
|
|
44
|
+
* Shadowed as `undefined` (best-effort determinism, not containment — see
|
|
45
|
+
* above): `globalThis`, `window`, `document`, `Date`, `Math`, `crypto`,
|
|
46
|
+
* `performance`, `fetch`, `setTimeout`, `setInterval`, `require`,
|
|
47
|
+
* `process`, `Function`. (`eval` is deliberately absent from this list —
|
|
48
|
+
* it cannot be shadowed as a parameter name in strict-mode code; see
|
|
49
|
+
* above.)
|
|
50
|
+
*
|
|
51
|
+
* `props` bare-identifier destructured params (`createSignal(count)` where
|
|
52
|
+
* `count` is a destructured prop, not a `props.x` member) are NOT bound —
|
|
53
|
+
* the evaluator only exposes `props` — so such an initializer throws
|
|
54
|
+
* `ReferenceError` and falls back to "unset", matching every prior
|
|
55
|
+
* evaluator's behavior for that shape. Extending the environment with
|
|
56
|
+
* `ir.metadata.propsParams` bindings is a natural follow-up if a fixture
|
|
57
|
+
* ever needs it.
|
|
58
|
+
*/
|
|
59
|
+
export type SignalInitEvalResult = {
|
|
60
|
+
ok: true;
|
|
61
|
+
value: unknown;
|
|
62
|
+
} | {
|
|
63
|
+
ok: false;
|
|
64
|
+
};
|
|
65
|
+
/**
|
|
66
|
+
* Evaluate `expr` (a JS-subset source expression) against `props`. Returns
|
|
67
|
+
* `{ ok: false }` when the expression fails to parse, throws at evaluation
|
|
68
|
+
* time (e.g. a `ReferenceError` for an unbound identifier), or evaluates to
|
|
69
|
+
* something the downstream serializers can't marshal (see
|
|
70
|
+
* {@link isTransportable}).
|
|
71
|
+
*/
|
|
72
|
+
export declare function tryEvaluateSignalInit(expr: string, props?: Record<string, unknown>): SignalInitEvalResult;
|
|
73
|
+
/**
|
|
74
|
+
* Drop-in replacement for the harnesses' former per-adapter regex
|
|
75
|
+
* evaluator: `null` means "could not evaluate, or evaluated to
|
|
76
|
+
* `undefined` — leave the signal/default unseeded", matching every prior
|
|
77
|
+
* evaluator's convention (an explicit JS `null` initializer also maps to
|
|
78
|
+
* `null` — the same "skip" outcome, since none of these harnesses
|
|
79
|
+
* distinguish "explicitly null" from "unset" downstream).
|
|
80
|
+
*/
|
|
81
|
+
export declare function evaluateSignalInit(expr: string, props?: Record<string, unknown>): unknown;
|
|
82
|
+
//# sourceMappingURL=signal-init-eval.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"signal-init-eval.d.ts","sourceRoot":"","sources":["../src/signal-init-eval.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAyDG;AAkBH,MAAM,MAAM,oBAAoB,GAAG;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,KAAK,EAAE,OAAO,CAAA;CAAE,GAAG;IAAE,EAAE,EAAE,KAAK,CAAA;CAAE,CAAA;AAqC/E;;;;;;GAMG;AACH,wBAAgB,qBAAqB,CACnC,IAAI,EAAE,MAAM,EACZ,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC9B,oBAAoB,CA6BtB;AAED;;;;;;;GAOG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAGzF"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Fully compile-time-known literal evaluation (#2208). A `ParsedExpr` that
|
|
3
|
+
* is a literal, a no-substitution (or fully-static) template literal, an
|
|
4
|
+
* array-literal of pure elements, or an object-literal of pure values
|
|
5
|
+
* evaluates here to its plain JS value. Consumed by each adapter's
|
|
6
|
+
* `renderLoop` to admit a function-scope local const whose initializer is
|
|
7
|
+
* entirely known at compile time as a loop source — inlining its value the
|
|
8
|
+
* same way a module-scope const already is — while still refusing a
|
|
9
|
+
* runtime-computed expression (`Object.entries(props.tags).filter(...)`,
|
|
10
|
+
* #2069) with BF101, since `call`/unresolvable-`member` shapes fall through
|
|
11
|
+
* to `null` below.
|
|
12
|
+
*
|
|
13
|
+
* Analysis only: this module never emits template syntax. Each adapter
|
|
14
|
+
* serializes the resolved JS value into its own native literal syntax
|
|
15
|
+
* (`packages/adapter-<name>/src/adapter/lib/static-value.ts`).
|
|
16
|
+
*/
|
|
17
|
+
import type { ParsedExpr } from './expression-parser.ts';
|
|
18
|
+
import type { ConstantInfo } from './types.ts';
|
|
19
|
+
/**
|
|
20
|
+
* Recursively evaluate a `ParsedExpr` that is a fully compile-time-known
|
|
21
|
+
* literal to its JS value. `bindings` lets a caller resolve identifiers
|
|
22
|
+
* (and member reads off them) against already-evaluated values — e.g. the
|
|
23
|
+
* Go adapter binding a loop's item parameter to one already-resolved array
|
|
24
|
+
* element while baking per-item child-component props. Returns `null` when
|
|
25
|
+
* the expression is not statically known (depends on a prop, signal,
|
|
26
|
+
* function call, or an identifier absent from `bindings`).
|
|
27
|
+
*/
|
|
28
|
+
export declare function evaluateStaticLiteral(expr: ParsedExpr, bindings?: ReadonlyMap<string, unknown>): {
|
|
29
|
+
value: unknown;
|
|
30
|
+
} | null;
|
|
31
|
+
/** `true` iff {@link evaluateStaticLiteral} resolves `expr` with no bindings. */
|
|
32
|
+
export declare function isFullyStaticLiteral(expr: ParsedExpr): boolean;
|
|
33
|
+
/**
|
|
34
|
+
* Shared loop-source resolution for `renderLoop` across adapters: the loop
|
|
35
|
+
* array is either an inline array-literal, or a bare identifier naming a
|
|
36
|
+
* FUNCTION-scope (`!isModule`) local const whose initializer evaluates
|
|
37
|
+
* statically. Module-scope consts are deliberately excluded — an existing,
|
|
38
|
+
* separate seeding path already handles those. Returns the evaluated items,
|
|
39
|
+
* or `null` if the source isn't resolvable this way (including when it
|
|
40
|
+
* resolves to something other than an array).
|
|
41
|
+
*/
|
|
42
|
+
export declare function resolveStaticLoopSource(arrayParsed: ParsedExpr | undefined, localConstants: ReadonlyArray<ConstantInfo> | undefined, opts?: {
|
|
43
|
+
isNameShadowed?: (name: string) => boolean;
|
|
44
|
+
}): unknown[] | null;
|
|
45
|
+
//# sourceMappingURL=static-literal.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"static-literal.d.ts","sourceRoot":"","sources":["../src/static-literal.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAA;AACxD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAA;AAE9C;;;;;;;;GAQG;AACH,wBAAgB,qBAAqB,CACnC,IAAI,EAAE,UAAU,EAChB,QAAQ,CAAC,EAAE,WAAW,CAAC,MAAM,EAAE,OAAO,CAAC,GACtC;IAAE,KAAK,EAAE,OAAO,CAAA;CAAE,GAAG,IAAI,CA+D3B;AAED,iFAAiF;AACjF,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,UAAU,GAAG,OAAO,CAE9D;AAED;;;;;;;;GAQG;AACH,wBAAgB,uBAAuB,CACrC,WAAW,EAAE,UAAU,GAAG,SAAS,EACnC,cAAc,EAAE,aAAa,CAAC,YAAY,CAAC,GAAG,SAAS,EACvD,IAAI,CAAC,EAAE;IAAE,cAAc,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAA;CAAE,GACpD,OAAO,EAAE,GAAG,IAAI,CAYlB"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@barefootjs/jsx",
|
|
3
|
-
"version": "0.18.
|
|
3
|
+
"version": "0.18.7",
|
|
4
4
|
"description": "JSX compiler for BarefootJS - transforms JSX to server HTML + client JS",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -53,7 +53,7 @@
|
|
|
53
53
|
"directory": "packages/jsx"
|
|
54
54
|
},
|
|
55
55
|
"dependencies": {
|
|
56
|
-
"@barefootjs/shared": "0.18.
|
|
56
|
+
"@barefootjs/shared": "0.18.7"
|
|
57
57
|
},
|
|
58
58
|
"peerDependencies": {
|
|
59
59
|
"@barefootjs/client": ">=0.2.0",
|
|
@@ -4351,7 +4351,7 @@ export function Example(_p, __bfKey) { return createComponent('Example', _p, __b
|
|
|
4351
4351
|
`;
|
|
4352
4352
|
|
|
4353
4353
|
exports[`docs/core/adapters/hono-adapter.md doc-examples L190 — (no label) 1`] = `
|
|
4354
|
-
"import { $, $t, __bfText, createComponent, createEffect, createSignal, escapeText, hydrate, mapArray } from '@barefootjs/client/runtime'
|
|
4354
|
+
"import { $, $t, __bfText, createComponent, createEffect, createSignal, escapeText, hydrate, mapArray, tAfter } from '@barefootjs/client/runtime'
|
|
4355
4355
|
|
|
4356
4356
|
export function initTodoItem(__scope, _p = {}) {
|
|
4357
4357
|
if (!__scope) return
|
|
@@ -4408,7 +4408,8 @@ export function initExample(__scope, _p = {}) {
|
|
|
4408
4408
|
__tpl_l0.innerHTML = \`<li data-key=""><!--bf:s0--><!--/--></li>\`
|
|
4409
4409
|
mapArray(() => items(), _s1, (item) => String(item), (item, __idx, __existing) => {
|
|
4410
4410
|
const __el = __existing ?? __tpl_l0.content.firstElementChild.cloneNode(true)
|
|
4411
|
-
|
|
4411
|
+
const __p = __existing ? null : [__el.firstChild]
|
|
4412
|
+
{ const __rt_s0 = __p ? tAfter(__p[0]) : $t(__el, 's0')[0]
|
|
4412
4413
|
if (__rt_s0) createEffect(() => { __rt_s0.textContent = String(item()) }) }
|
|
4413
4414
|
return __el
|
|
4414
4415
|
}, 'l0')
|
|
@@ -4472,7 +4473,7 @@ export function Counter(_p, __bfKey) { return createComponent('Counter', _p, __b
|
|
|
4472
4473
|
`;
|
|
4473
4474
|
|
|
4474
4475
|
exports[`docs/core/adapters/go-template-adapter.md doc-examples L168 — (no label) 1`] = `
|
|
4475
|
-
"import { $, $t, __bfText, createComponent, createEffect, createSignal, escapeText, hydrate, mapArray } from '@barefootjs/client/runtime'
|
|
4476
|
+
"import { $, $t, __bfText, createComponent, createEffect, createSignal, escapeText, hydrate, mapArray, tAfter } from '@barefootjs/client/runtime'
|
|
4476
4477
|
|
|
4477
4478
|
export function initTodoItem(__scope, _p = {}) {
|
|
4478
4479
|
if (!__scope) return
|
|
@@ -4529,7 +4530,8 @@ export function initExample(__scope, _p = {}) {
|
|
|
4529
4530
|
__tpl_l0.innerHTML = \`<li data-key=""><!--bf:s0--><!--/--></li>\`
|
|
4530
4531
|
mapArray(() => items(), _s1, (item) => String(item), (item, __idx, __existing) => {
|
|
4531
4532
|
const __el = __existing ?? __tpl_l0.content.firstElementChild.cloneNode(true)
|
|
4532
|
-
|
|
4533
|
+
const __p = __existing ? null : [__el.firstChild]
|
|
4534
|
+
{ const __rt_s0 = __p ? tAfter(__p[0]) : $t(__el, 's0')[0]
|
|
4533
4535
|
if (__rt_s0) createEffect(() => { __rt_s0.textContent = String(item()) }) }
|
|
4534
4536
|
return __el
|
|
4535
4537
|
}, 'l0')
|
|
@@ -4541,7 +4543,7 @@ export function Example(_p, __bfKey) { return createComponent('Example', _p, __b
|
|
|
4541
4543
|
`;
|
|
4542
4544
|
|
|
4543
4545
|
exports[`docs/core/adapters/go-template-adapter.md doc-examples L180 — (no label) 1`] = `
|
|
4544
|
-
"import { $, $t, __bfText, createComponent, createEffect, createSignal, escapeText, hydrate, mapArray } from '@barefootjs/client/runtime'
|
|
4546
|
+
"import { $, $t, __bfText, createComponent, createEffect, createSignal, escapeText, hydrate, mapArray, tAfter } from '@barefootjs/client/runtime'
|
|
4545
4547
|
|
|
4546
4548
|
export function initTodoItem(__scope, _p = {}) {
|
|
4547
4549
|
if (!__scope) return
|
|
@@ -4598,7 +4600,8 @@ export function initExample(__scope, _p = {}) {
|
|
|
4598
4600
|
__tpl_l0.innerHTML = \`<li data-key=""><!--bf:s0--><!--/--></li>\`
|
|
4599
4601
|
mapArray(() => items().filter(item => item.active), _s1, (item) => String(item.id), (item, __idx, __existing) => {
|
|
4600
4602
|
const __el = __existing ?? __tpl_l0.content.firstElementChild.cloneNode(true)
|
|
4601
|
-
|
|
4603
|
+
const __p = __existing ? null : [__el.firstChild]
|
|
4604
|
+
{ const __rt_s0 = __p ? tAfter(__p[0]) : $t(__el, 's0')[0]
|
|
4602
4605
|
if (__rt_s0) createEffect(() => { __rt_s0.textContent = String(item().name) }) }
|
|
4603
4606
|
return __el
|
|
4604
4607
|
}, 'l0')
|
|
@@ -4700,7 +4703,7 @@ export function initTodoList(__scope, _p = {}) {
|
|
|
4700
4703
|
|
|
4701
4704
|
}
|
|
4702
4705
|
|
|
4703
|
-
hydrate('TodoList', { init: initTodoList, template: (_p) => \`<ul bf="s1"><!--bf-loop:l0-->\${items.map((item) => \`\${renderChild('TodoItem', {}, item.id)}\`).join('')}<!--bf-/loop:l0--></ul>\` })
|
|
4706
|
+
hydrate('TodoList', { init: initTodoList, template: (_p) => \`<ul bf="s1"><!--bf-loop:l0-->\${_p.items.map((item) => \`\${renderChild('TodoItem', {}, item.id)}\`).join('')}<!--bf-/loop:l0--></ul>\` })
|
|
4704
4707
|
export function TodoList(_p, __bfKey) { return createComponent('TodoList', _p, __bfKey) }"
|
|
4705
4708
|
`;
|
|
4706
4709
|
|
|
@@ -5042,7 +5045,7 @@ export function StatementExample(_p, __bfKey) { return createComponent('Statemen
|
|
|
5042
5045
|
`;
|
|
5043
5046
|
|
|
5044
5047
|
exports[`docs/core/advanced/compiler-internals.md doc-examples L126 — (no label) 1`] = `
|
|
5045
|
-
"import { $, $t, __bfText, createComponent, createEffect, createSignal, escapeText, hydrate, mapArray } from '@barefootjs/client/runtime'
|
|
5048
|
+
"import { $, $t, __bfText, createComponent, createEffect, createSignal, escapeText, hydrate, mapArray, tAfter } from '@barefootjs/client/runtime'
|
|
5046
5049
|
|
|
5047
5050
|
export function initTodoItem(__scope, _p = {}) {
|
|
5048
5051
|
if (!__scope) return
|
|
@@ -5099,7 +5102,8 @@ export function initExample(__scope, _p = {}) {
|
|
|
5099
5102
|
__tpl_l0.innerHTML = \`<li data-key=""><!--bf:s0--><!--/--></li>\`
|
|
5100
5103
|
mapArray(() => todos().filter(t => !t.done).toSorted((a, b) => a.date - b.date), _s1, (t) => String(t.id), (t, __idx, __existing) => {
|
|
5101
5104
|
const __el = __existing ?? __tpl_l0.content.firstElementChild.cloneNode(true)
|
|
5102
|
-
|
|
5105
|
+
const __p = __existing ? null : [__el.firstChild]
|
|
5106
|
+
{ const __rt_s0 = __p ? tAfter(__p[0]) : $t(__el, 's0')[0]
|
|
5103
5107
|
if (__rt_s0) createEffect(() => { __rt_s0.textContent = String(t().name) }) }
|
|
5104
5108
|
return __el
|
|
5105
5109
|
}, 'l0')
|
|
@@ -5173,7 +5177,7 @@ export function StatementExample(_p, __bfKey) { return createComponent('Statemen
|
|
|
5173
5177
|
`;
|
|
5174
5178
|
|
|
5175
5179
|
exports[`docs/core/advanced/performance.md doc-examples L67 — ✅ Stable key — DOM nodes reused when list changes 1`] = `
|
|
5176
|
-
"import { $, $t, __bfText, createComponent, createEffect, createSignal, escapeText, hydrate, mapArray } from '@barefootjs/client/runtime'
|
|
5180
|
+
"import { $, $t, __bfText, createComponent, createEffect, createSignal, escapeText, hydrate, mapArray, tAfter } from '@barefootjs/client/runtime'
|
|
5177
5181
|
|
|
5178
5182
|
export function initTodoItem(__scope, _p = {}) {
|
|
5179
5183
|
if (!__scope) return
|
|
@@ -5230,7 +5234,8 @@ export function initExample(__scope, _p = {}) {
|
|
|
5230
5234
|
__tpl_l0.innerHTML = \`<li data-key=""><!--bf:s0--><!--/--></li>\`
|
|
5231
5235
|
mapArray(() => items(), _s1, (item) => String(item.id), (item, __idx, __existing) => {
|
|
5232
5236
|
const __el = __existing ?? __tpl_l0.content.firstElementChild.cloneNode(true)
|
|
5233
|
-
|
|
5237
|
+
const __p = __existing ? null : [__el.firstChild]
|
|
5238
|
+
{ const __rt_s0 = __p ? tAfter(__p[0]) : $t(__el, 's0')[0]
|
|
5234
5239
|
if (__rt_s0) createEffect(() => { __rt_s0.textContent = String(item().name) }) }
|
|
5235
5240
|
return __el
|
|
5236
5241
|
}, 'l0')
|
|
@@ -5242,7 +5247,7 @@ export function Example(_p, __bfKey) { return createComponent('Example', _p, __b
|
|
|
5242
5247
|
`;
|
|
5243
5248
|
|
|
5244
5249
|
exports[`docs/core/advanced/performance.md doc-examples L70 — ❌ Index key — DOM nodes recreated on reorder 1`] = `
|
|
5245
|
-
"import { $, $t, __bfText, createComponent, createEffect, createSignal, escapeText, hydrate, mapArray } from '@barefootjs/client/runtime'
|
|
5250
|
+
"import { $, $t, __bfText, createComponent, createEffect, createSignal, escapeText, hydrate, mapArray, tAfter } from '@barefootjs/client/runtime'
|
|
5246
5251
|
|
|
5247
5252
|
export function initTodoItem(__scope, _p = {}) {
|
|
5248
5253
|
if (!__scope) return
|
|
@@ -5299,7 +5304,8 @@ export function initExample(__scope, _p = {}) {
|
|
|
5299
5304
|
__tpl_l0.innerHTML = \`<li data-key=""><!--bf:s0--><!--/--></li>\`
|
|
5300
5305
|
mapArray(() => items(), _s1, (item, i) => String(i), (item, i, __existing) => {
|
|
5301
5306
|
const __el = __existing ?? __tpl_l0.content.firstElementChild.cloneNode(true)
|
|
5302
|
-
|
|
5307
|
+
const __p = __existing ? null : [__el.firstChild]
|
|
5308
|
+
{ const __rt_s0 = __p ? tAfter(__p[0]) : $t(__el, 's0')[0]
|
|
5303
5309
|
if (__rt_s0) createEffect(() => { __rt_s0.textContent = String(item().name) }) }
|
|
5304
5310
|
return __el
|
|
5305
5311
|
}, 'l0')
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `createSelector` compiler recognition (perf, #2143 gap 5).
|
|
3
|
+
*
|
|
4
|
+
* `createSelector`'s returned accessor is `Reactive<(key) => boolean>`
|
|
5
|
+
* branded exactly like a signal/memo getter, so the existing type-based
|
|
6
|
+
* reactivity analyzer (`reactivity-checker.ts`) recognises a call like
|
|
7
|
+
* `isSelected(row.id)` as reactive with no analyzer changes — the callee's
|
|
8
|
+
* type carries the brand, not the call's return type. These tests pin:
|
|
9
|
+
* - the classic js-framework-benchmark row compiles with `isSelected(row.id)`
|
|
10
|
+
* wired to a single per-row `createEffect` (not the legacy
|
|
11
|
+
* `selected() === row.id` shape, which would still work but subscribes
|
|
12
|
+
* every row to the raw signal)
|
|
13
|
+
* - the loop-param accessor wrap applies only to the call ARGUMENT
|
|
14
|
+
* (`row.id` -> `row().id`), leaving the `isSelected` callee untouched
|
|
15
|
+
* - the hoisted skeleton fast path (#2223) still fires for a selector-driven
|
|
16
|
+
* attr, since it's covered by a loop-child reactive-attr effect like any
|
|
17
|
+
* other dynamic attribute
|
|
18
|
+
* - `createSelector` is pulled into the runtime import line
|
|
19
|
+
* - the attr is auto-deferred out of the SSR-mirror `template:` lambda
|
|
20
|
+
* (mechanism #1638, same as `@barefootjs/form` accessors) — pinned as
|
|
21
|
+
* documented behavior, not a regression: full SSR parity for selector
|
|
22
|
+
* calls is a known follow-up, not in scope here
|
|
23
|
+
*/
|
|
24
|
+
|
|
25
|
+
import { describe, test, expect } from 'bun:test'
|
|
26
|
+
import { compileJSX } from '../compiler'
|
|
27
|
+
import { TestAdapter } from '../adapters/test-adapter'
|
|
28
|
+
|
|
29
|
+
const adapter = new TestAdapter()
|
|
30
|
+
|
|
31
|
+
function compile(source: string, filename: string): { clientJs: string; template: string; errors: readonly { severity: string }[] } {
|
|
32
|
+
const result = compileJSX(source, filename, { adapter })
|
|
33
|
+
const clientJs = result.files.find(f => f.type === 'clientJs')
|
|
34
|
+
const template = result.files.find(f => f.type === 'markedTemplate')
|
|
35
|
+
return { clientJs: clientJs?.content ?? '', template: template?.content ?? '', errors: result.errors }
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
describe('createSelector (perf, #2143 gap 5)', () => {
|
|
39
|
+
test('isSelected(row.id) in a loop body compiles to one per-row createEffect', () => {
|
|
40
|
+
const source = `
|
|
41
|
+
'use client'
|
|
42
|
+
import { createSignal, createSelector } from '@barefootjs/client'
|
|
43
|
+
|
|
44
|
+
interface RowData { id: number; label: string }
|
|
45
|
+
|
|
46
|
+
export function Bench() {
|
|
47
|
+
const [rows, setRows] = createSignal<RowData[]>([])
|
|
48
|
+
const [selected, setSelected] = createSignal<number>(0)
|
|
49
|
+
const isSelected = createSelector(selected)
|
|
50
|
+
return (
|
|
51
|
+
<table>
|
|
52
|
+
<tbody>
|
|
53
|
+
{rows().map(row => (
|
|
54
|
+
<tr key={row.id} className={isSelected(row.id) ? 'danger' : ''}></tr>
|
|
55
|
+
))}
|
|
56
|
+
</tbody>
|
|
57
|
+
</table>
|
|
58
|
+
)
|
|
59
|
+
}
|
|
60
|
+
`
|
|
61
|
+
const { clientJs, errors } = compile(source, 'Bench.tsx')
|
|
62
|
+
expect(errors.filter(e => e.severity === 'error')).toHaveLength(0)
|
|
63
|
+
|
|
64
|
+
// Loop-param wrap applies to the call ARGUMENT only.
|
|
65
|
+
expect(clientJs).toContain('isSelected(row().id)')
|
|
66
|
+
// The callee itself is never rewritten to an accessor call.
|
|
67
|
+
expect(clientJs).not.toContain('isSelected()(')
|
|
68
|
+
|
|
69
|
+
// Exactly one createEffect wraps the selector-driven class attribute —
|
|
70
|
+
// not the O(rows) `selected() === row.id` shape.
|
|
71
|
+
const effectCount = (clientJs.match(/createEffect\(/g) ?? []).length
|
|
72
|
+
expect(effectCount).toBe(1)
|
|
73
|
+
expect(clientJs).not.toContain('selected() ===')
|
|
74
|
+
|
|
75
|
+
// The hoisted skeleton fast path (#2223) still fires: a single-line
|
|
76
|
+
// renderItem clones from a once-per-loop template.
|
|
77
|
+
expect(clientJs).toMatch(/const __tpl_\w+ = document\.createElement\('template'\)/)
|
|
78
|
+
|
|
79
|
+
// createSelector is pulled into the runtime import line.
|
|
80
|
+
expect(clientJs).toMatch(/import \{[^}]*\bcreateSelector\b[^}]*\} from '@barefootjs\/client\/runtime'/)
|
|
81
|
+
})
|
|
82
|
+
|
|
83
|
+
test('selector-driven attr is deferred out of the SSR-mirror template lambda (documented, not a regression)', () => {
|
|
84
|
+
const source = `
|
|
85
|
+
'use client'
|
|
86
|
+
import { createSignal, createSelector } from '@barefootjs/client'
|
|
87
|
+
|
|
88
|
+
interface RowData { id: number; label: string }
|
|
89
|
+
|
|
90
|
+
export function Bench() {
|
|
91
|
+
const [rows, setRows] = createSignal<RowData[]>([])
|
|
92
|
+
const [selected, setSelected] = createSignal<number>(0)
|
|
93
|
+
const isSelected = createSelector(selected)
|
|
94
|
+
return (
|
|
95
|
+
<ul>
|
|
96
|
+
{rows().map(row => (
|
|
97
|
+
<li key={row.id} className={isSelected(row.id) ? 'danger' : ''}>{row.label}</li>
|
|
98
|
+
))}
|
|
99
|
+
</ul>
|
|
100
|
+
)
|
|
101
|
+
}
|
|
102
|
+
`
|
|
103
|
+
const { clientJs } = compile(source, 'BenchDefer.tsx')
|
|
104
|
+
const csrMirror = clientJs.slice(clientJs.indexOf('hydrate('))
|
|
105
|
+
// The class attribute never appears as a literal `class="..."` write in
|
|
106
|
+
// the SSR-mirror template string — it's covered entirely by the
|
|
107
|
+
// per-row createEffect, matching the documented auto-defer mechanism.
|
|
108
|
+
expect(csrMirror).not.toMatch(/class="danger"/)
|
|
109
|
+
})
|
|
110
|
+
})
|
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CSR/client-JS codegen vs loop-param shadowing (#2222).
|
|
3
|
+
*
|
|
4
|
+
* Two related bugs in the `hydrate(...)` `template:` lambda (a
|
|
5
|
+
* module-scope arrow, sibling to `initXxx` — NOT a closure over init's
|
|
6
|
+
* destructured locals):
|
|
7
|
+
*
|
|
8
|
+
* 1. When the loop's array source is a destructured prop, the lambda
|
|
9
|
+
* referenced the bare destructured name (`values.map(...)`) instead of
|
|
10
|
+
* `_p.values` — `ReferenceError: values is not defined` at runtime.
|
|
11
|
+
* Root cause: `transformMapCall`'s plain-`.map()` fallback and the
|
|
12
|
+
* simple-`filter().map()` path bypassed `setArray`, so
|
|
13
|
+
* `IRLoop.templateArray` (the `_p.`-rewritten form the chained paths
|
|
14
|
+
* already produce) stayed `undefined`.
|
|
15
|
+
*
|
|
16
|
+
* 2. Inside a loop callback body in that same lambda, prop/const
|
|
17
|
+
* substitution was scope-blind: an outer destructured prop
|
|
18
|
+
* (`_p.label`) or an inlinable const's literal got substituted at an
|
|
19
|
+
* occurrence that is actually the loop's own shadowing parameter.
|
|
20
|
+
* Same bug class as #2221, different code paths:
|
|
21
|
+
* - prop-shadow: `rewriteBarePropRefs` (IR build) collected prop
|
|
22
|
+
* refs from the expression node alone, never seeing the enclosing
|
|
23
|
+
* loop binding. Fixed scope-accurately via `ctx.loopParams` — the
|
|
24
|
+
* transform position's live loop-param set (includes destructured
|
|
25
|
+
* binding names and the index param).
|
|
26
|
+
* - const-shadow: `irToComponentTemplateWithOpts`'s `transformExpr`
|
|
27
|
+
* regex-inlined `inlinableConstants` across the whole expression
|
|
28
|
+
* text. Fixed by threading the enclosing loops' bound names
|
|
29
|
+
* through `TemplateOptions` and skipping those names.
|
|
30
|
+
*/
|
|
31
|
+
|
|
32
|
+
import { describe, test, expect } from 'bun:test'
|
|
33
|
+
import { compileJSX } from '../compiler'
|
|
34
|
+
import { TestAdapter } from '../adapters/test-adapter'
|
|
35
|
+
|
|
36
|
+
const adapter = new TestAdapter()
|
|
37
|
+
|
|
38
|
+
function clientJsFor(source: string): string {
|
|
39
|
+
const result = compileJSX(source, 'Repro.tsx', { adapter })
|
|
40
|
+
expect(result.errors.filter(e => e.severity === 'error')).toHaveLength(0)
|
|
41
|
+
const clientJs = result.files.find(f => f.type === 'clientJs')
|
|
42
|
+
expect(clientJs).toBeDefined()
|
|
43
|
+
return clientJs!.content
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
function templateLambda(content: string): string {
|
|
47
|
+
const line = content.split('\n').find(l => l.includes('hydrate('))
|
|
48
|
+
expect(line).toBeDefined()
|
|
49
|
+
return line!
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
describe('hydrate template: destructured-prop loop array source (#2222 bug 1)', () => {
|
|
53
|
+
test('plain .map() over a destructured prop references _p.<name>', () => {
|
|
54
|
+
const tpl = templateLambda(clientJsFor(`
|
|
55
|
+
'use client'
|
|
56
|
+
import { createSignal } from '@barefootjs/client'
|
|
57
|
+
export function Widget({ values }: { values: number[] }) {
|
|
58
|
+
const [n, setN] = createSignal(0)
|
|
59
|
+
return (
|
|
60
|
+
<ul data-n={n()} onClick={() => setN(n() + 1)}>
|
|
61
|
+
{values.map((v) => (
|
|
62
|
+
<li key={v}>{v * 2}</li>
|
|
63
|
+
))}
|
|
64
|
+
</ul>
|
|
65
|
+
)
|
|
66
|
+
}
|
|
67
|
+
`))
|
|
68
|
+
|
|
69
|
+
expect(tpl).toContain('_p.values.map((v)')
|
|
70
|
+
expect(tpl).not.toContain('{values.map')
|
|
71
|
+
})
|
|
72
|
+
|
|
73
|
+
test('simple filter().map() over a destructured prop references _p.<name>', () => {
|
|
74
|
+
const tpl = templateLambda(clientJsFor(`
|
|
75
|
+
'use client'
|
|
76
|
+
import { createSignal } from '@barefootjs/client'
|
|
77
|
+
export function Widget({ values }: { values: number[] }) {
|
|
78
|
+
const [n, setN] = createSignal(0)
|
|
79
|
+
return (
|
|
80
|
+
<ul data-n={n()} onClick={() => setN(n() + 1)}>
|
|
81
|
+
{values.filter((v) => v > 0).map((v) => (
|
|
82
|
+
<li key={v}>{v * 2}</li>
|
|
83
|
+
))}
|
|
84
|
+
</ul>
|
|
85
|
+
)
|
|
86
|
+
}
|
|
87
|
+
`))
|
|
88
|
+
|
|
89
|
+
expect(tpl).toContain('_p.values')
|
|
90
|
+
expect(tpl).not.toMatch(/[^.]\bvalues\.filter/)
|
|
91
|
+
})
|
|
92
|
+
})
|
|
93
|
+
|
|
94
|
+
describe('hydrate template: loop param shadowing an outer name (#2222 bug 2)', () => {
|
|
95
|
+
test('prop-shadow: the loop body uses the param, not _p.<name>; outside the loop keeps _p.<name>', () => {
|
|
96
|
+
const tpl = templateLambda(clientJsFor(`
|
|
97
|
+
'use client'
|
|
98
|
+
import { createSignal } from '@barefootjs/client'
|
|
99
|
+
export function Widget2({ label, values }: { label: string; values: number[] }) {
|
|
100
|
+
const [n, setN] = createSignal(0)
|
|
101
|
+
return (
|
|
102
|
+
<div data-n={n()} onClick={() => setN(n() + 1)}>
|
|
103
|
+
<p>{label}</p>
|
|
104
|
+
<ul>
|
|
105
|
+
{values.map((label) => (
|
|
106
|
+
<li key={label}>{1 + label}</li>
|
|
107
|
+
))}
|
|
108
|
+
</ul>
|
|
109
|
+
</div>
|
|
110
|
+
)
|
|
111
|
+
}
|
|
112
|
+
`))
|
|
113
|
+
|
|
114
|
+
// Outside the loop: the prop rewrite applies.
|
|
115
|
+
expect(tpl).toContain('escapeText(_p.label)')
|
|
116
|
+
// Inside the loop: the shadowing param must survive untouched.
|
|
117
|
+
expect(tpl).toContain('escapeText(1 + label)')
|
|
118
|
+
expect(tpl).not.toContain('1 + _p.label')
|
|
119
|
+
expect(tpl).not.toContain('data-key="${_p.label}"')
|
|
120
|
+
})
|
|
121
|
+
|
|
122
|
+
test('const-shadow: the loop body uses the param, not the inlined literal; outside the loop keeps the inline', () => {
|
|
123
|
+
const tpl = templateLambda(clientJsFor(`
|
|
124
|
+
'use client'
|
|
125
|
+
import { createSignal } from '@barefootjs/client'
|
|
126
|
+
export function Widget3({ values }: { values: number[] }) {
|
|
127
|
+
const label: string = 'x'
|
|
128
|
+
const [n, setN] = createSignal(0)
|
|
129
|
+
return (
|
|
130
|
+
<div data-n={n()} onClick={() => setN(n() + 1)}>
|
|
131
|
+
<p>{label}</p>
|
|
132
|
+
<ul>
|
|
133
|
+
{values.map((label) => (
|
|
134
|
+
<li key={label}>{1 + label}</li>
|
|
135
|
+
))}
|
|
136
|
+
</ul>
|
|
137
|
+
</div>
|
|
138
|
+
)
|
|
139
|
+
}
|
|
140
|
+
`))
|
|
141
|
+
|
|
142
|
+
// Outside the loop: const inlining still applies.
|
|
143
|
+
expect(tpl).toContain("${('x')}")
|
|
144
|
+
// Inside the loop: the shadowing param must survive untouched.
|
|
145
|
+
expect(tpl).toContain('escapeText(1 + label)')
|
|
146
|
+
expect(tpl).not.toContain("1 + ('x')")
|
|
147
|
+
expect(tpl).not.toContain('data-key="${`x`}"')
|
|
148
|
+
})
|
|
149
|
+
|
|
150
|
+
test('destructured loop param shadowing a prop is guarded via paramBindings names', () => {
|
|
151
|
+
const tpl = templateLambda(clientJsFor(`
|
|
152
|
+
'use client'
|
|
153
|
+
import { createSignal } from '@barefootjs/client'
|
|
154
|
+
export function Widget4({ name, rows }: { name: string; rows: { name: number }[] }) {
|
|
155
|
+
const [n, setN] = createSignal(0)
|
|
156
|
+
return (
|
|
157
|
+
<ul data-n={n()} onClick={() => setN(n() + 1)}>
|
|
158
|
+
{rows.map(({ name }) => (
|
|
159
|
+
<li key={name}>{1 + name}</li>
|
|
160
|
+
))}
|
|
161
|
+
</ul>
|
|
162
|
+
)
|
|
163
|
+
}
|
|
164
|
+
`))
|
|
165
|
+
|
|
166
|
+
expect(tpl).not.toContain('1 + _p.name')
|
|
167
|
+
})
|
|
168
|
+
|
|
169
|
+
test('a Unicode loop param shadowing a const is still guarded (#2238 Copilot review)', () => {
|
|
170
|
+
const tpl = templateLambda(clientJsFor(`
|
|
171
|
+
'use client'
|
|
172
|
+
import { createSignal } from '@barefootjs/client'
|
|
173
|
+
export function Widget6({ values }: { values: number[] }) {
|
|
174
|
+
const \u03c0: string = 'x'
|
|
175
|
+
const [n, setN] = createSignal(0)
|
|
176
|
+
return (
|
|
177
|
+
<div data-n={n()} onClick={() => setN(n() + 1)}>
|
|
178
|
+
<p>{\u03c0}</p>
|
|
179
|
+
<ul>
|
|
180
|
+
{values.map((\u03c0) => (
|
|
181
|
+
<li key={\u03c0}>{1 + \u03c0}</li>
|
|
182
|
+
))}
|
|
183
|
+
</ul>
|
|
184
|
+
</div>
|
|
185
|
+
)
|
|
186
|
+
}
|
|
187
|
+
`))
|
|
188
|
+
|
|
189
|
+
// The Unicode param must be recognised as a bare identifier (not a
|
|
190
|
+
// destructure pattern), so the const never substitutes in the body.
|
|
191
|
+
expect(tpl).toContain('1 + \u03c0')
|
|
192
|
+
expect(tpl).not.toContain("1 + ('x')")
|
|
193
|
+
})
|
|
194
|
+
|
|
195
|
+
test('a non-shadowing prop used inside the loop still rewrites to _p.<name>', () => {
|
|
196
|
+
const tpl = templateLambda(clientJsFor(`
|
|
197
|
+
'use client'
|
|
198
|
+
import { createSignal } from '@barefootjs/client'
|
|
199
|
+
export function Widget5({ prefix, values }: { prefix: string; values: number[] }) {
|
|
200
|
+
const [n, setN] = createSignal(0)
|
|
201
|
+
return (
|
|
202
|
+
<ul data-n={n()} onClick={() => setN(n() + 1)}>
|
|
203
|
+
{values.map((v) => (
|
|
204
|
+
<li key={v}>{prefix + v}</li>
|
|
205
|
+
))}
|
|
206
|
+
</ul>
|
|
207
|
+
)
|
|
208
|
+
}
|
|
209
|
+
`))
|
|
210
|
+
|
|
211
|
+
// A prop NOT shadowed by the loop param keeps its rewrite inside the body.
|
|
212
|
+
expect(tpl).toContain('_p.prefix + v')
|
|
213
|
+
})
|
|
214
|
+
})
|