typesea 0.1.0 → 0.2.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.
Files changed (285) hide show
  1. package/CHANGELOG.md +67 -6
  2. package/README.md +98 -17
  3. package/dist/adapters/index.d.ts +50 -8
  4. package/dist/adapters/index.d.ts.map +1 -1
  5. package/dist/adapters/index.js +169 -48
  6. package/dist/aot/index.d.ts +18 -2
  7. package/dist/aot/index.d.ts.map +1 -1
  8. package/dist/aot/index.js +93 -14
  9. package/dist/async/index.d.ts +28 -56
  10. package/dist/async/index.d.ts.map +1 -1
  11. package/dist/async/index.js +94 -37
  12. package/dist/builders/composite.d.ts +37 -6
  13. package/dist/builders/composite.d.ts.map +1 -1
  14. package/dist/builders/composite.js +84 -10
  15. package/dist/builders/index.d.ts +2 -0
  16. package/dist/builders/index.d.ts.map +1 -1
  17. package/dist/builders/index.js +2 -0
  18. package/dist/builders/modifier.d.ts +30 -5
  19. package/dist/builders/modifier.d.ts.map +1 -1
  20. package/dist/builders/modifier.js +38 -5
  21. package/dist/builders/object/guard.d.ts +18 -22
  22. package/dist/builders/object/guard.d.ts.map +1 -1
  23. package/dist/builders/object/guard.js +26 -26
  24. package/dist/builders/object/index.d.ts +2 -0
  25. package/dist/builders/object/index.d.ts.map +1 -1
  26. package/dist/builders/object/index.js +2 -0
  27. package/dist/builders/object/schema.d.ts +55 -9
  28. package/dist/builders/object/schema.d.ts.map +1 -1
  29. package/dist/builders/object/schema.js +92 -15
  30. package/dist/builders/object/types.d.ts +5 -31
  31. package/dist/builders/object/types.d.ts.map +1 -1
  32. package/dist/builders/object/types.js +2 -0
  33. package/dist/builders/scalar.d.ts +29 -8
  34. package/dist/builders/scalar.d.ts.map +1 -1
  35. package/dist/builders/scalar.js +33 -8
  36. package/dist/builders/table.d.ts +4 -0
  37. package/dist/builders/table.d.ts.map +1 -1
  38. package/dist/builders/table.js +4 -0
  39. package/dist/builders/types.d.ts +14 -4
  40. package/dist/builders/types.d.ts.map +1 -1
  41. package/dist/builders/types.js +2 -0
  42. package/dist/compile/check-composite.d.ts +22 -1
  43. package/dist/compile/check-composite.d.ts.map +1 -1
  44. package/dist/compile/check-composite.js +564 -24
  45. package/dist/compile/check-scalar.d.ts +78 -0
  46. package/dist/compile/check-scalar.d.ts.map +1 -1
  47. package/dist/compile/check-scalar.js +432 -1
  48. package/dist/compile/check.d.ts +12 -0
  49. package/dist/compile/check.d.ts.map +1 -1
  50. package/dist/compile/check.js +37 -0
  51. package/dist/compile/context.d.ts +47 -9
  52. package/dist/compile/context.d.ts.map +1 -1
  53. package/dist/compile/context.js +51 -8
  54. package/dist/compile/graph-predicate.d.ts +4 -2
  55. package/dist/compile/graph-predicate.d.ts.map +1 -1
  56. package/dist/compile/graph-predicate.js +1907 -171
  57. package/dist/compile/guard.d.ts +15 -24
  58. package/dist/compile/guard.d.ts.map +1 -1
  59. package/dist/compile/guard.js +158 -74
  60. package/dist/compile/index.d.ts +3 -1
  61. package/dist/compile/index.d.ts.map +1 -1
  62. package/dist/compile/index.js +2 -0
  63. package/dist/compile/issue.d.ts +110 -0
  64. package/dist/compile/issue.d.ts.map +1 -1
  65. package/dist/compile/issue.js +184 -1
  66. package/dist/compile/names.d.ts +12 -2
  67. package/dist/compile/names.d.ts.map +1 -1
  68. package/dist/compile/names.js +19 -3
  69. package/dist/compile/predicate.d.ts +24 -0
  70. package/dist/compile/predicate.d.ts.map +1 -1
  71. package/dist/compile/predicate.js +131 -5
  72. package/dist/compile/runtime.d.ts +80 -12
  73. package/dist/compile/runtime.d.ts.map +1 -1
  74. package/dist/compile/runtime.js +25 -6
  75. package/dist/compile/source.d.ts +10 -2
  76. package/dist/compile/source.d.ts.map +1 -1
  77. package/dist/compile/source.js +361 -26
  78. package/dist/compile/types.d.ts +20 -0
  79. package/dist/compile/types.d.ts.map +1 -1
  80. package/dist/compile/types.js +2 -0
  81. package/dist/decoder/index.d.ts +32 -46
  82. package/dist/decoder/index.d.ts.map +1 -1
  83. package/dist/decoder/index.js +102 -38
  84. package/dist/evaluate/check-composite.d.ts +59 -0
  85. package/dist/evaluate/check-composite.d.ts.map +1 -1
  86. package/dist/evaluate/check-composite.js +151 -3
  87. package/dist/evaluate/check-scalar.d.ts +16 -0
  88. package/dist/evaluate/check-scalar.d.ts.map +1 -1
  89. package/dist/evaluate/check-scalar.js +32 -0
  90. package/dist/evaluate/check.d.ts +7 -0
  91. package/dist/evaluate/check.d.ts.map +1 -1
  92. package/dist/evaluate/check.js +43 -0
  93. package/dist/evaluate/index.d.ts +2 -0
  94. package/dist/evaluate/index.d.ts.map +1 -1
  95. package/dist/evaluate/index.js +2 -0
  96. package/dist/evaluate/issue.d.ts +11 -1
  97. package/dist/evaluate/issue.d.ts.map +1 -1
  98. package/dist/evaluate/issue.js +15 -1
  99. package/dist/evaluate/predicate.d.ts +16 -5
  100. package/dist/evaluate/predicate.d.ts.map +1 -1
  101. package/dist/evaluate/predicate.js +20 -5
  102. package/dist/evaluate/shared.d.ts +59 -13
  103. package/dist/evaluate/shared.d.ts.map +1 -1
  104. package/dist/evaluate/shared.js +66 -8
  105. package/dist/evaluate/state.d.ts +35 -13
  106. package/dist/evaluate/state.d.ts.map +1 -1
  107. package/dist/evaluate/state.js +35 -2
  108. package/dist/guard/base.d.ts +79 -29
  109. package/dist/guard/base.d.ts.map +1 -1
  110. package/dist/guard/base.js +91 -29
  111. package/dist/guard/error.d.ts +10 -5
  112. package/dist/guard/error.d.ts.map +1 -1
  113. package/dist/guard/error.js +10 -5
  114. package/dist/guard/index.d.ts +2 -0
  115. package/dist/guard/index.d.ts.map +1 -1
  116. package/dist/guard/index.js +2 -0
  117. package/dist/guard/number.d.ts +26 -11
  118. package/dist/guard/number.d.ts.map +1 -1
  119. package/dist/guard/number.js +30 -11
  120. package/dist/guard/props.d.ts +27 -3
  121. package/dist/guard/props.d.ts.map +1 -1
  122. package/dist/guard/props.js +27 -3
  123. package/dist/guard/read.d.ts +62 -9
  124. package/dist/guard/read.d.ts.map +1 -1
  125. package/dist/guard/read.js +83 -10
  126. package/dist/guard/registry.d.ts +12 -2
  127. package/dist/guard/registry.d.ts.map +1 -1
  128. package/dist/guard/registry.js +15 -3
  129. package/dist/guard/string.d.ts +33 -13
  130. package/dist/guard/string.d.ts.map +1 -1
  131. package/dist/guard/string.js +37 -13
  132. package/dist/guard/types.d.ts +92 -40
  133. package/dist/guard/types.d.ts.map +1 -1
  134. package/dist/guard/types.js +2 -0
  135. package/dist/index.d.ts +1 -1
  136. package/dist/index.d.ts.map +1 -1
  137. package/dist/internal/index.d.ts +42 -6
  138. package/dist/internal/index.d.ts.map +1 -1
  139. package/dist/internal/index.js +51 -8
  140. package/dist/ir/builder.d.ts +16 -126
  141. package/dist/ir/builder.d.ts.map +1 -1
  142. package/dist/ir/builder.js +77 -137
  143. package/dist/ir/freeze.d.ts +4 -0
  144. package/dist/ir/freeze.d.ts.map +1 -1
  145. package/dist/ir/freeze.js +59 -0
  146. package/dist/ir/index.d.ts +3 -1
  147. package/dist/ir/index.d.ts.map +1 -1
  148. package/dist/ir/index.js +2 -0
  149. package/dist/ir/regexp.d.ts +2 -0
  150. package/dist/ir/regexp.d.ts.map +1 -1
  151. package/dist/ir/regexp.js +2 -0
  152. package/dist/ir/types.d.ts +90 -55
  153. package/dist/ir/types.d.ts.map +1 -1
  154. package/dist/ir/types.js +2 -0
  155. package/dist/ir/validate.d.ts +8 -1
  156. package/dist/ir/validate.d.ts.map +1 -1
  157. package/dist/ir/validate.js +477 -61
  158. package/dist/issue/index.d.ts +41 -9
  159. package/dist/issue/index.d.ts.map +1 -1
  160. package/dist/issue/index.js +61 -11
  161. package/dist/json-schema/emit-combinator.d.ts +44 -4
  162. package/dist/json-schema/emit-combinator.d.ts.map +1 -1
  163. package/dist/json-schema/emit-combinator.js +44 -4
  164. package/dist/json-schema/emit-composite.d.ts +10 -0
  165. package/dist/json-schema/emit-composite.d.ts.map +1 -1
  166. package/dist/json-schema/emit-composite.js +15 -1
  167. package/dist/json-schema/emit-scalar.d.ts +26 -3
  168. package/dist/json-schema/emit-scalar.d.ts.map +1 -1
  169. package/dist/json-schema/emit-scalar.js +70 -9
  170. package/dist/json-schema/emit-types.d.ts +11 -1
  171. package/dist/json-schema/emit-types.d.ts.map +1 -1
  172. package/dist/json-schema/emit-types.js +2 -0
  173. package/dist/json-schema/emit.d.ts +12 -1
  174. package/dist/json-schema/emit.d.ts.map +1 -1
  175. package/dist/json-schema/emit.js +12 -1
  176. package/dist/json-schema/freeze.d.ts +13 -2
  177. package/dist/json-schema/freeze.d.ts.map +1 -1
  178. package/dist/json-schema/freeze.js +41 -8
  179. package/dist/json-schema/index.d.ts +16 -2
  180. package/dist/json-schema/index.d.ts.map +1 -1
  181. package/dist/json-schema/index.js +23 -3
  182. package/dist/json-schema/issue.d.ts +4 -1
  183. package/dist/json-schema/issue.d.ts.map +1 -1
  184. package/dist/json-schema/issue.js +4 -1
  185. package/dist/json-schema/read.d.ts +24 -3
  186. package/dist/json-schema/read.d.ts.map +1 -1
  187. package/dist/json-schema/read.js +59 -12
  188. package/dist/json-schema/types.d.ts +38 -15
  189. package/dist/json-schema/types.d.ts.map +1 -1
  190. package/dist/json-schema/types.js +2 -0
  191. package/dist/kind/index.d.ts +15 -28
  192. package/dist/kind/index.d.ts.map +1 -1
  193. package/dist/kind/index.js +15 -10
  194. package/dist/lower/index.d.ts +6 -1
  195. package/dist/lower/index.d.ts.map +1 -1
  196. package/dist/lower/index.js +411 -44
  197. package/dist/message/index.d.ts +46 -10
  198. package/dist/message/index.d.ts.map +1 -1
  199. package/dist/message/index.js +88 -17
  200. package/dist/optimize/algebraic.d.ts +54 -0
  201. package/dist/optimize/algebraic.d.ts.map +1 -0
  202. package/dist/optimize/algebraic.js +314 -0
  203. package/dist/optimize/compact.d.ts +8 -1
  204. package/dist/optimize/compact.d.ts.map +1 -1
  205. package/dist/optimize/compact.js +13 -2
  206. package/dist/optimize/domain.d.ts +16 -0
  207. package/dist/optimize/domain.d.ts.map +1 -0
  208. package/dist/optimize/domain.js +615 -0
  209. package/dist/optimize/fold-boolean.d.ts +17 -2
  210. package/dist/optimize/fold-boolean.d.ts.map +1 -1
  211. package/dist/optimize/fold-boolean.js +59 -14
  212. package/dist/optimize/fold-common.d.ts +43 -8
  213. package/dist/optimize/fold-common.d.ts.map +1 -1
  214. package/dist/optimize/fold-common.js +37 -6
  215. package/dist/optimize/fold-constraints.d.ts +33 -0
  216. package/dist/optimize/fold-constraints.d.ts.map +1 -0
  217. package/dist/optimize/fold-constraints.js +484 -0
  218. package/dist/optimize/fold-scalar.d.ts +98 -13
  219. package/dist/optimize/fold-scalar.d.ts.map +1 -1
  220. package/dist/optimize/fold-scalar.js +98 -13
  221. package/dist/optimize/fold.d.ts +8 -1
  222. package/dist/optimize/fold.d.ts.map +1 -1
  223. package/dist/optimize/fold.js +22 -2
  224. package/dist/optimize/index.d.ts +9 -1
  225. package/dist/optimize/index.d.ts.map +1 -1
  226. package/dist/optimize/index.js +18 -3
  227. package/dist/optimize/map-node.d.ts +3 -1
  228. package/dist/optimize/map-node.d.ts.map +1 -1
  229. package/dist/optimize/map-node.js +45 -3
  230. package/dist/optimize/peephole.d.ts +16 -0
  231. package/dist/optimize/peephole.d.ts.map +1 -0
  232. package/dist/optimize/peephole.js +254 -0
  233. package/dist/optimize/remap.d.ts +2 -0
  234. package/dist/optimize/remap.d.ts.map +1 -1
  235. package/dist/optimize/remap.js +2 -0
  236. package/dist/optimize/rewrite.d.ts +13 -8
  237. package/dist/optimize/rewrite.d.ts.map +1 -1
  238. package/dist/optimize/rewrite.js +13 -8
  239. package/dist/plan/cache.d.ts +9 -3
  240. package/dist/plan/cache.d.ts.map +1 -1
  241. package/dist/plan/cache.js +21 -5
  242. package/dist/plan/index.d.ts +2 -0
  243. package/dist/plan/index.d.ts.map +1 -1
  244. package/dist/plan/index.js +2 -0
  245. package/dist/plan/predicate.d.ts +2 -0
  246. package/dist/plan/predicate.d.ts.map +1 -1
  247. package/dist/plan/predicate.js +268 -29
  248. package/dist/plan/schema-predicate.d.ts +6 -0
  249. package/dist/plan/schema-predicate.d.ts.map +1 -1
  250. package/dist/plan/schema-predicate.js +117 -13
  251. package/dist/plan/types.d.ts +2 -0
  252. package/dist/plan/types.d.ts.map +1 -1
  253. package/dist/plan/types.js +2 -0
  254. package/dist/result/index.d.ts +19 -5
  255. package/dist/result/index.d.ts.map +1 -1
  256. package/dist/result/index.js +10 -2
  257. package/dist/schema/common.d.ts +69 -6
  258. package/dist/schema/common.d.ts.map +1 -1
  259. package/dist/schema/common.js +104 -10
  260. package/dist/schema/freeze.d.ts +4 -0
  261. package/dist/schema/freeze.d.ts.map +1 -1
  262. package/dist/schema/freeze.js +18 -0
  263. package/dist/schema/index.d.ts +3 -0
  264. package/dist/schema/index.d.ts.map +1 -1
  265. package/dist/schema/index.js +3 -0
  266. package/dist/schema/lazy.d.ts +4 -0
  267. package/dist/schema/lazy.d.ts.map +1 -1
  268. package/dist/schema/lazy.js +4 -0
  269. package/dist/schema/literal.d.ts +7 -1
  270. package/dist/schema/literal.d.ts.map +1 -1
  271. package/dist/schema/literal.js +7 -1
  272. package/dist/schema/types.d.ts +20 -96
  273. package/dist/schema/types.d.ts.map +1 -1
  274. package/dist/schema/types.js +5 -1
  275. package/dist/schema/undefined.d.ts +17 -0
  276. package/dist/schema/undefined.d.ts.map +1 -0
  277. package/dist/schema/undefined.js +72 -0
  278. package/dist/schema/validate.d.ts +8 -1
  279. package/dist/schema/validate.d.ts.map +1 -1
  280. package/dist/schema/validate.js +146 -55
  281. package/docs/api.md +57 -0
  282. package/docs/assets/benchmark-headline.svg +163 -0
  283. package/docs/engine-notes.md +58 -15
  284. package/docs/index.html +130 -110
  285. package/package.json +65 -65
