jsxpression 0.1.41 → 0.2.1

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 (183) hide show
  1. package/lib/analyze/analysis-error.d.ts.map +1 -1
  2. package/lib/analyze/analysis-error.js +2 -7
  3. package/lib/analyze/analysis-error.js.map +1 -1
  4. package/lib/analyze/analysis-report.d.ts +13 -13
  5. package/lib/analyze/analysis-report.d.ts.map +1 -1
  6. package/lib/analyze/analysis-report.js +48 -45
  7. package/lib/analyze/analysis-report.js.map +1 -1
  8. package/lib/analyze/analyze.d.ts +1 -1
  9. package/lib/analyze/analyze.d.ts.map +1 -1
  10. package/lib/analyze/analyze.js +4 -4
  11. package/lib/analyze/analyze.js.map +1 -1
  12. package/lib/analyze/data/analyze.d.ts +1 -1
  13. package/lib/analyze/data/analyze.d.ts.map +1 -1
  14. package/lib/analyze/data/analyze.js +5 -5
  15. package/lib/analyze/data/analyze.js.map +1 -1
  16. package/lib/analyze/data/data-access.d.ts +1 -1
  17. package/lib/analyze/data/data-access.d.ts.map +1 -1
  18. package/lib/analyze/data/data-access.js +19 -15
  19. package/lib/analyze/data/data-access.js.map +1 -1
  20. package/lib/analyze/data/method-calls.d.ts +1 -1
  21. package/lib/analyze/data/method-calls.d.ts.map +1 -1
  22. package/lib/analyze/data/method-calls.js +5 -5
  23. package/lib/analyze/data/method-calls.js.map +1 -1
  24. package/lib/analyze/data/utils.d.ts +3 -3
  25. package/lib/analyze/data/utils.d.ts.map +1 -1
  26. package/lib/analyze/data/utils.js +6 -5
  27. package/lib/analyze/data/utils.js.map +1 -1
  28. package/lib/analyze/index.d.ts +1 -1
  29. package/lib/analyze/index.d.ts.map +1 -1
  30. package/lib/analyze/index.js +1 -1
  31. package/lib/analyze/index.js.map +1 -1
  32. package/lib/analyze/jsx/analyze.d.ts +1 -1
  33. package/lib/analyze/jsx/analyze.d.ts.map +1 -1
  34. package/lib/analyze/jsx/analyze.js +4 -4
  35. package/lib/analyze/jsx/analyze.js.map +1 -1
  36. package/lib/analyze/jsx/element-attributes.d.ts +1 -1
  37. package/lib/analyze/jsx/element-attributes.d.ts.map +1 -1
  38. package/lib/analyze/jsx/element-attributes.js +3 -3
  39. package/lib/analyze/jsx/element-attributes.js.map +1 -1
  40. package/lib/analyze/jsx/element-children.d.ts +1 -1
  41. package/lib/analyze/jsx/element-children.d.ts.map +1 -1
  42. package/lib/analyze/jsx/element-children.js +3 -3
  43. package/lib/analyze/jsx/element-children.js.map +1 -1
  44. package/lib/analyze/jsx/element-tags.d.ts +1 -1
  45. package/lib/analyze/jsx/element-tags.d.ts.map +1 -1
  46. package/lib/analyze/jsx/element-tags.js +2 -2
  47. package/lib/analyze/jsx/element-tags.js.map +1 -1
  48. package/lib/analyze/security/analyze.d.ts +1 -1
  49. package/lib/analyze/security/analyze.d.ts.map +1 -1
  50. package/lib/analyze/security/analyze.js +4 -4
  51. package/lib/analyze/security/analyze.js.map +1 -1
  52. package/lib/analyze/security/call-expressions.d.ts +1 -1
  53. package/lib/analyze/security/call-expressions.d.ts.map +1 -1
  54. package/lib/analyze/security/call-expressions.js +3 -5
  55. package/lib/analyze/security/call-expressions.js.map +1 -1
  56. package/lib/analyze/security/declarations.d.ts +1 -1
  57. package/lib/analyze/security/declarations.d.ts.map +1 -1
  58. package/lib/analyze/security/declarations.js +6 -6
  59. package/lib/analyze/security/declarations.js.map +1 -1
  60. package/lib/analyze/security/expressions.d.ts +1 -1
  61. package/lib/analyze/security/expressions.d.ts.map +1 -1
  62. package/lib/analyze/security/expressions.js +3 -6
  63. package/lib/analyze/security/expressions.js.map +1 -1
  64. package/lib/analyze/security/identifiers.d.ts +1 -1
  65. package/lib/analyze/security/identifiers.d.ts.map +1 -1
  66. package/lib/analyze/security/identifiers.js +19 -22
  67. package/lib/analyze/security/identifiers.js.map +1 -1
  68. package/lib/analyze/utils.d.ts +4 -4
  69. package/lib/analyze/utils.d.ts.map +1 -1
  70. package/lib/analyze/utils.js +5 -3
  71. package/lib/analyze/utils.js.map +1 -1
  72. package/lib/analyze/validation-context.d.ts +8 -8
  73. package/lib/analyze/validation-context.d.ts.map +1 -1
  74. package/lib/analyze/validation-context.js +23 -21
  75. package/lib/analyze/validation-context.js.map +1 -1
  76. package/lib/builtins.d.ts +6 -6
  77. package/lib/builtins.d.ts.map +1 -1
  78. package/lib/builtins.js +9 -8
  79. package/lib/builtins.js.map +1 -1
  80. package/lib/codegen/builtins/builtin-types.d.ts.map +1 -1
  81. package/lib/codegen/builtins/builtin-types.js +9 -13
  82. package/lib/codegen/builtins/builtin-types.js.map +1 -1
  83. package/lib/codegen/generate-typescript-definitions.d.ts +18 -17
  84. package/lib/codegen/generate-typescript-definitions.d.ts.map +1 -1
  85. package/lib/codegen/generate-typescript-definitions.js +19 -23
  86. package/lib/codegen/generate-typescript-definitions.js.map +1 -1
  87. package/lib/codegen/schema/component-types.d.ts.map +1 -1
  88. package/lib/codegen/schema/component-types.js +7 -4
  89. package/lib/codegen/schema/component-types.js.map +1 -1
  90. package/lib/codegen/schema/data-types.d.ts.map +1 -1
  91. package/lib/codegen/schema/data-types.js +1 -1
  92. package/lib/codegen/schema/data-types.js.map +1 -1
  93. package/lib/codegen/schema/function-types.d.ts.map +1 -1
  94. package/lib/codegen/schema/function-types.js +1 -3
  95. package/lib/codegen/schema/function-types.js.map +1 -1
  96. package/lib/codegen/schema/utils.d.ts +4 -3
  97. package/lib/codegen/schema/utils.d.ts.map +1 -1
  98. package/lib/codegen/schema/utils.js +12 -8
  99. package/lib/codegen/schema/utils.js.map +1 -1
  100. package/lib/compile/compilation-error.d.ts +1 -1
  101. package/lib/compile/compilation-error.d.ts.map +1 -1
  102. package/lib/compile/compilation-error.js +3 -1
  103. package/lib/compile/compilation-error.js.map +1 -1
  104. package/lib/compile/compile.d.ts.map +1 -1
  105. package/lib/compile/compile.js +5 -11
  106. package/lib/compile/compile.js.map +1 -1
  107. package/lib/evaluate/evaluate.d.ts +6 -6
  108. package/lib/evaluate/evaluate.d.ts.map +1 -1
  109. package/lib/evaluate/evaluate.js +1 -1
  110. package/lib/evaluate/evaluate.js.map +1 -1
  111. package/lib/evaluate/evaluation-error.d.ts.map +1 -1
  112. package/lib/evaluate/evaluation-error.js +1 -0
  113. package/lib/evaluate/evaluation-error.js.map +1 -1
  114. package/lib/index.d.ts +1 -1
  115. package/lib/index.d.ts.map +1 -1
  116. package/lib/index.js +1 -1
  117. package/lib/index.js.map +1 -1
  118. package/lib/jsx.d.ts +3 -3
  119. package/lib/jsx.d.ts.map +1 -1
  120. package/lib/jsx.js.map +1 -1
  121. package/lib/parse/parse-error.d.ts.map +1 -1
  122. package/lib/parse/parse-error.js +1 -0
  123. package/lib/parse/parse-error.js.map +1 -1
  124. package/lib/render.d.ts +25 -33
  125. package/lib/render.d.ts.map +1 -1
  126. package/lib/render.js +21 -26
  127. package/lib/render.js.map +1 -1
  128. package/lib/schema.d.ts +9 -9
  129. package/lib/schema.d.ts.map +1 -1
  130. package/lib/schema.js +1 -1
  131. package/lib/schema.js.map +1 -1
  132. package/lib/traverse.d.ts.map +1 -1
  133. package/lib/traverse.js.map +1 -1
  134. package/lib/validate.d.ts +14 -17
  135. package/lib/validate.d.ts.map +1 -1
  136. package/lib/validate.js +13 -14
  137. package/lib/validate.js.map +1 -1
  138. package/package.json +12 -12
  139. package/src/analyze/analysis-error.ts +2 -6
  140. package/src/analyze/analysis-report.ts +73 -62
  141. package/src/analyze/analyze.test.ts +60 -60
  142. package/src/analyze/analyze.ts +4 -4
  143. package/src/analyze/data/analyze.ts +5 -8
  144. package/src/analyze/data/data-access.ts +49 -46
  145. package/src/analyze/data/method-calls.ts +9 -18
  146. package/src/analyze/data/utils.ts +15 -19
  147. package/src/analyze/index.ts +1 -1
  148. package/src/analyze/jsx/analyze.ts +4 -4
  149. package/src/analyze/jsx/element-attributes.ts +5 -18
  150. package/src/analyze/jsx/element-children.ts +4 -8
  151. package/src/analyze/jsx/element-tags.ts +2 -2
  152. package/src/analyze/security/analyze.ts +4 -4
  153. package/src/analyze/security/call-expressions.ts +5 -18
  154. package/src/analyze/security/declarations.ts +14 -43
  155. package/src/analyze/security/expressions.ts +12 -49
  156. package/src/analyze/security/identifiers.ts +37 -39
  157. package/src/analyze/utils.ts +25 -19
  158. package/src/analyze/validation-context.ts +32 -23
  159. package/src/builtins.ts +27 -38
  160. package/src/codegen/builtins/builtin-types.ts +13 -20
  161. package/src/codegen/generate-typescript-definitions.test.ts +6 -6
  162. package/src/codegen/generate-typescript-definitions.ts +19 -23
  163. package/src/codegen/schema/component-types.ts +22 -12
  164. package/src/codegen/schema/data-types.ts +6 -6
  165. package/src/codegen/schema/function-types.ts +1 -3
  166. package/src/codegen/schema/utils.ts +24 -23
  167. package/src/compile/compilation-error.ts +5 -1
  168. package/src/compile/compile.test.ts +7 -21
  169. package/src/compile/compile.ts +18 -30
  170. package/src/evaluate/evaluate.test.ts +78 -94
  171. package/src/evaluate/evaluate.ts +15 -20
  172. package/src/evaluate/evaluation-error.ts +1 -0
  173. package/src/index.ts +1 -7
  174. package/src/jsx.ts +4 -6
  175. package/src/parse/parse-error.ts +1 -0
  176. package/src/parse/parse.test.ts +16 -18
  177. package/src/render.test.ts +4 -4
  178. package/src/render.ts +26 -38
  179. package/src/schema.ts +11 -11
  180. package/src/traverse.test.ts +6 -6
  181. package/src/traverse.ts +3 -3
  182. package/src/validate.ts +14 -17
  183. package/CHANGELOG.md +0 -8
