bonsai-js 0.2.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.
@@ -0,0 +1,564 @@
1
+ import { i as ExpressionError, n as BonsaiSecurityError } from "./errors-t5i9AEaf.mjs";
2
+ //#region src/lexer.ts
3
+ const KEYWORDS = new Map([
4
+ ["true", {
5
+ type: "Boolean",
6
+ value: "true"
7
+ }],
8
+ ["false", {
9
+ type: "Boolean",
10
+ value: "false"
11
+ }],
12
+ ["null", {
13
+ type: "Null",
14
+ value: "null"
15
+ }],
16
+ ["undefined", {
17
+ type: "Undefined",
18
+ value: "undefined"
19
+ }],
20
+ ["in", {
21
+ type: "Operator",
22
+ value: "in"
23
+ }],
24
+ ["not", {
25
+ type: "Operator",
26
+ value: "not"
27
+ }]
28
+ ]);
29
+ function isDigit(ch) {
30
+ return ch >= "0" && ch <= "9";
31
+ }
32
+ function isAlpha(ch) {
33
+ return ch >= "a" && ch <= "z" || ch >= "A" && ch <= "Z" || ch === "_" || ch === "$";
34
+ }
35
+ function isAlphaNumeric(ch) {
36
+ return isAlpha(ch) || isDigit(ch);
37
+ }
38
+ function isHexDigit(ch) {
39
+ return isDigit(ch) || ch >= "a" && ch <= "f" || ch >= "A" && ch <= "F";
40
+ }
41
+ function tokenize(source) {
42
+ const tokens = [];
43
+ let i = 0;
44
+ while (i < source.length) {
45
+ const ch = source[i];
46
+ if (ch === " " || ch === " " || ch === "\n" || ch === "\r") {
47
+ i++;
48
+ continue;
49
+ }
50
+ if (isDigit(ch)) {
51
+ const start = i;
52
+ if (ch === "0" && i + 1 < source.length && (source[i + 1] === "x" || source[i + 1] === "X")) {
53
+ i += 2;
54
+ while (i < source.length && (isHexDigit(source[i]) || source[i] === "_")) i++;
55
+ tokens.push({
56
+ type: "Number",
57
+ value: source.slice(start, i),
58
+ start,
59
+ end: i
60
+ });
61
+ continue;
62
+ }
63
+ if (ch === "0" && i + 1 < source.length && (source[i + 1] === "b" || source[i + 1] === "B")) {
64
+ i += 2;
65
+ while (i < source.length && (source[i] === "0" || source[i] === "1" || source[i] === "_")) i++;
66
+ tokens.push({
67
+ type: "Number",
68
+ value: source.slice(start, i),
69
+ start,
70
+ end: i
71
+ });
72
+ continue;
73
+ }
74
+ if (ch === "0" && i + 1 < source.length && (source[i + 1] === "o" || source[i + 1] === "O")) {
75
+ i += 2;
76
+ while (i < source.length && (source[i] >= "0" && source[i] <= "7" || source[i] === "_")) i++;
77
+ tokens.push({
78
+ type: "Number",
79
+ value: source.slice(start, i),
80
+ start,
81
+ end: i
82
+ });
83
+ continue;
84
+ }
85
+ while (i < source.length && (isDigit(source[i]) || source[i] === "_")) i++;
86
+ if (i < source.length && source[i] === "." && i + 1 < source.length && isDigit(source[i + 1])) {
87
+ i++;
88
+ while (i < source.length && (isDigit(source[i]) || source[i] === "_")) i++;
89
+ }
90
+ if (i < source.length && (source[i] === "e" || source[i] === "E")) {
91
+ i++;
92
+ if (i < source.length && (source[i] === "+" || source[i] === "-")) i++;
93
+ while (i < source.length && (isDigit(source[i]) || source[i] === "_")) i++;
94
+ }
95
+ tokens.push({
96
+ type: "Number",
97
+ value: source.slice(start, i),
98
+ start,
99
+ end: i
100
+ });
101
+ continue;
102
+ }
103
+ if (ch === "\"" || ch === "'") {
104
+ const quote = ch;
105
+ const start = i;
106
+ i++;
107
+ let value = "";
108
+ while (i < source.length && source[i] !== quote) {
109
+ if (source[i] === "\\") {
110
+ i++;
111
+ const escaped = source[i];
112
+ switch (escaped) {
113
+ case "n":
114
+ value += "\n";
115
+ break;
116
+ case "t":
117
+ value += " ";
118
+ break;
119
+ case "r":
120
+ value += "\r";
121
+ break;
122
+ case "\\":
123
+ value += "\\";
124
+ break;
125
+ case "0":
126
+ value += "\0";
127
+ break;
128
+ case "x": {
129
+ const hex = source.slice(i + 1, i + 3);
130
+ if (hex.length < 2 || !isHexDigit(hex[0]) || !isHexDigit(hex[1])) throw new ExpressionError("Invalid \\x escape: expected 2 hex digits", {
131
+ source,
132
+ start,
133
+ end: i + 3
134
+ });
135
+ value += String.fromCharCode(parseInt(hex, 16));
136
+ i += 2;
137
+ break;
138
+ }
139
+ case "u":
140
+ if (i + 1 < source.length && source[i + 1] === "{") {
141
+ const closeBrace = source.indexOf("}", i + 2);
142
+ if (closeBrace === -1) throw new ExpressionError("Invalid \\u{} escape: missing closing brace", {
143
+ source,
144
+ start,
145
+ end: source.length
146
+ });
147
+ const hex = source.slice(i + 2, closeBrace);
148
+ if (hex.length === 0) throw new ExpressionError("Invalid \\u{} escape: empty code point", {
149
+ source,
150
+ start,
151
+ end: closeBrace + 1
152
+ });
153
+ for (const c of hex) if (!isHexDigit(c)) throw new ExpressionError(`Invalid \\u{} escape: non-hex digit "${c}"`, {
154
+ source,
155
+ start,
156
+ end: closeBrace + 1
157
+ });
158
+ const MAX_UNICODE_CODE_POINT = 1114111;
159
+ const codePoint = parseInt(hex, 16);
160
+ if (codePoint > MAX_UNICODE_CODE_POINT) throw new ExpressionError("Invalid \\u{} escape: code point out of range", {
161
+ source,
162
+ start,
163
+ end: closeBrace + 1
164
+ });
165
+ value += String.fromCodePoint(codePoint);
166
+ i = closeBrace;
167
+ } else {
168
+ const UNICODE_ESCAPE_LEN = 4;
169
+ const hex = source.slice(i + 1, i + 1 + UNICODE_ESCAPE_LEN);
170
+ if (hex.length < UNICODE_ESCAPE_LEN) throw new ExpressionError("Invalid \\u escape: expected 4 hex digits", {
171
+ source,
172
+ start,
173
+ end: i + 1 + UNICODE_ESCAPE_LEN
174
+ });
175
+ for (const c of hex) if (!isHexDigit(c)) throw new ExpressionError("Invalid \\u escape: expected 4 hex digits", {
176
+ source,
177
+ start,
178
+ end: i + 1 + UNICODE_ESCAPE_LEN
179
+ });
180
+ value += String.fromCharCode(parseInt(hex, 16));
181
+ i += UNICODE_ESCAPE_LEN;
182
+ }
183
+ break;
184
+ default:
185
+ value += escaped;
186
+ break;
187
+ }
188
+ } else value += source[i];
189
+ i++;
190
+ }
191
+ if (i >= source.length) throw new ExpressionError("Unterminated string", {
192
+ source,
193
+ start,
194
+ end: i
195
+ });
196
+ i++;
197
+ tokens.push({
198
+ type: "String",
199
+ value,
200
+ start,
201
+ end: i
202
+ });
203
+ continue;
204
+ }
205
+ if (ch === "`") {
206
+ const start = i;
207
+ i++;
208
+ let raw = "`";
209
+ while (i < source.length && source[i] !== "`") if (source[i] === "$" && i + 1 < source.length && source[i + 1] === "{") {
210
+ raw += "${";
211
+ i += 2;
212
+ let depth = 1;
213
+ while (i < source.length && depth > 0) {
214
+ const ic = source[i];
215
+ if (ic === "\"" || ic === "'") {
216
+ raw += ic;
217
+ i++;
218
+ while (i < source.length && source[i] !== ic) {
219
+ if (source[i] === "\\" && i + 1 < source.length) {
220
+ raw += source[i] + source[i + 1];
221
+ i += 2;
222
+ continue;
223
+ }
224
+ raw += source[i];
225
+ i++;
226
+ }
227
+ if (i < source.length) {
228
+ raw += source[i];
229
+ i++;
230
+ }
231
+ continue;
232
+ }
233
+ if (ic === "{") depth++;
234
+ else if (ic === "}") depth--;
235
+ if (depth > 0) raw += ic;
236
+ i++;
237
+ }
238
+ raw += "}";
239
+ } else {
240
+ raw += source[i];
241
+ i++;
242
+ }
243
+ if (i >= source.length) throw new ExpressionError("Unterminated template literal", {
244
+ source,
245
+ start,
246
+ end: i
247
+ });
248
+ raw += "`";
249
+ i++;
250
+ tokens.push({
251
+ type: "TemplateLiteral",
252
+ value: raw,
253
+ start,
254
+ end: i
255
+ });
256
+ continue;
257
+ }
258
+ if (isAlpha(ch)) {
259
+ const start = i;
260
+ while (i < source.length && isAlphaNumeric(source[i])) i++;
261
+ const value = source.slice(start, i);
262
+ const kw = KEYWORDS.get(value);
263
+ if (kw) tokens.push({
264
+ type: kw.type,
265
+ value: kw.value,
266
+ start,
267
+ end: i
268
+ });
269
+ else tokens.push({
270
+ type: "Identifier",
271
+ value,
272
+ start,
273
+ end: i
274
+ });
275
+ continue;
276
+ }
277
+ const start = i;
278
+ if (ch === "." && i + 2 < source.length && source[i + 1] === "." && source[i + 2] === ".") {
279
+ tokens.push({
280
+ type: "Spread",
281
+ value: "...",
282
+ start,
283
+ end: i + 3
284
+ });
285
+ i += 3;
286
+ continue;
287
+ }
288
+ if (ch === ".") {
289
+ tokens.push({
290
+ type: "Punctuation",
291
+ value: ".",
292
+ start,
293
+ end: i + 1
294
+ });
295
+ i++;
296
+ continue;
297
+ }
298
+ if (ch === "|") {
299
+ if (i + 1 < source.length && source[i + 1] === ">") {
300
+ tokens.push({
301
+ type: "Pipe",
302
+ value: "|>",
303
+ start,
304
+ end: i + 2
305
+ });
306
+ i += 2;
307
+ continue;
308
+ }
309
+ if (i + 1 < source.length && source[i + 1] === "|") {
310
+ tokens.push({
311
+ type: "Operator",
312
+ value: "||",
313
+ start,
314
+ end: i + 2
315
+ });
316
+ i += 2;
317
+ continue;
318
+ }
319
+ }
320
+ if (ch === "&" && i + 1 < source.length && source[i + 1] === "&") {
321
+ tokens.push({
322
+ type: "Operator",
323
+ value: "&&",
324
+ start,
325
+ end: i + 2
326
+ });
327
+ i += 2;
328
+ continue;
329
+ }
330
+ if (ch === "=" && i + 1 < source.length && source[i + 1] === "=") {
331
+ tokens.push({
332
+ type: "Operator",
333
+ value: "==",
334
+ start,
335
+ end: i + 2
336
+ });
337
+ i += 2;
338
+ continue;
339
+ }
340
+ if (ch === "!" && i + 1 < source.length && source[i + 1] === "=") {
341
+ tokens.push({
342
+ type: "Operator",
343
+ value: "!=",
344
+ start,
345
+ end: i + 2
346
+ });
347
+ i += 2;
348
+ continue;
349
+ }
350
+ if (ch === "!") {
351
+ tokens.push({
352
+ type: "Operator",
353
+ value: "!",
354
+ start,
355
+ end: i + 1
356
+ });
357
+ i++;
358
+ continue;
359
+ }
360
+ if (ch === "<") {
361
+ if (i + 1 < source.length && source[i + 1] === "=") {
362
+ tokens.push({
363
+ type: "Operator",
364
+ value: "<=",
365
+ start,
366
+ end: i + 2
367
+ });
368
+ i += 2;
369
+ continue;
370
+ }
371
+ tokens.push({
372
+ type: "Operator",
373
+ value: "<",
374
+ start,
375
+ end: i + 1
376
+ });
377
+ i++;
378
+ continue;
379
+ }
380
+ if (ch === ">") {
381
+ if (i + 1 < source.length && source[i + 1] === "=") {
382
+ tokens.push({
383
+ type: "Operator",
384
+ value: ">=",
385
+ start,
386
+ end: i + 2
387
+ });
388
+ i += 2;
389
+ continue;
390
+ }
391
+ tokens.push({
392
+ type: "Operator",
393
+ value: ">",
394
+ start,
395
+ end: i + 1
396
+ });
397
+ i++;
398
+ continue;
399
+ }
400
+ if (ch === "*" && i + 1 < source.length && source[i + 1] === "*") {
401
+ tokens.push({
402
+ type: "Operator",
403
+ value: "**",
404
+ start,
405
+ end: i + 2
406
+ });
407
+ i += 2;
408
+ continue;
409
+ }
410
+ if (ch === "?") {
411
+ if (i + 1 < source.length && source[i + 1] === ".") {
412
+ tokens.push({
413
+ type: "OptionalChain",
414
+ value: "?.",
415
+ start,
416
+ end: i + 2
417
+ });
418
+ i += 2;
419
+ continue;
420
+ }
421
+ if (i + 1 < source.length && source[i + 1] === "?") {
422
+ tokens.push({
423
+ type: "NullishCoalescing",
424
+ value: "??",
425
+ start,
426
+ end: i + 2
427
+ });
428
+ i += 2;
429
+ continue;
430
+ }
431
+ tokens.push({
432
+ type: "Punctuation",
433
+ value: "?",
434
+ start,
435
+ end: i + 1
436
+ });
437
+ i++;
438
+ continue;
439
+ }
440
+ if (ch === "+" || ch === "-" || ch === "*" || ch === "/" || ch === "%") {
441
+ tokens.push({
442
+ type: "Operator",
443
+ value: ch,
444
+ start,
445
+ end: i + 1
446
+ });
447
+ i++;
448
+ continue;
449
+ }
450
+ if ("()[]{},:".includes(ch)) {
451
+ tokens.push({
452
+ type: "Punctuation",
453
+ value: ch,
454
+ start,
455
+ end: i + 1
456
+ });
457
+ i++;
458
+ continue;
459
+ }
460
+ throw new ExpressionError(`Unexpected character "${ch}"`, {
461
+ source,
462
+ start,
463
+ end: i + 1
464
+ });
465
+ }
466
+ tokens.push({
467
+ type: "EOF",
468
+ value: "",
469
+ start: i,
470
+ end: i
471
+ });
472
+ return tokens;
473
+ }
474
+ //#endregion
475
+ //#region src/execution-context.ts
476
+ const BLOCKED_PROPERTIES = new Set([
477
+ "__proto__",
478
+ "constructor",
479
+ "prototype"
480
+ ]);
481
+ const MAX_INDEX_DIGITS = 10;
482
+ function isCanonicalIndex(key) {
483
+ if (key.length === 0 || key.length > MAX_INDEX_DIGITS) return false;
484
+ const n = Number(key);
485
+ return Number.isInteger(n) && n >= 0 && String(n) === key;
486
+ }
487
+ const TIMEOUT_CHECK_INTERVAL = 1e3;
488
+ const DEFAULT_MAX_DEPTH = 100;
489
+ const DEFAULT_MAX_ARRAY_LENGTH = 1e5;
490
+ /** Immutable per-instance security configuration derived from BonsaiOptions. */
491
+ var SecurityPolicy = class {
492
+ maxDepth;
493
+ maxArrayLength;
494
+ timeout;
495
+ allowedProperties;
496
+ deniedProperties;
497
+ constructor(options = {}) {
498
+ this.maxDepth = options.maxDepth ?? DEFAULT_MAX_DEPTH;
499
+ this.maxArrayLength = options.maxArrayLength ?? DEFAULT_MAX_ARRAY_LENGTH;
500
+ this.timeout = options.timeout ?? 0;
501
+ this.allowedProperties = options.allowedProperties ? new Set(options.allowedProperties) : void 0;
502
+ this.deniedProperties = options.deniedProperties ? new Set(options.deniedProperties) : void 0;
503
+ }
504
+ };
505
+ /** Mutable per-evaluation state: tracks depth, step count, and deadline for a single evaluation. */
506
+ var ExecutionContext = class {
507
+ stepCount = 0;
508
+ depth = 0;
509
+ deadline;
510
+ policy;
511
+ now;
512
+ constructor(policy, now = Date.now) {
513
+ this.policy = policy;
514
+ this.now = now;
515
+ this.deadline = policy.timeout ? now() + policy.timeout : 0;
516
+ }
517
+ /** Reset mutable state for reuse. Avoids allocating a new instance per evaluation. */
518
+ reset() {
519
+ this.stepCount = 0;
520
+ this.depth = 0;
521
+ this.deadline = this.policy.timeout ? this.now() + this.policy.timeout : 0;
522
+ }
523
+ step() {
524
+ if (this.deadline) {
525
+ this.stepCount++;
526
+ if (this.stepCount % TIMEOUT_CHECK_INTERVAL === 0) this.checkTimeout();
527
+ }
528
+ }
529
+ checkTimeout() {
530
+ if (this.deadline && this.now() >= this.deadline) throw new BonsaiSecurityError("TIMEOUT", `Expression timeout: exceeded ${this.policy.timeout}ms`);
531
+ }
532
+ enterDepth() {
533
+ if (++this.depth > this.policy.maxDepth) throw new BonsaiSecurityError("MAX_DEPTH", `Maximum expression depth (${this.policy.maxDepth}) exceeded`);
534
+ }
535
+ exitDepth() {
536
+ this.depth--;
537
+ }
538
+ withDepth(fn) {
539
+ this.enterDepth();
540
+ try {
541
+ return fn();
542
+ } finally {
543
+ this.exitDepth();
544
+ }
545
+ }
546
+ checkNameAccess(key, kind) {
547
+ if (BLOCKED_PROPERTIES.has(key)) throw new BonsaiSecurityError("BLOCKED_PROPERTY", `Blocked: access to "${key}" is not allowed`);
548
+ if (kind === "identifier" || kind === "object-key") return;
549
+ if (isCanonicalIndex(key)) return;
550
+ if (this.policy.allowedProperties) {
551
+ if (!this.policy.allowedProperties.has(key)) throw new BonsaiSecurityError("PROPERTY_NOT_ALLOWED", `Blocked: "${key}" is not in allowed properties`);
552
+ }
553
+ if (this.policy.deniedProperties) {
554
+ if (this.policy.deniedProperties.has(key)) throw new BonsaiSecurityError("PROPERTY_DENIED", `Blocked: "${key}" is in denied properties`);
555
+ }
556
+ }
557
+ checkArrayLength(length) {
558
+ if (length > this.policy.maxArrayLength) throw new BonsaiSecurityError("MAX_ARRAY_LENGTH", `Array length (${length}) exceeds maximum (${this.policy.maxArrayLength})`);
559
+ }
560
+ };
561
+ //#endregion
562
+ export { tokenize as i, ExecutionContext as n, SecurityPolicy as r, BLOCKED_PROPERTIES as t };
563
+
564
+ //# sourceMappingURL=execution-context-DqYC3L92.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"execution-context-DqYC3L92.mjs","names":[],"sources":["../src/lexer.ts","../src/execution-context.ts"],"sourcesContent":["import type { Token, PunctuationValue } from './types.js'\nimport { ExpressionError } from './errors.js'\n\nconst KEYWORDS = new Map<string, { type: Token['type']; value: string }>([\n ['true', { type: 'Boolean', value: 'true' }],\n ['false', { type: 'Boolean', value: 'false' }],\n ['null', { type: 'Null', value: 'null' }],\n ['undefined', { type: 'Undefined', value: 'undefined' }],\n ['in', { type: 'Operator', value: 'in' }],\n ['not', { type: 'Operator', value: 'not' }],\n])\n\nfunction isDigit(ch: string): boolean {\n return ch >= '0' && ch <= '9'\n}\n\nfunction isAlpha(ch: string): boolean {\n return (ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') || ch === '_' || ch === '$'\n}\n\nfunction isAlphaNumeric(ch: string): boolean {\n return isAlpha(ch) || isDigit(ch)\n}\n\nfunction isHexDigit(ch: string): boolean {\n return isDigit(ch) || (ch >= 'a' && ch <= 'f') || (ch >= 'A' && ch <= 'F')\n}\n\nexport function tokenize(source: string): Token[] {\n const tokens: Token[] = []\n let i = 0\n\n while (i < source.length) {\n const ch = source[i]\n\n // Skip whitespace\n if (ch === ' ' || ch === '\\t' || ch === '\\n' || ch === '\\r') {\n i++\n continue\n }\n\n // Numbers: decimal, hex, binary, octal, scientific, underscores\n if (isDigit(ch)) {\n const start = i\n\n // Hex: 0x...\n if (ch === '0' && i + 1 < source.length && (source[i + 1] === 'x' || source[i + 1] === 'X')) {\n i += 2\n while (i < source.length && (isHexDigit(source[i]) || source[i] === '_')) i++\n tokens.push({ type: 'Number', value: source.slice(start, i), start, end: i })\n continue\n }\n\n // Binary: 0b...\n if (ch === '0' && i + 1 < source.length && (source[i + 1] === 'b' || source[i + 1] === 'B')) {\n i += 2\n while (i < source.length && (source[i] === '0' || source[i] === '1' || source[i] === '_')) i++\n tokens.push({ type: 'Number', value: source.slice(start, i), start, end: i })\n continue\n }\n\n // Octal: 0o...\n if (ch === '0' && i + 1 < source.length && (source[i + 1] === 'o' || source[i + 1] === 'O')) {\n i += 2\n while (i < source.length && ((source[i] >= '0' && source[i] <= '7') || source[i] === '_')) i++\n tokens.push({ type: 'Number', value: source.slice(start, i), start, end: i })\n continue\n }\n\n // Decimal (with optional underscore separators)\n while (i < source.length && (isDigit(source[i]) || source[i] === '_')) i++\n if (i < source.length && source[i] === '.' && i + 1 < source.length && isDigit(source[i + 1])) {\n i++ // skip '.'\n while (i < source.length && (isDigit(source[i]) || source[i] === '_')) i++\n }\n\n // Scientific notation: e/E followed by optional +/- and digits\n if (i < source.length && (source[i] === 'e' || source[i] === 'E')) {\n i++\n if (i < source.length && (source[i] === '+' || source[i] === '-')) i++\n while (i < source.length && (isDigit(source[i]) || source[i] === '_')) i++\n }\n\n tokens.push({ type: 'Number', value: source.slice(start, i), start, end: i })\n continue\n }\n\n // Strings\n if (ch === '\"' || ch === \"'\") {\n const quote = ch\n const start = i\n i++ // skip opening quote\n let value = ''\n while (i < source.length && source[i] !== quote) {\n if (source[i] === '\\\\') {\n i++\n const escaped = source[i]\n switch (escaped) {\n case 'n': value += '\\n'; break\n case 't': value += '\\t'; break\n case 'r': value += '\\r'; break\n case '\\\\': value += '\\\\'; break\n case '0': value += '\\0'; break\n case 'x': {\n const hex = source.slice(i + 1, i + 3)\n if (hex.length < 2 || !isHexDigit(hex[0]) || !isHexDigit(hex[1])) {\n throw new ExpressionError('Invalid \\\\x escape: expected 2 hex digits', { source, start, end: i + 3 })\n }\n value += String.fromCharCode(parseInt(hex, 16))\n i += 2\n break\n }\n case 'u': {\n if (i + 1 < source.length && source[i + 1] === '{') {\n const closeBrace = source.indexOf('}', i + 2)\n if (closeBrace === -1) {\n throw new ExpressionError('Invalid \\\\u{} escape: missing closing brace', { source, start, end: source.length })\n }\n const hex = source.slice(i + 2, closeBrace)\n if (hex.length === 0) {\n throw new ExpressionError('Invalid \\\\u{} escape: empty code point', { source, start, end: closeBrace + 1 })\n }\n for (const c of hex) {\n if (!isHexDigit(c)) {\n throw new ExpressionError(`Invalid \\\\u{} escape: non-hex digit \"${c}\"`, { source, start, end: closeBrace + 1 })\n }\n }\n const MAX_UNICODE_CODE_POINT = 0x10FFFF\n const codePoint = parseInt(hex, 16)\n if (codePoint > MAX_UNICODE_CODE_POINT) {\n throw new ExpressionError('Invalid \\\\u{} escape: code point out of range', { source, start, end: closeBrace + 1 })\n }\n value += String.fromCodePoint(codePoint)\n i = closeBrace\n } else {\n const UNICODE_ESCAPE_LEN = 4\n const hex = source.slice(i + 1, i + 1 + UNICODE_ESCAPE_LEN)\n if (hex.length < UNICODE_ESCAPE_LEN) {\n throw new ExpressionError('Invalid \\\\u escape: expected 4 hex digits', { source, start, end: i + 1 + UNICODE_ESCAPE_LEN })\n }\n for (const c of hex) {\n if (!isHexDigit(c)) {\n throw new ExpressionError('Invalid \\\\u escape: expected 4 hex digits', { source, start, end: i + 1 + UNICODE_ESCAPE_LEN })\n }\n }\n value += String.fromCharCode(parseInt(hex, 16))\n i += UNICODE_ESCAPE_LEN\n }\n break\n }\n default: value += escaped; break\n }\n } else {\n value += source[i]\n }\n i++\n }\n if (i >= source.length) {\n throw new ExpressionError('Unterminated string', { source, start, end: i })\n }\n i++ // skip closing quote\n tokens.push({ type: 'String', value, start, end: i })\n continue\n }\n\n // Template literals\n if (ch === '`') {\n const start = i\n i++ // skip opening backtick\n let raw = '`'\n while (i < source.length && source[i] !== '`') {\n if (source[i] === '$' && i + 1 < source.length && source[i + 1] === '{') {\n raw += '${'\n i += 2\n let depth = 1\n while (i < source.length && depth > 0) {\n const ic = source[i]\n // Skip string literals inside interpolations\n if (ic === '\"' || ic === \"'\") {\n raw += ic\n i++\n while (i < source.length && source[i] !== ic) {\n if (source[i] === '\\\\' && i + 1 < source.length) {\n raw += source[i] + source[i + 1]\n i += 2\n continue\n }\n raw += source[i]\n i++\n }\n if (i < source.length) {\n raw += source[i] // closing quote\n i++\n }\n continue\n }\n if (ic === '{') depth++\n else if (ic === '}') depth--\n if (depth > 0) raw += ic\n i++\n }\n raw += '}'\n } else {\n raw += source[i]\n i++\n }\n }\n if (i >= source.length) {\n throw new ExpressionError('Unterminated template literal', { source, start, end: i })\n }\n raw += '`'\n i++ // skip closing backtick\n tokens.push({ type: 'TemplateLiteral', value: raw, start, end: i })\n continue\n }\n\n // Identifiers and keywords\n if (isAlpha(ch)) {\n const start = i\n while (i < source.length && isAlphaNumeric(source[i])) i++\n const value = source.slice(start, i)\n const kw = KEYWORDS.get(value)\n if (kw) {\n tokens.push({ type: kw.type, value: kw.value, start, end: i } as Token)\n } else {\n tokens.push({ type: 'Identifier', value, start, end: i })\n }\n continue\n }\n\n // Multi-character operators and punctuation\n const start = i\n\n // Spread operator ...\n if (ch === '.' && i + 2 < source.length && source[i + 1] === '.' && source[i + 2] === '.') {\n tokens.push({ type: 'Spread', value: '...', start, end: i + 3 })\n i += 3\n continue\n }\n\n // Dot (punctuation)\n if (ch === '.') {\n tokens.push({ type: 'Punctuation', value: '.', start, end: i + 1 })\n i++\n continue\n }\n\n // Pipe |> or logical ||\n if (ch === '|') {\n if (i + 1 < source.length && source[i + 1] === '>') {\n tokens.push({ type: 'Pipe', value: '|>', start, end: i + 2 })\n i += 2\n continue\n }\n if (i + 1 < source.length && source[i + 1] === '|') {\n tokens.push({ type: 'Operator', value: '||', start, end: i + 2 })\n i += 2\n continue\n }\n }\n\n // &&\n if (ch === '&' && i + 1 < source.length && source[i + 1] === '&') {\n tokens.push({ type: 'Operator', value: '&&', start, end: i + 2 })\n i += 2\n continue\n }\n\n // == !=\n if (ch === '=' && i + 1 < source.length && source[i + 1] === '=') {\n tokens.push({ type: 'Operator', value: '==', start, end: i + 2 })\n i += 2\n continue\n }\n if (ch === '!' && i + 1 < source.length && source[i + 1] === '=') {\n tokens.push({ type: 'Operator', value: '!=', start, end: i + 2 })\n i += 2\n continue\n }\n\n // ! (logical not) - must come after != check\n if (ch === '!') {\n tokens.push({ type: 'Operator', value: '!', start, end: i + 1 })\n i++\n continue\n }\n\n // <= >= < >\n if (ch === '<') {\n if (i + 1 < source.length && source[i + 1] === '=') {\n tokens.push({ type: 'Operator', value: '<=', start, end: i + 2 })\n i += 2\n continue\n }\n tokens.push({ type: 'Operator', value: '<', start, end: i + 1 })\n i++\n continue\n }\n if (ch === '>') {\n if (i + 1 < source.length && source[i + 1] === '=') {\n tokens.push({ type: 'Operator', value: '>=', start, end: i + 2 })\n i += 2\n continue\n }\n tokens.push({ type: 'Operator', value: '>', start, end: i + 1 })\n i++\n continue\n }\n\n // ** (exponentiation) — must come before single *\n if (ch === '*' && i + 1 < source.length && source[i + 1] === '*') {\n tokens.push({ type: 'Operator', value: '**', start, end: i + 2 })\n i += 2\n continue\n }\n\n // ?. (optional chaining) or ?? (nullish coalescing) or ? (ternary)\n if (ch === '?') {\n if (i + 1 < source.length && source[i + 1] === '.') {\n tokens.push({ type: 'OptionalChain', value: '?.', start, end: i + 2 })\n i += 2\n continue\n }\n if (i + 1 < source.length && source[i + 1] === '?') {\n tokens.push({ type: 'NullishCoalescing', value: '??', start, end: i + 2 })\n i += 2\n continue\n }\n tokens.push({ type: 'Punctuation', value: '?', start, end: i + 1 })\n i++\n continue\n }\n\n // Single-character operators\n if (ch === '+' || ch === '-' || ch === '*' || ch === '/' || ch === '%') {\n tokens.push({ type: 'Operator', value: ch, start, end: i + 1 })\n i++\n continue\n }\n\n // Punctuation\n if ('()[]{},:'.includes(ch)) {\n tokens.push({ type: 'Punctuation', value: ch as PunctuationValue, start, end: i + 1 })\n i++\n continue\n }\n\n throw new ExpressionError(`Unexpected character \"${ch}\"`, { source, start, end: i + 1 })\n }\n\n tokens.push({ type: 'EOF', value: '', start: i, end: i })\n return tokens\n}\n","import type { BonsaiOptions } from './types.js'\nimport { BonsaiSecurityError } from './errors.js'\n\n/**\n * Discriminates how a property name is being accessed so security checks can\n * apply different rules (e.g. root identifiers bypass allow/deny lists).\n */\nexport type AccessKind = 'identifier' | 'member' | 'method' | 'object-key'\n\nexport const BLOCKED_PROPERTIES: ReadonlySet<string> = new Set([\n '__proto__', 'constructor', 'prototype',\n])\n\nconst MAX_INDEX_DIGITS = 10\n\nfunction isCanonicalIndex(key: string): boolean {\n if (key.length === 0 || key.length > MAX_INDEX_DIGITS) return false\n const n = Number(key)\n return Number.isInteger(n) && n >= 0 && String(n) === key\n}\n\nconst TIMEOUT_CHECK_INTERVAL = 1000\nconst DEFAULT_MAX_DEPTH = 100\nconst DEFAULT_MAX_ARRAY_LENGTH = 100_000\n\n/** Immutable per-instance security configuration derived from BonsaiOptions. */\nexport class SecurityPolicy {\n readonly maxDepth: number\n readonly maxArrayLength: number\n readonly timeout: number\n readonly allowedProperties?: ReadonlySet<string>\n readonly deniedProperties?: ReadonlySet<string>\n\n constructor(options: BonsaiOptions = {}) {\n this.maxDepth = options.maxDepth ?? DEFAULT_MAX_DEPTH\n this.maxArrayLength = options.maxArrayLength ?? DEFAULT_MAX_ARRAY_LENGTH\n this.timeout = options.timeout ?? 0\n this.allowedProperties = options.allowedProperties\n ? new Set(options.allowedProperties)\n : undefined\n this.deniedProperties = options.deniedProperties\n ? new Set(options.deniedProperties)\n : undefined\n }\n}\n\n/** Mutable per-evaluation state: tracks depth, step count, and deadline for a single evaluation. */\nexport class ExecutionContext {\n private stepCount = 0\n private depth = 0\n private deadline: number\n readonly policy: SecurityPolicy\n private readonly now: () => number\n\n constructor(policy: SecurityPolicy, now: () => number = Date.now) {\n this.policy = policy\n this.now = now\n this.deadline = policy.timeout ? now() + policy.timeout : 0\n }\n\n /** Reset mutable state for reuse. Avoids allocating a new instance per evaluation. */\n reset(): void {\n this.stepCount = 0\n this.depth = 0\n this.deadline = this.policy.timeout ? this.now() + this.policy.timeout : 0\n }\n\n step(): void {\n if (this.deadline) {\n this.stepCount++\n if (this.stepCount % TIMEOUT_CHECK_INTERVAL === 0) {\n this.checkTimeout()\n }\n }\n }\n\n checkTimeout(): void {\n if (this.deadline && this.now() >= this.deadline) {\n throw new BonsaiSecurityError(\n 'TIMEOUT',\n `Expression timeout: exceeded ${this.policy.timeout}ms`,\n )\n }\n }\n\n enterDepth(): void {\n if (++this.depth > this.policy.maxDepth) {\n throw new BonsaiSecurityError(\n 'MAX_DEPTH',\n `Maximum expression depth (${this.policy.maxDepth}) exceeded`,\n )\n }\n }\n\n exitDepth(): void {\n this.depth--\n }\n\n withDepth<T>(fn: () => T): T {\n this.enterDepth()\n try {\n return fn()\n } finally {\n this.exitDepth()\n }\n }\n\n checkNameAccess(key: string, kind: AccessKind): void {\n if (BLOCKED_PROPERTIES.has(key)) {\n throw new BonsaiSecurityError(\n 'BLOCKED_PROPERTY',\n `Blocked: access to \"${key}\" is not allowed`,\n )\n }\n\n if (kind === 'identifier' || kind === 'object-key') return\n\n if (isCanonicalIndex(key)) return\n\n if (this.policy.allowedProperties) {\n if (!this.policy.allowedProperties.has(key)) {\n throw new BonsaiSecurityError(\n 'PROPERTY_NOT_ALLOWED',\n `Blocked: \"${key}\" is not in allowed properties`,\n )\n }\n }\n\n if (this.policy.deniedProperties) {\n if (this.policy.deniedProperties.has(key)) {\n throw new BonsaiSecurityError(\n 'PROPERTY_DENIED',\n `Blocked: \"${key}\" is in denied properties`,\n )\n }\n }\n }\n\n checkArrayLength(length: number): void {\n if (length > this.policy.maxArrayLength) {\n throw new BonsaiSecurityError(\n 'MAX_ARRAY_LENGTH',\n `Array length (${length}) exceeds maximum (${this.policy.maxArrayLength})`,\n )\n }\n }\n}\n"],"mappings":"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"}
package/dist/index.d.mts CHANGED
@@ -1,4 +1,4 @@
1
- import { a as CompiledExpression, c as Token, d as ValidationResult, i as BonsaiPlugin, l as TokenType, n as BonsaiInstance, o as ExpressionReferences, r as BonsaiOptions, s as FunctionFn, t as ASTNode, u as TransformFn } from "./types-ClpZDF5z.mjs";
1
+ import { a as CompiledExpression, c as InferredTypeName, d as Token, f as TokenType, i as BonsaiPlugin, l as PolicySnapshot, m as ValidationResult, n as BonsaiInstance, o as ExpressionReferences, p as TransformFn, r as BonsaiOptions, s as FunctionFn, t as ASTNode, u as ResolveResult } from "./types-BhsZZsLY.mjs";
2
2
 