@@ -1,30 +1,85 @@
1
1
  /**
2
2
  * @file compile/check-composite.ts
3
3
  * @brief Composite diagnostic validator snippets.
4
+ * @details Generated-source helpers keep the side-table ABI and JavaScript source shape
5
+ * stable across runtime and AOT emission.
4
6
  */
5
7
  import { ObjectModeTag, PresenceTag, SchemaTag } from "../kind/index.js";
6
- import { pushKeyset, pushLiteral, stringRef } from "./context.js";
7
- import { emitIssue, emitIssueExpr } from "./issue.js";
8
+ import { schemaCanAcceptUndefined } from "../schema/index.js";
9
+ import { pushLiteral, stringRef } from "./context.js";
10
+ import { emitIssue, emitIssueAtSegment, emitIssueAtTwoSegments, emitIssueExprAtSegment } from "./issue.js";
11
+ import { emitLeafCheckAtSegment, emitLeafCheckAtTwoSegments, emitUndefinedLeafCheckAtTwoSegments, emitUndefinedLeafCheckAtSegment } from "./check-scalar.js";
8
12
  import { stringLiteral } from "./names.js";
9
13
  /**
10
14
  * @brief emit array check.
15
+ * @details Generated-source helpers keep the side-table ABI and JavaScript source shape
16
+ * stable across runtime and AOT emission.
17
+ * @param item Schema applied to each logical array slot.
18
+ * @param value Generated expression for the candidate value.
19
+ * @param path Generated expression for the mutable diagnostic path.
20
+ * @param issues Generated expression for the diagnostic buffer.
21
+ * @param context Shared code-generation context.
22
+ * @param emitChild Fallback emitter for non-leaf child validators.
23
+ * @returns JavaScript source for array diagnostics.
11
24
  */
