typesea 0.1.0 → 0.3.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 (301) hide show
  1. package/CHANGELOG.md +85 -6
  2. package/README.md +143 -28
  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 +19 -3
  7. package/dist/aot/index.d.ts.map +1 -1
  8. package/dist/aot/index.js +115 -17
  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 +43 -9
  13. package/dist/builders/composite.d.ts.map +1 -1
  14. package/dist/builders/composite.js +100 -17
  15. package/dist/builders/index.d.ts +8 -5
  16. package/dist/builders/index.d.ts.map +1 -1
  17. package/dist/builders/index.js +7 -4
  18. package/dist/builders/modifier.d.ts +36 -5
  19. package/dist/builders/modifier.d.ts.map +1 -1
  20. package/dist/builders/modifier.js +52 -5
  21. package/dist/builders/object/guard.d.ts +72 -24
  22. package/dist/builders/object/guard.d.ts.map +1 -1
  23. package/dist/builders/object/guard.js +139 -29
  24. package/dist/builders/object/index.d.ts +4 -2
  25. package/dist/builders/object/index.d.ts.map +1 -1
  26. package/dist/builders/object/index.js +3 -1
  27. package/dist/builders/object/schema.d.ts +88 -11
  28. package/dist/builders/object/schema.d.ts.map +1 -1
  29. package/dist/builders/object/schema.js +290 -23
  30. package/dist/builders/object/types.d.ts +20 -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/runtime.d.ts +40 -0
  34. package/dist/builders/runtime.d.ts.map +1 -0
  35. package/dist/builders/runtime.js +150 -0
  36. package/dist/builders/scalar.d.ts +49 -9
  37. package/dist/builders/scalar.d.ts.map +1 -1
  38. package/dist/builders/scalar.js +87 -9
  39. package/dist/builders/table.d.ts +35 -5
  40. package/dist/builders/table.d.ts.map +1 -1
  41. package/dist/builders/table.js +35 -5
  42. package/dist/builders/types.d.ts +20 -4
  43. package/dist/builders/types.d.ts.map +1 -1
  44. package/dist/builders/types.js +2 -0
  45. package/dist/compile/check-composite.d.ts +25 -2
  46. package/dist/compile/check-composite.d.ts.map +1 -1
  47. package/dist/compile/check-composite.js +699 -27
  48. package/dist/compile/check-scalar.d.ts +88 -0
  49. package/dist/compile/check-scalar.d.ts.map +1 -1
  50. package/dist/compile/check-scalar.js +570 -3
  51. package/dist/compile/check.d.ts +12 -0
  52. package/dist/compile/check.d.ts.map +1 -1
  53. package/dist/compile/check.js +62 -3
  54. package/dist/compile/context.d.ts +47 -9
  55. package/dist/compile/context.d.ts.map +1 -1
  56. package/dist/compile/context.js +53 -8
  57. package/dist/compile/first.d.ts +26 -0
  58. package/dist/compile/first.d.ts.map +1 -0
  59. package/dist/compile/first.js +850 -0
  60. package/dist/compile/graph-predicate.d.ts +4 -2
  61. package/dist/compile/graph-predicate.d.ts.map +1 -1
  62. package/dist/compile/graph-predicate.js +2272 -165
  63. package/dist/compile/guard.d.ts +16 -24
  64. package/dist/compile/guard.d.ts.map +1 -1
  65. package/dist/compile/guard.js +202 -72
  66. package/dist/compile/index.d.ts +3 -1
  67. package/dist/compile/index.d.ts.map +1 -1
  68. package/dist/compile/index.js +2 -0
  69. package/dist/compile/issue.d.ts +110 -0
  70. package/dist/compile/issue.d.ts.map +1 -1
  71. package/dist/compile/issue.js +184 -1
  72. package/dist/compile/names.d.ts +12 -2
  73. package/dist/compile/names.d.ts.map +1 -1
  74. package/dist/compile/names.js +19 -3
  75. package/dist/compile/predicate.d.ts +24 -0
  76. package/dist/compile/predicate.d.ts.map +1 -1
  77. package/dist/compile/predicate.js +287 -10
  78. package/dist/compile/runtime.d.ts +100 -13
  79. package/dist/compile/runtime.d.ts.map +1 -1
  80. package/dist/compile/runtime.js +56 -6
  81. package/dist/compile/source.d.ts +10 -2
  82. package/dist/compile/source.d.ts.map +1 -1
  83. package/dist/compile/source.js +385 -26
  84. package/dist/compile/types.d.ts +22 -0
  85. package/dist/compile/types.d.ts.map +1 -1
  86. package/dist/compile/types.js +2 -0
  87. package/dist/decoder/index.d.ts +92 -46
  88. package/dist/decoder/index.d.ts.map +1 -1
  89. package/dist/decoder/index.js +266 -39
  90. package/dist/evaluate/check-composite.d.ts +111 -2
  91. package/dist/evaluate/check-composite.d.ts.map +1 -1
  92. package/dist/evaluate/check-composite.js +343 -8
  93. package/dist/evaluate/check-scalar.d.ts +25 -0
  94. package/dist/evaluate/check-scalar.d.ts.map +1 -1
  95. package/dist/evaluate/check-scalar.js +124 -3
  96. package/dist/evaluate/check.d.ts +7 -0
  97. package/dist/evaluate/check.d.ts.map +1 -1
  98. package/dist/evaluate/check.js +62 -4
  99. package/dist/evaluate/index.d.ts +2 -0
  100. package/dist/evaluate/index.d.ts.map +1 -1
  101. package/dist/evaluate/index.js +2 -0
  102. package/dist/evaluate/issue.d.ts +11 -1
  103. package/dist/evaluate/issue.d.ts.map +1 -1
  104. package/dist/evaluate/issue.js +15 -1
  105. package/dist/evaluate/predicate.d.ts +16 -5
  106. package/dist/evaluate/predicate.d.ts.map +1 -1
  107. package/dist/evaluate/predicate.js +20 -5
  108. package/dist/evaluate/shared.d.ts +78 -13
  109. package/dist/evaluate/shared.d.ts.map +1 -1
  110. package/dist/evaluate/shared.js +101 -8
  111. package/dist/evaluate/state.d.ts +35 -13
  112. package/dist/evaluate/state.d.ts.map +1 -1
  113. package/dist/evaluate/state.js +35 -2
  114. package/dist/guard/array.d.ts +48 -0
  115. package/dist/guard/array.d.ts.map +1 -0
  116. package/dist/guard/array.js +84 -0
  117. package/dist/guard/base.d.ts +111 -31
  118. package/dist/guard/base.d.ts.map +1 -1
  119. package/dist/guard/base.js +165 -32
  120. package/dist/guard/date.d.ts +34 -0
  121. package/dist/guard/date.d.ts.map +1 -0
  122. package/dist/guard/date.js +60 -0
  123. package/dist/guard/error.d.ts +10 -5
  124. package/dist/guard/error.d.ts.map +1 -1
  125. package/dist/guard/error.js +10 -5
  126. package/dist/guard/index.d.ts +4 -0
  127. package/dist/guard/index.d.ts.map +1 -1
  128. package/dist/guard/index.js +4 -0
  129. package/dist/guard/number.d.ts +86 -11
  130. package/dist/guard/number.d.ts.map +1 -1
  131. package/dist/guard/number.js +159 -11
  132. package/dist/guard/props.d.ts +27 -3
  133. package/dist/guard/props.d.ts.map +1 -1
  134. package/dist/guard/props.js +27 -3
  135. package/dist/guard/read.d.ts +115 -10
  136. package/dist/guard/read.d.ts.map +1 -1
  137. package/dist/guard/read.js +185 -10
  138. package/dist/guard/registry.d.ts +12 -2
  139. package/dist/guard/registry.d.ts.map +1 -1
  140. package/dist/guard/registry.js +15 -3
  141. package/dist/guard/string.d.ts +115 -13
  142. package/dist/guard/string.d.ts.map +1 -1
  143. package/dist/guard/string.js +250 -13
  144. package/dist/guard/types.d.ts +110 -40
  145. package/dist/guard/types.d.ts.map +1 -1
  146. package/dist/guard/types.js +2 -0
  147. package/dist/index.d.ts +5 -5
  148. package/dist/index.d.ts.map +1 -1
  149. package/dist/index.js +4 -4
  150. package/dist/internal/index.d.ts +42 -6
  151. package/dist/internal/index.d.ts.map +1 -1
  152. package/dist/internal/index.js +51 -8
  153. package/dist/ir/builder.d.ts +17 -127
  154. package/dist/ir/builder.d.ts.map +1 -1
  155. package/dist/ir/builder.js +80 -137
  156. package/dist/ir/freeze.d.ts +4 -0
  157. package/dist/ir/freeze.d.ts.map +1 -1
  158. package/dist/ir/freeze.js +66 -0
  159. package/dist/ir/index.d.ts +3 -1
  160. package/dist/ir/index.d.ts.map +1 -1
  161. package/dist/ir/index.js +2 -0
  162. package/dist/ir/regexp.d.ts +2 -0
  163. package/dist/ir/regexp.d.ts.map +1 -1
  164. package/dist/ir/regexp.js +2 -0
  165. package/dist/ir/types.d.ts +94 -56
  166. package/dist/ir/types.d.ts.map +1 -1
  167. package/dist/ir/types.js +2 -0
  168. package/dist/ir/validate.d.ts +8 -1
  169. package/dist/ir/validate.d.ts.map +1 -1
  170. package/dist/ir/validate.js +511 -61
  171. package/dist/issue/index.d.ts +42 -10
  172. package/dist/issue/index.d.ts.map +1 -1
  173. package/dist/issue/index.js +65 -11
  174. package/dist/json-schema/emit-combinator.d.ts +44 -4
  175. package/dist/json-schema/emit-combinator.d.ts.map +1 -1
  176. package/dist/json-schema/emit-combinator.js +44 -4
  177. package/dist/json-schema/emit-composite.d.ts +16 -2
  178. package/dist/json-schema/emit-composite.d.ts.map +1 -1
  179. package/dist/json-schema/emit-composite.js +81 -13
  180. package/dist/json-schema/emit-scalar.d.ts +26 -3
  181. package/dist/json-schema/emit-scalar.d.ts.map +1 -1
  182. package/dist/json-schema/emit-scalar.js +124 -10
  183. package/dist/json-schema/emit-types.d.ts +11 -1
  184. package/dist/json-schema/emit-types.d.ts.map +1 -1
  185. package/dist/json-schema/emit-types.js +2 -0
  186. package/dist/json-schema/emit.d.ts +12 -1
  187. package/dist/json-schema/emit.d.ts.map +1 -1
  188. package/dist/json-schema/emit.js +23 -3
  189. package/dist/json-schema/freeze.d.ts +13 -2
  190. package/dist/json-schema/freeze.d.ts.map +1 -1
  191. package/dist/json-schema/freeze.js +41 -8
  192. package/dist/json-schema/index.d.ts +16 -2
  193. package/dist/json-schema/index.d.ts.map +1 -1
  194. package/dist/json-schema/index.js +23 -3
  195. package/dist/json-schema/issue.d.ts +4 -1
  196. package/dist/json-schema/issue.d.ts.map +1 -1
  197. package/dist/json-schema/issue.js +4 -1
  198. package/dist/json-schema/read.d.ts +24 -3
  199. package/dist/json-schema/read.d.ts.map +1 -1
  200. package/dist/json-schema/read.js +59 -12
  201. package/dist/json-schema/types.d.ts +45 -16
  202. package/dist/json-schema/types.d.ts.map +1 -1
  203. package/dist/json-schema/types.js +2 -0
  204. package/dist/kind/index.d.ts +40 -28
  205. package/dist/kind/index.d.ts.map +1 -1
  206. package/dist/kind/index.js +41 -13
  207. package/dist/lower/index.d.ts +6 -1
  208. package/dist/lower/index.d.ts.map +1 -1
  209. package/dist/lower/index.js +462 -46
  210. package/dist/message/index.d.ts +64 -10
  211. package/dist/message/index.d.ts.map +1 -1
  212. package/dist/message/index.js +155 -17
  213. package/dist/optimize/algebraic.d.ts +54 -0
  214. package/dist/optimize/algebraic.d.ts.map +1 -0
  215. package/dist/optimize/algebraic.js +314 -0
  216. package/dist/optimize/compact.d.ts +8 -1
  217. package/dist/optimize/compact.d.ts.map +1 -1
  218. package/dist/optimize/compact.js +13 -2
  219. package/dist/optimize/domain.d.ts +16 -0
  220. package/dist/optimize/domain.d.ts.map +1 -0
  221. package/dist/optimize/domain.js +619 -0
  222. package/dist/optimize/fold-boolean.d.ts +17 -2
  223. package/dist/optimize/fold-boolean.d.ts.map +1 -1
  224. package/dist/optimize/fold-boolean.js +59 -14
  225. package/dist/optimize/fold-common.d.ts +43 -8
  226. package/dist/optimize/fold-common.d.ts.map +1 -1
  227. package/dist/optimize/fold-common.js +37 -6
  228. package/dist/optimize/fold-constraints.d.ts +33 -0
  229. package/dist/optimize/fold-constraints.d.ts.map +1 -0
  230. package/dist/optimize/fold-constraints.js +484 -0
  231. package/dist/optimize/fold-scalar.d.ts +98 -13
  232. package/dist/optimize/fold-scalar.d.ts.map +1 -1
  233. package/dist/optimize/fold-scalar.js +98 -13
  234. package/dist/optimize/fold.d.ts +8 -1
  235. package/dist/optimize/fold.d.ts.map +1 -1
  236. package/dist/optimize/fold.js +22 -2
  237. package/dist/optimize/index.d.ts +9 -1
  238. package/dist/optimize/index.d.ts.map +1 -1
  239. package/dist/optimize/index.js +18 -3
  240. package/dist/optimize/map-node.d.ts +3 -1
  241. package/dist/optimize/map-node.d.ts.map +1 -1
  242. package/dist/optimize/map-node.js +48 -3
  243. package/dist/optimize/peephole.d.ts +16 -0
  244. package/dist/optimize/peephole.d.ts.map +1 -0
  245. package/dist/optimize/peephole.js +254 -0
  246. package/dist/optimize/remap.d.ts +2 -0
  247. package/dist/optimize/remap.d.ts.map +1 -1
  248. package/dist/optimize/remap.js +2 -0
  249. package/dist/optimize/rewrite.d.ts +13 -8
  250. package/dist/optimize/rewrite.d.ts.map +1 -1
  251. package/dist/optimize/rewrite.js +13 -8
  252. package/dist/plan/cache.d.ts +9 -3
  253. package/dist/plan/cache.d.ts.map +1 -1
  254. package/dist/plan/cache.js +34 -6
  255. package/dist/plan/index.d.ts +2 -0
  256. package/dist/plan/index.d.ts.map +1 -1
  257. package/dist/plan/index.js +2 -0
  258. package/dist/plan/predicate.d.ts +2 -0
  259. package/dist/plan/predicate.d.ts.map +1 -1
  260. package/dist/plan/predicate.js +298 -29
  261. package/dist/plan/schema-predicate.d.ts +6 -0
  262. package/dist/plan/schema-predicate.d.ts.map +1 -1
  263. package/dist/plan/schema-predicate.js +382 -19
  264. package/dist/plan/types.d.ts +2 -0
  265. package/dist/plan/types.d.ts.map +1 -1
  266. package/dist/plan/types.js +2 -0
  267. package/dist/result/index.d.ts +19 -5
  268. package/dist/result/index.d.ts.map +1 -1
  269. package/dist/result/index.js +10 -2
  270. package/dist/schema/common.d.ts +69 -6
  271. package/dist/schema/common.d.ts.map +1 -1
  272. package/dist/schema/common.js +104 -10
  273. package/dist/schema/freeze.d.ts +4 -0
  274. package/dist/schema/freeze.d.ts.map +1 -1
  275. package/dist/schema/freeze.js +40 -0
  276. package/dist/schema/index.d.ts +5 -2
  277. package/dist/schema/index.d.ts.map +1 -1
  278. package/dist/schema/index.js +4 -1
  279. package/dist/schema/lazy.d.ts +4 -0
  280. package/dist/schema/lazy.d.ts.map +1 -1
  281. package/dist/schema/lazy.js +4 -0
  282. package/dist/schema/literal.d.ts +7 -1
  283. package/dist/schema/literal.d.ts.map +1 -1
  284. package/dist/schema/literal.js +7 -1
  285. package/dist/schema/types.d.ts +109 -100
  286. package/dist/schema/types.d.ts.map +1 -1
  287. package/dist/schema/types.js +13 -2
  288. package/dist/schema/undefined.d.ts +17 -0
  289. package/dist/schema/undefined.d.ts.map +1 -0
  290. package/dist/schema/undefined.js +77 -0
  291. package/dist/schema/validate.d.ts +8 -1
  292. package/dist/schema/validate.d.ts.map +1 -1
  293. package/dist/schema/validate.js +255 -57
  294. package/docs/api.md +128 -8
  295. package/docs/assets/benchmark-headline.svg +163 -0
  296. package/docs/engine-notes.md +62 -15
  297. package/docs/index.html +1340 -702
  298. package/docs/ko/api.md +375 -0
  299. package/docs/ko/engine-notes.md +156 -0
  300. package/docs/ko/readme.md +378 -0
  301. package/package.json +66 -65
