@barefootjs/jsx 0.18.5 → 0.19.0
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/expression-parser.d.ts +8 -0
- package/dist/expression-parser.d.ts.map +1 -1
- package/dist/index.d.ts +15 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1002 -284
- 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/phases/props-extraction.d.ts +0 -1
- package/dist/ir-to-client-js/phases/props-extraction.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__/client-js-generation.test.ts +40 -0
- 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__/props-destructuring.test.ts +61 -8
- 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 +36 -22
- package/src/expression-parser.ts +33 -0
- package/src/index.ts +20 -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/phases/props-extraction.ts +5 -9
- 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
|
@@ -0,0 +1,128 @@
|
|
|
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
|
+
|
|
18
|
+
import type { ParsedExpr } from './expression-parser.ts'
|
|
19
|
+
import type { ConstantInfo } from './types.ts'
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Recursively evaluate a `ParsedExpr` that is a fully compile-time-known
|
|
23
|
+
* literal to its JS value. `bindings` lets a caller resolve identifiers
|
|
24
|
+
* (and member reads off them) against already-evaluated values — e.g. the
|
|
25
|
+
* Go adapter binding a loop's item parameter to one already-resolved array
|
|
26
|
+
* element while baking per-item child-component props. Returns `null` when
|
|
27
|
+
* the expression is not statically known (depends on a prop, signal,
|
|
28
|
+
* function call, or an identifier absent from `bindings`).
|
|
29
|
+
*/
|
|
30
|
+
export function evaluateStaticLiteral(
|
|
31
|
+
expr: ParsedExpr,
|
|
32
|
+
bindings?: ReadonlyMap<string, unknown>,
|
|
33
|
+
): { value: unknown } | null {
|
|
34
|
+
switch (expr.kind) {
|
|
35
|
+
case 'literal':
|
|
36
|
+
return { value: expr.value }
|
|
37
|
+
case 'template-literal': {
|
|
38
|
+
let out = ''
|
|
39
|
+
for (const part of expr.parts) {
|
|
40
|
+
if (part.type === 'string') {
|
|
41
|
+
out += part.value
|
|
42
|
+
continue
|
|
43
|
+
}
|
|
44
|
+
const resolved = evaluateStaticLiteral(part.expr, bindings)
|
|
45
|
+
if (!resolved) return null
|
|
46
|
+
out += String(resolved.value)
|
|
47
|
+
}
|
|
48
|
+
return { value: out }
|
|
49
|
+
}
|
|
50
|
+
case 'array-literal': {
|
|
51
|
+
const values: unknown[] = []
|
|
52
|
+
for (const element of expr.elements) {
|
|
53
|
+
const resolved = evaluateStaticLiteral(element, bindings)
|
|
54
|
+
if (!resolved) return null
|
|
55
|
+
values.push(resolved.value)
|
|
56
|
+
}
|
|
57
|
+
return { value: values }
|
|
58
|
+
}
|
|
59
|
+
case 'object-literal': {
|
|
60
|
+
// Shorthand (`{ a }`) and explicit (`{ a: value }`) properties both
|
|
61
|
+
// carry their resolved tree in `value` (shorthand's is an
|
|
62
|
+
// `identifier`) — recursing here handles both uniformly: a shorthand
|
|
63
|
+
// property only resolves when `bindings` supplies it.
|
|
64
|
+
const out: Record<string, unknown> = {}
|
|
65
|
+
for (const prop of expr.properties) {
|
|
66
|
+
const resolved = evaluateStaticLiteral(prop.value, bindings)
|
|
67
|
+
if (!resolved) return null
|
|
68
|
+
out[prop.key] = resolved.value
|
|
69
|
+
}
|
|
70
|
+
return { value: out }
|
|
71
|
+
}
|
|
72
|
+
case 'unary': {
|
|
73
|
+
const resolved = evaluateStaticLiteral(expr.argument, bindings)
|
|
74
|
+
if (!resolved) return null
|
|
75
|
+
if (expr.op === '-') return typeof resolved.value === 'number' ? { value: -resolved.value } : null
|
|
76
|
+
if (expr.op === '+') return typeof resolved.value === 'number' ? { value: +resolved.value } : null
|
|
77
|
+
if (expr.op === '!') return { value: !resolved.value }
|
|
78
|
+
return null
|
|
79
|
+
}
|
|
80
|
+
case 'identifier':
|
|
81
|
+
return bindings?.has(expr.name) ? { value: bindings.get(expr.name) } : null
|
|
82
|
+
case 'member': {
|
|
83
|
+
const base = evaluateStaticLiteral(expr.object, bindings)
|
|
84
|
+
if (!base || base.value === null || typeof base.value !== 'object') return null
|
|
85
|
+
return { value: (base.value as Record<string, unknown>)[expr.property] }
|
|
86
|
+
}
|
|
87
|
+
case 'index-access': {
|
|
88
|
+
const base = evaluateStaticLiteral(expr.object, bindings)
|
|
89
|
+
const index = evaluateStaticLiteral(expr.index, bindings)
|
|
90
|
+
if (!base || !index || !Array.isArray(base.value) || typeof index.value !== 'number') return null
|
|
91
|
+
return { value: base.value[index.value] }
|
|
92
|
+
}
|
|
93
|
+
default:
|
|
94
|
+
return null
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/** `true` iff {@link evaluateStaticLiteral} resolves `expr` with no bindings. */
|
|
99
|
+
export function isFullyStaticLiteral(expr: ParsedExpr): boolean {
|
|
100
|
+
return evaluateStaticLiteral(expr) !== null
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* Shared loop-source resolution for `renderLoop` across adapters: the loop
|
|
105
|
+
* array is either an inline array-literal, or a bare identifier naming a
|
|
106
|
+
* FUNCTION-scope (`!isModule`) local const whose initializer evaluates
|
|
107
|
+
* statically. Module-scope consts are deliberately excluded — an existing,
|
|
108
|
+
* separate seeding path already handles those. Returns the evaluated items,
|
|
109
|
+
* or `null` if the source isn't resolvable this way (including when it
|
|
110
|
+
* resolves to something other than an array).
|
|
111
|
+
*/
|
|
112
|
+
export function resolveStaticLoopSource(
|
|
113
|
+
arrayParsed: ParsedExpr | undefined,
|
|
114
|
+
localConstants: ReadonlyArray<ConstantInfo> | undefined,
|
|
115
|
+
opts?: { isNameShadowed?: (name: string) => boolean },
|
|
116
|
+
): unknown[] | null {
|
|
117
|
+
if (!arrayParsed) return null
|
|
118
|
+
let target = arrayParsed
|
|
119
|
+
if (arrayParsed.kind === 'identifier') {
|
|
120
|
+
if (opts?.isNameShadowed?.(arrayParsed.name)) return null
|
|
121
|
+
const local = localConstants?.find(c => c.name === arrayParsed.name)
|
|
122
|
+
if (!local || local.isModule || !local.parsed) return null
|
|
123
|
+
target = local.parsed
|
|
124
|
+
}
|
|
125
|
+
const resolved = evaluateStaticLiteral(target)
|
|
126
|
+
if (!resolved || !Array.isArray(resolved.value)) return null
|
|
127
|
+
return resolved.value
|
|
128
|
+
}
|