12
25
  export function emitArrayCheck(item, value, path, issues, context, emitChild) {
13
- const itemFunction = emitChild(item, context);
26
+ if (isUnsafeMode(context)) {
27
+ return emitUnsafeArrayCheck(item, value, path, issues, context, emitChild);
28
+ }
29
+ const itemValue = "av";
30
+ const itemLeaf = emitLeafCheckAtSegment(item, itemValue, path, "i", issues, context);
31
+ const missingLeaf = itemLeaf === undefined
32
+ ? undefined
33
+ : emitUndefinedLeafCheckAtSegment(item, path, "i", issues, context);
34
+ let missingCheck;
35
+ let itemCheck;
36
+ if (itemLeaf === undefined || missingLeaf === undefined) {
37
+ const itemFunction = emitChild(item, context);
38
+ missingCheck = `${path}.push(i);${itemFunction}(undefined,${path},${issues});${path}.pop();`;
39
+ itemCheck = `${path}.push(i);${itemFunction}(${itemValue},${path},${issues});${path}.pop();`;
40
+ }
41
+ else {
42
+ missingCheck = missingLeaf;
43
+ itemCheck = itemLeaf;
44
+ }
45
+ const presentCheck = itemCheck === ""
46
+ ? ""
47
+ : `const ${itemValue}=d.value;${itemCheck}`;
48
+ if (schemaCanAcceptUndefined(item)) {
49
+ /*
50
+ * Generated diagnostics mirror the interpreter: holes are valid only
51
+ * after the item schema admits undefined, while present accessors still
52
+ * produce a data-property issue instead of executing.
53
+ */
54
+ return [
55
+ `if(!Array.isArray(${value})){${emitIssue(issues, path, "expected_array", "array", `a(${value})`)}return;}`,
56
+ `const xs=Object.getOwnPropertyNames(${value});`,
57
+ "for(let xi=0;xi<xs.length;xi+=1){",
58
+ "const key=xs[xi];",
59
+ `if(!ai(key,${value}.length))continue;`,
60
+ "const i=Number(key);",
61
+ `const d=gp(${value},key);`,
62
+ `if(d!==undefined&&!h.call(d,"value")){${emitIssueAtSegment(issues, path, "i", "expected_array", "data property", stringLiteral("accessor"))}}else if(d!==undefined){${presentCheck}}`,
63
+ "}"
64
+ ].join("");
65
+ }
14
66
  return [
15
67
  `if(!Array.isArray(${value})){${emitIssue(issues, path, "expected_array", "array", `a(${value})`)}return;}`,
16
68
  `for(let i=0;i<${value}.length;i+=1){`,
17
69
  `const d=gp(${value},i);`,
18
- `${path}.push(i);`,
19
- `if(d!==undefined&&!h.call(d,"value")){${emitIssue(issues, path, "expected_array", "data property", stringLiteral("accessor"))}}else{${itemFunction}(d===undefined?undefined:d.value,${path},${issues});}`,
20
- `${path}.pop();`,
70
+ `if(d===undefined){${missingCheck}}else if(!h.call(d,"value")){${emitIssueAtSegment(issues, path, "i", "expected_array", "data property", stringLiteral("accessor"))}}else{${presentCheck}}`,
21
71
  "}"
22
72
  ].join("");
23
73
  }
