@velarscript/compiler 0.12.0 → 0.13.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 (109) hide show
  1. package/dist/advisory-suppression.d.ts +62 -0
  2. package/dist/advisory-suppression.d.ts.map +1 -0
  3. package/dist/advisory-suppression.js +179 -0
  4. package/dist/advisory-suppression.js.map +1 -0
  5. package/dist/analyzer.d.ts +405 -17
  6. package/dist/analyzer.d.ts.map +1 -1
  7. package/dist/analyzer.js +1755 -211
  8. package/dist/analyzer.js.map +1 -1
  9. package/dist/ast.d.ts +6 -3
  10. package/dist/ast.d.ts.map +1 -1
  11. package/dist/ast.js.map +1 -1
  12. package/dist/binding-stability.d.ts +22 -0
  13. package/dist/binding-stability.d.ts.map +1 -0
  14. package/dist/binding-stability.js +63 -0
  15. package/dist/binding-stability.js.map +1 -0
  16. package/dist/collection-lowering-runtime.d.ts +1 -1
  17. package/dist/collection-lowering-runtime.d.ts.map +1 -1
  18. package/dist/collection-lowering-runtime.js +183 -56
  19. package/dist/collection-lowering-runtime.js.map +1 -1
  20. package/dist/diagnostic.d.ts +34 -0
  21. package/dist/diagnostic.d.ts.map +1 -1
  22. package/dist/diagnostic.js +11 -1
  23. package/dist/diagnostic.js.map +1 -1
  24. package/dist/embedded-javascript.d.ts +12 -1
  25. package/dist/embedded-javascript.d.ts.map +1 -1
  26. package/dist/embedded-javascript.js +111 -2
  27. package/dist/embedded-javascript.js.map +1 -1
  28. package/dist/embedded-module.d.ts.map +1 -1
  29. package/dist/embedded-module.js +22 -0
  30. package/dist/embedded-module.js.map +1 -1
  31. package/dist/emitter.d.ts +83 -1
  32. package/dist/emitter.d.ts.map +1 -1
  33. package/dist/emitter.js +518 -41
  34. package/dist/emitter.js.map +1 -1
  35. package/dist/error-runtime.d.ts +9 -0
  36. package/dist/error-runtime.d.ts.map +1 -1
  37. package/dist/error-runtime.js +21 -0
  38. package/dist/error-runtime.js.map +1 -1
  39. package/dist/extension.d.ts +5 -2
  40. package/dist/extension.d.ts.map +1 -1
  41. package/dist/extension.js +2 -1
  42. package/dist/extension.js.map +1 -1
  43. package/dist/formatter.d.ts.map +1 -1
  44. package/dist/formatter.js +222 -91
  45. package/dist/formatter.js.map +1 -1
  46. package/dist/index.d.ts +10 -2
  47. package/dist/index.d.ts.map +1 -1
  48. package/dist/index.js +43 -5
  49. package/dist/index.js.map +1 -1
  50. package/dist/interpolated-string.d.ts.map +1 -1
  51. package/dist/interpolated-string.js +29 -2
  52. package/dist/interpolated-string.js.map +1 -1
  53. package/dist/json-runtime.d.ts.map +1 -1
  54. package/dist/json-runtime.js +27 -3
  55. package/dist/json-runtime.js.map +1 -1
  56. package/dist/lexer.d.ts +217 -1
  57. package/dist/lexer.d.ts.map +1 -1
  58. package/dist/lexer.js +799 -37
  59. package/dist/lexer.js.map +1 -1
  60. package/dist/limits.d.ts +9 -0
  61. package/dist/limits.d.ts.map +1 -1
  62. package/dist/limits.js +9 -0
  63. package/dist/limits.js.map +1 -1
  64. package/dist/mechanical-fix.d.ts.map +1 -1
  65. package/dist/mechanical-fix.js +38 -0
  66. package/dist/mechanical-fix.js.map +1 -1
  67. package/dist/parser.d.ts +30 -1
  68. package/dist/parser.d.ts.map +1 -1
  69. package/dist/parser.js +137 -21
  70. package/dist/parser.js.map +1 -1
  71. package/dist/promise-runtime.d.ts +20 -1
  72. package/dist/promise-runtime.d.ts.map +1 -1
  73. package/dist/promise-runtime.js +38 -3
  74. package/dist/promise-runtime.js.map +1 -1
  75. package/dist/reactive-bridge-runtime.d.ts.map +1 -1
  76. package/dist/reactive-bridge-runtime.js +7 -1
  77. package/dist/reactive-bridge-runtime.js.map +1 -1
  78. package/dist/runtime-abi.d.ts +21 -1
  79. package/dist/runtime-abi.d.ts.map +1 -1
  80. package/dist/runtime-abi.js +23 -3
  81. package/dist/runtime-abi.js.map +1 -1
  82. package/dist/source-names.d.ts +26 -0
  83. package/dist/source-names.d.ts.map +1 -1
  84. package/dist/source-names.js +49 -5
  85. package/dist/source-names.js.map +1 -1
  86. package/dist/source.d.ts.map +1 -1
  87. package/dist/source.js +13 -0
  88. package/dist/source.js.map +1 -1
  89. package/dist/stable-order.d.ts +16 -0
  90. package/dist/stable-order.d.ts.map +1 -0
  91. package/dist/stable-order.js +18 -0
  92. package/dist/stable-order.js.map +1 -0
  93. package/dist/text-runtime.d.ts.map +1 -1
  94. package/dist/text-runtime.js +182 -41
  95. package/dist/text-runtime.js.map +1 -1
  96. package/dist/token.d.ts +11 -0
  97. package/dist/token.d.ts.map +1 -1
  98. package/dist/token.js.map +1 -1
  99. package/dist/type-registry-runtime.d.ts.map +1 -1
  100. package/dist/type-registry-runtime.js +8 -1
  101. package/dist/type-registry-runtime.js.map +1 -1
  102. package/dist/type-validation-runtime.d.ts.map +1 -1
  103. package/dist/type-validation-runtime.js +129 -1
  104. package/dist/type-validation-runtime.js.map +1 -1
  105. package/dist/types.d.ts +17 -1
  106. package/dist/types.d.ts.map +1 -1
  107. package/dist/types.js +161 -17
  108. package/dist/types.js.map +1 -1
  109. package/package.json +1 -1
@@ -6,6 +6,7 @@ const __velarTextNativeString = globalThis.String;
6
6
  const __velarTextNativeNumber = globalThis.Number;
7
7
  const __velarTextNativeMath = globalThis.Math;
8
8
  const __velarTextNativeObject = globalThis.Object;
9
+ const __velarTextNativeMap = globalThis.Map;
9
10
  const __velarTextNativeTypeError = globalThis.TypeError;
10
11
  const __velarTextNativeRangeError = globalThis.RangeError;
11
12
  const __velarTextGetOwnPropertyDescriptor = __velarTextNativeObject.getOwnPropertyDescriptor;