3
3
  //#region src/errors.d.ts
4
4
  interface ErrorLocation {
@@ -73,5 +73,5 @@ declare function evaluateExpression<T = unknown>(expression: string, context?: R
73
73
  */
74
74
  declare function bonsai(options?: BonsaiOptions): BonsaiInstance;
75
75
  //#endregion
76
- export { type ASTNode, type BonsaiInstance, type BonsaiOptions, type BonsaiPlugin, BonsaiReferenceError, BonsaiSecurityError, BonsaiTypeError, type CompiledExpression, ExpressionError, type ExpressionReferences, type FunctionFn, type Token, type TokenType, type TransformFn, type ValidationResult, bonsai, compile, evaluateExpression, formatBonsaiError, formatError, parse, tokenize };
76
+ export { type ASTNode, type BonsaiInstance, type BonsaiOptions, type BonsaiPlugin, BonsaiReferenceError, BonsaiSecurityError, BonsaiTypeError, type CompiledExpression, ExpressionError, type ExpressionReferences, type FunctionFn, type InferredTypeName, type PolicySnapshot, type ResolveResult, type Token, type TokenType, type TransformFn, type ValidationResult, bonsai, compile, evaluateExpression, formatBonsaiError, formatError, parse, tokenize };
77
77
  //# sourceMappingURL=index.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.mts","names":[],"sources":["../src/errors.ts","../src/lexer.ts","../src/parser.ts","../src/compiler.ts","../src/index.ts"],"mappings":";;;UAIiB,aAAA;EACf,MAAA;EACA,KAAA;EACA,GAAA;AAAA;;cAIW,eAAA,SAAwB,KAAA;EAAA,SAC1B,UAAA;EAAA,SACA,KAAA;EAAA,SACA,GAAA;EAAA,SACA,MAAA;EAAA,SACA,UAAA;cAGP,OAAA,UACA,QAAA,EAAU,aAAA,EACV,UAAA;AAAA;;cAcS,eAAA,SAAwB,KAAA;EAAA,SAC1B,SAAA;EAAA,SACA,QAAA;EAAA,SACA,QAAA;EACT,QAAA,GAAW,aAAA;EACX,SAAA;cAEY,SAAA,UAAmB,QAAA,UAAkB,KAAA;AAAA;;cAetC,mBAAA,SAA4B,KAAA;EAAA,SAC9B,IAAA;EACT,QAAA,GAAW,aAAA;EACX,SAAA;cAEY,IAAA,UAAc,OAAA;AAAA;;cAQf,oBAAA,SAA6B,KAAA;EAAA,SAC/B,UAAA;EAAA,SACA,IAAA;EAAA,SACA,UAAA;EACT,QAAA,GAAW,aAAA;EACX,SAAA;cAEY,IAAA,uCAA2C,UAAA,UAAoB,UAAA;AAAA;;iBAmE7D,WAAA,CACd,OAAA,UACA,QAAA,EAAU,aAAA,EACV,UAAA;;iBA6Bc,iBAAA,CAAkB,KAAA;;;iBCpJlB,QAAA,CAAS,MAAA,WAAiB,KAAA;;;iBCS1B,KAAA,CAAM,MAAA,UAAgB,MAAA,YAAa,OAAA;;;iBCnCnC,OAAA,CAAQ,GAAA,EAAK,OAAA,GAAU,OAAA;;;;;;;iBC8CvB,kBAAA,aAAA,CAAgC,UAAA,UAAoB,OAAA,GAAU,MAAA,oBAA0B,CAAA;;AJrCxG;;;;;;;;;;iBIqDgB,MAAA,CAAO,OAAA,GAAS,aAAA,GAAqB,cAAA"}
1
+ {"version":3,"file":"index.d.mts","names":[],"sources":["../src/errors.ts","../src/lexer.ts","../src/parser.ts","../src/compiler.ts","../src/index.ts"],"mappings":";;;UAIiB,aAAA;EACf,MAAA;EACA,KAAA;EACA,GAAA;AAAA;;cAIW,eAAA,SAAwB,KAAA;EAAA,SAC1B,UAAA;EAAA,SACA,KAAA;EAAA,SACA,GAAA;EAAA,SACA,MAAA;EAAA,SACA,UAAA;cAGP,OAAA,UACA,QAAA,EAAU,aAAA,EACV,UAAA;AAAA;;cAcS,eAAA,SAAwB,KAAA;EAAA,SAC1B,SAAA;EAAA,SACA,QAAA;EAAA,SACA,QAAA;EACT,QAAA,GAAW,aAAA;EACX,SAAA;cAEY,SAAA,UAAmB,QAAA,UAAkB,KAAA;AAAA;;cAetC,mBAAA,SAA4B,KAAA;EAAA,SAC9B,IAAA;EACT,QAAA,GAAW,aAAA;EACX,SAAA;cAEY,IAAA,UAAc,OAAA;AAAA;;cAQf,oBAAA,SAA6B,KAAA;EAAA,SAC/B,UAAA;EAAA,SACA,IAAA;EAAA,SACA,UAAA;EACT,QAAA,GAAW,aAAA;EACX,SAAA;cAEY,IAAA,uCAA2C,UAAA,UAAoB,UAAA;AAAA;;iBAmE7D,WAAA,CACd,OAAA,UACA,QAAA,EAAU,aAAA,EACV,UAAA;;iBA6Bc,iBAAA,CAAkB,KAAA;;;iBCpJlB,QAAA,CAAS,MAAA,WAAiB,KAAA;;;iBCS1B,KAAA,CAAM,MAAA,UAAgB,MAAA,YAAa,OAAA;;;iBCnCnC,OAAA,CAAQ,GAAA,EAAK,OAAA,GAAU,OAAA;;;;;;;iBCiDvB,kBAAA,aAAA,CAAgC,UAAA,UAAoB,OAAA,GAAU,MAAA,oBAA0B,CAAA;;AJxCxG;;;;;;;;;;iBIwDgB,MAAA,CAAO,OAAA,GAAS,aAAA,GAAqB,cAAA"}