@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.
Files changed (88) hide show
  1. package/dist/adapters/dangerous-inner-html.d.ts +77 -0
  2. package/dist/adapters/dangerous-inner-html.d.ts.map +1 -0
  3. package/dist/adapters/loop-bound-names.d.ts +22 -0
  4. package/dist/adapters/loop-bound-names.d.ts.map +1 -0
  5. package/dist/adapters/parsed-expr-emitter.d.ts.map +1 -1
  6. package/dist/analyzer.d.ts.map +1 -1
  7. package/dist/index.d.ts +14 -4
  8. package/dist/index.d.ts.map +1 -1
  9. package/dist/index.js +977 -273
  10. package/dist/ir-to-client-js/collect-elements.d.ts.map +1 -1
  11. package/dist/ir-to-client-js/control-flow/plan/build-inner-loop.d.ts.map +1 -1
  12. package/dist/ir-to-client-js/control-flow/plan/build-loop-child-arm.d.ts.map +1 -1
  13. package/dist/ir-to-client-js/control-flow/plan/build-loop.d.ts.map +1 -1
  14. package/dist/ir-to-client-js/control-flow/plan/loop-child-arm.d.ts +9 -0
  15. package/dist/ir-to-client-js/control-flow/plan/loop-child-arm.d.ts.map +1 -1
  16. package/dist/ir-to-client-js/control-flow/plan/loop.d.ts +9 -0
  17. package/dist/ir-to-client-js/control-flow/plan/loop.d.ts.map +1 -1
  18. package/dist/ir-to-client-js/control-flow/shared.d.ts +45 -3
  19. package/dist/ir-to-client-js/control-flow/shared.d.ts.map +1 -1
  20. package/dist/ir-to-client-js/control-flow/stringify/loop-child-arm.d.ts.map +1 -1
  21. package/dist/ir-to-client-js/control-flow/stringify/loop.d.ts +1 -0
  22. package/dist/ir-to-client-js/control-flow/stringify/loop.d.ts.map +1 -1
  23. package/dist/ir-to-client-js/control-flow/stringify/reactive-effects.d.ts +10 -0
  24. package/dist/ir-to-client-js/control-flow/stringify/reactive-effects.d.ts.map +1 -1
  25. package/dist/ir-to-client-js/control-flow/stringify/skeleton-paths.d.ts +38 -0
  26. package/dist/ir-to-client-js/control-flow/stringify/skeleton-paths.d.ts.map +1 -0
  27. package/dist/ir-to-client-js/control-flow/stringify/template-parse.d.ts +19 -0
  28. package/dist/ir-to-client-js/control-flow/stringify/template-parse.d.ts.map +1 -1
  29. package/dist/ir-to-client-js/csr-substitute.d.ts +23 -0
  30. package/dist/ir-to-client-js/csr-substitute.d.ts.map +1 -1
  31. package/dist/ir-to-client-js/html-template.d.ts +42 -0
  32. package/dist/ir-to-client-js/html-template.d.ts.map +1 -1
  33. package/dist/ir-to-client-js/imports.d.ts +2 -2
  34. package/dist/ir-to-client-js/imports.d.ts.map +1 -1
  35. package/dist/ir-to-client-js/plan/static-array-child-init.d.ts +20 -1
  36. package/dist/ir-to-client-js/plan/static-array-child-init.d.ts.map +1 -1
  37. package/dist/ir-to-client-js/reactivity.d.ts.map +1 -1
  38. package/dist/ir-to-client-js/stringify/static-array-child-init.d.ts +1 -1
  39. package/dist/ir-to-client-js/types.d.ts +21 -0
  40. package/dist/ir-to-client-js/types.d.ts.map +1 -1
  41. package/dist/jsx-to-ir.d.ts.map +1 -1
  42. package/dist/signal-init-eval.d.ts +82 -0
  43. package/dist/signal-init-eval.d.ts.map +1 -0
  44. package/dist/static-literal.d.ts +45 -0
  45. package/dist/static-literal.d.ts.map +1 -0
  46. package/package.json +2 -2
  47. package/src/__tests__/__snapshots__/doc-examples.test.ts.snap +19 -13
  48. package/src/__tests__/create-selector.test.ts +110 -0
  49. package/src/__tests__/csr-template-loop-shadowing.test.ts +214 -0
  50. package/src/__tests__/dangerous-inner-html-resolver.test.ts +197 -0
  51. package/src/__tests__/inner-loop-svg-namespace.test.ts +245 -0
  52. package/src/__tests__/loop-bound-names.test.ts +102 -0
  53. package/src/__tests__/loop-plan-classification.test.ts +2 -0
  54. package/src/__tests__/map-function-reference.test.ts +303 -0
  55. package/src/__tests__/nested-loop-index-param.test.ts +285 -0
  56. package/src/__tests__/signal-init-eval.test.ts +138 -0
  57. package/src/__tests__/static-array-inner-loop-index-param.test.ts +180 -0
  58. package/src/__tests__/static-literal.test.ts +126 -0
  59. package/src/__tests__/string-concat-identifier.test.ts +55 -0
  60. package/src/adapters/dangerous-inner-html.ts +186 -0
  61. package/src/adapters/loop-bound-names.ts +80 -0
  62. package/src/adapters/parsed-expr-emitter.ts +9 -0
  63. package/src/analyzer.ts +6 -0
  64. package/src/index.ts +19 -3
  65. package/src/ir-to-client-js/collect-elements.ts +15 -3
  66. package/src/ir-to-client-js/control-flow/plan/build-inner-loop.ts +21 -4
  67. package/src/ir-to-client-js/control-flow/plan/build-loop-child-arm.ts +13 -1
  68. package/src/ir-to-client-js/control-flow/plan/build-loop.ts +1 -0
  69. package/src/ir-to-client-js/control-flow/plan/loop-child-arm.ts +9 -0
  70. package/src/ir-to-client-js/control-flow/plan/loop.ts +9 -0
  71. package/src/ir-to-client-js/control-flow/shared.ts +103 -6
  72. package/src/ir-to-client-js/control-flow/stringify/inner-loop.ts +11 -2
  73. package/src/ir-to-client-js/control-flow/stringify/loop-child-arm.ts +5 -0
  74. package/src/ir-to-client-js/control-flow/stringify/loop.ts +53 -10
  75. package/src/ir-to-client-js/control-flow/stringify/reactive-effects.ts +25 -4
  76. package/src/ir-to-client-js/control-flow/stringify/skeleton-paths.ts +70 -0
  77. package/src/ir-to-client-js/control-flow/stringify/template-parse.ts +25 -1
  78. package/src/ir-to-client-js/csr-substitute.ts +53 -0
  79. package/src/ir-to-client-js/html-template.ts +235 -2
  80. package/src/ir-to-client-js/imports.ts +1 -0
  81. package/src/ir-to-client-js/plan/build-static-array-child-init.ts +12 -1
  82. package/src/ir-to-client-js/plan/static-array-child-init.ts +20 -1
  83. package/src/ir-to-client-js/reactivity.ts +6 -0
  84. package/src/ir-to-client-js/stringify/static-array-child-init.ts +11 -6
  85. package/src/ir-to-client-js/types.ts +21 -0
  86. package/src/jsx-to-ir.ts +230 -39
  87. package/src/signal-init-eval.ts +165 -0
  88. 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
+ }