24
74
  /**
25
75
  * @brief emit tuple check.
76
+ * @details Generated-source helpers keep the side-table ABI and JavaScript source shape
77
+ * stable across runtime and AOT emission.
26
78
  */
27
79
  export function emitTupleCheck(items, value, path, issues, context, emitChild) {
80
+ if (isUnsafeMode(context)) {
81
+ return emitUnsafeTupleCheck(items, value, path, issues, context, emitChild);
82
+ }
28
83
  const parts = [
29
84
  `if(!Array.isArray(${value})){${emitIssue(issues, path, "expected_tuple", "tuple", `a(${value})`)}return;}`,
30
85
  `if(${value}.length!==${String(items.length)}){${emitIssue(issues, path, "expected_tuple_length", `length ${String(items.length)}`, `"length "+String(${value}.length)`)}}`,
@@ -35,48 +90,392 @@ export function emitTupleCheck(items, value, path, issues, context, emitChild) {
35
90
  if (item === undefined) {
36
91
  continue;
37
92
  }
93
+ const indexExpression = String(index);
94
+ const itemValue = `tv${indexExpression}`;
95
+ const itemLeaf = emitLeafCheckAtSegment(item, itemValue, path, indexExpression, issues, context);
96
+ const missingLeaf = itemLeaf === undefined
97
+ ? undefined
98
+ : emitUndefinedLeafCheckAtSegment(item, path, indexExpression, issues, context);
99
+ let missingCheck;
100
+ let itemCheck;
101
+ if (itemLeaf === undefined || missingLeaf === undefined) {
102
+ const itemFunction = emitChild(item, context);
103
+ missingCheck = `${path}.push(${indexExpression});${itemFunction}(undefined,${path},${issues});${path}.pop();`;
104
+ itemCheck = `${path}.push(${indexExpression});${itemFunction}(${itemValue},${path},${issues});${path}.pop();`;
105
+ }
106
+ else {
107
+ missingCheck = missingLeaf;
108
+ itemCheck = itemLeaf;
109
+ }
110
+ const presentCheck = itemCheck === ""
111
+ ? ""
112
+ : `const ${itemValue}=d.value;${itemCheck}`;
113
+ parts.push(`if(${indexExpression}<n){const d=gp(${value},${indexExpression});if(d===undefined){${missingCheck}}else if(!h.call(d,"value")){${emitIssueAtSegment(issues, path, indexExpression, "expected_tuple", "data property", stringLiteral("accessor"))}}else{${presentCheck}}}`);
114
+ }
115
+ return parts.join("");
116
+ }
117
+ /**
118
+ * @brief Execute emit unsafe array check.
119
+ * @details Code generation helpers keep emitted JavaScript shape stable across runtime and AOT paths.
120
+ */
121
+ function emitUnsafeArrayCheck(item, value, path, issues, context, emitChild) {
122
+ const itemValue = "av";
123
+ const itemLeaf = emitLeafCheckAtSegment(item, itemValue, path, "i", issues, context);
124
+ let itemCheck;
125
+ if (itemLeaf === undefined) {
38
126
  const itemFunction = emitChild(item, context);
39
- parts.push(`if(${String(index)}<n){const d=gp(${value},${String(index)});${path}.push(${String(index)});if(d!==undefined&&!h.call(d,"value")){${emitIssue(issues, path, "expected_tuple", "data property", stringLiteral("accessor"))}}else{${itemFunction}(d===undefined?undefined:d.value,${path},${issues});}${path}.pop();}`);
127
+ itemCheck = `${path}.push(i);${itemFunction}(${itemValue},${path},${issues});${path}.pop();`;
128
+ }
129
+ else {
130
+ itemCheck = itemLeaf;
131
+ }
132
+ const parts = [
133
+ `if(!Array.isArray(${value})){${emitIssue(issues, path, "expected_array", "array", `a(${value})`)}return;}`
134
+ ];
135
+ if (itemCheck !== "") {
136
+ parts.push(`for(let i=0;i<${value}.length;i+=1){`, `const ${itemValue}=${value}[i];`, itemCheck, "}");
137
+ }
138
+ return parts.join("");
139
+ }
140
+ /**
141
+ * @brief Execute emit unsafe tuple check.
142
+ * @details Code generation helpers keep emitted JavaScript shape stable across runtime and AOT paths.
143
+ */
144
+ function emitUnsafeTupleCheck(items, value, path, issues, context, emitChild) {
145
+ const parts = [
146
+ `if(!Array.isArray(${value})){${emitIssue(issues, path, "expected_tuple", "tuple", `a(${value})`)}return;}`,
147
+ `if(${value}.length!==${String(items.length)}){${emitIssue(issues, path, "expected_tuple_length", `length ${String(items.length)}`, `"length "+String(${value}.length)`)}}`,
148
+ `const n=${value}.length<${String(items.length)}?${value}.length:${String(items.length)};`
149
+ ];
150
+ for (let index = 0; index < items.length; index += 1) {
151
+ const item = items[index];
152
+ if (item === undefined) {
153
+ continue;
154
+ }
155
+ const indexExpression = String(index);
156
+ const itemValue = `tv${indexExpression}`;
157
+ const itemLeaf = emitLeafCheckAtSegment(item, itemValue, path, indexExpression, issues, context);
158
+ let itemCheck;
159
+ if (itemLeaf === undefined) {
160
+ const itemFunction = emitChild(item, context);
161
+ itemCheck = `${path}.push(${indexExpression});${itemFunction}(${itemValue},${path},${issues});${path}.pop();`;
162
+ }
163
+ else {
164
+ itemCheck = itemLeaf;
165
+ }
166
+ if (itemCheck !== "") {
167
+ parts.push(`if(${indexExpression}<n){const ${itemValue}=${value}[${indexExpression}];${itemCheck}}`);
168
+ }
40
169
  }
41
170
  return parts.join("");
42
171
  }
172
+ /**
173
+ * @brief emit array check at one appended object-field segment.
174
+ * @details Generated-source helpers keep the side-table ABI and JavaScript source shape
175
+ * stable across runtime and AOT emission.
176
+ * @param item Schema applied to each logical array slot.
177
+ * @param value Generated expression for the candidate value.
178
+ * @param path Generated expression for the mutable diagnostic path.
179
+ * @param segmentExpression Generated parent path segment.
180
+ * @param issues Generated expression for the diagnostic buffer.
181
+ * @param context Shared code-generation context.
182
+ * @returns JavaScript source, or undefined when the caller must fall back.
183
+ */
184
+ function emitArrayCheckAtSegment(item, value, path, segmentExpression, issues, context) {
185
+ if (isUnsafeMode(context)) {
186
+ return emitUnsafeArrayCheckAtSegment(item, value, path, segmentExpression, issues, context);
187
+ }
188
+ const itemValue = "av";
189
+ const itemLeaf = emitLeafCheckAtTwoSegments(item, itemValue, path, segmentExpression, "i", issues, context);
190
+ const missingLeaf = itemLeaf === undefined
191
+ ? undefined
192
+ : emitUndefinedLeafCheckAtTwoSegments(item, path, segmentExpression, "i", issues, context);
193
+ if (itemLeaf === undefined || missingLeaf === undefined) {
194
+ return undefined;
195
+ }
196
+ const presentCheck = itemLeaf === ""
197
+ ? ""
198
+ : `const ${itemValue}=vd.value;${itemLeaf}`;
199
+ if (schemaCanAcceptUndefined(item)) {
200
+ /*
201
+ * The two-segment variant is used inside object fields. It keeps the
202
+ * parent key and array index inline so diagnostics avoid path-stack churn.
203
+ */
204
+ return [
205
+ `if(!Array.isArray(${value})){${emitIssueAtSegment(issues, path, segmentExpression, "expected_array", "array", `a(${value})`)}}else{`,
206
+ `const xs=Object.getOwnPropertyNames(${value});`,
207
+ "for(let xi=0;xi<xs.length;xi+=1){",
208
+ "const key=xs[xi];",
209
+ `if(!ai(key,${value}.length))continue;`,
210
+ "const i=Number(key);",
211
+ `const vd=gp(${value},key);`,
212
+ `if(vd!==undefined&&!h.call(vd,"value")){${emitIssueAtTwoSegments(issues, path, segmentExpression, "i", "expected_array", "data property", stringLiteral("accessor"))}}else if(vd!==undefined){${presentCheck}}`,
213
+ "}",
214
+ "}"
215
+ ].join("");
216
+ }
217
+ return [
218
+ `if(!Array.isArray(${value})){${emitIssueAtSegment(issues, path, segmentExpression, "expected_array", "array", `a(${value})`)}}else{`,
219
+ `for(let i=0;i<${value}.length;i+=1){`,
220
+ `const vd=gp(${value},i);`,
221
+ `if(vd===undefined){${missingLeaf}}else if(!h.call(vd,"value")){${emitIssueAtTwoSegments(issues, path, segmentExpression, "i", "expected_array", "data property", stringLiteral("accessor"))}}else{${presentCheck}}`,
222
+ "}",
223
+ "}"
224
+ ].join("");
225
+ }
226
+ /**
227
+ * @brief emit tuple check at one appended object-field segment.
228
+ * @details Generated-source helpers keep the side-table ABI and JavaScript source shape
229
+ * stable across runtime and AOT emission.
230
+ */
231
+ function emitTupleCheckAtSegment(items, value, path, segmentExpression, issues, context) {
232
+ if (isUnsafeMode(context)) {
233
+ return emitUnsafeTupleCheckAtSegment(items, value, path, segmentExpression, issues, context);
234
+ }
235
+ const parts = [
236
+ `if(!Array.isArray(${value})){${emitIssueAtSegment(issues, path, segmentExpression, "expected_tuple", "tuple", `a(${value})`)}}else{`,
237
+ `if(${value}.length!==${String(items.length)}){${emitIssueAtSegment(issues, path, segmentExpression, "expected_tuple_length", `length ${String(items.length)}`, `"length "+String(${value}.length)`)}}`,
238
+ `const n=${value}.length<${String(items.length)}?${value}.length:${String(items.length)};`
239
+ ];
240
+ for (let index = 0; index < items.length; index += 1) {
241
+ const item = items[index];
242
+ if (item === undefined) {
243
+ continue;
244
+ }
245
+ const indexExpression = String(index);
246
+ const itemValue = `tv${indexExpression}`;
247
+ const itemLeaf = emitLeafCheckAtTwoSegments(item, itemValue, path, segmentExpression, indexExpression, issues, context);
248
+ const missingLeaf = itemLeaf === undefined
249
+ ? undefined
250
+ : emitUndefinedLeafCheckAtTwoSegments(item, path, segmentExpression, indexExpression, issues, context);
251
+ if (itemLeaf === undefined || missingLeaf === undefined) {
252
+ return undefined;
253
+ }
254
+ const presentCheck = itemLeaf === ""
255
+ ? ""
256
+ : `const ${itemValue}=td.value;${itemLeaf}`;
257
+ parts.push(`if(${indexExpression}<n){const td=gp(${value},${indexExpression});if(td===undefined){${missingLeaf}}else if(!h.call(td,"value")){${emitIssueAtTwoSegments(issues, path, segmentExpression, indexExpression, "expected_tuple", "data property", stringLiteral("accessor"))}}else{${presentCheck}}}`);
258
+ }
259
+ parts.push("}");
260
+ return parts.join("");
261
+ }
262
+ /**
263
+ * @brief Execute emit unsafe array check at segment.
264
+ * @details Code generation helpers keep emitted JavaScript shape stable across runtime and AOT paths.
265
+ */
266
+ function emitUnsafeArrayCheckAtSegment(item, value, path, segmentExpression, issues, context) {
267
+ const itemLeaf = emitLeafCheckAtTwoSegments(item, "av", path, segmentExpression, "i", issues, context);
268
+ if (itemLeaf === undefined) {
269
+ return undefined;
270
+ }
271
+ const parts = [
272
+ `if(!Array.isArray(${value})){${emitIssueAtSegment(issues, path, segmentExpression, "expected_array", "array", `a(${value})`)}}`
273
+ ];
274
+ if (itemLeaf !== "") {
275
+ parts.push("else{", `for(let i=0;i<${value}.length;i+=1){`, `const av=${value}[i];`, itemLeaf, "}", "}");
276
+ }
277
+ return parts.join("");
278
+ }
279
+ /**
280
+ * @brief Execute emit unsafe tuple check at segment.
281
+ * @details Code generation helpers keep emitted JavaScript shape stable across runtime and AOT paths.
282
+ */
283
+ function emitUnsafeTupleCheckAtSegment(items, value, path, segmentExpression, issues, context) {
284
+ const parts = [
285
+ `if(!Array.isArray(${value})){${emitIssueAtSegment(issues, path, segmentExpression, "expected_tuple", "tuple", `a(${value})`)}}else{`,
286
+ `if(${value}.length!==${String(items.length)}){${emitIssueAtSegment(issues, path, segmentExpression, "expected_tuple_length", `length ${String(items.length)}`, `"length "+String(${value}.length)`)}}`,
287
+ `const n=${value}.length<${String(items.length)}?${value}.length:${String(items.length)};`
288
+ ];
289
+ for (let index = 0; index < items.length; index += 1) {
290
+ const item = items[index];
291
+ if (item === undefined) {
292
+ continue;
293
+ }
294
+ const indexExpression = String(index);
295
+ const itemValue = `tv${indexExpression}`;
296
+ const itemLeaf = emitLeafCheckAtTwoSegments(item, itemValue, path, segmentExpression, indexExpression, issues, context);
297
+ if (itemLeaf === undefined) {
298
+ return undefined;
299
+ }
300
+ if (itemLeaf !== "") {
301
+ parts.push(`if(${indexExpression}<n){const ${itemValue}=${value}[${indexExpression}];${itemLeaf}}`);
302
+ }
303
+ }
304
+ parts.push("}");
305
+ return parts.join("");
306
+ }
43
307
  /**
44
308
  * @brief emit record check.
309
+ * @details Generated-source helpers keep the side-table ABI and JavaScript source shape
310
+ * stable across runtime and AOT emission.
45
311
  */
46
312
  export function emitRecordCheck(item, value, path, issues, context, emitChild) {
47
- const itemFunction = emitChild(item, context);
313
+ if (isUnsafeMode(context)) {
314
+ return emitUnsafeRecordCheck(item, value, path, issues, context, emitChild);
315
+ }
316
+ const itemValue = "rv";
317
+ const itemLeaf = emitLeafCheckAtSegment(item, itemValue, path, "key", issues, context);
318
+ let itemCheck;
319
+ if (itemLeaf === undefined) {
320
+ const itemFunction = emitChild(item, context);
321
+ itemCheck = `${path}.push(key);${itemFunction}(${itemValue},${path},${issues});${path}.pop();`;
322
+ }
323
+ else {
324
+ itemCheck = itemLeaf;
325
+ }
326
+ const presentCheck = itemCheck === ""
327
+ ? ""
328
+ : `const ${itemValue}=d.value;${itemCheck}`;
48
329
  return [
49
- `if(!o(${value})){${emitIssue(issues, path, "expected_record", "record", `a(${value})`)}return;}`,
50
- `const ks=Object.keys(${value});`,
51
- "for(let i=0;i<ks.length;i+=1){",
52
- "const key=ks[i];",
53
- `if(key!==undefined){const d=g(${value},key);${path}.push(key);if(d===undefined){${emitIssue(issues, path, "expected_record", "data property", stringLiteral("accessor or missing"))}}else{${itemFunction}(d.value,${path},${issues});}${path}.pop();}`,
330
+ `if(${objectRejectExpression(value)}){${emitIssue(issues, path, "expected_record", "record", `a(${value})`)}return;}`,
331
+ `for(const key in ${value}){`,
332
+ `if(!h.call(${value},key))continue;`,
333
+ `const d=gp(${value},key);if(d===undefined||!h.call(d,"value")){${emitIssueAtSegment(issues, path, "key", "expected_record", "data property", stringLiteral("accessor or missing"))}}else{${presentCheck}}`,
54
334
  "}"
55
335
  ].join("");
56
336
  }
337
+ /**
338
+ * @brief emit record check at one appended object-field segment.
339
+ * @details Generated-source helpers keep the side-table ABI and JavaScript source shape
340
+ * stable across runtime and AOT emission.
341
+ */
342
+ function emitRecordCheckAtSegment(item, value, path, segmentExpression, issues, context) {
343
+ if (isUnsafeMode(context)) {
344
+ return emitUnsafeRecordCheckAtSegment(item, value, path, segmentExpression, issues, context);
345
+ }
346
+ const itemValue = "rv";
347
+ const itemLeaf = emitLeafCheckAtTwoSegments(item, itemValue, path, segmentExpression, "key", issues, context);
348
+ if (itemLeaf === undefined) {
349
+ return undefined;
350
+ }
351
+ const presentCheck = itemLeaf === ""
352
+ ? ""
353
+ : `const ${itemValue}=rd.value;${itemLeaf}`;
354
+ return [
355
+ `if(${objectRejectExpression(value)}){${emitIssueAtSegment(issues, path, segmentExpression, "expected_record", "record", `a(${value})`)}}else{`,
356
+ `for(const key in ${value}){`,
357
+ `if(!h.call(${value},key))continue;`,
358
+ `const rd=gp(${value},key);if(rd===undefined||!h.call(rd,"value")){${emitIssueAtTwoSegments(issues, path, segmentExpression, "key", "expected_record", "data property", stringLiteral("accessor or missing"))}}else{${presentCheck}}`,
359
+ "}",
360
+ "}"
361
+ ].join("");
362
+ }
363
+ /**
364
+ * @brief Execute emit unsafe record check.
365
+ * @details Code generation helpers keep emitted JavaScript shape stable across runtime and AOT paths.
366
+ */
367
+ function emitUnsafeRecordCheck(item, value, path, issues, context, emitChild) {
368
+ const itemValue = "rv";
369
+ const itemLeaf = emitLeafCheckAtSegment(item, itemValue, path, "key", issues, context);
370
+ let itemCheck;
371
+ if (itemLeaf === undefined) {
372
+ const itemFunction = emitChild(item, context);
373
+ itemCheck = `${path}.push(key);${itemFunction}(${itemValue},${path},${issues});${path}.pop();`;
374
+ }
375
+ else {
376
+ itemCheck = itemLeaf;
377
+ }
378
+ const parts = [
379
+ `if(${objectRejectExpression(value)}){${emitIssue(issues, path, "expected_record", "record", `a(${value})`)}return;}`
380
+ ];
381
+ if (itemCheck !== "") {
382
+ parts.push(`for(const key in ${value}){`, isUncheckedMode(context) ? "" : `if(!h.call(${value},key))continue;`, `const ${itemValue}=${value}[key];`, itemCheck, "}");
383
+ }
384
+ return parts.join("");
385
+ }
386
+ /**
387
+ * @brief Execute emit unsafe record check at segment.
388
+ * @details Code generation helpers keep emitted JavaScript shape stable across runtime and AOT paths.
389
+ */
390
+ function emitUnsafeRecordCheckAtSegment(item, value, path, segmentExpression, issues, context) {
391
+ const itemLeaf = emitLeafCheckAtTwoSegments(item, "rv", path, segmentExpression, "key", issues, context);
392
+ if (itemLeaf === undefined) {
393
+ return undefined;
394
+ }
395
+ const parts = [
396
+ `if(${objectRejectExpression(value)}){${emitIssueAtSegment(issues, path, segmentExpression, "expected_record", "record", `a(${value})`)}}`
397
+ ];
398
+ if (itemLeaf !== "") {
399
+ parts.push("else{", `for(const key in ${value}){`, isUncheckedMode(context) ? "" : `if(!h.call(${value},key))continue;`, `const rv=${value}[key];`, itemLeaf, "}", "}");
400
+ }
401
+ return parts.join("");
402
+ }
57
403
  /**
58
404
  * @brief emit object check.
405
+ * @details Generated-source helpers keep the side-table ABI and JavaScript source shape
406
+ * stable across runtime and AOT emission.
59
407
  */
60
408
  export function emitObjectCheck(schema, value, path, issues, context, emitChild) {
409
+ if (isUnsafeMode(context)) {
410
+ return emitUnsafeObjectCheck(schema, value, path, issues, context, emitChild);
411
+ }
61
412
  const parts = [
62
- `if(!o(${value})){${emitIssue(issues, path, "expected_object", "object", `a(${value})`)}return;}`
413
+ `if(${objectRejectExpression(value)}){${emitIssue(issues, path, "expected_object", "object", `a(${value})`)}return;}`
63
414
  ];
64
415
  const entries = schema.entries;
416
+ const keyExpressions = [];
65
417
  for (let index = 0; index < entries.length; index += 1) {
66
418
  const entry = entries[index];
67
419
  if (entry === undefined) {
68
420
  continue;
69
421
  }
70
422
  const key = stringRef(context, entry.key);
71
- const child = emitChild(entry.schema, context);
423
+ keyExpressions.push(key);
424
+ const itemValue = `v${String(index)}`;
425
+ const leaf = emitLeafCheckAtSegment(entry.schema, itemValue, path, key, issues, context);
426
+ const composite = leaf === undefined
427
+ ? emitCompositeCheckAtSegment(entry.schema, itemValue, path, key, issues, context)
428
+ : undefined;
429
+ let childCheck = leaf ?? composite;
430
+ if (childCheck === undefined) {
431
+ const child = emitChild(entry.schema, context);
432
+ childCheck = `${path}.push(${key});${child}(${itemValue},${path},${issues});${path}.pop();`;
433
+ }
434
+ const presentCheck = childCheck === ""
435
+ ? ""
436
+ : `const ${itemValue}=d.value;${childCheck}`;
72
437
  if (entry.presence === PresenceTag.Required) {
73
- parts.push(`{const d=g(${value},${key});if(d===undefined){${path}.push(${key});${emitIssue(issues, path, "expected_required_key", "present key", stringLiteral("missing"))}${path}.pop();}else{${path}.push(${key});${child}(d.value,${path},${issues});${path}.pop();}}`);
438
+ parts.push(`{const d=gp(${value},${key});if(d===undefined||!h.call(d,"value")){${emitIssueAtSegment(issues, path, key, "expected_required_key", "present key", stringLiteral("missing"))}}else{${presentCheck}}}`);
74
439
  }
75
440
  else {
76
- parts.push(`if(h.call(${value},${key})){const d=g(${value},${key});${path}.push(${key});if(d===undefined){${emitIssue(issues, path, "expected_object", "data property", stringLiteral("accessor"))}}else{${child}(d.value,${path},${issues});}${path}.pop();}`);
441
+ parts.push(`if(h.call(${value},${key})){const d=gp(${value},${key});if(d===undefined||!h.call(d,"value")){${emitIssueAtSegment(issues, path, key, "expected_object", "data property", stringLiteral("accessor"))}}else{${presentCheck}}}`);
77
442
  }
78
443
  }
79
444
  if (schema.mode === ObjectModeTag.Strict) {
445
+ parts.push(`const xs=Object.getOwnPropertyNames(${value});const xn=xs.length;for(let i=0;i<xn;i+=1){const key=xs[i];if(!(${safeKeyMembershipExpression("key", keyExpressions)})){${emitIssueAtSegment(issues, path, "key", "unrecognized_key", "known key", stringLiteral("extra key"))}}}const ys=Object.getOwnPropertySymbols(${value});const yn=ys.length;for(let i=0;i<yn;i+=1){const key=ys[i];if(key!==undefined){${emitIssueAtSegment(issues, path, "String(key)", "unrecognized_key", "known key", stringLiteral("extra key"))}}}`);
446
+ }
447
+ return parts.join("");
448
+ }
449
+ /**
450
+ * @brief Execute emit unsafe object check.
451
+ * @details Code generation helpers keep emitted JavaScript shape stable across runtime and AOT paths.
452
+ */
453
+ function emitUnsafeObjectCheck(schema, value, path, issues, context, emitChild) {
454
+ const parts = [
455
+ `if(${objectRejectExpression(value)}){${emitIssue(issues, path, "expected_object", "object", `a(${value})`)}return;}`
456
+ ];
457
+ const entries = schema.entries;
458
+ for (let index = 0; index < entries.length; index += 1) {
459
+ const entry = entries[index];
460
+ if (entry === undefined) {
461
+ continue;
462
+ }
463
+ const key = unsafeStringLiteralExpression(entry.key);
464
+ const itemValue = `v${String(index)}`;
465
+ const childCheck = emitObjectFieldCheck(entry.schema, itemValue, path, key, issues, context, emitChild);
466
+ parts.push(`{const ${itemValue}=${unsafePropertyReadExpression(value, entry.key)};`);
467
+ if (entry.presence === PresenceTag.Optional) {
468
+ parts.push(`if(${itemValue}!==undefined){${childCheck}}else if(h.call(${value},${key})){${childCheck}}`);
469
+ }
470
+ else if (schemaCanAcceptUndefined(entry.schema)) {
471
+ parts.push(`if(${itemValue}===undefined&&!h.call(${value},${key})){${emitIssueAtSegment(issues, path, key, "expected_required_key", "present key", stringLiteral("missing"))}}else{${childCheck}}`);
472
+ }
473
+ else {
474
+ parts.push(childCheck);
475
+ }
476
+ parts.push("}");
477
+ }
478
+ if (schema.mode === ObjectModeTag.Strict && !isUncheckedMode(context)) {
80
479
  const keys = new Array(schema.entries.length);
81
480
  for (let index = 0; index < schema.entries.length; index += 1) {
82
481
  const entry = schema.entries[index];
@@ -84,22 +483,58 @@ export function emitObjectCheck(schema, value, path, issues, context, emitChild)
84
483
  keys[index] = entry.key;
85
484
  }
86
485
  }
87
- parts.push(`const xs=Reflect.ownKeys(${value});for(let i=0;i<xs.length;i+=1){const key=xs[i];if(key!==undefined&&(typeof key!=="string"||!k[${String(pushKeyset(context, keys))}].includes(key))){${path}.push(typeof key==="string"?key:String(key));${emitIssue(issues, path, "unrecognized_key", "known key", stringLiteral("extra key"))}${path}.pop();}}`);
486
+ parts.push(`for(const key in ${value}){if(h.call(${value},key)&&!(${unsafeKeyMembershipExpression("key", keys)})){${emitIssueAtSegment(issues, path, "key", "unrecognized_key", "known key", stringLiteral("extra key"))}}}`);
88
487
  }
89
488
  return parts.join("");
90
489
  }