@@ -30,9 +30,7 @@ describe("compile", () => {
30
30
  it("should compile nested ternary expressions", () => {
31
31
  const ast = parse("<div>{props.level > 2 ? 'high' : props.level > 1 ? 'medium' : 'low'}</div>");
32
32
  const result = compile(ast);
33
- expect(result).toBe(
34
- '"use strict";return h("div", null, ((props.level > 2)?"high":((props.level > 1)?"medium":"low")));'
35
- );
33
+ expect(result).toBe('"use strict";return h("div", null, ((props.level > 2)?"high":((props.level > 1)?"medium":"low")));');
36
34
  });
37
35
 
38
36
  it("should compile nested JSX elements", () => {
@@ -44,9 +42,7 @@ describe("compile", () => {
44
42
  it("should compile nested array operations", () => {
45
43
  const ast = parse("<div>{props.items.map(x => x.split(',').map(y => y.trim()).join(' ')).join(' | ')}</div>");
46
44
  const result = compile(ast);
47
- expect(result).toBe(
48
- '"use strict";return h("div", null, props.items.map((x) => x.split(",").map((y) => y.trim()).join(" ")).join(" | "));'
49
- );
45
+ expect(result).toBe('"use strict";return h("div", null, props.items.map((x) => x.split(",").map((y) => y.trim()).join(" ")).join(" | "));');
50
46
  });
51
47
 
52
48
  it("should compile bare expression containers", () => {
@@ -217,23 +213,17 @@ describe("compile", () => {
217
213
  it("should compile function with props parameter", () => {
218
214
  const ast = parse('function Badge({ label }) {\n return <span>{label}</span>\n}\nreturn <Badge label="hi" />');
219
215
  const result = compile(ast);
220
- expect(result).toBe(
221
- '"use strict";function Badge({ label }) { return h("span", null, label); }return h(Badge, { label: "hi" });'
222
- );
216
+ expect(result).toBe('"use strict";function Badge({ label }) { return h("span", null, label); }return h(Badge, { label: "hi" });');
223
217
  });
224
218
 
225
219
  it("should compile function with default parameter", () => {
226
220
  const ast = parse("function Badge({ label = 'default' }) {\n return <span>{label}</span>\n}\nreturn <Badge />");
227
221
  const result = compile(ast);
228
- expect(result).toBe(
229
- '"use strict";function Badge({ label = "default" }) { return h("span", null, label); }return h(Badge, null);'
230
- );
222
+ expect(result).toBe('"use strict";function Badge({ label = "default" }) { return h("span", null, label); }return h(Badge, null);');
231
223
  });
232
224
 
233
225
  it("should compile function with const inside body", () => {
234
- const ast = parse(
235
- "function Badge({ value }) {\n const doubled = value * 2;\n return <span>{doubled}</span>\n}\nreturn <Badge value={5} />"
236
- );
226
+ const ast = parse("function Badge({ value }) {\n const doubled = value * 2;\n return <span>{doubled}</span>\n}\nreturn <Badge value={5} />");
237
227
  const result = compile(ast);
238
228
  expect(result).toContain("const doubled = (value * 2);");
239
229
  expect(result).toContain('return h("span", null, doubled);');
@@ -248,9 +238,7 @@ describe("compile", () => {
248
238
  });
249
239
 
250
240
  it("should compile multiple function declarations", () => {
251
- const ast = parse(
252
- "function A() {\n return <span>a</span>\n}\nfunction B() {\n return <span>b</span>\n}\nreturn <div><A /><B /></div>"
253
- );
241
+ const ast = parse("function A() {\n return <span>a</span>\n}\nfunction B() {\n return <span>b</span>\n}\nreturn <div><A /><B /></div>");
254
242
  const result = compile(ast);
255
243
  expect(result).toContain("function A()");
256
244
  expect(result).toContain("function B()");
@@ -259,9 +247,7 @@ describe("compile", () => {
259
247
  });
260
248
 
261
249
  it("should compile function calling another function", () => {
262
- const ast = parse(
263
- "function Inner() {\n return <span>inner</span>\n}\nfunction Outer() {\n return <div><Inner /></div>\n}\nreturn <Outer />"
264
- );
250
+ const ast = parse("function Inner() {\n return <span>inner</span>\n}\nfunction Outer() {\n return <div><Inner /></div>\n}\nreturn <Outer />");
265
251
  const result = compile(ast);
266
252
  expect(result).toContain("function Inner()");
267
253
  expect(result).toContain("function Outer()");
@@ -11,7 +11,6 @@ import type {
11
11
  Super,
12
12
  VariableDeclaration,
13
13
  } from "acorn";
14
-
15
14
  import {
16
15
  isJsxElement,
17
16
  isJsxEmptyExpression,
@@ -40,7 +39,7 @@ export function compile(ast: Program): string {
40
39
  }
41
40
  }
42
41
 
43
- const parts: string[] = ['"use strict";'];
42
+ const parts: Array<string> = ['"use strict";'];
44
43
 
45
44
  const hasDeclarations = ast.body.some((s) => s.type === "VariableDeclaration" || s.type === "FunctionDeclaration");
46
45
 
@@ -108,13 +107,13 @@ function emitJsxName(nameNode: JSXNameNode, localFunctions: Set<string>): string
108
107
  return JSON.stringify(JSON.parse(left) + "." + JSON.parse(right));
109
108
  }
110
109
  default:
111
- throw CompilationError.fromNode(`Unsupported JSX name: ${(nameNode as any).type}`, nameNode);
110
+ throw CompilationError.fromNode(`Unsupported JSX name: ${(nameNode as { type: string }).type}`, nameNode);
112
111
  }
113
112
  }
114
113
 
115
- function emitAttributes(attributes: (JSXAttribute | JSXSpreadAttribute)[], localFunctions: Set<string>): string {
116
- const parts: string[] = [];
117
- let currentObj: string[] = [];
114
+ function emitAttributes(attributes: Array<JSXAttribute | JSXSpreadAttribute>, localFunctions: Set<string>): string {
115
+ const parts: Array<string> = [];
116
+ let currentObj: Array<string> = [];
118
117
 
119
118
  const flushCurrent = (): void => {
120
119
  if (currentObj.length) {
@@ -136,7 +135,7 @@ function emitAttributes(attributes: (JSXAttribute | JSXSpreadAttribute)[], local
136
135
 
137
136
  const key = attribute.name?.name;
138
137
 
139
- let value: string;
138
+ let value: string = "";
140
139
  if (!attribute.value) {
141
140
  value = "true";
142
141
  } else if (attribute.value.type === "Literal") {
@@ -163,8 +162,8 @@ function emitAttributes(attributes: (JSXAttribute | JSXSpreadAttribute)[], local
163
162
  return `Object.assign({}, ${parts.join(", ")})`;
164
163
  }
165
164
 
166
- function emitJsxChildren(children: JSXNode[], localFunctions: Set<string>): string[] {
167
- const result: string[] = [];
165
+ function emitJsxChildren(children: Array<JSXNode>, localFunctions: Set<string>): Array<string> {
166
+ const result: Array<string> = [];
168
167
 
169
168
  for (const child of children) {
170
169
  if (isJsxText(child)) {
@@ -195,7 +194,7 @@ function emitExpression(node: CompilableExpression, localFunctions: Set<string>)
195
194
  case "Identifier":
196
195
  return node.name;
197
196
  case "TemplateLiteral": {
198
- const bits: string[] = [];
197
+ const bits: Array<string> = [];
199
198
  node.quasis.forEach((quasi, index) => {
200
199
  bits.push(JSON.stringify(quasi.value.cooked ?? ""));
201
200
  if (node.expressions.length > index) {
@@ -210,10 +209,7 @@ function emitExpression(node: CompilableExpression, localFunctions: Set<string>)
210
209
  return `${node.operator}${emitExpression(node.argument, localFunctions)}`;
211
210
  case "BinaryExpression":
212
211
  case "LogicalExpression":
213
- return `(${emitExpression(node.left, localFunctions)} ${node.operator} ${emitExpression(
214
- node.right,
215
- localFunctions
216
- )})`;
212
+ return `(${emitExpression(node.left, localFunctions)} ${node.operator} ${emitExpression(node.right, localFunctions)})`;
217
213
  case "ConditionalExpression":
218
214
  return `(${emitExpression(node.test, localFunctions)}?${emitExpression(
219
215
  node.consequent,
@@ -245,12 +241,9 @@ function emitExpression(node: CompilableExpression, localFunctions: Set<string>)
245
241
  }
246
242
  case "MemberExpression": {
247
243
  const obj = emitExpression(node.object, localFunctions);
248
- let prop: string;
249
- if (node.computed) {
250
- prop = `[${emitExpression(node.property, localFunctions)}]`;
251
- } else {
252
- prop = `.${getAstKeyString(node.property as Identifier | Literal)}`;
253
- }
244
+ const prop: string = node.computed
245
+ ? `[${emitExpression(node.property, localFunctions)}]`
246
+ : `.${getAstKeyString(node.property as Identifier | Literal)}`;
254
247
  return `${obj}${prop}`;
255
248
  }
256
249
  case "CallExpression": {
@@ -266,9 +259,7 @@ function emitExpression(node: CompilableExpression, localFunctions: Set<string>)
266
259
  return `${callee}(${args})`;
267
260
  }
268
261
  case "ArrowFunctionExpression": {
269
- const params = node.params
270
- .map((param) => emitExpression(param as CompilableExpression, localFunctions))
271
- .join(", ");
262
+ const params = node.params.map((param) => emitExpression(param as CompilableExpression, localFunctions)).join(", ");
272
263
  const body = emitExpression(node.body as CompilableExpression, localFunctions);
273
264
  return `(${params}) => ${body}`;
274
265
  }
@@ -327,13 +318,13 @@ function emitParam(param: Pattern, localFunctions: Set<string>): string {
327
318
  case "Identifier":
328
319
  return param.name;
329
320
  case "ObjectPattern": {
330
- const props = (param as any).properties.map((p: any) => {
321
+ const props = param.properties.map((p) => {
331
322
  if (p.type === "RestElement") {
332
323
  return `...${emitParam(p.argument, localFunctions)}`;
333
324
  }
334
325
  const key = (p.key as Identifier).name;
335
326
  if (p.value.type === "AssignmentPattern") {
336
- return `${key} = ${emitExpression(p.value.right as CompilableExpression, localFunctions)}`;
327
+ return `${key} = ${emitExpression(p.value.right, localFunctions)}`;
337
328
  }
338
329
  if (p.value !== p.key && p.value.type === "Identifier" && p.value.name !== key) {
339
330
  return `${key}: ${emitParam(p.value, localFunctions)}`;
@@ -343,12 +334,9 @@ function emitParam(param: Pattern, localFunctions: Set<string>): string {
343
334
  return `{ ${props.join(", ")} }`;
344
335
  }
345
336
  case "AssignmentPattern":
346
- return `${emitParam((param as any).left, localFunctions)} = ${emitExpression(
347
- (param as any).right as CompilableExpression,
348
- localFunctions
349
- )}`;
337
+ return `${emitParam(param.left, localFunctions)} = ${emitExpression(param.right, localFunctions)}`;
350
338
  case "RestElement":
351
- return `...${emitParam((param as any).argument, localFunctions)}`;
339
+ return `...${emitParam(param.argument, localFunctions)}`;
352
340
  default:
353
341
  throw CompilationError.fromNode(`Unsupported parameter: ${param.type}`, param);
354
342
  }
@@ -1,35 +1,35 @@
1
1
  import { describe, it, expect, vi } from "vitest";
2
- import { evaluate, type EvaluateOptions } from "./evaluate.js";
3
2
  import { compile } from "../compile/index.js";
4
3
  import { parse } from "../parse/index.js";
5
4
  import type { Schema } from "../schema.js";
6
-
5
+ import { evaluate, type Component, type CreateElement, type EvaluateOptions, type Node as EvalNode, type PropsDict } from "./evaluate.js";
7
6
  import { EvaluationError } from "./evaluation-error.js";
8
7
 
9
8
  type Node = {
10
9
  type: string;
11
10
  props: Record<string, unknown>;
12
- children: Node[];
11
+ children: Array<Node>;
13
12
  };
14
13
 
15
- function createPermissiveSchema(componentNames: string[]): Schema {
14
+ function createPermissiveSchema(componentNames: Array<string>): Schema {
16
15
  return {
17
16
  elements: Object.fromEntries(componentNames.map((name) => [name, {}])),
18
17
  };
19
18
  }
20
19
 
21
20
  describe("evaluate", () => {
22
- const compileAndEvaluate = (source: string, options: EvaluateOptions = {}): Node => {
23
- const componentNames = Object.keys(options.components || {});
21
+ const compileAndEvaluate = (source: string, options: EvaluateOptions<Node> = {}): Node => {
22
+ const componentNames = Object.keys(options.components ?? {});
24
23
  const schema = createPermissiveSchema(componentNames);
25
24
  return evaluate(compile(parse(source)), schema, options);
26
25
  };
27
26
 
28
27
  it("should evaluate JSX with props", () => {
29
- const TestComponent = (props: any): Node => ({
28
+ const TestComponent = (props: PropsDict): Node => ({
30
29
  type: "TestComponent",
31
30
  props: { x: props.x, y: props.y },
32
- children: props.children,
31
+ // props.children is genuinely dynamic (mixed strings/numbers/nested Node results); this fixture assumes the Node shape its own assertions expect.
32
+ children: props.children as Array<Node>,
33
33
  });
34
34
 
35
35
  const result = compileAndEvaluate("<Test x={x} y={y}>Hello</Test>", {
@@ -47,7 +47,7 @@ describe("evaluate", () => {
47
47
  });
48
48
 
49
49
  it("should evaluate JSX with Math operations", () => {
50
- const TestComponent = (props: any): Node => ({
50
+ const TestComponent = (props: PropsDict): Node => ({
51
51
  type: "TestComponent",
52
52
  props,
53
53
  children: [],
@@ -68,16 +68,15 @@ describe("evaluate", () => {
68
68
  const emptySchema = createPermissiveSchema([]);
69
69
 
70
70
  expect(() => evaluate(compiled, emptySchema, { components: {} })).toThrow(EvaluationError);
71
- expect(() => evaluate(compiled, emptySchema, { components: {} })).toThrow(
72
- 'component "UnknownComponent" is not allowed'
73
- );
71
+ expect(() => evaluate(compiled, emptySchema, { components: {} })).toThrow('component "UnknownComponent" is not allowed');
74
72
  });
75
73
 
76
74
  it("should deep-freeze props to prevent mutations", () => {
77
- const TestComponent = (props: any): Node => {
75
+ const TestComponent = (props: PropsDict): Node => {
78
76
  expect(() => {
79
- props.nested.value = 999;
80
- }).toThrow();
77
+ // props.nested's shape isn't known statically; this test only cares that mutating it throws once frozen.
78
+ (props.nested as Record<string, unknown>).value = 999;
79
+ }).toThrow(TypeError);
81
80
  return { type: "Test", props, children: [] };
82
81
  };
83
82
 
@@ -93,16 +92,16 @@ describe("evaluate", () => {
93
92
  });
94
93
 
95
94
  it("should evaluate nested elements", () => {
96
- const OuterComponent = (props: any): Node => ({
95
+ const OuterComponent = (props: PropsDict): Node => ({
97
96
  type: "Outer",
98
97
  props: { x: props.x },
99
- children: props.children,
98
+ children: props.children as Array<Node>,
100
99
  });
101
100
 
102
- const InnerComponent = (props: any): Node => ({
101
+ const InnerComponent = (props: PropsDict): Node => ({
103
102
  type: "Inner",
104
103
  props: { y: props.y },
105
- children: props.children,
104
+ children: props.children as Array<Node>,
106
105
  });
107
106
 
108
107
  const result = compileAndEvaluate("<Outer x={x}><Inner y={y}>Text</Inner></Outer>", {
@@ -123,10 +122,10 @@ describe("evaluate", () => {
123
122
  });
124
123
 
125
124
  it("should use custom createElement when provided", () => {
126
- const customCreateElement = (type: any, props: any, ...children: any[]): Node => ({
127
- type: type.name || "Unknown",
125
+ const customCreateElement = (type: Component, props: PropsDict | undefined, ...children: Array<unknown>): Node => ({
126
+ type: type.name,
128
127
  props: { ...props, custom: true },
129
- children,
128
+ children: children as Array<Node>,
130
129
  });
131
130
 
132
131
  const TestComponent = (): Node => ({ type: "Test", props: {}, children: [] });
@@ -146,7 +145,7 @@ describe("evaluate", () => {
146
145
  });
147
146
 
148
147
  it("should evaluate conditional expressions with props", () => {
149
- const TestComponent = (props: any): Node => ({
148
+ const TestComponent = (props: PropsDict): Node => ({
150
149
  type: "TestComponent",
151
150
  props,
152
151
  children: [],
@@ -163,7 +162,7 @@ describe("evaluate", () => {
163
162
  });
164
163
 
165
164
  it("should evaluate array methods on props", () => {
166
- const TestComponent = (props: any): Node => ({
165
+ const TestComponent = (props: PropsDict): Node => ({
167
166
  type: "TestComponent",
168
167
  props,
169
168
  children: [],
@@ -195,7 +194,7 @@ describe("evaluate", () => {
195
194
  });
196
195
 
197
196
  it("should evaluate logical operators with props", () => {
198
- const TestComponent = (props: any): Node => ({
197
+ const TestComponent = (props: PropsDict): Node => ({
199
198
  type: "TestComponent",
200
199
  props,
201
200
  children: [],
@@ -212,10 +211,10 @@ describe("evaluate", () => {
212
211
  });
213
212
 
214
213
  it("should flatten and filter children correctly", () => {
215
- const TestComponent = (props: any): Node => ({
214
+ const TestComponent = (props: PropsDict): Node => ({
216
215
  type: "Test",
217
216
  props: {},
218
- children: props.children,
217
+ children: props.children as Array<Node>,
219
218
  });
220
219
 
221
220
  const result = compileAndEvaluate("<Test>{show && 'Visible'}{false}{'Always'}</Test>", {
@@ -240,10 +239,10 @@ describe("evaluate", () => {
240
239
  });
241
240
 
242
241
  it("should handle empty JSX expressions", () => {
243
- const TestComponent = (props: any): Node => ({
242
+ const TestComponent = (props: PropsDict): Node => ({
244
243
  type: "Test",
245
244
  props: {},
246
- children: props.children,
245
+ children: props.children as Array<Node>,
247
246
  });
248
247
 
249
248
  const result = compileAndEvaluate("<Test>{}{value}{}</Test>", {
@@ -255,25 +254,22 @@ describe("evaluate", () => {
255
254
  });
256
255
 
257
256
  it("should evaluate complex nested expressions", () => {
258
- const TestComponent = (props: any): Node => ({
257
+ const TestComponent = (props: PropsDict): Node => ({
259
258
  type: "Test",
260
259
  props,
261
260
  children: [],
262
261
  });
263
262
 
264
- const result = compileAndEvaluate(
265
- "<Test values={items.filter(x => x > 2).map(x => x * 2).join(', ')}>Text</Test>",
266
- {
267
- data: { items: [1, 2, 3, 4, 5] },
268
- components: { Test: TestComponent },
269
- }
270
- );
263
+ const result = compileAndEvaluate("<Test values={items.filter(x => x > 2).map(x => x * 2).join(', ')}>Text</Test>", {
264
+ data: { items: [1, 2, 3, 4, 5] },
265
+ components: { Test: TestComponent },
266
+ });
271
267
 
272
268
  expect(result.props.values).toBe("6, 8, 10");
273
269
  });
274
270
 
275
271
  it("should pass correct parameters to custom createElement", () => {
276
- const mockCreateElement = vi.fn();
272
+ const mockCreateElement = vi.fn<CreateElement<EvalNode>>();
277
273
 
278
274
  compileAndEvaluate("<Test x={10}>Hello</Test>", {
279
275
  components: { Test: () => ({ type: "Test", props: {}, children: [] }) },
@@ -284,7 +280,7 @@ describe("evaluate", () => {
284
280
  });
285
281
 
286
282
  it("should handle string literals in expressions", () => {
287
- const TestComponent = (props: any): Node => ({
283
+ const TestComponent = (props: PropsDict): Node => ({
288
284
  type: "Test",
289
285
  props,
290
286
  children: [],
@@ -299,7 +295,7 @@ describe("evaluate", () => {
299
295
  });
300
296
 
301
297
  it("should handle numeric operations", () => {
302
- const TestComponent = (props: any): Node => ({
298
+ const TestComponent = (props: PropsDict): Node => ({
303
299
  type: "Test",
304
300
  props,
305
301
  children: [],
@@ -314,10 +310,10 @@ describe("evaluate", () => {
314
310
  });
315
311
 
316
312
  it("should handle data access in children", () => {
317
- const TestComponent = (props: any): Node => ({
313
+ const TestComponent = (props: PropsDict): Node => ({
318
314
  type: "Test",
319
315
  props: {},
320
- children: props.children,
316
+ children: props.children as Array<Node>,
321
317
  });
322
318
 
323
319
  const result = compileAndEvaluate("<Test>Hello {name}!</Test>", {
@@ -330,7 +326,7 @@ describe("evaluate", () => {
330
326
 
331
327
  describe("const declarations", () => {
332
328
  it("should evaluate const with literal value", () => {
333
- const TestComponent = (props: any): Node => ({
329
+ const TestComponent = (props: PropsDict): Node => ({
334
330
  type: "Test",
335
331
  props,
336
332
  children: [],
@@ -344,7 +340,7 @@ describe("evaluate", () => {
344
340
  });
345
341
 
346
342
  it("should evaluate const with computed expression", () => {
347
- const TestComponent = (props: any): Node => ({
343
+ const TestComponent = (props: PropsDict): Node => ({
348
344
  type: "Test",
349
345
  props,
350
346
  children: [],
@@ -359,7 +355,7 @@ describe("evaluate", () => {
359
355
  });
360
356
 
361
357
  it("should evaluate const referencing data", () => {
362
- const TestComponent = (props: any): Node => ({
358
+ const TestComponent = (props: PropsDict): Node => ({
363
359
  type: "Test",
364
360
  props,
365
361
  children: [],
@@ -374,19 +370,16 @@ describe("evaluate", () => {
374
370
  });
375
371
 
376
372
  it("should evaluate const with computed array", () => {
377
- const TestComponent = (props: any): Node => ({
373
+ const TestComponent = (props: PropsDict): Node => ({
378
374
  type: "Test",
379
375
  props,
380
376
  children: [],
381
377
  });
382
378
 
383
- const result = compileAndEvaluate(
384
- "const filtered = items.filter(x => x > 2);\nreturn <Test count={filtered.length}>Text</Test>",
385
- {
386
- data: { items: [1, 2, 3, 4, 5] },
387
- components: { Test: TestComponent },
388
- }
389
- );
379
+ const result = compileAndEvaluate("const filtered = items.filter(x => x > 2);\nreturn <Test count={filtered.length}>Text</Test>", {
380
+ data: { items: [1, 2, 3, 4, 5] },
381
+ components: { Test: TestComponent },
382
+ });
390
383
 
391
384
  expect(result.props.count).toBe(3);
392
385
  });
@@ -394,25 +387,22 @@ describe("evaluate", () => {
394
387
 
395
388
  describe("function declarations", () => {
396
389
  it("should evaluate user-defined component", () => {
397
- const Span = (props: any): Node => ({
390
+ const Span = (props: PropsDict): Node => ({
398
391
  type: "Span",
399
392
  props: {},
400
- children: props.children,
393
+ children: props.children as Array<Node>,
401
394
  });
402
395
 
403
- const result = compileAndEvaluate(
404
- 'function Badge({ label }) {\n return <Span>{label}</Span>\n}\nreturn <Badge label="hello" />',
405
- {
406
- components: { Span },
407
- }
408
- );
396
+ const result = compileAndEvaluate('function Badge({ label }) {\n return <Span>{label}</Span>\n}\nreturn <Badge label="hello" />', {
397
+ components: { Span },
398
+ });
409
399
 
410
400
  expect(result.type).toBe("Span");
411
401
  expect(result.children).toEqual(["hello"]);
412
402
  });
413
403
 
414
404
  it("should evaluate function with const inside", () => {
415
- const Span = (props: any): Node => ({
405
+ const Span = (props: PropsDict): Node => ({
416
406
  type: "Span",
417
407
  props,
418
408
  children: [],
@@ -429,16 +419,16 @@ describe("evaluate", () => {
429
419
  });
430
420
 
431
421
  it("should evaluate nested user-defined components", () => {
432
- const Span = (props: any): Node => ({
422
+ const Span = (props: PropsDict): Node => ({
433
423
  type: "Span",
434
424
  props: {},
435
- children: props.children,
425
+ children: props.children as Array<Node>,
436
426
  });
437
427
 
438
- const Div = (props: any): Node => ({
428
+ const Div = (props: PropsDict): Node => ({
439
429
  type: "Div",
440
430
  props: {},
441
- children: props.children,
431
+ children: props.children as Array<Node>,
442
432
  });
443
433
 
444
434
  const result = compileAndEvaluate(
@@ -455,16 +445,16 @@ describe("evaluate", () => {
455
445
  });
456
446
 
457
447
  it("should evaluate function with children", () => {
458
- const Div = (props: any): Node => ({
448
+ const Div = (props: PropsDict): Node => ({
459
449
  type: "Div",
460
450
  props: {},
461
- children: props.children,
451
+ children: props.children as Array<Node>,
462
452
  });
463
453
 
464
- const Span = (props: any): Node => ({
454
+ const Span = (props: PropsDict): Node => ({
465
455
  type: "Span",
466
456
  props: {},
467
- children: props.children,
457
+ children: props.children as Array<Node>,
468
458
  });
469
459
 
470
460
  const result = compileAndEvaluate(
@@ -480,36 +470,30 @@ describe("evaluate", () => {
480
470
  });
481
471
 
482
472
  it("should evaluate function with default parameter values", () => {
483
- const Span = (props: any): Node => ({
473
+ const Span = (props: PropsDict): Node => ({
484
474
  type: "Span",
485
475
  props: {},
486
- children: props.children,
476
+ children: props.children as Array<Node>,
487
477
  });
488
478
 
489
- const result = compileAndEvaluate(
490
- "function Badge({ label = 'default' }) {\n return <Span>{label}</Span>\n}\nreturn <Badge />",
491
- {
492
- components: { Span },
493
- }
494
- );
479
+ const result = compileAndEvaluate("function Badge({ label = 'default' }) {\n return <Span>{label}</Span>\n}\nreturn <Badge />", {
480
+ components: { Span },
481
+ });
495
482
 
496
483
  expect(result.children).toEqual(["default"]);
497
484
  });
498
485
 
499
486
  it("should evaluate function with data access", () => {
500
- const Span = (props: any): Node => ({
487
+ const Span = (props: PropsDict): Node => ({
501
488
  type: "Span",
502
489
  props: {},
503
- children: props.children,
490
+ children: props.children as Array<Node>,
504
491
  });
505
492
 
506
- const result = compileAndEvaluate(
507
- "function Greeting() {\n return <Span>Hello {name}</Span>\n}\nreturn <Greeting />",
508
- {
509
- data: { name: "World" },
510
- components: { Span },
511
- }
512
- );
493
+ const result = compileAndEvaluate("function Greeting() {\n return <Span>Hello {name}</Span>\n}\nreturn <Greeting />", {
494
+ data: { name: "World" },
495
+ components: { Span },
496
+ });
513
497
 
514
498
  expect(result.children).toEqual(["Hello", "World"]);
515
499
  });
@@ -517,7 +501,7 @@ describe("evaluate", () => {
517
501
 
518
502
  describe("const and function combined", () => {
519
503
  it("should evaluate const used in function body", () => {
520
- const Span = (props: any): Node => ({
504
+ const Span = (props: PropsDict): Node => ({
521
505
  type: "Span",
522
506
  props,
523
507
  children: [],
@@ -534,16 +518,16 @@ describe("evaluate", () => {
534
518
  });
535
519
 
536
520
  it("should evaluate function used in map with const", () => {
537
- const Div = (props: any): Node => ({
521
+ const Div = (props: PropsDict): Node => ({
538
522
  type: "Div",
539
523
  props: {},
540
- children: props.children,
524
+ children: props.children as Array<Node>,
541
525
  });
542
526
 
543
- const Span = (props: any): Node => ({
527
+ const Span = (props: PropsDict): Node => ({
544
528
  type: "Span",
545
529
  props: {},
546
- children: props.children,
530
+ children: props.children as Array<Node>,
547
531
  });
548
532
 
549
533
  const result = compileAndEvaluate(
@@ -561,7 +545,7 @@ describe("evaluate", () => {
561
545
 
562
546
  describe("String builtin", () => {
563
547
  it("should evaluate String() conversion", () => {
564
- const TestComponent = (props: any): Node => ({
548
+ const TestComponent = (props: PropsDict): Node => ({
565
549
  type: "Test",
566
550
  props,
567
551
  children: [],
@@ -575,7 +559,7 @@ describe("evaluate", () => {
575
559
  });
576
560
 
577
561
  it("should evaluate String() with boolean", () => {
578
- const TestComponent = (props: any): Node => ({
562
+ const TestComponent = (props: PropsDict): Node => ({
579
563
  type: "Test",
580
564
  props,
581
565
  children: [],