@shwfed/nuxt 0.7.8 → 0.7.9

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 (99) hide show
  1. package/dist/module.json +1 -1
  2. package/dist/runtime/components/app.d.vue.ts +0 -2
  3. package/dist/runtime/components/app.vue +1 -7
  4. package/dist/runtime/components/app.vue.d.ts +0 -2
  5. package/dist/runtime/components/fields.d.vue.ts +155 -0
  6. package/dist/runtime/components/fields.vue +312 -0
  7. package/dist/runtime/components/fields.vue.d.ts +155 -0
  8. package/dist/runtime/components/ui/button-group/ButtonGroupSeparator.vue +1 -1
  9. package/dist/runtime/components/ui/button-group/ButtonGroupText.vue +1 -1
  10. package/dist/runtime/components/ui/calendar/Calendar.d.vue.ts +5 -12
  11. package/dist/runtime/components/ui/calendar/Calendar.vue +77 -92
  12. package/dist/runtime/components/ui/calendar/Calendar.vue.d.ts +5 -12
  13. package/dist/runtime/components/ui/calendar/CalendarCellTrigger.vue +1 -1
  14. package/dist/runtime/components/ui/calendar/index.d.ts +1 -1
  15. package/dist/runtime/components/ui/command/CommandGroup.vue +4 -0
  16. package/dist/runtime/components/ui/dialog/DialogOverlay.vue +1 -1
  17. package/dist/runtime/components/ui/dropdown-menu/DropdownMenuCheckboxItem.vue +1 -1
  18. package/dist/runtime/components/ui/dropdown-menu/DropdownMenuSubTrigger.vue +1 -1
  19. package/dist/runtime/components/ui/field/FieldDescription.vue +1 -1
  20. package/dist/runtime/components/ui/field/FieldError.vue +1 -1
  21. package/dist/runtime/components/ui/field/FieldLabel.vue +1 -1
  22. package/dist/runtime/components/ui/field/FieldSeparator.vue +1 -1
  23. package/dist/runtime/components/ui/field/index.js +7 -5
  24. package/dist/runtime/components/ui/input/Input.vue +1 -1
  25. package/dist/runtime/components/ui/input-group/InputGroup.vue +3 -0
  26. package/dist/runtime/components/ui/input-group/InputGroupCombobox.d.vue.ts +4 -1
  27. package/dist/runtime/components/ui/input-group/InputGroupCombobox.vue +10 -4
  28. package/dist/runtime/components/ui/input-group/InputGroupCombobox.vue.d.ts +4 -1
  29. package/dist/runtime/components/ui/input-group/InputGroupComboboxInput.vue +3 -1
  30. package/dist/runtime/components/ui/input-group/InputGroupInput.vue +1 -1
  31. package/dist/runtime/components/ui/input-group/InputGroupNumberField.vue +1 -1
  32. package/dist/runtime/components/ui/input-group/InputGroupText.vue +1 -1
  33. package/dist/runtime/components/ui/input-group/InputGroupTextarea.vue +1 -1
  34. package/dist/runtime/components/ui/input-group/index.js +1 -1
  35. package/dist/runtime/components/ui/label/Label.vue +1 -1
  36. package/dist/runtime/components/ui/native-select/NativeSelect.vue +3 -3
  37. package/dist/runtime/components/ui/navigation-menu/NavigationMenuLink.vue +1 -1
  38. package/dist/runtime/components/ui/navigation-menu/NavigationMenuViewport.vue +1 -1
  39. package/dist/runtime/components/ui/range-calendar/RangeCalendarCell.vue +1 -1
  40. package/dist/runtime/components/ui/range-calendar/RangeCalendarCellTrigger.vue +1 -1
  41. package/dist/runtime/components/ui/sheet/SheetOverlay.vue +1 -1
  42. package/dist/runtime/components/ui/switch/Switch.d.vue.ts +24 -0
  43. package/dist/runtime/components/ui/switch/Switch.vue +46 -0
  44. package/dist/runtime/components/ui/switch/Switch.vue.d.ts +24 -0
  45. package/dist/runtime/components/ui/switch/index.d.ts +1 -0
  46. package/dist/runtime/components/ui/switch/index.js +1 -0
  47. package/dist/runtime/components/ui/textarea/Textarea.vue +1 -1
  48. package/dist/runtime/plugins/cel/env.d.ts +2 -2
  49. package/dist/runtime/plugins/cel/env.js +5 -4
  50. package/dist/runtime/plugins/cel/index.d.ts +3 -3
  51. package/dist/runtime/plugins/cel/index.js +7 -3
  52. package/dist/runtime/plugins/markdown/index.d.ts +1 -1
  53. package/dist/runtime/utils/coders.d.ts +7 -0
  54. package/dist/runtime/utils/coders.js +39 -0
  55. package/dist/runtime/vendor/cel/index.d.ts +17 -0
  56. package/dist/runtime/vendor/cel/index.js +10 -0
  57. package/dist/runtime/vendor/cel-js/LICENSE +21 -0
  58. package/dist/runtime/vendor/cel-js/UPSTREAM.md +17 -0
  59. package/dist/runtime/vendor/cel-js/lib/errors.d.ts +21 -0
  60. package/dist/runtime/vendor/cel-js/lib/errors.js +97 -0
  61. package/dist/runtime/vendor/cel-js/lib/evaluator.d.ts +4 -0
  62. package/dist/runtime/vendor/cel-js/lib/evaluator.js +192 -0
  63. package/dist/runtime/vendor/cel-js/lib/functions.d.ts +53 -0
  64. package/dist/runtime/vendor/cel-js/lib/functions.js +513 -0
  65. package/dist/runtime/vendor/cel-js/lib/globals.d.ts +27 -0
  66. package/dist/runtime/vendor/cel-js/lib/globals.js +33 -0
  67. package/dist/runtime/vendor/cel-js/lib/index.d.ts +469 -0
  68. package/dist/runtime/vendor/cel-js/lib/index.js +18 -0
  69. package/dist/runtime/vendor/cel-js/lib/macros.d.ts +1 -0
  70. package/dist/runtime/vendor/cel-js/lib/macros.js +230 -0
  71. package/dist/runtime/vendor/cel-js/lib/operators.d.ts +117 -0
  72. package/dist/runtime/vendor/cel-js/lib/operators.js +739 -0
  73. package/dist/runtime/vendor/cel-js/lib/optional.d.ts +14 -0
  74. package/dist/runtime/vendor/cel-js/lib/optional.js +161 -0
  75. package/dist/runtime/vendor/cel-js/lib/options.d.ts +23 -0
  76. package/dist/runtime/vendor/cel-js/lib/options.js +47 -0
  77. package/dist/runtime/vendor/cel-js/lib/overloads.d.ts +1 -0
  78. package/dist/runtime/vendor/cel-js/lib/overloads.js +214 -0
  79. package/dist/runtime/vendor/cel-js/lib/parser.d.ts +56 -0
  80. package/dist/runtime/vendor/cel-js/lib/parser.js +827 -0
  81. package/dist/runtime/vendor/cel-js/lib/registry.d.ts +279 -0
  82. package/dist/runtime/vendor/cel-js/lib/registry.js +1596 -0
  83. package/dist/runtime/vendor/cel-js/lib/serialize.d.ts +1 -0
  84. package/dist/runtime/vendor/cel-js/lib/serialize.js +259 -0
  85. package/dist/runtime/vendor/cel-js/lib/type-checker.d.ts +26 -0
  86. package/dist/runtime/vendor/cel-js/lib/type-checker.js +81 -0
  87. package/package.json +7 -4
  88. package/dist/runtime/components/locale.d.vue.ts +0 -14
  89. package/dist/runtime/components/locale.vue +0 -89
  90. package/dist/runtime/components/locale.vue.d.ts +0 -14
  91. package/dist/runtime/components/query.d.vue.ts +0 -30
  92. package/dist/runtime/components/query.vue +0 -266
  93. package/dist/runtime/components/query.vue.d.ts +0 -30
  94. package/dist/runtime/utilities/query-config/global.d.ts +0 -4
  95. package/dist/runtime/utilities/query-config/global.js +0 -18
  96. package/dist/runtime/utilities/query-config/index.d.ts +0 -3
  97. package/dist/runtime/utilities/query-config/index.js +0 -14
  98. package/dist/runtime/utilities/query-config/schema.d.ts +0 -96
  99. package/dist/runtime/utilities/query-config/schema.js +0 -51