490
+ /**
491
+ * @brief Execute emit object field check.
492
+ * @details Code generation helpers keep emitted JavaScript shape stable across runtime and AOT paths.
493
+ */
494
+ function emitObjectFieldCheck(schema, value, path, segmentExpression, issues, context, emitChild) {
495
+ const leaf = emitLeafCheckAtSegment(schema, value, path, segmentExpression, issues, context);
496
+ if (leaf !== undefined) {
497
+ return leaf;
498
+ }
499
+ const composite = emitCompositeCheckAtSegment(schema, value, path, segmentExpression, issues, context);
500
+ if (composite !== undefined) {
501
+ return composite;
502
+ }
503
+ const child = emitChild(schema, context);
504
+ return `${path}.push(${segmentExpression});${child}(${value},${path},${issues});${path}.pop();`;
505
+ }
506
+ /**
507
+ * @brief Execute emit composite check at segment.
508
+ * @details Code generation helpers keep emitted JavaScript shape stable across runtime and AOT paths.
509
+ */
510
+ function emitCompositeCheckAtSegment(schema, value, path, segmentExpression, issues, context) {
511
+ switch (schema.tag) {
512
+ case SchemaTag.Array:
513
+ return emitArrayCheckAtSegment(schema.item, value, path, segmentExpression, issues, context);
514
+ case SchemaTag.Tuple:
515
+ return emitTupleCheckAtSegment(schema.items, value, path, segmentExpression, issues, context);
516
+ case SchemaTag.Record:
517
+ return emitRecordCheckAtSegment(schema.value, value, path, segmentExpression, issues, context);
518
+ default:
519
+ return undefined;
520
+ }
521
+ }
91
522
  /**
92
523
  * @brief emit discriminated union check.
524
+ * @details Generated-source helpers keep the side-table ABI and JavaScript source shape
525
+ * stable across runtime and AOT emission.
93
526
  */