@@ -25,9 +26,12 @@ const __velarNativeStringTrim = __velarTextGetOwnPropertyDescriptor(__velarTextS
25
26
  const __velarNativeStringUpper = __velarTextGetOwnPropertyDescriptor(__velarTextStringPrototype, "toUpperCase")?.value;
26
27
  const __velarNativeStringLower = __velarTextGetOwnPropertyDescriptor(__velarTextStringPrototype, "toLowerCase")?.value;
27
28
  const __velarNativeStringSplit = __velarTextGetOwnPropertyDescriptor(__velarTextStringPrototype, "split")?.value;
28
- const __velarNativeStringReplace = __velarTextGetOwnPropertyDescriptor(__velarTextStringPrototype, "replace")?.value;
29
29
  const __velarNativeStringReplaceAll = __velarTextGetOwnPropertyDescriptor(__velarTextStringPrototype, "replaceAll")?.value;
30
30
  const __velarNativeStringRepeat = __velarTextGetOwnPropertyDescriptor(__velarTextStringPrototype, "repeat")?.value;
31
+ const __velarTextMapPrototype = typeof __velarTextNativeMap === "function" ? __velarTextGetOwnPropertyDescriptor(__velarTextNativeMap, "prototype")?.value : null;
32
+ const __velarTextMapGet = __velarTextMapPrototype ? __velarTextGetOwnPropertyDescriptor(__velarTextMapPrototype, "get")?.value : null;
33
+ const __velarTextMapSet = __velarTextMapPrototype ? __velarTextGetOwnPropertyDescriptor(__velarTextMapPrototype, "set")?.value : null;
34
+ const __velarTextMapClear = __velarTextMapPrototype ? __velarTextGetOwnPropertyDescriptor(__velarTextMapPrototype, "clear")?.value : null;
31
35
  const __velarTextSurrogatePattern = /[\u{10000}-\u{10FFFF}\uD800-\uDFFF]/u;
32
36
  const __velarTextRegExpPrototype = typeof __velarTextRuntimeGetPrototypeOf === "function" ? __velarTextRuntimeGetPrototypeOf(__velarTextSurrogatePattern) : null;
33
37
  const __velarTextSurrogateExec = __velarTextRegExpPrototype ? __velarTextGetOwnPropertyDescriptor(__velarTextRegExpPrototype, "exec")?.value : null;
@@ -66,48 +70,146 @@ function __velarTextNextCodePointOffset(value, offset) {
66
70
  const second = __velarTextCall(__velarNativeStringCharCodeAt, value, [offset + 1]);
67
71
  return second >= 0xDC00 && second <= 0xDFFF ? offset + 2 : offset + 1;
68
72
  }
69
- function __velarTextCodePointLength(value) {
70
- if (__velarTextCall(__velarTextSurrogateExec, __velarTextSurrogatePattern, [value]) === null) return value.length;
73
+ // D90 R7, performance half. Measuring a string used to be a whole-string job
74
+ // every single time: the surrogate probe ran per call, and one astral character
75
+ // anywhere forced every offset conversion to walk code points from zero, which
76
+ // made a loop of char/slice calls quadratic: 20,000 char/slice calls over a
77
+ // 200 KiB string with one leading astral character took 17.1 s, and 34 ms
78
+ // once measurement was memoised. A measurement is a pure function of an
79
+ // immutable value, so it is memoised: a dense string answers offset conversions in
80
+ // O(1) when no surrogate pair splits it, and otherwise the checkpoint list
81
+ // records the code-unit offset of every stride-th code point so a conversion
82
+ // starts from the nearest checkpoint instead of from the start of the string.
83
+ // The cache may only change the cost of an answer, never the answer.
84
+ const __velarTextCheckpointStride = 64;
85
+ const __velarTextMeasureMinimumUnits = 64;
86
+ // The cache holds its keys strongly, so its budget is memory the program has
87
+ // stopped using but cannot reclaim. Eight MiB buys the loops that matter and
88
+ // bounds what a document-processing program leaves behind; a single string
89
+ // larger than the budget still measures once and stays, because evicting the
90
+ // string a loop is walking would put the cliff back. The entry count only
91
+ // bounds the cache's own bookkeeping, so it is set well above the number of
92
+ // strings a loop cycles through: a tighter count made a walk over 65 short
93
+ // strings 15x slower than the same walk over 64.
94
+ const __velarTextMeasureCacheEntries = 512;
95
+ const __velarTextMeasureCacheUnits = 8 * 1024 * 1024;
96
+ const __velarTextMeasureCache = typeof __velarTextNativeMap === "function"
97
+ && typeof __velarTextMapGet === "function" && typeof __velarTextMapSet === "function" && typeof __velarTextMapClear === "function"
98
+ ? new __velarTextNativeMap() : null;
99
+ let __velarTextMeasureCacheCount = 0;
100
+ let __velarTextMeasureCacheHeld = 0;
101
+ function __velarTextMeasureText(value) {
102
+ if (__velarTextCall(__velarTextSurrogateExec, __velarTextSurrogatePattern, [value]) === null) {
103
+ return { length: value.length, dense: true, checkpoints: null };
104
+ }
105
+ const checkpoints = new __velarTextNativeArray();
71
106
  let length = 0, offset = 0;
72
- while (offset < value.length) { offset = __velarTextNextCodePointOffset(value, offset); length += 1; }
73
- return length;
107
+ while (offset < value.length) {
108
+ if (length % __velarTextCheckpointStride === 0) checkpoints[length / __velarTextCheckpointStride] = offset;
109
+ offset = __velarTextNextCodePointOffset(value, offset);
110
+ length += 1;
111
+ }
112
+ // A string that carries only unpaired surrogates still has one unit per code
113
+ // point, so it keeps the O(1) path even though the probe matched.
114
+ return { length: length, dense: length === value.length, checkpoints: checkpoints };
74
115
  }
75
- function __velarTextCodePointPrefix(value, count) { return __velarTextCall(__velarNativeStringSlice, value, [0, __velarTextCodeUnitOffset(value, count)]); }
76
- // A string whose code-point count equals its code-unit count carries no
77
- // surrogate pair, so a code-point position is already a code-unit offset.
78
- // The codePointLength argument lets a caller that has already measured the string reuse
79
- // that measurement; without it the surrogate probe answers the same question
80
- // in one native scan. Walking code points from zero instead made every offset
81
- // conversion O(corpus + position), which is what turned slice-based document
82
- // scanning quadratic.
83
- function __velarTextOneUnitPerCodePoint(value, codePointLength) {
84
- if (codePointLength >= 0) return codePointLength === value.length;
85
- return __velarTextCall(__velarTextSurrogateExec, __velarTextSurrogatePattern, [value]) === null;
116
+ function __velarTextMeasure(value) {
117
+ if (__velarTextMeasureCache === null || value.length < __velarTextMeasureMinimumUnits) return __velarTextMeasureText(value);
118
+ const cached = __velarTextCall(__velarTextMapGet, __velarTextMeasureCache, [value]);
119
+ if (cached !== undefined) return cached;
120
+ const measured = __velarTextMeasureText(value);
121
+ if (__velarTextMeasureCacheCount >= __velarTextMeasureCacheEntries
122
+ || (__velarTextMeasureCacheCount > 0 && __velarTextMeasureCacheHeld + value.length > __velarTextMeasureCacheUnits)) {
123
+ __velarTextCall(__velarTextMapClear, __velarTextMeasureCache, []);
124
+ __velarTextMeasureCacheCount = 0;
125
+ __velarTextMeasureCacheHeld = 0;
126
+ }
127
+ __velarTextCall(__velarTextMapSet, __velarTextMeasureCache, [value, measured]);
128
+ __velarTextMeasureCacheCount += 1;
129
+ __velarTextMeasureCacheHeld += value.length;
130
+ return measured;
131
+ }
132
+ function __velarTextCodePointLength(value) {
133
+ return __velarTextMeasure(value).length;
86
134
  }
87
- function __velarTextCodeUnitOffset(value, position, codePointLength = -1) {
88
- if (__velarTextOneUnitPerCodePoint(value, codePointLength)) return position < value.length ? position : value.length;
89
- let offset = 0, current = 0;
135
+ function __velarTextCodePointPrefix(value, count) { return __velarTextCall(__velarNativeStringSlice, value, [0, __velarTextCodeUnitOffset(value, count)]); }
136
+ function __velarTextCodeUnitOffset(value, position) {
137
+ const measured = __velarTextMeasure(value);
138
+ if (measured.dense) return position < value.length ? position : value.length;
139
+ if (position <= 0) return 0;
140
+ const checkpoints = measured.checkpoints;
141
+ let block = __velarTextCall(__velarTextMathFloor, __velarTextNativeMath, [position / __velarTextCheckpointStride]);
142
+ if (block >= checkpoints.length) block = checkpoints.length - 1;
143
+ let offset = checkpoints[block], current = block * __velarTextCheckpointStride;
90
144
  while (offset < value.length && current < position) { offset = __velarTextNextCodePointOffset(value, offset); current += 1; }
91
145
  return offset;
92
146
  }
93
- function __velarTextCodePointIndex(value, unitOffset, codePointLength = -1) {
94
- if (__velarTextOneUnitPerCodePoint(value, codePointLength)) return unitOffset <= value.length ? unitOffset : null;
95
- let offset = 0, position = 0;
147
+ function __velarTextCodePointIndex(value, unitOffset) {
148
+ const measured = __velarTextMeasure(value);
149
+ if (measured.dense) return unitOffset <= value.length ? unitOffset : null;
150
+ if (unitOffset < 0 || unitOffset > value.length) return null;
151
+ const checkpoints = measured.checkpoints;
152
+ let low = 0, high = checkpoints.length - 1;
153
+ while (low < high) {
154
+ const middle = low + __velarTextCall(__velarTextMathFloor, __velarTextNativeMath, [(high - low + 1) / 2]);
155
+ if (checkpoints[middle] <= unitOffset) low = middle; else high = middle - 1;
156
+ }
157
+ let offset = checkpoints[low], position = low * __velarTextCheckpointStride;
96
158
  while (offset < unitOffset && offset < value.length) { offset = __velarTextNextCodePointOffset(value, offset); position += 1; }
97
159
  return offset === unitOffset ? position : null;
98
160
  }
99
161
  function __velarTextCodePointDistance(value, start, end) {
162
+ if (__velarTextMeasure(value).dense) return end >= start ? end - start : null;
100
163
  let offset = start, distance = 0;
101
164
  while (offset < end) { offset = __velarTextNextCodePointOffset(value, offset); distance += 1; }
102
165
  return offset === end ? distance : null;
103
166
  }
167
+ // D90 R7: a code-unit offset sits between two code points unless it splits a
168
+ // surrogate pair, and only an adjacent lead/trail pair can be split. The test
169
+ // is O(1), so every search below can reject a mid-pair hit without measuring
170
+ // the string.
171
+ function __velarTextIsBoundary(value, offset) {
172
+ if (offset <= 0 || offset >= value.length) return true;
173
+ const lead = __velarTextCall(__velarNativeStringCharCodeAt, value, [offset - 1]);
174
+ if (lead < 0xD800 || lead > 0xDBFF) return true;
175
+ const trail = __velarTextCall(__velarNativeStringCharCodeAt, value, [offset]);
176
+ return trail < 0xDC00 || trail > 0xDFFF;
177
+ }
178
+ // D90 R7, performance half. A match can only start inside a pair when the
179
+ // needle starts with a trail surrogate, and can only end inside one when the
180
+ // needle ends with a lead surrogate: the unit the gate reads at each end of a
181
+ // match is the needle's own edge unit. Both are properties of the needle
182
+ // alone, so one O(1) look says whether the native scan already answers what
183
+ // the bounded scan answers, and an ordinary needle keeps native speed on any
184
+ // haystack. The needle must not be empty; each caller handles that case.
185
+ function __velarTextNeedsBoundaryCheck(search) {
186
+ const first = __velarTextCall(__velarNativeStringCharCodeAt, search, [0]);
187
+ if (first >= 0xDC00 && first <= 0xDFFF) return true;
188
+ const last = __velarTextCall(__velarNativeStringCharCodeAt, search, [search.length - 1]);
189
+ return last >= 0xD800 && last <= 0xDBFF;
190
+ }
191
+ // Every search operation goes through here so that a match is accepted only
192
+ // when it starts and ends on a code-point boundary. A needle that begins or
193
+ // ends with an unpaired surrogate therefore never matches inside a pair, which
194
+ // is what keeps split/replace/replaceAll from manufacturing lone surrogates.
195
+ // The needle must not be empty; each caller handles that case in its own voice.
196
+ function __velarTextBoundedIndexOf(value, search, cursor) {
197
+ if (!__velarTextNeedsBoundaryCheck(search)) return __velarTextCall(__velarNativeStringIndexOf, value, [search, cursor]);
198
+ while (cursor <= value.length) {
199
+ const found = __velarTextCall(__velarNativeStringIndexOf, value, [search, cursor]);
200
+ if (found < 0) return -1;
201
+ if (__velarTextIsBoundary(value, found) && __velarTextIsBoundary(value, found + search.length)) return found;
202
+ cursor = found + 1;
203
+ }
204
+ return -1;
205
+ }
104
206
  function __velarTextReplacementOutputUnits(value, search, replacement, all) {
105
207
  let matches = 0;
106
208
  if (search === "") matches = all ? __velarTextCodePointLength(value) + 1 : 1;
107
209
  else {
108
210
  let cursor = 0;
109
211
  while (true) {
110
- const index = __velarTextCall(__velarNativeStringIndexOf, value, [search, cursor]);
212
+ const index = __velarTextBoundedIndexOf(value, search, cursor);
111
213
  if (index < 0) break;
112
214
  matches += 1;
113
215
  if (!all) break;
@@ -157,8 +259,14 @@ function __velarStringCompare(left, right) {
157
259
  // which one is known only at runtime. A string pair keeps code-point order
158
260
  // (TXT-D1); everything else uses the plain relational order, exactly as a
159
261
  // monomorphic comparison of that category would.
262
+ // D90 R6: one NaN policy. A NaN may be held and tested with .isNaN(), but an
263
+ // operation that orders it raises instead of answering. Without this the
264
+ // "neither less nor greater" arm returned 0, which made NaN compare both <=
265
+ // and >= as true at a generic site while the same source on a plain number
266
+ // answered false, and produced genuinely mis-sorted output.
160
267
  function __velarOrderCompare(left, right) {
161
268
  if (typeof left === "string" && typeof right === "string") return __velarStringCompare(left, right);
269
+ if (left !== left || right !== right) throw new __velarTextNativeTypeError("ordered comparison found NaN, which has no ordering; drop it with filter(x => not x.isNaN()) or fix the upstream computation");
162
270
  return left < right ? -1 : left > right ? 1 : 0;
163
271
  }
164
272
  function __velarStringSize(value) { return __velarTextCodePointLength(__velarTextValue(value)); }
@@ -173,7 +281,7 @@ function __velarStringSlice(value, start = 0, end = null) {
173
281
  if (!__velarTextCall(__velarTextNumberIsInteger, __velarTextNativeNumber, [start]) || !__velarTextCall(__velarTextNumberIsInteger, __velarTextNativeNumber, [end])) throw new __velarTextNativeTypeError("String.slice positions must be integers");
174
282
  const first = start < 0 ? __velarTextCall(__velarTextMathMax, __velarTextNativeMath, [total + start, 0]) : __velarTextCall(__velarTextMathMin, __velarTextNativeMath, [start, total]);
175
283
  const last = end < 0 ? __velarTextCall(__velarTextMathMax, __velarTextNativeMath, [total + end, 0]) : __velarTextCall(__velarTextMathMin, __velarTextNativeMath, [end, total]);
176
- return __velarTextCall(__velarNativeStringSlice, value, [__velarTextCodeUnitOffset(value, first, total), __velarTextCodeUnitOffset(value, last, total)]);
284
+ return __velarTextCall(__velarNativeStringSlice, value, [__velarTextCodeUnitOffset(value, first), __velarTextCodeUnitOffset(value, last)]);
177
285
  }
178
286
  function __velarStringChar(value, index) {
179
287
  value = __velarTextValue(value);
@@ -182,25 +290,23 @@ function __velarStringChar(value, index) {
182
290
  if (index < 0) index += total;
183
291
  if (index < 0) return null;
184
292
  if (index >= total) return null;
185
- const start = __velarTextCodeUnitOffset(value, index, total);
293
+ const start = __velarTextCodeUnitOffset(value, index);
186
294
  return __velarTextCall(__velarNativeStringSlice, value, [start, __velarTextNextCodePointOffset(value, start)]);
187
295
  }
188
- function __velarStringHas(value, text) { return __velarTextCall(__velarNativeStringIndexOf, __velarTextValue(value), [__velarTextArgument(text, "String.has text")]) >= 0; }
296
+ function __velarStringHas(value, text) {
297
+ value = __velarTextValue(value); text = __velarTextArgument(text, "String.has text");
298
+ return text === "" || __velarTextBoundedIndexOf(value, text, 0) >= 0;
299
+ }
189
300
  function __velarStringIndex(value, text, start = 0) {
190
301
  value = __velarTextValue(value); text = __velarTextArgument(text, "String.index text");
191
302
  if (!__velarTextCall(__velarTextNumberIsInteger, __velarTextNativeNumber, [start])) throw new __velarTextNativeTypeError("String.index start must be an integer");
192
303
  const total = __velarTextCodePointLength(value);
193
304
  const first = start < 0 ? __velarTextCall(__velarTextMathMax, __velarTextNativeMath, [total + start, 0]) : __velarTextCall(__velarTextMathMin, __velarTextNativeMath, [start, total]);
194
- let cursor = __velarTextCodeUnitOffset(value, first, total);
305
+ const cursor = __velarTextCodeUnitOffset(value, first);
195
306
  if (text === "") return first;
196
- while (cursor <= value.length) {
197
- const found = __velarTextCall(__velarNativeStringIndexOf, value, [text, cursor]);
198
- if (found < 0) return null;
199
- const position = __velarTextCodePointIndex(value, found, total);
200
- if (position !== null && __velarTextCodePointIndex(value, found + text.length, total) !== null) return position;
201
- cursor = found + 1;
202
- }
203
- return null;
307
+ const found = __velarTextBoundedIndexOf(value, text, cursor);
308
+ if (found < 0) return null;
309
+ return __velarTextCodePointIndex(value, found);
204
310
  }
205
311
  function __velarStringCount(value, text) {
206
312
  value = __velarTextValue(value); text = __velarTextArgument(text, "String.count text");
@@ -208,7 +314,7 @@ function __velarStringCount(value, text) {
208
314
  let count = 0;
209
315
  let cursor = 0;
210
316
  while (true) {
211
- const index = __velarTextCall(__velarNativeStringIndexOf, value, [text, cursor]);
317
+ const index = __velarTextBoundedIndexOf(value, text, cursor);
212
318
  if (index < 0) return count;
213
319
  count += 1;
214
320
  cursor = index + text.length;
@@ -216,12 +322,12 @@ function __velarStringCount(value, text) {
216
322
  }
217
323
  function __velarStringStartsWith(value, text) {
218
324
  value = __velarTextValue(value); text = __velarTextArgument(text, "String.startsWith text");
219
- return __velarTextCall(__velarNativeStringIndexOf, value, [text, 0]) === 0;
325
+ return __velarTextCall(__velarNativeStringIndexOf, value, [text, 0]) === 0 && __velarTextIsBoundary(value, text.length);
220
326
  }
221
327
  function __velarStringEndsWith(value, text) {
222
328
  value = __velarTextValue(value); text = __velarTextArgument(text, "String.endsWith text");
223
329
  const start = value.length - text.length;
224
- return start >= 0 && __velarTextCall(__velarNativeStringIndexOf, value, [text, start]) === start;
330
+ return start >= 0 && __velarTextIsBoundary(value, start) && __velarTextCall(__velarNativeStringIndexOf, value, [text, start]) === start;
225
331
  }
226
332
  function __velarStringSplit(value, separator) {
227
333
  value = __velarTextValue(value); separator = __velarTextArgument(separator, "String.split separator");
@@ -237,12 +343,35 @@ function __velarStringSplit(value, separator) {
237
343
  }
238
344
  return output;
239
345
  }
240
- return __velarTextList(__velarTextCall(__velarNativeStringSplit, value, [separator, __velarMaxTextItems + 1]), "String.split");
346
+ // The native split matches UTF-16 code units, so it would cut a surrogate
347
+ // pair in half on a separator that begins or ends with an unpaired
348
+ // surrogate. Every other separator makes the two scans agree match for
349
+ // match, and the native one is the faster: its limit argument also stops it
350
+ // before it can build an oversize array.
351
+ if (!__velarTextNeedsBoundaryCheck(separator)) {
352
+ return __velarTextList(__velarTextCall(__velarNativeStringSplit, value, [separator, __velarMaxTextItems + 1]), "String.split");
353
+ }
354
+ // Searching on code-point boundaries keeps every piece well formed; the
355
+ // pieces themselves are still plain slices of the input.
356
+ const parts = new __velarTextNativeArray();
357
+ let cursor = 0;
358
+ while (true) {
359
+ const found = __velarTextBoundedIndexOf(value, separator, cursor);
360
+ if (found < 0) break;
361
+ parts[parts.length] = __velarTextCall(__velarNativeStringSlice, value, [cursor, found]);
362
+ if (parts.length > __velarMaxTextItems) return __velarTextList(parts, "String.split");
363
+ cursor = found + separator.length;
364
+ }
365
+ parts[parts.length] = __velarTextCall(__velarNativeStringSlice, value, [cursor]);
366
+ return __velarTextList(parts, "String.split");
241
367
  }
242
368
  function __velarStringReplace(value, from, to) {
243
369
  value = __velarTextValue(value); from = __velarTextArgument(from, "String.replace from"); to = __velarTextArgument(to, "String.replace to");
244
370
  if (__velarTextReplacementOutputUnits(value, from, to, false) > __velarMaxTextCodeUnits) throw new __velarTextNativeRangeError("String.replace output cannot exceed 16 MiB");
245
- return __velarTextCall(__velarNativeStringReplace, value, [from, () => to]);
371
+ if (from === "") return to + value;
372
+ const found = __velarTextBoundedIndexOf(value, from, 0);
373
+ if (found < 0) return value;
374
+ return __velarTextCall(__velarNativeStringSlice, value, [0, found]) + to + __velarTextCall(__velarNativeStringSlice, value, [found + from.length]);
246
375
  }
247
376
  function __velarStringReplaceAll(value, from, to) {
248
377
  value = __velarTextValue(value); from = __velarTextArgument(from, "String.replaceAll from"); to = __velarTextArgument(to, "String.replaceAll to");
@@ -253,7 +382,19 @@ function __velarStringReplaceAll(value, from, to) {
253
382
  while (offset < value.length) { const next = __velarTextNextCodePointOffset(value, offset); output += __velarTextCall(__velarNativeStringSlice, value, [offset, next]) + to; offset = next; }
254
383
  return output;
255
384
  }
256
- return __velarTextCall(__velarNativeStringReplaceAll, value, [from, () => to]);
385
+ // A separator that cannot split a pair leaves nothing for the bounded walk
386
+ // to reject, so the native rewrite answers the same string faster. The
387
+ // replacement is passed as a function so that a '$' in it stays literal.
388
+ if (!__velarTextNeedsBoundaryCheck(from)) return __velarTextCall(__velarNativeStringReplaceAll, value, [from, () => to]);
389
+ let output = "";
390
+ let cursor = 0;
391
+ while (true) {
392
+ const found = __velarTextBoundedIndexOf(value, from, cursor);
393
+ if (found < 0) break;
394
+ output += __velarTextCall(__velarNativeStringSlice, value, [cursor, found]) + to;
395
+ cursor = found + from.length;
396
+ }
397
+ return output + __velarTextCall(__velarNativeStringSlice, value, [cursor]);
257
398
  }
258
399
  function __velarStringPad(value, size, fill, start) {
259
400
  const name = start ? "String.padStart" : "String.padEnd";
@@ -1 +1 @@
1
- {"version":3,"file":"text-runtime.js","sourceRoot":"","sources":["../src/text-runtime.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,yBAAyB,GAAG,MAAM,CAAC,GAAG,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA2RlD,CAAC,SAAS,EAAE,CAAC"}
1
+ {"version":3,"file":"text-runtime.js","sourceRoot":"","sources":["../src/text-runtime.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,yBAAyB,GAAG,MAAM,CAAC,GAAG,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAwalD,CAAC,SAAS,EAAE,CAAC"}
package/dist/token.d.ts CHANGED
@@ -14,6 +14,17 @@ export interface Token {
14
14
  readonly span: Span;
15
15
  readonly payload?: unknown;
16
16
  }
17
+ /**
18
+ * A number token's payload, carried only when the author's own spelling differs
19
+ * from the value the token holds — digit separators (`1_000_000_1`) and an
20
+ * uppercase radix prefix (`0X20`) are the two differences the lexer makes.
21
+ * D90 R6's representability report quotes the literal back at the author, and
22
+ * quoting the normalized spelling would show them text that appears nowhere in
23
+ * their source.
24
+ */
25
+ export interface NumberTokenPayload {
26
+ readonly written: string;
27
+ }
17
28
  /**
18
29
  * Hard reserved words: spellings the lexer always turns into a keyword token,
19
30
  * so they can never name a binding. D30 item 16 softened the statement-head
@@ -1 +1 @@
1
- {"version":3,"file":"token.d.ts","sourceRoot":"","sources":["../src/token.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,aAAa,CAAC;AAExC,MAAM,MAAM,SAAS,GACjB,YAAY,GACZ,QAAQ,GACR,QAAQ,GACR,SAAS,GACT,gBAAgB,GAChB,YAAY,GACZ,OAAO,GACP,KAAK,GACL,KAAK,GACL,OAAO,GACP,OAAO,GACP,QAAQ,GACR,QAAQ,GACR,IAAI,GACJ,QAAQ,GACR,QAAQ,GACR,QAAQ,GACR,MAAM,GACN,UAAU,GACV,OAAO,GACP,SAAS,GACT,UAAU,GACV,SAAS,GACT,QAAQ,GACR,OAAO,GACP,QAAQ,GACR,OAAO,GACP,QAAQ,GACR,IAAI,GACJ,MAAM,GACN,KAAK,GACL,IAAI,GACJ,OAAO,GACP,OAAO,GACP,UAAU,GACV,KAAK,GACL,OAAO,GACP,SAAS,GACT,MAAM,GACN,IAAI,GACJ,MAAM,GACN,OAAO,GACP,MAAM,GACN,KAAK,GACL,IAAI,GACJ,KAAK,GACL,SAAS,GACT,QAAQ,GACR,QAAQ,GACR,WAAW,GACX,YAAY,GACZ,aAAa,GACb,cAAc,GACd,WAAW,GACX,YAAY,GACZ,OAAO,GACP,OAAO;AACT,mGAAmG,IAAI,IAAI,GACzG,KAAK,GACL,UAAU,GACV,UAAU;AACZ;;;;;GAKG;GACD,MAAM,GACN,aAAa,GACb,SAAS,GACT,OAAO,GACP,UAAU,GACV,MAAM,GACN,KAAK,GACL,OAAO,GACP,OAAO,GACP,WAAW,GACX,YAAY,GACZ,oBAAoB,GACpB,QAAQ,GACR,YAAY,GACZ,aAAa,GACb,YAAY,GACZ,aAAa,GACb,eAAe,GACf,aAAa,GACb,cAAc,GACd,cAAc,GACd,iBAAiB,GACjB,kBAAkB,GAClB,0BAA0B,GAC1B,OAAO,GACP,UAAU,GACV,MAAM,GACN,WAAW,GACX,SAAS,GACT,cAAc,GACd,MAAM,GACN,OAAO,GACP,MAAM,GACN,UAAU,GACV,OAAO,GACP,SAAS,GACT,KAAK,CAAC;AAEV,MAAM,WAAW,KAAK;IACpB,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC;IACzB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAC;IACpB,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,CAAC;CAC5B;AAED;;;;;;;GAOG;AACH,eAAO,MAAM,YAAY,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,CAyC5D,CAAC"}
1
+ {"version":3,"file":"token.d.ts","sourceRoot":"","sources":["../src/token.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,aAAa,CAAC;AAExC,MAAM,MAAM,SAAS,GACjB,YAAY,GACZ,QAAQ,GACR,QAAQ,GACR,SAAS,GACT,gBAAgB,GAChB,YAAY,GACZ,OAAO,GACP,KAAK,GACL,KAAK,GACL,OAAO,GACP,OAAO,GACP,QAAQ,GACR,QAAQ,GACR,IAAI,GACJ,QAAQ,GACR,QAAQ,GACR,QAAQ,GACR,MAAM,GACN,UAAU,GACV,OAAO,GACP,SAAS,GACT,UAAU,GACV,SAAS,GACT,QAAQ,GACR,OAAO,GACP,QAAQ,GACR,OAAO,GACP,QAAQ,GACR,IAAI,GACJ,MAAM,GACN,KAAK,GACL,IAAI,GACJ,OAAO,GACP,OAAO,GACP,UAAU,GACV,KAAK,GACL,OAAO,GACP,SAAS,GACT,MAAM,GACN,IAAI,GACJ,MAAM,GACN,OAAO,GACP,MAAM,GACN,KAAK,GACL,IAAI,GACJ,KAAK,GACL,SAAS,GACT,QAAQ,GACR,QAAQ,GACR,WAAW,GACX,YAAY,GACZ,aAAa,GACb,cAAc,GACd,WAAW,GACX,YAAY,GACZ,OAAO,GACP,OAAO;AACT,mGAAmG,IAAI,IAAI,GACzG,KAAK,GACL,UAAU,GACV,UAAU;AACZ;;;;;GAKG;GACD,MAAM,GACN,aAAa,GACb,SAAS,GACT,OAAO,GACP,UAAU,GACV,MAAM,GACN,KAAK,GACL,OAAO,GACP,OAAO,GACP,WAAW,GACX,YAAY,GACZ,oBAAoB,GACpB,QAAQ,GACR,YAAY,GACZ,aAAa,GACb,YAAY,GACZ,aAAa,GACb,eAAe,GACf,aAAa,GACb,cAAc,GACd,cAAc,GACd,iBAAiB,GACjB,kBAAkB,GAClB,0BAA0B,GAC1B,OAAO,GACP,UAAU,GACV,MAAM,GACN,WAAW,GACX,SAAS,GACT,cAAc,GACd,MAAM,GACN,OAAO,GACP,MAAM,GACN,UAAU,GACV,OAAO,GACP,SAAS,GACT,KAAK,CAAC;AAEV,MAAM,WAAW,KAAK;IACpB,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC;IACzB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAC;IACpB,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,CAAC;CAC5B;AAED;;;;;;;GAOG;AACH,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CAC1B;AAED;;;;;;;GAOG;AACH,eAAO,MAAM,YAAY,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,CAyC5D,CAAC"}
package/dist/token.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"token.js","sourceRoot":"","sources":["../src/token.ts"],"names":[],"mappings":"AAmHA;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,YAAY,GAAwC;IAC/D,KAAK,EAAE,OAAO;IACd,GAAG,EAAE,KAAK;IACV,GAAG,EAAE,KAAK;IACV,KAAK,EAAE,OAAO;IACd,KAAK,EAAE,OAAO;IACd,MAAM,EAAE,QAAQ;IAChB,MAAM,EAAE,QAAQ;IAChB,EAAE,EAAE,IAAI;IACR,MAAM,EAAE,QAAQ;IAChB,MAAM,EAAE,QAAQ;IAChB,MAAM,EAAE,QAAQ;IAChB,IAAI,EAAE,MAAM;IACZ,QAAQ,EAAE,UAAU;IACpB,KAAK,EAAE,OAAO;IACd,OAAO,EAAE,SAAS;IAClB,QAAQ,EAAE,UAAU;IACpB,OAAO,EAAE,SAAS;IAClB,MAAM,EAAE,QAAQ;IAChB,KAAK,EAAE,OAAO;IACd,MAAM,EAAE,QAAQ;IAChB,KAAK,EAAE,OAAO;IACd,MAAM,EAAE,QAAQ;IAChB,EAAE,EAAE,IAAI;IACR,IAAI,EAAE,MAAM;IACZ,GAAG,EAAE,KAAK;IACV,EAAE,EAAE,IAAI;IACR,KAAK,EAAE,OAAO;IACd,KAAK,EAAE,OAAO;IACd,QAAQ,EAAE,UAAU;IACpB,GAAG,EAAE,KAAK;IACV,KAAK,EAAE,OAAO;IACd,OAAO,EAAE,SAAS;IAClB,IAAI,EAAE,MAAM;IACZ,EAAE,EAAE,IAAI;IACR,IAAI,EAAE,MAAM;IACZ,KAAK,EAAE,OAAO;IACd,IAAI,EAAE,MAAM;IACZ,GAAG,EAAE,KAAK;IACV,EAAE,EAAE,IAAI;IACR,GAAG,EAAE,KAAK;CACX,CAAC"}
1
+ {"version":3,"file":"token.js","sourceRoot":"","sources":["../src/token.ts"],"names":[],"mappings":"AA+HA;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,YAAY,GAAwC;IAC/D,KAAK,EAAE,OAAO;IACd,GAAG,EAAE,KAAK;IACV,GAAG,EAAE,KAAK;IACV,KAAK,EAAE,OAAO;IACd,KAAK,EAAE,OAAO;IACd,MAAM,EAAE,QAAQ;IAChB,MAAM,EAAE,QAAQ;IAChB,EAAE,EAAE,IAAI;IACR,MAAM,EAAE,QAAQ;IAChB,MAAM,EAAE,QAAQ;IAChB,MAAM,EAAE,QAAQ;IAChB,IAAI,EAAE,MAAM;IACZ,QAAQ,EAAE,UAAU;IACpB,KAAK,EAAE,OAAO;IACd,OAAO,EAAE,SAAS;IAClB,QAAQ,EAAE,UAAU;IACpB,OAAO,EAAE,SAAS;IAClB,MAAM,EAAE,QAAQ;IAChB,KAAK,EAAE,OAAO;IACd,MAAM,EAAE,QAAQ;IAChB,KAAK,EAAE,OAAO;IACd,MAAM,EAAE,QAAQ;IAChB,EAAE,EAAE,IAAI;IACR,IAAI,EAAE,MAAM;IACZ,GAAG,EAAE,KAAK;IACV,EAAE,EAAE,IAAI;IACR,KAAK,EAAE,OAAO;IACd,KAAK,EAAE,OAAO;IACd,QAAQ,EAAE,UAAU;IACpB,GAAG,EAAE,KAAK;IACV,KAAK,EAAE,OAAO;IACd,OAAO,EAAE,SAAS;IAClB,IAAI,EAAE,MAAM;IACZ,EAAE,EAAE,IAAI;IACR,IAAI,EAAE,MAAM;IACZ,KAAK,EAAE,OAAO;IACd,IAAI,EAAE,MAAM;IACZ,GAAG,EAAE,KAAK;IACV,EAAE,EAAE,IAAI;IACR,GAAG,EAAE,KAAK;CACX,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"type-registry-runtime.d.ts","sourceRoot":"","sources":["../src/type-registry-runtime.ts"],"names":[],"mappings":"AAEA;;;;GAIG;AACH,eAAO,MAAM,2BAA2B,QA2C3B,CAAC"}
1
+ {"version":3,"file":"type-registry-runtime.d.ts","sourceRoot":"","sources":["../src/type-registry-runtime.ts"],"names":[],"mappings":"AAEA;;;;GAIG;AACH,eAAO,MAAM,2BAA2B,QAkD3B,CAAC"}
@@ -42,7 +42,14 @@ function __velarRegisterRuntimeType(value) {
42
42
  }
43
43
  function __velarRequireRuntimeType(value, name, optional = false) {
44
44
  if (optional && value == null) return null;
45
- if (!value || typeof value !== "object" || !__velarTypeCall(__velarTypeWeakSetHas, __velarRuntimeTypeRegistry, [value])) {
45
+ // Registry membership proves the value was registered somewhere in this
46
+ // realm; it does not prove it still presents the Type surface. A module built
47
+ // by another generation registers into the same WeakSet whenever both
48
+ // generations share the registry key, so the surface itself is asserted here:
49
+ // 'is' and 'parse' are the two operations every caller of this helper goes on
50
+ // to invoke.
51
+ if (!value || typeof value !== "object" || !__velarTypeCall(__velarTypeWeakSetHas, __velarRuntimeTypeRegistry, [value])
52
+ || typeof value.is !== "function" || typeof value.parse !== "function") {
46
53
  throw new __velarTypeNativeTypeError(name + " requires a compiler-known VelarScript runtime type");
47
54
  }
48
55
  return value;
@@ -1 +1 @@
1
- {"version":3,"file":"type-registry-runtime.js","sourceRoot":"","sources":["../src/type-registry-runtime.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,uBAAuB,EAAE,MAAM,kBAAkB,CAAC;AAE3D;;;;GAIG;AACH,MAAM,CAAC,MAAM,2BAA2B,GAAG,MAAM,CAAC,GAAG,CAAA;;;;;;;;;;;;kGAY6C,IAAI,CAAC,SAAS,CAAC,uBAAuB,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA+BxI,CAAC,SAAS,EAAE,CAAC"}
1
+ {"version":3,"file":"type-registry-runtime.js","sourceRoot":"","sources":["../src/type-registry-runtime.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,uBAAuB,EAAE,MAAM,kBAAkB,CAAC;AAE3D;;;;GAIG;AACH,MAAM,CAAC,MAAM,2BAA2B,GAAG,MAAM,CAAC,GAAG,CAAA;;;;;;;;;;;;kGAY6C,IAAI,CAAC,SAAS,CAAC,uBAAuB,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAsCxI,CAAC,SAAS,EAAE,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"type-validation-runtime.d.ts","sourceRoot":"","sources":["../src/type-validation-runtime.ts"],"names":[],"mappings":"AAGA;;;;GAIG;AACH,eAAO,MAAM,6BAA6B,QAgD7B,CAAC;AAEd,+DAA+D;AAC/D,eAAO,MAAM,qCAAqC,QAsCrC,CAAC;AAEd,eAAO,MAAM,8BAA8B,QAc9B,CAAC;AAEd,eAAO,MAAM,4BAA4B,oCAAoC,CAAC;AAE9E;;;;GAIG;AACH,eAAO,MAAM,mCAAmC,QA+BnC,CAAC"}
1
+ {"version":3,"file":"type-validation-runtime.d.ts","sourceRoot":"","sources":["../src/type-validation-runtime.ts"],"names":[],"mappings":"AAGA;;;;GAIG;AACH,eAAO,MAAM,6BAA6B,QAgL7B,CAAC;AAEd,+DAA+D;AAC/D,eAAO,MAAM,qCAAqC,QAsCrC,CAAC;AAEd,eAAO,MAAM,8BAA8B,QAc9B,CAAC;AAEd,eAAO,MAAM,4BAA4B,oCAAoC,CAAC;AAE9E;;;;GAIG;AACH,eAAO,MAAM,mCAAmC,QA+BnC,CAAC"}
@@ -24,11 +24,19 @@ const __velarValidationSetDeleteOperation = __velarCollectionGetOwnPropertyDescr
24
24
  const __velarValidationSetSizeOperation = __velarCollectionGetOwnPropertyDescriptor(__velarValidationSetPrototype, "size")?.get;
25
25
  const __velarValidationFunctionHasInstanceOperation = __velarCollectionGetOwnPropertyDescriptor(__velarValidationFunctionPrototype, __velarValidationHasInstanceSymbol)?.value;
26
26
  const __velarValidationFreezeOperation = __velarCollectionGetOwnPropertyDescriptor(__velarCollectionNativeObject, "freeze")?.value;
27
- function __velarValidationState() { return { active: new __velarValidationNativeWeakMap(), depth: 0 }; }
27
+ const __velarValidationDefinePropertyOperation = __velarCollectionGetOwnPropertyDescriptor(__velarCollectionNativeObject, "defineProperty")?.value;
28
+ const __velarValidationMapSetOperation = __velarCollectionGetOwnPropertyDescriptor(__velarCollectionMapPrototype, "set")?.value;
29
+ const __velarValidationMapGetOperation = __velarCollectionGetOwnPropertyDescriptor(__velarCollectionMapPrototype, "get")?.value;
30
+ // D90 rule R5: the per-call graph state carries both the validator's cycle
31
+ // guard and the copy memo, because parse runs one then the other over the same
32
+ // object graph. 'copies' stays null until something is actually copied.
33
+ function __velarValidationState() { return { active: new __velarValidationNativeWeakMap(), depth: 0, copies: null, copy: __velarValidationCopy }; }
28
34
  function __velarValidationSet() { return new __velarValidationNativeSet(); }
29
35
  function __velarValidationWeakMapGet(value, key) { return __velarCollectionHostCall(__velarValidationWeakMapGetOperation, value, [key]); }
30
36
  function __velarValidationWeakMapSet(value, key, item) { return __velarCollectionHostCall(__velarValidationWeakMapSetOperation, value, [key, item]); }
31
37
  function __velarValidationWeakMapDelete(value, key) { return __velarCollectionHostCall(__velarValidationWeakMapDeleteOperation, value, [key]); }
38
+ function __velarValidationMapGet(value, key) { return __velarCollectionHostCall(__velarValidationMapGetOperation, value, [key]); }
39
+ function __velarValidationMapSet(value, key, item) { return __velarCollectionHostCall(__velarValidationMapSetOperation, value, [key, item]); }
32
40
  function __velarValidationSetHas(value, item) { return __velarCollectionHostCall(__velarValidationSetHasOperation, value, [item]); }
33
41
  function __velarValidationSetAdd(value, item) { return __velarCollectionHostCall(__velarValidationSetAddOperation, value, [item]); }
34
42
  function __velarValidationSetDelete(value, item) { return __velarCollectionHostCall(__velarValidationSetDeleteOperation, value, [item]); }
@@ -48,6 +56,126 @@ function __velarValidationIsPlainObject(value) {
48
56
  if (prototype === null) return true;
49
57
  return __velarCollectionHostCall(__velarCollectionGetPrototypeOf, __velarCollectionNativeObject, [prototype]) === null;
50
58
  }
59
+ // D90 rule R5: parse returns a copy, so "validated" means "and it stays
60
+ // valid" rather than "it was correct at the instant of the check". The copy
61
+ // follows the declared shape — the generated validators supply one callback
62
+ // per element position — and the memo answers per source object *and* copy
63
+ // plan, so a shared or cyclic subgraph is copied once per declared shape and
64
+ // the copy preserves the sharing the source had. Keying on the source alone
65
+ // would hand the second projection of one object the first projection's copy:
66
+ // a value the caller never wrote and no declared type ever accepted. The four
67
+ // container members are spelled with an "Of" suffix because this runtime
68
+ // reaches every host collection through a captured operation: no member call
69
+ // inside it may read as a get, set, has, add, or delete call, which is the
70
+ // boundary gate's rule for this file.
71
+ const __velarValidationCopy = {
72
+ seen(state, value, plan) {
73
+ if (state.copies === null) return undefined;
74
+ const plans = __velarValidationWeakMapGet(state.copies, value);
75
+ return plans === undefined ? undefined : __velarValidationMapGet(plans, plan);
76
+ },
77
+ remember(state, value, copy, plan) {
78
+ if (state.copies === null) state.copies = new __velarValidationNativeWeakMap();
79
+ let plans = __velarValidationWeakMapGet(state.copies, value);
80
+ if (plans === undefined) {
81
+ plans = new __velarCollectionNativeMap();
82
+ __velarValidationWeakMapSet(state.copies, value, plans);
83
+ }
84
+ __velarValidationMapSet(plans, plan, copy);
85
+ return copy;
86
+ },
87
+ object(state, value, plan) {
88
+ return __velarValidationCopy.remember(state, value, {}, plan);
89
+ },
90
+ // Fields are written through defineProperty so a field literally named
91
+ // '__proto__' lands as an own data property instead of retargeting the
92
+ // copy's prototype, and so every copied field is an ordinary mutable
93
+ // enumerable data property whatever the source's descriptor said.
94
+ field(target, name, value) {
95
+ __velarCollectionHostCall(__velarValidationDefinePropertyOperation, __velarCollectionNativeObject, [target, name, { value: value, writable: true, enumerable: true, configurable: true }]);
96
+ },
97
+ // A null element callback means the element position has nothing to copy —
98
+ // a primitive, an enum member, a class instance, or an opaque 'unknown'.
99
+ // 'plan' is the container position's own stable identity: the emitter hoists
100
+ // one function per distinct copy plan and hands it in as both the element
101
+ // callback and the key this memo files the copy under.
102
+ listOf(value, state, item, plan) {
103
+ const found = __velarValidationCopy.seen(state, value, plan);
104
+ if (found !== undefined) return found;
105
+ const result = __velarValidationCopy.remember(state, value, [], plan);
106
+ const length = __velarValidationOwnDescriptor(value, "length")?.value ?? 0;
107
+ for (let index = 0; index < length; index += 1) {
108
+ const descriptor = __velarValidationOwnDescriptor(value, index);
109
+ result[index] = item === null ? descriptor?.value : item(descriptor?.value, state);
110
+ }
111
+ return result;
112
+ },
113
+ setOf(value, state, item, plan) {
114
+ const found = __velarValidationCopy.seen(state, value, plan);
115
+ if (found !== undefined) return found;
116
+ const result = __velarValidationCopy.remember(state, value, __velarValidationSet(), plan);
117
+ const iterator = __velarCollectionSetTypeIterator(value);
118
+ while (true) {
119
+ const step = __velarCollectionSetTypeNext(iterator);
120
+ if (step.done) break;
121
+ __velarValidationSetAdd(result, item === null ? step.value : item(step.value, state));
122
+ }
123
+ return result;
124
+ },
125
+ mapOf(value, state, key, item, plan) {
126
+ const found = __velarValidationCopy.seen(state, value, plan);
127
+ if (found !== undefined) return found;
128
+ const result = __velarValidationCopy.remember(state, value, new __velarCollectionNativeMap(), plan);
129
+ const iterator = __velarCollectionMapTypeIterator(value);
130
+ while (true) {
131
+ const step = __velarCollectionMapTypeNext(iterator);
132
+ if (step.done) break;
133
+ const entry = step.value;
134
+ __velarValidationMapSet(result, key === null ? entry[0] : key(entry[0], state), item === null ? entry[1] : item(entry[1], state));
135
+ }
136
+ return result;
137
+ },
138
+ recordOf(value, state, item, plan) {
139
+ const found = __velarValidationCopy.seen(state, value, plan);
140
+ if (found !== undefined) return found;
141
+ const result = __velarValidationCopy.remember(state, value, {}, plan);
142
+ const keys = __velarCollectionHostCall(__velarCollectionOwnKeys, __velarCollectionNativeReflect, [value]);
143
+ for (let index = 0; index < keys.length; index += 1) {
144
+ const name = keys[index];
145
+ if (typeof name !== "string") continue;
146
+ const descriptor = __velarValidationOwnDescriptor(value, name);
147
+ if (!descriptor?.enumerable || !("value" in descriptor)) continue;
148
+ __velarValidationCopy.field(result, name, item === null ? descriptor.value : item(descriptor.value, state));
149
+ }
150
+ return result;
151
+ },
152
+ // A generic instantiation supplies a predicate per type argument but no copy
153
+ // plan, and a structural or union position is validated as a shape the
154
+ // predicate did not fully decide. Both copy the plain data they can see:
155
+ // arrays, Maps, Sets, and plain objects recurse; anything else — a class
156
+ // instance, a promise, a function, a binary buffer — is not plain data and
157
+ // passes through by reference.
158
+ plain(value, state) {
159
+ if (value === null || typeof value !== "object") return value;
160
+ const found = __velarValidationCopy.seen(state, value, __velarValidationCopy.plain);
161
+ if (found !== undefined) return found;
162
+ if (__velarValidationIsArray(value)) return __velarValidationCopy.listOf(value, state, __velarValidationCopy.plain, __velarValidationCopy.plain);
163
+ if (__velarIsMap(value)) return __velarValidationCopy.mapOf(value, state, __velarValidationCopy.plain, __velarValidationCopy.plain, __velarValidationCopy.plain);
164
+ if (__velarIsSet(value)) return __velarValidationCopy.setOf(value, state, __velarValidationCopy.plain, __velarValidationCopy.plain);
165
+ if (!__velarValidationIsPlainObject(value)) return value;
166
+ return __velarValidationCopy.recordOf(value, state, __velarValidationCopy.plain, __velarValidationCopy.plain);
167
+ },
168
+ // A Type object from a target extension, or one emitted by an older build,
169
+ // may carry no copy plan; the structural copy is what is left to fall back on.
170
+ // A Type that does answer 'copy' owns its own plan identity — a declared
171
+ // record files under its copy function, an instantiation under its arguments
172
+ // — so nothing is threaded in from here.
173
+ through(type, value, state) {
174
+ const operation = type === null || type === undefined ? undefined : type.copy;
175
+ if (typeof operation !== "function") return __velarValidationCopy.plain(value, state);
176
+ return __velarCollectionHostCall(operation, type, [value, state]);
177
+ },
178
+ };
51
179
  // Teaching suffix for record parse failures caused by the plain-object rule.
52
180
  function __velarValidationRejectionHint(value) {
53
181
  if (value === null || typeof value !== "object" || __velarValidationIsArray(value) || __velarValidationIsPlainObject(value)) return "";
@@ -1 +1 @@
1
- {"version":3,"file":"type-validation-runtime.js","sourceRoot":"","sources":["../src/type-validation-runtime.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iCAAiC,EAAE,6BAA6B,EAAE,MAAM,yBAAyB,CAAC;AAC3G,OAAO,EAAE,2BAA2B,EAAE,MAAM,4BAA4B,CAAC;AAEzE;;;;GAIG;AACH,MAAM,CAAC,MAAM,6BAA6B,GAAG,MAAM,CAAC,GAAG,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAgDtD,CAAC,SAAS,EAAE,CAAC;AAEd,+DAA+D;AAC/D,MAAM,CAAC,MAAM,qCAAqC,GAAG,MAAM,CAAC,GAAG,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAsC9D,CAAC,SAAS,EAAE,CAAC;AAEd,MAAM,CAAC,MAAM,8BAA8B,GAAG,MAAM,CAAC,GAAG,CAAA;;;;;;;;;;;;;;CAcvD,CAAC,SAAS,EAAE,CAAC;AAEd,MAAM,CAAC,MAAM,4BAA4B,GAAG,iCAAiC,CAAC;AAE9E;;;;GAIG;AACH,MAAM,CAAC,MAAM,mCAAmC,GAAG,MAAM,CAAC,GAAG,CAAA;EAC3D,iCAAiC;EACjC,6BAA6B;EAC7B,2BAA2B;EAC3B,6BAA6B;EAC7B,qCAAqC;EACrC,8BAA8B;;;;;;;;;;;;;;;;;;;;;;;;;CAyB/B,CAAC,SAAS,EAAE,CAAC"}
1
+ {"version":3,"file":"type-validation-runtime.js","sourceRoot":"","sources":["../src/type-validation-runtime.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iCAAiC,EAAE,6BAA6B,EAAE,MAAM,yBAAyB,CAAC;AAC3G,OAAO,EAAE,2BAA2B,EAAE,MAAM,4BAA4B,CAAC;AAEzE;;;;GAIG;AACH,MAAM,CAAC,MAAM,6BAA6B,GAAG,MAAM,CAAC,GAAG,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAgLtD,CAAC,SAAS,EAAE,CAAC;AAEd,+DAA+D;AAC/D,MAAM,CAAC,MAAM,qCAAqC,GAAG,MAAM,CAAC,GAAG,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAsC9D,CAAC,SAAS,EAAE,CAAC;AAEd,MAAM,CAAC,MAAM,8BAA8B,GAAG,MAAM,CAAC,GAAG,CAAA;;;;;;;;;;;;;;CAcvD,CAAC,SAAS,EAAE,CAAC;AAEd,MAAM,CAAC,MAAM,4BAA4B,GAAG,iCAAiC,CAAC;AAE9E;;;;GAIG;AACH,MAAM,CAAC,MAAM,mCAAmC,GAAG,MAAM,CAAC,GAAG,CAAA;EAC3D,iCAAiC;EACjC,6BAA6B;EAC7B,2BAA2B;EAC3B,6BAA6B;EAC7B,qCAAqC;EACrC,8BAA8B;;;;;;;;;;;;;;;;;;;;;;;;;CAyB/B,CAAC,SAAS,EAAE,CAAC"}
package/dist/types.d.ts CHANGED
@@ -69,9 +69,16 @@ export interface GenericApplication {
69
69
  readonly name: string;
70
70
  readonly arguments: readonly ValueType[];
71
71
  }
72
- export type ValueType = {
72
+ export type ValueType =
73
+ /**
74
+ * `restricted` is the recursion placeholder and `boundary` is the `unknown`
75
+ * a program wrote down — the type of data nobody has checked yet. Neither
76
+ * may be absorbed by a merge; see `mergeTypes`.
77
+ */
78
+ {
73
79
  readonly kind: "unknown";
74
80
  readonly restricted?: boolean;
81
+ readonly boundary?: true;
75
82
  }
76
83
  /**
77
84
  * `textConvertible` marks the compiler-owned text-conversion domain (charter
@@ -212,6 +219,14 @@ export type BinaryStorageKind = "bytes" | "uint8" | "uint16" | "uint32" | "float
212
219
  */
213
220
  export declare function binaryStorageKind(type: ValueType): BinaryStorageKind | null;
214
221
  export declare const unknownType: ValueType;
222
+ /**
223
+ * The `unknown` a program wrote in an annotation, and the type every boundary
224
+ * that hands back unchecked data should carry. It differs from the inference
225
+ * seed above in exactly one rule — a merge may not absorb it — so `unknown`
226
+ * arriving from outside stays unassignable until the value is validated,
227
+ * instead of being retyped as whatever the other branch produced.
228
+ */
229
+ export declare const boundaryUnknownType: ValueType;
215
230
  export declare const invalidType: ValueType;
216
231
  export declare const anyType: ValueType;
217
232
  /** The declared parameter domain of the built-in `str`; see `isTextConvertibleType`. */
@@ -320,6 +335,7 @@ export declare function typeContainsParameter(type: ValueType, matches?: (parame
320
335
  kind: "parameter";
321
336
  }>) => boolean): boolean;
322
337
  export declare function typeContainsRuntimeTypeCheck(type: ValueType): boolean;
338
+ export declare function typeContainsAnyOutput(type: ValueType): boolean;
323
339
  export declare function substituteTypeParameters(type: ValueType, bindings: readonly (ValueType | null)[]): ValueType;
324
340
  export declare function bindNamedTypeParameters(type: ValueType, parameters: ReadonlyMap<string, ValueType>): ValueType;
325
341
  /**