@@ -1,6 +1,8 @@
1
1
  /**
2
2
  * @file compile-runtime.ts
3
3
  * @brief Runtime support passed into generated validator factories.
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
  * @section side_tables Side-table ABI
6
8
  * Generated validators receive literals, regexps, keysets, strings, and
@@ -9,7 +11,12 @@
9
11
  */
10
12
  import { checkSchema, isSchema } from "../evaluate/index.js";
11
13
  /**
12
- * @brief make dynamic check.
14
+ * @brief Build the boolean fallback table reader for generated validators.
15
+ * @details Missing table slots fail closed. That preserves the security
16
+ * invariant that malformed generated code cannot accidentally accept a value by
17
+ * indexing outside the schema side table.
18
+ * @param schemas Schema side table captured by the compiled guard.
19
+ * @returns Boolean fallback callback used by emitted predicates.
13
20
  */
14
21
  export function makeDynamicCheck(schemas) {
15
22
  return (schemaIndex, value) => {
@@ -18,7 +25,12 @@ export function makeDynamicCheck(schemas) {
18
25
  };
19
26
  }
20
27
  /**
21
- * @brief make dynamic issue check.
28
+ * @brief Build the diagnostic fallback table reader for generated validators.
29
+ * @details Nested interpreter issues are re-rooted under the path supplied by
30
+ * generated code. This lets compiled object and array checks delegate complex
31
+ * children without losing exact issue locations.
32
+ * @param schemas Schema side table captured by the compiled guard.
33
+ * @returns Issue fallback callback used by emitted collectors.
22
34
  */
23
35
  export function makeDynamicIssueCheck(schemas) {
24
36
  return (schemaIndex, value, path, issues) => {
@@ -34,19 +46,57 @@ export function makeDynamicIssueCheck(schemas) {
34
46
  for (let index = 0; index < nested.length; index += 1) {
35
47
  const issue = nested[index];
36
48
  if (issue !== undefined) {
37
- issues.push({
38
- path: path.concat(issue.path),
49
+ const nestedPath = Object.freeze(path.concat(issue.path));
50
+ issues.push(Object.freeze({
51
+ path: nestedPath,
39
52
  code: issue.code,
40
53
  expected: issue.expected,
41
54
  actual: issue.actual,
42
55
  message: issue.message
43
- });
56
+ }));
44
57
  }
45
58
  }
46
59
  };
47
60
  }
48
61
  /**
49
- * @brief strict keys.
62
+ * @brief Build the first-fault fallback table reader for generated validators.
63
+ * @details This path is entered only for opaque schema fragments that codegen
64
+ * cannot inline. The nested interpreter result is re-rooted once and returned.
65
+ * @param schemas Schema side table captured by the compiled guard.
66
+ * @returns First-issue fallback callback used by emitted collectors.
67
+ */
68
+ export function makeDynamicFirstIssueCheck(schemas) {
69
+ return (schemaIndex, value, path) => {
70
+ const schema = schemas[schemaIndex];
71
+ if (schema === undefined) {
72
+ return undefined;
73
+ }
74
+ const result = checkSchema(schema, value);
75
+ if (result.ok) {
76
+ return undefined;
77
+ }
78
+ const issue = result.error[0];
79
+ if (issue === undefined) {
80
+ return undefined;
81
+ }
82
+ const nestedPath = Object.freeze(path.concat(issue.path));
83
+ return Object.freeze({
84
+ path: nestedPath,
85
+ code: issue.code,
86
+ expected: issue.expected,
87
+ actual: issue.actual,
88
+ message: issue.message
89
+ });
90
+ };
91
+ }
92
+ /**
93
+ * @brief Safe strict-object key membership helper for generated validators.
94
+ * @details The default compiled mode uses Reflect.ownKeys so symbol and
95
+ * non-enumerable extras are rejected as strictly as the interpreter. Unsafe
96
+ * modes may emit a cheaper loop, but this helper remains the conservative ABI.
97
+ * @param value Candidate object value.
98
+ * @param keys Allowed string keys for the strict object schema.
99
+ * @returns True when every own key belongs to the schema key set.
50
100
  */
51
101
  export function strictKeys(value, keys) {
52
102
  if (typeof value !== "object" || value === null || Array.isArray(value)) {
@@ -1,11 +1,19 @@
1
1
  /**
2
2
  * @file compile/source.ts
3
3
  * @brief Generated validator source bundle assembly.
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 type { Schema } from "../schema/index.js";
6
- import type { CompiledSourceBundle } from "./types.js";
8
+ import type { CompileMode, CompiledSourceBundle } from "./types.js";
7
9
  /**
8
10
  * @brief emit compiled source bundle.
11
+ * @details Generated-source helpers keep the side-table ABI and JavaScript source shape
12
+ * stable across runtime and AOT emission.
13
+ * @param schema Root schema to compile.
14
+ * @param name Requested public function name.
15
+ * @param mode Compile mode controlling safety and allocation tradeoffs.
16
+ * @returns Generated source plus side tables consumed by the runtime factory.
9
17
  */
10
- export declare function emitCompiledSourceBundle(schema: Schema, name: string): CompiledSourceBundle;
18
+ export declare function emitCompiledSourceBundle(schema: Schema, name: string, mode?: CompileMode): CompiledSourceBundle;
11
19
  //# sourceMappingURL=source.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"source.d.ts","sourceRoot":"","sources":["../../src/compile/source.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAKjD,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AAEvD;;GAEG;AACH,wBAAgB,wBAAwB,CACtC,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,MAAM,GACX,oBAAoB,CAuCtB"}
1
+ {"version":3,"file":"source.d.ts","sourceRoot":"","sources":["../../src/compile/source.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAMjD,OAAO,KAAK,EAAE,WAAW,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AAEpE;;;;;;;;GAQG;AACH,wBAAgB,wBAAwB,CACpC,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,MAAM,EACZ,IAAI,GAAE,WAAoB,GAC3B,oBAAoB,CAsDtB"}
@@ -1,44 +1,64 @@
1
1
  /**
2
2
  * @file compile/source.ts
3
3
  * @brief Generated validator source bundle assembly.
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 { emitCheckFunction, emitCheckFunctions } from "./check.js";
6
8
  import { createEmitContext } from "./context.js";
9
+ import { emitFirstFunction, emitFirstFunctions } from "./first.js";
7
10
  import { emitGraphFunction, emitGraphFunctions } from "./graph-predicate.js";
8
11
  import { safeFunctionName } from "./names.js";
9
12
  /**
10
13
  * @brief emit compiled source bundle.
14
+ * @details Generated-source helpers keep the side-table ABI and JavaScript source shape
15
+ * stable across runtime and AOT emission.
16
+ * @param schema Root schema to compile.
17
+ * @param name Requested public function name.
18
+ * @param mode Compile mode controlling safety and allocation tradeoffs.
19
+ * @returns Generated source plus side tables consumed by the runtime factory.
11
20
  */
12
- export function emitCompiledSourceBundle(schema, name) {
13
- const context = createEmitContext();
14
- const root = emitGraphFunction(schema, context);
15
- const checkRoot = emitCheckFunction(schema, context);
21
+ export function emitCompiledSourceBundle(schema, name, mode = "safe") {
22
+ const context = createEmitContext(mode);
16
23
  const functionName = safeFunctionName(name);
24
+ const directRoot = canUseDirectRootFunctionName(functionName);
25
+ /*
26
+ * A direct root function gives V8 a stable, named hot predicate. Names that
27
+ * collide with helper or generated ids are wrapped to avoid shadowing.
28
+ */
29
+ const root = emitGraphFunction(schema, context, directRoot ? functionName : undefined);
30
+ const checkRoot = emitCheckFunction(schema, context);
31
+ const firstRoot = emitFirstFunction(schema, context);
17
32
  const checkFunctionName = `${functionName}_check`;
33
+ const resultFunctionName = `${functionName}_result`;
34
+ const firstFunctionName = `${functionName}_first`;
35
+ const isProperty = directRoot
36
+ ? `is:${root}`
37
+ : `is:function ${functionName}(x){return ${root}(x);}`;
38
+ const graphFunctions = emitGraphFunctions(context);
39
+ const checkFunctions = emitCheckFunctions(context);
40
+ const firstFunctions = emitFirstFunctions(context);
41
+ const rootPathIsFrozen = canReuseFrozenRootPath(checkFunctions);
42
+ const firstPathIsFrozen = canReuseFrozenRootPath(firstFunctions);
43
+ const rootPath = rootPathIsFrozen ? "z" : "[]";
44
+ const firstPath = firstPathIsFrozen ? "z" : "[]";
45
+ /*
46
+ * Boolean is() owns the hot path; check()/result() first reuse it so valid
47
+ * data avoids diagnostic allocation. Only failing inputs enter the check tree.
48
+ */
49
+ const issueCollector = `check:function ${checkFunctionName}(x){if(${root}(x))return;const s=[];${checkRoot}(x,${rootPath},s);return s;}`;
50
+ const resultCollector = `result:function ${resultFunctionName}(x){if(${root}(x))return ${emitSuccessResult(mode, "x")};const s=[];${checkRoot}(x,${rootPath},s);return Object.freeze({ok:false,error:Object.freeze(s)});}`;
51
+ const firstCollector = `first:function ${firstFunctionName}(x){if(${root}(x))return ${emitSuccessResult(mode, "x")};const e=${firstRoot}(x,${firstPath});if(e===undefined)return ${emitSuccessResult(mode, "x")};return Object.freeze({ok:false,error:Object.freeze([e])});}`;
52
+ const body = [
53
+ graphFunctions,
54
+ checkFunctions,
55
+ firstFunctions,
56
+ `return {${isProperty},${issueCollector},${resultCollector},${firstCollector}};`
57
+ ].join("");
18
58
  const source = [
19
59
  "\"use strict\";",
20
- "const h=Object.prototype.hasOwnProperty;",
21
- "const gp=Object.getOwnPropertyDescriptor;",
22
- "const o=function(v){return typeof v===\"object\"&&v!==null&&!Array.isArray(v);};",
23
- "const ph=function(v){return (typeof v===\"object\"&&v!==null)||typeof v===\"function\";};",
24
- "const g=function(v,k){const d=gp(v,k);return d!==undefined&&h.call(d,\"value\")?d:undefined;};",
25
- "const gv=function(v,k){if(!ph(v))return undefined;const d=gp(v,k);return d!==undefined&&h.call(d,\"value\")?d.value:undefined;};",
26
- "const ho=function(v,k){return ph(v)&&h.call(v,k);};",
27
- "const hd=function(v,k){if(!ph(v))return false;const d=gp(v,k);return d!==undefined&&h.call(d,\"value\");};",
28
- "const fn=function(v){return typeof v===\"number\"&&Number.isFinite(v);};",
29
- "const nc=function(x,y,gte){return typeof x===\"number\"&&typeof y===\"number\"&&(gte?x>=y:x<=y);};",
30
- "const sb=function(v,b,min){return typeof v===\"string\"&&(min?v.length>=b:v.length<=b);};",
31
- "const rx=function(v,re){if(typeof v!==\"string\")return false;re.lastIndex=0;const ok=re.test(v);re.lastIndex=0;return ok;};",
32
- "const ea=function(v,f){if(!Array.isArray(v))return false;for(let i=0;i<v.length;i+=1){const d=gp(v,i);if(d!==undefined&&!h.call(d,\"value\"))return false;if(!f(d===undefined?undefined:d.value))return false;}return true;};",
33
- "const ev=function(v,i,f){const d=gp(v,i);if(d!==undefined&&!h.call(d,\"value\"))return false;return f(d===undefined?undefined:d.value);};",
34
- "const er=function(v,f){if(!o(v))return false;const ks=Object.keys(v);for(let i=0;i<ks.length;i+=1){const key=ks[i];if(key===undefined)return false;const d=gp(v,key);if(d===undefined||!h.call(d,\"value\")||!f(d.value))return false;}return true;};",
35
- "const dj=function(v,key,ks){if(!o(v))return false;const d=g(v,key);if(d===undefined||typeof d.value!==\"string\")return false;const i=ks.indexOf(d.value);return i>=0&&arguments[i+3](v);};",
36
- "const a=function(v){if(v===null)return \"null\";if(Array.isArray(v))return \"array\";if(typeof v===\"bigint\")return \"bigint\";if(typeof v===\"symbol\")return \"symbol\";if(typeof v===\"number\"&&Number.isNaN(v))return \"nan\";return typeof v;};",
37
- "const le=function(v){if(v===null)return \"null\";if(v===undefined)return \"undefined\";if(typeof v===\"string\")return JSON.stringify(v);if(typeof v===\"number\"&&Object.is(v,-0))return \"-0\";if(typeof v===\"symbol\")return String(v);return String(v);};",
38
- "const q=function(s,p,c,e,x){s.push({path:p.slice(),code:c,expected:e,actual:x,message:undefined});};",
39
- emitGraphFunctions(context),
40
- emitCheckFunctions(context),
41
- `return {is:function ${functionName}(x){return ${root}(x);},check:function ${checkFunctionName}(x){const s=[];if(${root}(x))return s;${checkRoot}(x,[],s);return s;}};`
60
+ emitHelperPrelude(body, rootPathIsFrozen),
61
+ body
42
62
  ].join("");
43
63
  return {
44
64
  source,
@@ -49,3 +69,342 @@ export function emitCompiledSourceBundle(schema, name) {
49
69
  dynamicSchemas: context.schemas
50
70
  };
51
71
  }
72
+ /**
73
+ * @brief Emit the success Result expression for compiled result().
74
+ * @details Generated-source helpers keep the side-table ABI and JavaScript source shape
75
+ * stable across runtime and AOT emission.
76
+ * @param mode Compile mode controlling object freezing.
77
+ * @param value Generated expression for the accepted runtime value.
78
+ * @returns JavaScript source for the success branch.
79
+ */
80
+ function emitSuccessResult(mode, value) {
81
+ if (mode === "safe") {
82
+ return `Object.freeze({ok:true,value:${value}})`;
83
+ }
84
+ return `{ok:true,value:${value}}`;
85
+ }
86
+ /**
87
+ * @brief Decide whether the root predicate can use the public function name.
88
+ * @details Generated-source helpers keep the side-table ABI and JavaScript source shape
89
+ * stable across runtime and AOT emission.
90
+ * @param name Sanitized generated function name.
91
+ * @returns True when the name cannot shadow helpers or generated child ids.
92
+ */
93
+ function canUseDirectRootFunctionName(name) {
94
+ return !isRuntimeHelperName(name) &&
95
+ !isFactoryParameterName(name) &&
96
+ !isGeneratedFunctionName(name);
97
+ }
98
+ /**
99
+ * @brief Decide whether the generated check tree mutates the path stack.
100
+ * @details Generated-source helpers keep the side-table ABI and JavaScript source shape
101
+ * stable across runtime and AOT emission.
102
+ * @param checkFunctions Generated diagnostic function source.
103
+ * @returns True when the frozen empty path singleton can be reused.
104
+ */
105
+ function canReuseFrozenRootPath(checkFunctions) {
106
+ return !checkFunctions.includes("p.push(");
107
+ }
108
+ /**
109
+ * @brief Test whether a name is a generated factory parameter.
110
+ * @details Generated-source helpers keep the side-table ABI and JavaScript source shape
111
+ * stable across runtime and AOT emission.
112
+ * @param name Candidate identifier.
113
+ * @returns True when the name would shadow a factory side table.
114
+ */
115
+ function isFactoryParameterName(name) {
116
+ switch (name) {
117
+ case "l":
118
+ case "r":
119
+ case "k":
120
+ case "u":
121
+ case "d":
122
+ case "m":
123
+ case "mf":
124
+ case "sk":
125
+ case "w":
126
+ return true;
127
+ default:
128
+ return false;
129
+ }
130
+ }
131
+ /**
132
+ * @brief Test whether a name matches TypeSea child function naming.
133
+ * @details Generated-source helpers keep the side-table ABI and JavaScript source shape
134
+ * stable across runtime and AOT emission.
135
+ * @param name Candidate identifier.
136
+ * @returns True for generated predicate/check names such as `p0` or `c12`.
137
+ */
138
+ function isGeneratedFunctionName(name) {
139
+ if (name.length < 2) {
140
+ return false;
141
+ }
142
+ const first = name.charCodeAt(0);
143
+ if (first !== 99 && first !== 112) {
144
+ return false;
145
+ }
146
+ for (let index = 1; index < name.length; index += 1) {
147
+ const code = name.charCodeAt(index);
148
+ if (code < 48 || code > 57) {
149
+ return false;
150
+ }
151
+ }
152
+ return true;
153
+ }
154
+ /**
155
+ * @brief emit helper prelude.
156
+ * @details Generated-source helpers keep the side-table ABI and JavaScript source shape
157
+ * stable across runtime and AOT emission.
158
+ * @param body Generated factory body without helper definitions.
159
+ * @param rootPathIsFrozen True when path helpers may use the frozen empty path.
160
+ * @returns JavaScript source for only the helpers referenced by `body`.
161
+ */
162
+ function emitHelperPrelude(body, rootPathIsFrozen) {
163
+ const needed = readNeededHelpers(body);
164
+ const chunks = [];
165
+ pushHelper(chunks, needed, "z", "const z=Object.freeze([]);");
166
+ pushHelper(chunks, needed, "h", "const h=Object.prototype.hasOwnProperty;");
167
+ pushHelper(chunks, needed, "gp", "const gp=Object.getOwnPropertyDescriptor;");
168
+ pushHelper(chunks, needed, "o", "const o=function(v){return typeof v===\"object\"&&v!==null&&!Array.isArray(v);};");
169
+ pushHelper(chunks, needed, "ph", "const ph=function(v){return (typeof v===\"object\"&&v!==null)||typeof v===\"function\";};");
170
+ pushHelper(chunks, needed, "g", "const g=function(v,k){const d=gp(v,k);return d!==undefined&&h.call(d,\"value\")?d:undefined;};");
171
+ pushHelper(chunks, needed, "gv", "const gv=function(v,k){if(!ph(v))return undefined;const d=gp(v,k);return d!==undefined&&h.call(d,\"value\")?d.value:undefined;};");
172
+ pushHelper(chunks, needed, "ho", "const ho=function(v,k){return ph(v)&&h.call(v,k);};");
173
+ pushHelper(chunks, needed, "hd", "const hd=function(v,k){if(!ph(v))return false;const d=gp(v,k);return d!==undefined&&h.call(d,\"value\");};");
174
+ pushHelper(chunks, needed, "fn", "const fn=function(v){return typeof v===\"number\"&&Number.isFinite(v);};");
175
+ pushHelper(chunks, needed, "nc", "const nc=function(x,y,gte){return typeof x===\"number\"&&typeof y===\"number\"&&(gte?x>=y:x<=y);};");
176
+ pushHelper(chunks, needed, "dg", "const __tg=Date.prototype.getTime;const dg=function(v){return v instanceof Date&&Number.isFinite(__tg.call(v));};const dt=function(v){return __tg.call(v);};");
177
+ pushHelper(chunks, needed, "sb", "const sb=function(v,b,min){return typeof v===\"string\"&&(min?v.length>=b:v.length<=b);};");
178
+ pushHelper(chunks, needed, "rx", "const rx=function(v,re){if(typeof v!==\"string\")return false;re.lastIndex=0;const ok=re.test(v);re.lastIndex=0;return ok;};");
179
+ pushHelper(chunks, needed, "ai", "const ai=function(k,n){if(k.length===0||k===\"length\")return false;const i=Number(k);return Number.isInteger(i)&&i>=0&&i<=4294967294&&i<n&&String(i)===k;};");
180
+ pushHelper(chunks, needed, "ea", "const ea=function(v,f){if(!Array.isArray(v))return false;for(let i=0;i<v.length;i+=1){const d=gp(v,i);if(!f(d===undefined?undefined:d.value))return false;}return true;};");
181
+ pushHelper(chunks, needed, "eu", "const eu=function(v,f){if(!Array.isArray(v))return false;const xs=Object.getOwnPropertyNames(v);for(let i=0;i<xs.length;i+=1){const k=xs[i];if(!ai(k,v.length))continue;const d=gp(v,k);if(d!==undefined&&!h.call(d,\"value\"))return false;if(d!==undefined&&!f(d.value))return false;}return true;};");
182
+ pushHelper(chunks, needed, "ev", "const ev=function(v,i,f){const d=gp(v,i);if(d!==undefined&&!h.call(d,\"value\"))return false;return f(d===undefined?undefined:d.value);};");
183
+ pushHelper(chunks, needed, "er", "const er=function(v,f){if(!o(v))return false;for(const key in v){if(!h.call(v,key))continue;const d=gp(v,key);if(d===undefined||!h.call(d,\"value\")||!f(d.value))return false;}return true;};");
184
+ pushHelper(chunks, needed, "dj", "const dj=function(v,key,ks){if(!o(v))return false;const d=g(v,key);if(d===undefined||typeof d.value!==\"string\")return false;const i=ks.indexOf(d.value);return i>=0&&arguments[i+3](v);};");
185
+ pushHelper(chunks, needed, "a", "const a=function(v){if(v===null)return \"null\";if(Array.isArray(v))return \"array\";if(v instanceof Date)return \"date\";if(v instanceof Map)return \"map\";if(v instanceof Set)return \"set\";if(typeof v===\"bigint\")return \"bigint\";if(typeof v===\"symbol\")return \"symbol\";if(typeof v===\"number\"&&Number.isNaN(v))return \"nan\";return typeof v;};");
186
+ pushHelper(chunks, needed, "le", "const le=function(v){if(v===null)return \"null\";if(v===undefined)return \"undefined\";if(typeof v===\"string\")return JSON.stringify(v);if(typeof v===\"number\"&&Object.is(v,-0))return \"-0\";if(typeof v===\"symbol\")return String(v);return String(v);};");
187
+ pushHelper(chunks, needed, "w", "const w=function(){const x=new Array(u.length);for(let i=0;i<u.length;i+=1)x[i]=Object.freeze([u[i]]);return x;}();");
188
+ pushHelper(chunks, needed, "q", rootPathIsFrozen
189
+ ? "const q=function(s,p,c,e,x){s.push(Object.freeze({path:z,code:c,expected:e,actual:x,message:undefined}));};"
190
+ : "const q=function(s,p,c,e,x){const y=p.length===0?z:Object.freeze(p.slice());s.push(Object.freeze({path:y,code:c,expected:e,actual:x,message:undefined}));};");
191
+ pushHelper(chunks, needed, "q1", rootPathIsFrozen
192
+ ? "const q1=function(s,p,k,c,e,x){s.push(Object.freeze({path:Object.freeze([k]),code:c,expected:e,actual:x,message:undefined}));};"
193
+ : "const q1=function(s,p,k,c,e,x){const n=p.length;const y=n===0?[k]:p.slice();if(n!==0)y.push(k);Object.freeze(y);s.push(Object.freeze({path:y,code:c,expected:e,actual:x,message:undefined}));};");
194
+ pushHelper(chunks, needed, "q1s", rootPathIsFrozen
195
+ ? "const q1s=function(s,p,i,c,e,x){s.push(Object.freeze({path:w[i],code:c,expected:e,actual:x,message:undefined}));};"
196
+ : "const q1s=function(s,p,i,c,e,x){const n=p.length;if(n===0){s.push(Object.freeze({path:w[i],code:c,expected:e,actual:x,message:undefined}));return;}const y=p.slice();y.push(u[i]);Object.freeze(y);s.push(Object.freeze({path:y,code:c,expected:e,actual:x,message:undefined}));};");
197
+ pushHelper(chunks, needed, "q2", rootPathIsFrozen
198
+ ? "const q2=function(s,p,a,b,c,e,x){s.push(Object.freeze({path:Object.freeze([a,b]),code:c,expected:e,actual:x,message:undefined}));};"
199
+ : "const q2=function(s,p,a,b,c,e,x){const n=p.length;const y=n===0?[a,b]:p.slice();if(n!==0){y.push(a);y.push(b);}Object.freeze(y);s.push(Object.freeze({path:y,code:c,expected:e,actual:x,message:undefined}));};");
200
+ pushHelper(chunks, needed, "fq", "const fq=function(p,c,e,x){const y=p.length===0?z:Object.freeze(p.slice());return Object.freeze({path:y,code:c,expected:e,actual:x,message:undefined});};");
201
+ pushHelper(chunks, needed, "fq1", "const fq1=function(p,k,c,e,x){const n=p.length;const y=n===0?[k]:p.slice();if(n!==0)y.push(k);Object.freeze(y);return Object.freeze({path:y,code:c,expected:e,actual:x,message:undefined});};");
202
+ pushHelper(chunks, needed, "fq1s", "const fq1s=function(p,i,c,e,x){if(p.length===0)return Object.freeze({path:w[i],code:c,expected:e,actual:x,message:undefined});const y=p.slice();y.push(u[i]);Object.freeze(y);return Object.freeze({path:y,code:c,expected:e,actual:x,message:undefined});};");
203
+ pushHelper(chunks, needed, "fq2", "const fq2=function(p,a,b,c,e,x){const n=p.length;const y=n===0?[a,b]:p.slice();if(n!==0){y.push(a);y.push(b);}Object.freeze(y);return Object.freeze({path:y,code:c,expected:e,actual:x,message:undefined});};");
204
+ return chunks.join("");
205
+ }
206
+ /**
207
+ * @brief Append one helper definition when referenced by generated code.
208
+ * @details Generated-source helpers keep the side-table ABI and JavaScript source shape
209
+ * stable across runtime and AOT emission.
210
+ * @param chunks Mutable helper source list.
211
+ * @param needed Helper names discovered in generated function bodies.
212
+ * @param name Helper identifier.
213
+ * @param source Helper source text.
214
+ */
215
+ function pushHelper(chunks, needed, name, source) {
216
+ if (needed.has(name)) {
217
+ chunks.push(source);
218
+ }
219
+ }
220
+ /**
221
+ * @brief Discover runtime helpers referenced by generated validator bodies.
222
+ * @details Generated-source helpers keep the side-table ABI and JavaScript source shape
223
+ * stable across runtime and AOT emission.
224
+ * @param body Generated factory body without helper definitions.
225
+ * @returns Closed helper-name set including transitive helper dependencies.
226
+ */
227
+ function readNeededHelpers(body) {
228
+ const needed = new Set();
229
+ markCalledHelpers(body, needed);
230
+ closeHelperDependencies(needed);
231
+ return needed;
232
+ }
233
+ /**
234
+ * @brief Scan generated source for helper calls without allocating RegExp objects.
235
+ * @details Helper names are intentionally short. Scanning by identifier prevents
236
+ * false positives such as the `o(` suffix in a user function named `foo`.
237
+ * @param body Generated factory body without helper definitions.
238
+ * @param needed Mutable helper-name set.
239
+ */
240
+ function markCalledHelpers(body, needed) {
241
+ let index = 0;
242
+ while (index < body.length) {
243
+ const code = body.charCodeAt(index);
244
+ if (!isIdentifierStartCode(code)) {
245
+ index += 1;
246
+ continue;
247
+ }
248
+ const start = index;
249
+ index += 1;
250
+ while (index < body.length && isIdentifierPartCode(body.charCodeAt(index))) {
251
+ index += 1;
252
+ }
253
+ const name = body.slice(start, index);
254
+ if (name === "z") {
255
+ /*
256
+ * The frozen empty path is referenced as a value, not a call. It gets
257
+ * special handling because the call scanner would otherwise miss it.
258
+ */
259
+ needed.add("z");
260
+ continue;
261
+ }
262
+ if (!isRuntimeHelperName(name) || isFunctionNamePosition(body, start)) {
263
+ continue;
264
+ }
265
+ if (body.charCodeAt(index) === 40) {
266
+ needed.add(name);
267
+ continue;
268
+ }
269
+ if (name === "h" && body.startsWith(".call(", index)) {
270
+ /*
271
+ * hasOwnProperty is used through h.call(...). This is still a helper
272
+ * dependency even though it is not written as h(...).
273
+ */
274
+ needed.add("h");
275
+ }
276
+ }
277
+ }
278
+ /**
279
+ * @brief close helper dependencies.
280
+ * @details Generated-source helpers keep the side-table ABI and JavaScript source shape
281
+ * stable across runtime and AOT emission.
282
+ * @param needed Mutable helper-name set.
283
+ * @post Every helper required by another helper has been inserted.
284
+ */
285
+ function closeHelperDependencies(needed) {
286
+ let changed = true;
287
+ while (changed) {
288
+ changed = false;
289
+ changed = addDependencies(needed, "g", ["gp", "h"]) || changed;
290
+ changed = addDependencies(needed, "gv", ["ph", "gp", "h"]) || changed;
291
+ changed = addDependencies(needed, "ho", ["ph", "h"]) || changed;
292
+ changed = addDependencies(needed, "hd", ["ph", "gp", "h"]) || changed;
293
+ changed = addDependencies(needed, "ea", ["gp", "h"]) || changed;
294
+ changed = addDependencies(needed, "eu", ["ai", "gp", "h"]) || changed;
295
+ changed = addDependencies(needed, "ev", ["gp", "h"]) || changed;
296
+ changed = addDependencies(needed, "er", ["o", "gp", "h"]) || changed;
297
+ changed = addDependencies(needed, "dj", ["o", "g"]) || changed;
298
+ changed = addDependencies(needed, "dt", ["dg"]) || changed;
299
+ changed = addDependencies(needed, "q", ["z"]) || changed;
300
+ changed = addDependencies(needed, "q1s", ["w"]) || changed;
301
+ changed = addDependencies(needed, "fq", ["z"]) || changed;
302
+ changed = addDependencies(needed, "fq1", ["z"]) || changed;
303
+ changed = addDependencies(needed, "fq1s", ["w"]) || changed;
304
+ }
305
+ }
306
+ /**
307
+ * @brief add dependencies.
308
+ * @details Generated-source helpers keep the side-table ABI and JavaScript source shape
309
+ * stable across runtime and AOT emission.
310
+ * @param needed Mutable helper-name set.
311
+ * @param name Helper whose dependencies should be inserted.
312
+ * @param dependencies Helper names required by `name`.
313
+ * @returns True when the set changed.
314
+ */
315
+ function addDependencies(needed, name, dependencies) {
316
+ if (!needed.has(name)) {
317
+ return false;
318
+ }
319
+ let changed = false;
320
+ for (let index = 0; index < dependencies.length; index += 1) {
321
+ const dependency = dependencies[index];
322
+ if (dependency !== undefined && !needed.has(dependency)) {
323
+ needed.add(dependency);
324
+ changed = true;
325
+ }
326
+ }
327
+ return changed;
328
+ }
329
+ /**
330
+ * @brief Test whether an identifier is a generated runtime helper.
331
+ * @details Generated-source helpers keep the side-table ABI and JavaScript source shape
332
+ * stable across runtime and AOT emission.
333
+ * @param name Candidate identifier.
334
+ * @returns True when `name` is reserved for helper prelude emission.
335
+ */
336
+ function isRuntimeHelperName(name) {
337
+ switch (name) {
338
+ case "h":
339
+ case "z":
340
+ case "gp":
341
+ case "o":
342
+ case "ph":
343
+ case "g":
344
+ case "gv":
345
+ case "ho":
346
+ case "hd":
347
+ case "fn":
348
+ case "nc":
349
+ case "dg":
350
+ case "dt":
351
+ case "sb":
352
+ case "rx":
353
+ case "ai":
354
+ case "ea":
355
+ case "eu":
356
+ case "ev":
357
+ case "er":
358
+ case "dj":
359
+ case "a":
360
+ case "le":
361
+ case "w":
362
+ case "q":
363
+ case "q1":
364
+ case "q1s":
365
+ case "q2":
366
+ case "fq":
367
+ case "fq1":
368
+ case "fq1s":
369
+ case "fq2":
370
+ return true;
371
+ default:
372
+ return false;
373
+ }
374
+ }
375
+ /**
376
+ * @brief Test whether an identifier occurrence is a function declaration name.
377
+ * @details Generated-source helpers keep the side-table ABI and JavaScript source shape
378
+ * stable across runtime and AOT emission.
379
+ * @param source Full generated source being scanned.
380
+ * @param start Start offset of the identifier.
381
+ * @returns True when the identifier follows `function `.
382
+ */
383
+ function isFunctionNamePosition(source, start) {
384
+ const prefix = "function ";
385
+ return start >= prefix.length &&
386
+ source.slice(start - prefix.length, start) === prefix;
387
+ }
388
+ /**
389
+ * @brief Test ASCII identifier-start characters used by generated code.
390
+ * @details Generated-source helpers keep the side-table ABI and JavaScript source shape
391
+ * stable across runtime and AOT emission.
392
+ * @param code Character code under inspection.
393
+ * @returns True for `$`, `_`, and ASCII letters.
394
+ */
395
+ function isIdentifierStartCode(code) {
396
+ return code === 36 ||
397
+ code === 95 ||
398
+ (code >= 65 && code <= 90) ||
399
+ (code >= 97 && code <= 122);
400
+ }
401
+ /**
402
+ * @brief Test ASCII identifier-part characters used by generated code.
403
+ * @details Generated-source helpers keep the side-table ABI and JavaScript source shape
404
+ * stable across runtime and AOT emission.
405
+ * @param code Character code under inspection.
406
+ * @returns True for identifier-start characters and digits.
407
+ */
408
+ function isIdentifierPartCode(code) {
409
+ return isIdentifierStartCode(code) || (code >= 48 && code <= 57);
410
+ }
@@ -1,13 +1,18 @@
1
1
  /**
2
2
  * @file compile/types.ts
3
3
  * @brief Shared compile-time data contracts.
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 type { Guard, Presence } from "../guard/index.js";
6
8
  import type { LiteralValue, Schema } from "../schema/index.js";
7
9
  /**
8
10
  * @brief emit context.
11
+ * @details Generated-source helpers keep the side-table ABI and JavaScript source shape
12
+ * stable across runtime and AOT emission.
9
13
  */
10
14
  export interface EmitContext {
15
+ readonly mode: CompileMode;
11
16
  readonly literals: LiteralValue[];
12
17
  readonly regexps: RegExp[];
13
18
  readonly keysets: (readonly string[])[];
@@ -17,10 +22,20 @@ export interface EmitContext {
17
22
  readonly functionNames: Map<Schema, string>;
18
23
  readonly checkFunctions: FunctionSource[];
19
24
  readonly checkFunctionNames: Map<Schema, string>;
25
+ readonly firstFunctions: FunctionSource[];
26
+ readonly firstFunctionNames: Map<Schema, string>;
20
27
  readonly stringIndexes: Map<string, number>;
21
28
  }
29
+ /**
30
+ * @brief compile mode.
31
+ * @details Generated-source helpers keep the side-table ABI and JavaScript source shape
32
+ * stable across runtime and AOT emission.
33
+ */
34
+ export type CompileMode = "safe" | "unsafe" | "unchecked";
22
35
  /**
23
36
  * @brief function source.
37
+ * @details Generated-source helpers keep the side-table ABI and JavaScript source shape
38
+ * stable across runtime and AOT emission.
24
39
  */
25
40
  export interface FunctionSource {
26
41
  readonly name: string;
@@ -28,6 +43,8 @@ export interface FunctionSource {
28
43
  }
29
44
  /**
30
45
  * @brief compiled source bundle.
46
+ * @details Generated-source helpers keep the side-table ABI and JavaScript source shape
47
+ * stable across runtime and AOT emission.
31
48
  */
32
49
  export interface CompiledSourceBundle {
33
50
  readonly source: string;
@@ -39,14 +56,19 @@ export interface CompiledSourceBundle {
39
56
  }
40
57
  /**
41
58
  * @brief compiled guard.
59
+ * @details Generated-source helpers keep the side-table ABI and JavaScript source shape
60
+ * stable across runtime and AOT emission.
42
61
  */
43
62
  export interface CompiledGuard<TValue, TPresence extends Presence = "required"> extends Guard<TValue, TPresence> {
44
63
  readonly source: string;
45
64
  }
46
65
  /**
47
66
  * @brief compile options.
67
+ * @details Generated-source helpers keep the side-table ABI and JavaScript source shape
68
+ * stable across runtime and AOT emission.
48
69
  */
49
70
  export interface CompileOptions {
50
71
  readonly name: string | undefined;
72
+ readonly mode: CompileMode | undefined;
51
73
  }
52
74
  //# sourceMappingURL=types.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/compile/types.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AACzD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAE/D;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,QAAQ,EAAE,YAAY,EAAE,CAAC;IAClC,QAAQ,CAAC,OAAO,EAAE,MAAM,EAAE,CAAC;IAC3B,QAAQ,CAAC,OAAO,EAAE,CAAC,SAAS,MAAM,EAAE,CAAC,EAAE,CAAC;IACxC,QAAQ,CAAC,OAAO,EAAE,MAAM,EAAE,CAAC;IAC3B,QAAQ,CAAC,OAAO,EAAE,MAAM,EAAE,CAAC;IAC3B,QAAQ,CAAC,SAAS,EAAE,cAAc,EAAE,CAAC;IACrC,QAAQ,CAAC,aAAa,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC5C,QAAQ,CAAC,cAAc,EAAE,cAAc,EAAE,CAAC;IAC1C,QAAQ,CAAC,kBAAkB,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjD,QAAQ,CAAC,aAAa,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC7C;AAED;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,IAAI,EAAE,MAAM,CAAC;CACd;AAED;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,QAAQ,EAAE,SAAS,YAAY,EAAE,CAAC;IAC3C,QAAQ,CAAC,OAAO,EAAE,SAAS,MAAM,EAAE,CAAC;IACpC,QAAQ,CAAC,OAAO,EAAE,SAAS,CAAC,SAAS,MAAM,EAAE,CAAC,EAAE,CAAC;IACjD,QAAQ,CAAC,OAAO,EAAE,SAAS,MAAM,EAAE,CAAC;IACpC,QAAQ,CAAC,cAAc,EAAE,SAAS,MAAM,EAAE,CAAC;CAC5C;AAED;;GAEG;AACH,MAAM,WAAW,aAAa,CAC5B,MAAM,EACN,SAAS,SAAS,QAAQ,GAAG,UAAU,CACvC,SAAQ,KAAK,CAAC,MAAM,EAAE,SAAS,CAAC;IAChC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB;AAED;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,CAAC;CACnC"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/compile/types.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AACzD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAE/D;;;;GAIG;AACH,MAAM,WAAW,WAAW;IACxB,QAAQ,CAAC,IAAI,EAAE,WAAW,CAAC;IAC3B,QAAQ,CAAC,QAAQ,EAAE,YAAY,EAAE,CAAC;IAClC,QAAQ,CAAC,OAAO,EAAE,MAAM,EAAE,CAAC;IAC3B,QAAQ,CAAC,OAAO,EAAE,CAAC,SAAS,MAAM,EAAE,CAAC,EAAE,CAAC;IACxC,QAAQ,CAAC,OAAO,EAAE,MAAM,EAAE,CAAC;IAC3B,QAAQ,CAAC,OAAO,EAAE,MAAM,EAAE,CAAC;IAC3B,QAAQ,CAAC,SAAS,EAAE,cAAc,EAAE,CAAC;IACrC,QAAQ,CAAC,aAAa,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC5C,QAAQ,CAAC,cAAc,EAAE,cAAc,EAAE,CAAC;IAC1C,QAAQ,CAAC,kBAAkB,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjD,QAAQ,CAAC,cAAc,EAAE,cAAc,EAAE,CAAC;IAC1C,QAAQ,CAAC,kBAAkB,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjD,QAAQ,CAAC,aAAa,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC/C;AAED;;;;GAIG;AACH,MAAM,MAAM,WAAW,GAAG,MAAM,GAAG,QAAQ,GAAG,WAAW,CAAC;AAE1D;;;;GAIG;AACH,MAAM,WAAW,cAAc;IAC3B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,IAAI,EAAE,MAAM,CAAC;CAChB;AAED;;;;GAIG;AACH,MAAM,WAAW,oBAAoB;IACjC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,QAAQ,EAAE,SAAS,YAAY,EAAE,CAAC;IAC3C,QAAQ,CAAC,OAAO,EAAE,SAAS,MAAM,EAAE,CAAC;IACpC,QAAQ,CAAC,OAAO,EAAE,SAAS,CAAC,SAAS,MAAM,EAAE,CAAC,EAAE,CAAC;IACjD,QAAQ,CAAC,OAAO,EAAE,SAAS,MAAM,EAAE,CAAC;IACpC,QAAQ,CAAC,cAAc,EAAE,SAAS,MAAM,EAAE,CAAC;CAC9C;AAED;;;;GAIG;AACH,MAAM,WAAW,aAAa,CAC1B,MAAM,EACN,SAAS,SAAS,QAAQ,GAAG,UAAU,CACzC,SAAQ,KAAK,CAAC,MAAM,EAAE,SAAS,CAAC;IAC9B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CAC3B;AAED;;;;GAIG;AACH,MAAM,WAAW,cAAc;IAC3B,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,CAAC;IAClC,QAAQ,CAAC,IAAI,EAAE,WAAW,GAAG,SAAS,CAAC;CAC1C"}
@@ -1,5 +1,7 @@
1
1
  /**
2
2
  * @file compile/types.ts
3
3
  * @brief Shared compile-time data contracts.
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
  export {};