94
527
  export function emitDiscriminatedUnionCheck(key, cases, value, path, issues, context, emitChild) {
528
+ if (isUnsafeMode(context)) {
529
+ return emitUnsafeDiscriminatedUnionCheck(key, cases, value, path, issues, context, emitChild);
530
+ }
95
531
  const keyRef = stringRef(context, key);
96
- const descriptor = `g(${value},${keyRef})`;
97
532
  const parts = [
98
- `if(!o(${value})){${emitIssue(issues, path, "expected_object", "object", `a(${value})`)}return;}`,
99
- `const dd=${descriptor};`,
100
- `if(dd===undefined){${path}.push(${keyRef});${emitIssue(issues, path, "expected_discriminant", "data property", stringLiteral("missing or accessor"))}${path}.pop();return;}`,
533
+ `if(${objectRejectExpression(value)}){${emitIssue(issues, path, "expected_object", "object", `a(${value})`)}return;}`,
534
+ `const dd=gp(${value},${keyRef});`,
535
+ `if(dd===undefined||!h.call(dd,"value")){${emitIssueAtSegment(issues, path, keyRef, "expected_discriminant", "data property", stringLiteral("missing or accessor"))}return;}`,
101
536
  "const dv=dd.value;",
102
- `if(typeof dv!=="string"){${path}.push(${keyRef});${emitIssue(issues, path, "expected_discriminant", "string discriminant", "a(dv)")}${path}.pop();return;}`
537
+ `if(typeof dv!=="string"){${emitIssueAtSegment(issues, path, keyRef, "expected_discriminant", "string discriminant", "a(dv)")}return;}`
103
538
  ];
104
539
  for (let index = 0; index < cases.length; index += 1) {
105
540
  const unionCase = cases[index];
@@ -112,6 +547,111 @@ export function emitDiscriminatedUnionCheck(key, cases, value, path, issues, con
112
547
  const check = emitChild(schema, context);
113
548
  parts.push(`if(Object.is(dv,l[${String(literalIndex)}])){${check}(${value},${path},${issues});return;}`);
114
549
  }
115
- parts.push(`${path}.push(${keyRef});${emitIssueExpr(issues, path, "expected_discriminant", stringLiteral("known discriminant"), "le(dv)")}${path}.pop();`);
550
+ parts.push(emitIssueExprAtSegment(issues, path, keyRef, "expected_discriminant", stringLiteral("known discriminant"), "le(dv)"));
551
+ return parts.join("");
552
+ }
553
+ /**
554
+ * @brief Execute emit unsafe discriminated union check.
555
+ * @details Code generation helpers keep emitted JavaScript shape stable across runtime and AOT paths.
556
+ */
557
+ function emitUnsafeDiscriminatedUnionCheck(key, cases, value, path, issues, context, emitChild) {
558
+ const keyRef = unsafeStringLiteralExpression(key);
559
+ const parts = [
560
+ `if(${objectRejectExpression(value)}){${emitIssue(issues, path, "expected_object", "object", `a(${value})`)}return;}`,
561
+ `const dv=${unsafePropertyReadExpression(value, key)};`,
562
+ `if(typeof dv!=="string"){${emitIssueAtSegment(issues, path, keyRef, "expected_discriminant", "string discriminant", "a(dv)")}return;}`
563
+ ];
564
+ for (let index = 0; index < cases.length; index += 1) {
565
+ const unionCase = cases[index];
566
+ if (unionCase === undefined) {
567
+ continue;
568
+ }
569
+ const literal = unionCase.literal;
570
+ const schema = unionCase.schema;
571
+ const check = emitChild(schema, context);
572
+ parts.push(`if(dv===${unsafeStringLiteralExpression(literal)}){${check}(${value},${path},${issues});return;}`);
573
+ }
574
+ parts.push(emitIssueExprAtSegment(issues, path, keyRef, "expected_discriminant", stringLiteral("known discriminant"), "le(dv)"));
116
575
  return parts.join("");
117
576
  }
577
+ /**
578
+ * @brief Execute object reject expression.
579
+ * @details Code generation helpers keep emitted JavaScript shape stable across runtime and AOT paths.
580
+ */
581
+ function objectRejectExpression(value) {
582
+ return `typeof ${value}!=="object"||${value}===null||Array.isArray(${value})`;
583
+ }
584
+ /**
585
+ * @brief Check unsafe mode.
586
+ * @details Code generation helpers keep emitted JavaScript shape stable across runtime and AOT paths.
587
+ */
588
+ function isUnsafeMode(context) {
589
+ return context.mode !== "safe";
590
+ }
591
+ /**
592
+ * @brief Check unchecked mode.
593
+ * @details Code generation helpers keep emitted JavaScript shape stable across runtime and AOT paths.
594
+ */
595
+ function isUncheckedMode(context) {
596
+ return context.mode === "unchecked";
597
+ }
598
+ /**
599
+ * @brief Execute unsafe property read expression.
600
+ * @details Code generation helpers keep emitted JavaScript shape stable across runtime and AOT paths.
601
+ */
602
+ function unsafePropertyReadExpression(objectExpression, key) {
603
+ if (isAsciiIdentifierName(key)) {
604
+ return `${objectExpression}.${key}`;
605
+ }
606
+ return `${objectExpression}[${unsafeStringLiteralExpression(key)}]`;
607
+ }
608
+ /**
609
+ * @brief Execute unsafe key membership expression.
610
+ * @details Code generation helpers keep emitted JavaScript shape stable across runtime and AOT paths.
611
+ */
612
+ function unsafeKeyMembershipExpression(key, keys) {
613
+ if (keys.length === 0) {
614
+ return "false";
615
+ }
616
+ const parts = new Array(keys.length);
617
+ for (let index = 0; index < keys.length; index += 1) {
618
+ const value = keys[index];
619
+ parts[index] = value === undefined
620
+ ? "false"
621
+ : `${key}===${unsafeStringLiteralExpression(value)}`;
622
+ }
623
+ return parts.join("||");
624
+ }
625
+ /**
626
+ * @brief Execute safe key membership expression.
627
+ * @details Code generation helpers keep emitted JavaScript shape stable across runtime and AOT paths.
628
+ */
629
+ function safeKeyMembershipExpression(key, keyExpressions) {
630
+ if (keyExpressions.length === 0) {
631
+ return "false";
632
+ }
633
+ const parts = new Array(keyExpressions.length);
634
+ for (let index = 0; index < keyExpressions.length; index += 1) {
635
+ const expression = keyExpressions[index];
636
+ parts[index] = expression === undefined
637
+ ? "false"
638
+ : `${key}===${expression}`;
639
+ }
640
+ return parts.join("||");
641
+ }
642
+ /**
643
+ * @brief Check ascii identifier name.
644
+ * @details Code generation helpers keep emitted JavaScript shape stable across runtime and AOT paths.
645
+ */
646
+ function isAsciiIdentifierName(value) {
647
+ return /^[A-Za-z_$][0-9A-Za-z_$]*$/u.test(value);
648
+ }
649
+ /**
650
+ * @brief Execute unsafe string literal expression.
651
+ * @details Code generation helpers keep emitted JavaScript shape stable across runtime and AOT paths.
652
+ */
653
+ function unsafeStringLiteralExpression(value) {
654
+ return JSON.stringify(value)
655
+ .replace(/\u2028/gu, "\\u2028")
656
+ .replace(/\u2029/gu, "\\u2029");
657
+ }