@@ -0,0 +1,827 @@
1
+ import {UnsignedInt} from './functions.js'
2
+ import {ParseError} from './errors.js'
3
+ import {OPERATORS as OPS} from './operators.js'
4
+ import {RESERVED, isAsync} from './globals.js'
5
+
6
+ const TOKEN = {
7
+ EOF: 0,
8
+ NUMBER: 1,
9
+ STRING: 2,
10
+ BOOLEAN: 3,
11
+ NULL: 4,
12
+ IDENTIFIER: 5,
13
+ PLUS: 6,
14
+ MINUS: 7,
15
+ MULTIPLY: 8,
16
+ DIVIDE: 9,
17
+ MODULO: 10,
18
+ EQ: 11,
19
+ NE: 12,
20
+ LT: 13,
21
+ LE: 14,
22
+ GT: 15,
23
+ GE: 16,
24
+ AND: 17,
25
+ OR: 18,
26
+ NOT: 19,
27
+ IN: 20,
28
+ LPAREN: 21,
29
+ RPAREN: 22,
30
+ LBRACKET: 23,
31
+ RBRACKET: 24,
32
+ LBRACE: 25,
33
+ RBRACE: 26,
34
+ DOT: 27,
35
+ COMMA: 28,
36
+ COLON: 29,
37
+ QUESTION: 30,
38
+ BYTES: 31
39
+ }
40
+
41
+ const OP_FOR_TOKEN = {
42
+ [TOKEN.EQ]: OPS['=='],
43
+ [TOKEN.PLUS]: OPS['+'],
44
+ [TOKEN.MINUS]: OPS['-'],
45
+ [TOKEN.MULTIPLY]: OPS['*'],
46
+ [TOKEN.DIVIDE]: OPS['/'],
47
+ [TOKEN.MODULO]: OPS['%'],
48
+ [TOKEN.LE]: OPS['<='],
49
+ [TOKEN.LT]: OPS['<'],
50
+ [TOKEN.GE]: OPS['>='],
51
+ [TOKEN.GT]: OPS['>'],
52
+ [TOKEN.NE]: OPS['!='],
53
+ [TOKEN.IN]: OPS['in']
54
+ }
55
+
56
+ const TOKEN_BY_NUMBER = {}
57
+ for (const key in TOKEN) TOKEN_BY_NUMBER[TOKEN[key]] = key
58
+
59
+ const HEX_CODES = new Uint8Array(128)
60
+ for (const ch of '0123456789abcdefABCDEF') HEX_CODES[ch.charCodeAt(0)] = 1
61
+
62
+ const STRING_ESCAPES = {
63
+ '\\': '\\',
64
+ '?': '?',
65
+ '"': '"',
66
+ "'": "'",
67
+ '`': '`',
68
+ a: '\x07',
69
+ b: '\b',
70
+ f: '\f',
71
+ n: '\n',
72
+ r: '\r',
73
+ t: '\t',
74
+ v: '\v'
75
+ }
76
+
77
+ export class ASTNode {
78
+ #meta
79
+ constructor(input, pos, op, args) {
80
+ this.#meta = {input, pos, evaluate: op.evaluate, check: op.check}
81
+ this.op = op.name
82
+ this.args = args
83
+ }
84
+
85
+ clone(op, args) {
86
+ return new ASTNode(this.#meta.input, this.#meta.pos, op, args)
87
+ }
88
+
89
+ get meta() {
90
+ return this.#meta
91
+ }
92
+
93
+ #computeIsAsync() {
94
+ const ast = this.#meta.alternate ?? this
95
+
96
+ // prettier-ignore
97
+ switch (ast.op) {
98
+ case 'value': case 'id': case 'accuValue': case 'accuInc':
99
+ return false
100
+ case 'accuPush':
101
+ return ast.args.maybeAsync
102
+ case '!_': case '-_':
103
+ if (ast.candidates?.async !== false) return true
104
+ return ast.args.maybeAsync
105
+ case '!=': case '==': case 'in': case '+': case '-': case '*':
106
+ case '/': case '%': case '<': case '<=': case '>': case '>=':
107
+ if (ast.candidates?.async !== false) return true
108
+ return ast.args.some((a) => a.maybeAsync)
109
+ case 'call': case 'rcall':
110
+ if (ast.candidates?.async !== false) return true
111
+ return (ast.receiverWithArgs || ast.args[1]).some((a) => a.maybeAsync)
112
+ case 'comprehension':
113
+ return ast.args.iterable.maybeAsync || ast.args.step.maybeAsync
114
+ case '.': case '.?':
115
+ return ast.args[0].maybeAsync
116
+ case '?:': case 'list':
117
+ case '[]': case '[?]':
118
+ return ast.args.some((a) => a.maybeAsync)
119
+ case '||': case '&&':
120
+ return ast.args.some((a) => a.maybeAsync)
121
+ case 'map':
122
+ return ast.args.some((a) => a[0].maybeAsync || a[1].maybeAsync)
123
+ default:
124
+ return true
125
+ }
126
+ }
127
+
128
+ /**
129
+ * Check whether we can optimize away async calling
130
+ * If no ast members includes a function, we can optimize the call
131
+ * for which we want to return true here.
132
+ * @returns {boolean}
133
+ */
134
+ get maybeAsync() {
135
+ return (this.#meta.async ??= this.#computeIsAsync())
136
+ }
137
+
138
+ check(chk, ast, ctx) {
139
+ const meta = this.#meta
140
+ if (meta.alternate) return chk.check(meta.alternate, ctx)
141
+ else if (meta.macro) return meta.macro.typeCheck(chk, meta.macro, ctx)
142
+ return meta.check(chk, ast, ctx)
143
+ }
144
+
145
+ evaluate(ev, ast, ctx) {
146
+ const meta = this.#meta
147
+ if (meta.alternate) this.evaluate = this.#evaluateAlternate
148
+ else if (meta.macro) this.evaluate = this.#evaluateMacro
149
+ else this.evaluate = meta.evaluate
150
+ return this.evaluate(ev, ast, ctx)
151
+ }
152
+
153
+ #evaluateAlternate(ev, ast, ctx) {
154
+ return (ast = this.#meta.alternate).evaluate(ev, ast, ctx)
155
+ }
156
+
157
+ #evaluateMacro(ev, ast, ctx) {
158
+ return (ast = this.#meta.macro).evaluate(ev, ast, ctx)
159
+ }
160
+
161
+ setMeta(key, value) {
162
+ return ((this.#meta[key] = value), this)
163
+ }
164
+
165
+ get input() {
166
+ return this.#meta.input
167
+ }
168
+
169
+ get pos() {
170
+ return this.#meta.pos
171
+ }
172
+
173
+ toOldStructure() {
174
+ const args = Array.isArray(this.args) ? this.args : [this.args]
175
+ return [this.op, ...args.map((a) => (a instanceof ASTNode ? a.toOldStructure() : a))]
176
+ }
177
+ }
178
+
179
+ class Lexer {
180
+ input
181
+ pos
182
+ length
183
+
184
+ tokenPos
185
+ tokenType
186
+ tokenValue
187
+
188
+ reset(input) {
189
+ this.pos = 0
190
+ this.input = input
191
+ this.length = input.length
192
+ return input
193
+ }
194
+
195
+ token(pos, type, value) {
196
+ this.tokenPos = pos
197
+ this.tokenType = type
198
+ this.tokenValue = value
199
+ return this
200
+ }
201
+
202
+ // Read next token
203
+ nextToken() {
204
+ while (true) {
205
+ const {pos, input, length} = this
206
+ if (pos >= length) return this.token(pos, TOKEN.EOF)
207
+
208
+ const ch = input[pos]
209
+ switch (ch) {
210
+ // Whitespaces
211
+ case ' ':
212
+ case '\t':
213
+ case '\n':
214
+ case '\r':
215
+ this.pos++
216
+ continue
217
+
218
+ // Operators
219
+ case '=':
220
+ if (input[pos + 1] !== '=') break
221
+ return this.token((this.pos += 2) - 2, TOKEN.EQ)
222
+ case '&':
223
+ if (input[pos + 1] !== '&') break
224
+ return this.token((this.pos += 2) - 2, TOKEN.AND)
225
+ case '|':
226
+ if (input[pos + 1] !== '|') break
227
+ return this.token((this.pos += 2) - 2, TOKEN.OR)
228
+ case '+':
229
+ return this.token(this.pos++, TOKEN.PLUS)
230
+ case '-':
231
+ return this.token(this.pos++, TOKEN.MINUS)
232
+ case '*':
233
+ return this.token(this.pos++, TOKEN.MULTIPLY)
234
+ case '/':
235
+ if (input[pos + 1] === '/') {
236
+ while (this.pos < length && this.input[this.pos] !== '\n') this.pos++
237
+ continue
238
+ }
239
+ return this.token(this.pos++, TOKEN.DIVIDE)
240
+ case '%':
241
+ return this.token(this.pos++, TOKEN.MODULO)
242
+ case '<':
243
+ if (input[pos + 1] === '=') return this.token((this.pos += 2) - 2, TOKEN.LE)
244
+ return this.token(this.pos++, TOKEN.LT)
245
+ case '>':
246
+ if (input[pos + 1] === '=') return this.token((this.pos += 2) - 2, TOKEN.GE)
247
+ return this.token(this.pos++, TOKEN.GT)
248
+ case '!':
249
+ if (input[pos + 1] === '=') return this.token((this.pos += 2) - 2, TOKEN.NE)
250
+ return this.token(this.pos++, TOKEN.NOT)
251
+ case '(':
252
+ return this.token(this.pos++, TOKEN.LPAREN)
253
+ case ')':
254
+ return this.token(this.pos++, TOKEN.RPAREN)
255
+ case '[':
256
+ return this.token(this.pos++, TOKEN.LBRACKET)
257
+ case ']':
258
+ return this.token(this.pos++, TOKEN.RBRACKET)
259
+ case '{':
260
+ return this.token(this.pos++, TOKEN.LBRACE)
261
+ case '}':
262
+ return this.token(this.pos++, TOKEN.RBRACE)
263
+ case '.':
264
+ return this.token(this.pos++, TOKEN.DOT)
265
+ case ',':
266
+ return this.token(this.pos++, TOKEN.COMMA)
267
+ case ':':
268
+ return this.token(this.pos++, TOKEN.COLON)
269
+ case '?':
270
+ return this.token(this.pos++, TOKEN.QUESTION)
271
+ case `"`:
272
+ case `'`:
273
+ return this.readString(ch)
274
+ // Check for string prefixes (b, B, r, R followed by quote)
275
+ case 'b':
276
+ case 'B':
277
+ case 'r':
278
+ case 'R': {
279
+ // This is a prefixed string, advance past the prefix and read string
280
+ const next = input[pos + 1]
281
+ if (next === '"' || next === "'") return ++this.pos && this.readString(next, ch)
282
+ return this.readIdentifier()
283
+ }
284
+ default: {
285
+ const code = ch.charCodeAt(0)
286
+ if (code <= 57 && code >= 48) return this.readNumber()
287
+ if (this._isIdentifierCharCode(code)) return this.readIdentifier()
288
+ }
289
+ }
290
+
291
+ throw new ParseError(`Unexpected character: ${ch}`, {pos, input})
292
+ }
293
+ }
294
+
295
+ // Characters: 0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_
296
+ _isIdentifierCharCode(c) {
297
+ if (c < 48 || c > 122) return false
298
+ return c >= 97 || (c >= 65 && c <= 90) || c <= 57 || c === 95
299
+ }
300
+
301
+ _parseAsDouble(start, end) {
302
+ const value = Number(this.input.substring(start, end))
303
+ if (Number.isFinite(value)) return this.token(start, TOKEN.NUMBER, value)
304
+ throw new ParseError(`Invalid number: ${value}`, {pos: start, input: this.input})
305
+ }
306
+
307
+ _parseAsBigInt(start, end, isHex, unsigned) {
308
+ const string = this.input.substring(start, end)
309
+ if (unsigned === 'u' || unsigned === 'U') {
310
+ this.pos++
311
+ try {
312
+ return this.token(start, TOKEN.NUMBER, new UnsignedInt(string))
313
+ } catch (_err) {}
314
+ } else {
315
+ try {
316
+ return this.token(start, TOKEN.NUMBER, BigInt(string))
317
+ } catch (_err) {}
318
+ }
319
+
320
+ throw new ParseError(isHex ? `Invalid hex integer: ${string}` : `Invalid integer: ${string}`, {
321
+ pos: start,
322
+ input: this.input
323
+ })
324
+ }
325
+
326
+ _readDigits(input, length, pos, code) {
327
+ while (pos < length && (code = input.charCodeAt(pos)) && !(code > 57 || code < 48)) pos++
328
+ return pos
329
+ }
330
+
331
+ _readExponent(input, length, pos) {
332
+ let ch = pos < length && input[pos]
333
+ if (ch === 'e' || ch === 'E') {
334
+ ch = ++pos < length && input[pos]
335
+ if (ch === '-' || ch === '+') pos++
336
+ const start = pos
337
+ pos = this._readDigits(input, length, pos)
338
+ if (start === pos) throw new ParseError('Invalid exponent', {pos, input})
339
+ }
340
+ return pos
341
+ }
342
+
343
+ readNumber() {
344
+ const {input, length, pos: start} = this
345
+ let pos = start
346
+ if (input[pos] === '0' && (input[pos + 1] === 'x' || input[pos + 1] === 'X')) {
347
+ pos += 2
348
+ while (pos < length && HEX_CODES[input[pos].charCodeAt(0)]) pos++
349
+ return this._parseAsBigInt(start, (this.pos = pos), true, input[pos])
350
+ }
351
+
352
+ pos = this._readDigits(input, length, pos)
353
+ if (pos + 1 < length) {
354
+ let isDouble = false
355
+ let afterpos = input[pos] === '.' ? this._readDigits(input, length, pos + 1) : pos + 1
356
+ if (afterpos !== pos + 1) (isDouble = true) && (pos = afterpos)
357
+
358
+ afterpos = this._readExponent(input, length, pos)
359
+ if (afterpos !== pos) (isDouble = true) && (pos = afterpos)
360
+ if (isDouble) return this._parseAsDouble(start, (this.pos = pos))
361
+ }
362
+ return this._parseAsBigInt(start, (this.pos = pos), false, input[pos])
363
+ }
364
+
365
+ readString(del, prefix) {
366
+ const {input: i, pos: s} = this
367
+ if (i[s + 1] === del && i[s + 2] === del) return this.readTripleQuotedString(del, prefix)
368
+ return this.readSingleQuotedString(del, prefix)
369
+ }
370
+
371
+ _closeQuotedString(rawValue, prefix, pos) {
372
+ switch (prefix) {
373
+ case 'b':
374
+ case 'B': {
375
+ const processed = this.processEscapes(rawValue, true)
376
+ const bytes = new Uint8Array(processed.length)
377
+ for (let i = 0; i < processed.length; i++) bytes[i] = processed.charCodeAt(i) & 0xff
378
+ return this.token(pos - 1, TOKEN.BYTES, bytes)
379
+ }
380
+ case 'r':
381
+ case 'R': {
382
+ return this.token(pos - 1, TOKEN.STRING, rawValue)
383
+ }
384
+ default: {
385
+ const value = this.processEscapes(rawValue, false)
386
+ return this.token(pos, TOKEN.STRING, value)
387
+ }
388
+ }
389
+ }
390
+
391
+ readSingleQuotedString(delimiter, prefix) {
392
+ const {input, length, pos: start} = this
393
+
394
+ let ch
395
+ let pos = this.pos + 1
396
+ while (pos < length && (ch = input[pos])) {
397
+ switch (ch) {
398
+ case delimiter:
399
+ const rawValue = input.slice(start + 1, pos)
400
+ this.pos = ++pos
401
+ return this._closeQuotedString(rawValue, prefix, start)
402
+ case '\n':
403
+ case '\r':
404
+ throw new ParseError('Newlines not allowed in single-quoted strings', {pos: start, input})
405
+ case '\\':
406
+ pos++
407
+ }
408
+ pos++
409
+ }
410
+ throw new ParseError('Unterminated string', {pos: start, input})
411
+ }
412
+
413
+ readTripleQuotedString(delimiter, prefix) {
414
+ const {input, length, pos: start} = this
415
+
416
+ let ch
417
+ let pos = this.pos + 3
418
+ while (pos < length && (ch = input[pos])) {
419
+ switch (ch) {
420
+ case delimiter:
421
+ if (input[pos + 1] === delimiter && input[pos + 2] === delimiter) {
422
+ const rawValue = input.slice(start + 3, pos)
423
+ this.pos = pos + 3
424
+ return this._closeQuotedString(rawValue, prefix, start)
425
+ }
426
+ break
427
+ case '\\':
428
+ pos++
429
+ }
430
+ pos++
431
+ }
432
+ throw new ParseError('Unterminated triple-quoted string', {pos: start, input})
433
+ }
434
+
435
+ processEscapes(str, isBytes) {
436
+ if (!str.includes('\\')) return str
437
+
438
+ let result = ''
439
+ let i = 0
440
+ while (i < str.length) {
441
+ if (str[i] !== '\\' || i + 1 >= str.length) {
442
+ result += str[i++]
443
+ continue
444
+ }
445
+
446
+ const next = str[i + 1]
447
+ if (STRING_ESCAPES[next]) {
448
+ result += STRING_ESCAPES[next]
449
+ i += 2
450
+ } else if (next === 'u') {
451
+ if (isBytes) throw new ParseError('\\u not allowed in bytes literals')
452
+ const hex = str.substring(i + 2, (i += 6))
453
+ if (!/^[0-9a-fA-F]{4}$/.test(hex)) throw new ParseError(`Invalid Unicode escape: \\u${hex}`)
454
+ const c = Number.parseInt(hex, 16)
455
+ if (c >= 0xd800 && c <= 0xdfff) throw new ParseError(`Invalid Unicode surrogate: \\u${hex}`)
456
+ result += String.fromCharCode(c)
457
+ } else if (next === 'U') {
458
+ if (isBytes) throw new ParseError('\\U not allowed in bytes literals')
459
+ const hex = str.substring(i + 2, (i += 10))
460
+ if (!/^[0-9a-fA-F]{8}$/.test(hex)) throw new ParseError(`Invalid Unicode escape: \\U${hex}`)
461
+ const c = Number.parseInt(hex, 16)
462
+ if (c > 0x10ffff) throw new ParseError(`Invalid Unicode escape: \\U${hex}`)
463
+ if (c >= 0xd800 && c <= 0xdfff) throw new ParseError(`Invalid Unicode surrogate: \\U${hex}`)
464
+ result += String.fromCodePoint(c)
465
+ } else if (next === 'x' || next === 'X') {
466
+ const h = str.substring(i + 2, (i += 4))
467
+ if (!/^[0-9a-fA-F]{2}$/.test(h)) throw new ParseError(`Invalid hex escape: \\${next}${h}`)
468
+ result += String.fromCharCode(Number.parseInt(h, 16))
469
+ } else if (next >= '0' && next <= '7') {
470
+ const o = str.substring(i + 1, (i += 4))
471
+ if (!/^[0-7]{3}$/.test(o)) throw new ParseError('Octal escape must be 3 digits')
472
+ const value = Number.parseInt(o, 8)
473
+ if (value > 0xff) throw new ParseError(`Octal escape out of range: \\${o}`)
474
+ result += String.fromCharCode(value)
475
+ } else {
476
+ throw new ParseError(`Invalid escape sequence: \\${next}`)
477
+ }
478
+ }
479
+
480
+ return result
481
+ }
482
+
483
+ readIdentifier() {
484
+ const {pos, input, length} = this
485
+ let p = pos
486
+ while (p < length && this._isIdentifierCharCode(input[p].charCodeAt(0))) p++
487
+ const value = input.substring(pos, (this.pos = p))
488
+ switch (value) {
489
+ case 'true':
490
+ return this.token(pos, TOKEN.BOOLEAN, true)
491
+ case 'false':
492
+ return this.token(pos, TOKEN.BOOLEAN, false)
493
+ case 'null':
494
+ return this.token(pos, TOKEN.NULL, null)
495
+ case 'in':
496
+ return this.token(pos, TOKEN.IN)
497
+ default:
498
+ return this.token(pos, TOKEN.IDENTIFIER, value)
499
+ }
500
+ }
501
+ }
502
+
503
+ export class Parser {
504
+ lexer = null
505
+ input = null
506
+ maxDepthRemaining = null
507
+ astNodesRemaining = null
508
+
509
+ type = null
510
+ pos = null
511
+
512
+ constructor(limits, registry) {
513
+ this.limits = limits
514
+ this.registry = registry
515
+ this.lexer = new Lexer()
516
+ }
517
+
518
+ #limitExceeded(limitKey, pos = this.pos) {
519
+ throw new ParseError(`Exceeded ${limitKey} (${this.limits[limitKey]})`, {
520
+ pos,
521
+ input: this.input
522
+ })
523
+ }
524
+
525
+ #node(pos, op, args) {
526
+ const node = new ASTNode(this.input, pos, op, args)
527
+ if (!this.astNodesRemaining--) this.#limitExceeded('maxAstNodes', pos)
528
+ return node
529
+ }
530
+
531
+ #advanceToken(returnValue = this.pos) {
532
+ const l = this.lexer.nextToken()
533
+ this.pos = l.tokenPos
534
+ this.type = l.tokenType
535
+ return returnValue
536
+ }
537
+
538
+ // The value of the current token is accessed less regularly,
539
+ // so we use a getter to reduce assignment overhead
540
+ get value() {
541
+ return this.lexer.tokenValue
542
+ }
543
+
544
+ consume(expectedType) {
545
+ if (this.type === expectedType) return this.#advanceToken()
546
+ throw new ParseError(
547
+ `Expected ${TOKEN_BY_NUMBER[expectedType]}, got ${TOKEN_BY_NUMBER[this.type]}`,
548
+ {pos: this.pos, input: this.input}
549
+ )
550
+ }
551
+
552
+ match(type) {
553
+ return this.type === type
554
+ }
555
+
556
+ // Parse entry point
557
+ parse(input) {
558
+ if (typeof input !== 'string') throw new ParseError('Expression must be a string')
559
+ this.input = this.lexer.reset(input)
560
+ this.#advanceToken()
561
+ this.maxDepthRemaining = this.limits.maxDepth
562
+ this.astNodesRemaining = this.limits.maxAstNodes
563
+
564
+ const result = this.parseExpression()
565
+ if (this.match(TOKEN.EOF)) return result
566
+
567
+ throw new ParseError(`Unexpected character: '${this.input[this.lexer.pos - 1]}'`, {
568
+ pos: this.pos,
569
+ input: this.input
570
+ })
571
+ }
572
+
573
+ #expandMacro(pos, op, args) {
574
+ const [methodName, receiver, fnArgs] = op === OPS.rcall ? args : [args[0], null, args[1]]
575
+ const decl = this.registry.findMacro(methodName, !!receiver, fnArgs.length)
576
+ const ast = this.#node(pos, op, args)
577
+ if (!decl) return ast
578
+ const macro = decl.handler({ast, args: fnArgs, receiver, methodName, parser: this})
579
+ if (macro.callAst) return ast.setMeta('alternate', macro.callAst)
580
+ return ast.setMeta('macro', macro).setMeta('async', isAsync(macro.evaluate, macro.async))
581
+ }
582
+
583
+ // Expression ::= LogicalOr ('?' Expression ':' Expression)?
584
+ parseExpression() {
585
+ if (!this.maxDepthRemaining--) this.#limitExceeded('maxDepth')
586
+ const expr = this.parseLogicalOr()
587
+ if (!this.match(TOKEN.QUESTION)) return ++this.maxDepthRemaining && expr
588
+
589
+ const questionPos = this.#advanceToken()
590
+ const consequent = this.parseExpression()
591
+ this.consume(TOKEN.COLON)
592
+ const alternate = this.parseExpression()
593
+ this.maxDepthRemaining++
594
+ return this.#node(questionPos, OPS.ternary, [expr, consequent, alternate])
595
+ }
596
+
597
+ // LogicalOr ::= LogicalAnd ('||' LogicalAnd)*
598
+ parseLogicalOr() {
599
+ let expr = this.parseLogicalAnd()
600
+ while (this.match(TOKEN.OR))
601
+ expr = this.#node(this.#advanceToken(), OPS['||'], [expr, this.parseLogicalAnd()])
602
+ return expr
603
+ }
604
+
605
+ // LogicalAnd ::= Equality ('&&' Equality)*
606
+ parseLogicalAnd() {
607
+ let expr = this.parseEquality()
608
+ while (this.match(TOKEN.AND))
609
+ expr = this.#node(this.#advanceToken(), OPS['&&'], [expr, this.parseEquality()])
610
+ return expr
611
+ }
612
+
613
+ // Equality ::= Relational (('==' | '!=') Relational)*
614
+ parseEquality() {
615
+ let expr = this.parseRelational()
616
+ while (this.match(TOKEN.EQ) || this.match(TOKEN.NE)) {
617
+ const op = OP_FOR_TOKEN[this.type]
618
+ expr = this.#node(this.#advanceToken(), op, [expr, this.parseRelational()])
619
+ }
620
+ return expr
621
+ }
622
+
623
+ // Relational ::= Additive (('<' | '<=' | '>' | '>=' | 'in') Additive)*
624
+ parseRelational() {
625
+ let expr = this.parseAdditive()
626
+ while (
627
+ this.match(TOKEN.LT) ||
628
+ this.match(TOKEN.LE) ||
629
+ this.match(TOKEN.GT) ||
630
+ this.match(TOKEN.GE) ||
631
+ this.match(TOKEN.IN)
632
+ ) {
633
+ const op = OP_FOR_TOKEN[this.type]
634
+ expr = this.#node(this.#advanceToken(), op, [expr, this.parseAdditive()])
635
+ }
636
+ return expr
637
+ }
638
+
639
+ // Additive ::= Multiplicative (('+' | '-') Multiplicative)*
640
+ parseAdditive() {
641
+ let expr = this.parseMultiplicative()
642
+ while (this.match(TOKEN.PLUS) || this.match(TOKEN.MINUS)) {
643
+ const op = OP_FOR_TOKEN[this.type]
644
+ expr = this.#node(this.#advanceToken(), op, [expr, this.parseMultiplicative()])
645
+ }
646
+ return expr
647
+ }
648
+
649
+ // Multiplicative ::= Unary (('*' | '/' | '%') Unary)*
650
+ parseMultiplicative() {
651
+ let expr = this.parseUnary()
652
+ while (this.match(TOKEN.MULTIPLY) || this.match(TOKEN.DIVIDE) || this.match(TOKEN.MODULO)) {
653
+ const op = OP_FOR_TOKEN[this.type]
654
+ expr = this.#node(this.#advanceToken(), op, [expr, this.parseUnary()])
655
+ }
656
+ return expr
657
+ }
658
+
659
+ // Unary ::= ('!' | '-')* Postfix
660
+ parseUnary() {
661
+ if (this.type === TOKEN.NOT)
662
+ return this.#node(this.#advanceToken(), OPS.unaryNot, this.parseUnary())
663
+ if (this.type === TOKEN.MINUS)
664
+ return this.#node(this.#advanceToken(), OPS.unaryMinus, this.parseUnary())
665
+ return this.parsePostfix()
666
+ }
667
+
668
+ // Postfix ::= Primary (('.' IDENTIFIER ('(' ArgumentList ')')? | '[' Expression ']'))*
669
+ parsePostfix() {
670
+ let expr = this.parsePrimary()
671
+ const depth = this.maxDepthRemaining
672
+ while (true) {
673
+ if (this.match(TOKEN.DOT)) {
674
+ const dot = this.#advanceToken()
675
+ if (!this.maxDepthRemaining--) this.#limitExceeded('maxDepth', dot)
676
+
677
+ const op =
678
+ this.match(TOKEN.QUESTION) && this.registry.enableOptionalTypes && this.#advanceToken()
679
+ ? OPS.optionalFieldAccess
680
+ : OPS.fieldAccess
681
+
682
+ const propertyValue = this.value
683
+ const propertyPos = this.consume(TOKEN.IDENTIFIER)
684
+ if (op === OPS.fieldAccess && this.match(TOKEN.LPAREN) && this.#advanceToken()) {
685
+ const args = this.parseArgumentList()
686
+ this.consume(TOKEN.RPAREN)
687
+ expr = this.#expandMacro(propertyPos, OPS.rcall, [propertyValue, expr, args])
688
+ } else {
689
+ expr = this.#node(propertyPos, op, [expr, propertyValue])
690
+ }
691
+ continue
692
+ }
693
+
694
+ if (this.match(TOKEN.LBRACKET)) {
695
+ const bracket = this.#advanceToken()
696
+ if (!this.maxDepthRemaining--) this.#limitExceeded('maxDepth', bracket)
697
+
698
+ const op =
699
+ this.match(TOKEN.QUESTION) && this.registry.enableOptionalTypes && this.#advanceToken()
700
+ ? OPS.optionalBracketAccess
701
+ : OPS.bracketAccess
702
+
703
+ const index = this.parseExpression()
704
+ this.consume(TOKEN.RBRACKET)
705
+ expr = this.#node(bracket, op, [expr, index])
706
+ continue
707
+ }
708
+ break
709
+ }
710
+ this.maxDepthRemaining = depth
711
+ return expr
712
+ }
713
+
714
+ // Primary ::= NUMBER | STRING | BOOLEAN | NULL | IDENTIFIER | '(' Expression ')' | Array | Object
715
+ parsePrimary() {
716
+ switch (this.type) {
717
+ case TOKEN.NUMBER:
718
+ case TOKEN.STRING:
719
+ case TOKEN.BYTES:
720
+ case TOKEN.BOOLEAN:
721
+ case TOKEN.NULL:
722
+ return this.#consumeLiteral()
723
+ case TOKEN.IDENTIFIER:
724
+ return this.#parseIdentifierPrimary()
725
+ case TOKEN.LPAREN:
726
+ return this.#parseParenthesizedExpression()
727
+ case TOKEN.LBRACKET:
728
+ return this.parseList()
729
+ case TOKEN.LBRACE:
730
+ return this.parseMap()
731
+ }
732
+
733
+ throw new ParseError(`Unexpected token: ${TOKEN_BY_NUMBER[this.type]}`, {
734
+ pos: this.pos,
735
+ input: this.input
736
+ })
737
+ }
738
+
739
+ #consumeLiteral() {
740
+ return this.#advanceToken(this.#node(this.pos, OPS.value, this.value))
741
+ }
742
+
743
+ #parseIdentifierPrimary() {
744
+ const value = this.value
745
+ const pos = this.consume(TOKEN.IDENTIFIER)
746
+ if (RESERVED.has(value)) {
747
+ throw new ParseError(`Reserved identifier: ${value}`, {
748
+ pos: pos,
749
+ input: this.input
750
+ })
751
+ }
752
+
753
+ if (!this.match(TOKEN.LPAREN)) return this.#node(pos, OPS.id, value)
754
+ this.#advanceToken()
755
+ const args = this.parseArgumentList()
756
+ this.consume(TOKEN.RPAREN)
757
+ return this.#expandMacro(pos, OPS.call, [value, args])
758
+ }
759
+
760
+ #parseParenthesizedExpression() {
761
+ this.consume(TOKEN.LPAREN)
762
+ const expr = this.parseExpression()
763
+ this.consume(TOKEN.RPAREN)
764
+ return expr
765
+ }
766
+
767
+ parseList() {
768
+ const token = this.consume(TOKEN.LBRACKET)
769
+ const elements = []
770
+ let remainingElements = this.limits.maxListElements
771
+
772
+ if (!this.match(TOKEN.RBRACKET)) {
773
+ elements.push(this.parseExpression())
774
+ if (!remainingElements--) this.#limitExceeded('maxListElements', elements.at(-1).pos)
775
+ while (this.match(TOKEN.COMMA)) {
776
+ this.#advanceToken()
777
+ if (this.match(TOKEN.RBRACKET)) break
778
+ elements.push(this.parseExpression())
779
+ if (!remainingElements--) this.#limitExceeded('maxListElements', elements.at(-1).pos)
780
+ }
781
+ }
782
+
783
+ this.consume(TOKEN.RBRACKET)
784
+ return this.#node(token, OPS.list, elements)
785
+ }
786
+
787
+ parseMap() {
788
+ const token = this.consume(TOKEN.LBRACE)
789
+ const props = []
790
+ let remainingEntries = this.limits.maxMapEntries
791
+
792
+ if (!this.match(TOKEN.RBRACE)) {
793
+ props.push(this.parseProperty())
794
+ if (!remainingEntries--) this.#limitExceeded('maxMapEntries', props.at(-1)[0].pos)
795
+ while (this.match(TOKEN.COMMA)) {
796
+ this.#advanceToken()
797
+ if (this.match(TOKEN.RBRACE)) break
798
+ props.push(this.parseProperty())
799
+ if (!remainingEntries--) this.#limitExceeded('maxMapEntries', props.at(-1)[0].pos)
800
+ }
801
+ }
802
+
803
+ this.consume(TOKEN.RBRACE)
804
+ return this.#node(token, OPS.map, props)
805
+ }
806
+
807
+ parseProperty() {
808
+ return [this.parseExpression(), (this.consume(TOKEN.COLON), this.parseExpression())]
809
+ }
810
+
811
+ parseArgumentList() {
812
+ const args = []
813
+ let remainingArgs = this.limits.maxCallArguments
814
+
815
+ if (!this.match(TOKEN.RPAREN)) {
816
+ args.push(this.parseExpression())
817
+ if (!remainingArgs--) this.#limitExceeded('maxCallArguments', args.at(-1).pos)
818
+ while (this.match(TOKEN.COMMA)) {
819
+ this.#advanceToken()
820
+ if (this.match(TOKEN.RPAREN)) break
821
+ args.push(this.parseExpression())
822
+ if (!remainingArgs--) this.#limitExceeded('maxCallArguments', args.at(-1).pos)
823
+ }
824
+ }
825
+ return args
826
+ }
827
+ }