ecma-evaluator 2.0.9 → 2.1.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.
- package/README.md +11 -495
- package/README.zh-CN.md +11 -494
- package/dist/cjs/Evaluator.d.cts +26 -3
- package/dist/cjs/TemplateParser.d.cts +12 -0
- package/dist/cjs/index.cjs +468 -40
- package/dist/cjs/index.cjs.map +1 -1
- package/dist/esm/Evaluator.d.mts +26 -3
- package/dist/esm/TemplateParser.d.mts +12 -0
- package/dist/esm/index.mjs +468 -40
- package/dist/esm/index.mjs.map +1 -1
- package/package.json +77 -67
package/dist/esm/index.mjs
CHANGED
|
@@ -35,6 +35,7 @@ var mutableMethods = [
|
|
|
35
35
|
"Array.prototype.sort",
|
|
36
36
|
"Array.prototype.fill",
|
|
37
37
|
"Array.prototype.copyWithin",
|
|
38
|
+
"Object.create",
|
|
38
39
|
"Object.defineProperty",
|
|
39
40
|
"Object.defineProperties",
|
|
40
41
|
"Object.preventExtensions",
|
|
@@ -144,8 +145,6 @@ var mutableMethods = [
|
|
|
144
145
|
"DataView.prototype.setFloat64",
|
|
145
146
|
"DataView.prototype.setBigInt64",
|
|
146
147
|
"DataView.prototype.setBigUint64",
|
|
147
|
-
"Promise.prototype.catch",
|
|
148
|
-
"Promise.prototype.finally",
|
|
149
148
|
"Generator.prototype.next",
|
|
150
149
|
"Generator.prototype.return",
|
|
151
150
|
"Generator.prototype.throw",
|
|
@@ -180,7 +179,8 @@ var dangerousMethods = [
|
|
|
180
179
|
"Object.getOwnPropertyDescriptors",
|
|
181
180
|
"Object.getOwnPropertyNames",
|
|
182
181
|
"Object.getOwnPropertySymbols",
|
|
183
|
-
"
|
|
182
|
+
"Error.captureStackTrace",
|
|
183
|
+
"Error.prepareStackTrace"
|
|
184
184
|
];
|
|
185
185
|
mutableMethods.push("Object.prototype.__proto__");
|
|
186
186
|
var blockedMethods = _to_consumable_array(mutableMethods).concat(_to_consumable_array(dangerousMethods));
|
|
@@ -227,6 +227,10 @@ var blockedGlobalBuiltIns = [
|
|
|
227
227
|
"Reflect",
|
|
228
228
|
"Atomics",
|
|
229
229
|
"WebAssembly",
|
|
230
|
+
"SharedArrayBuffer",
|
|
231
|
+
"queueMicrotask",
|
|
232
|
+
"AbortSignal",
|
|
233
|
+
"Promise",
|
|
230
234
|
"console",
|
|
231
235
|
"Intl",
|
|
232
236
|
"Deno"
|
|
@@ -322,14 +326,173 @@ var ERROR_MESSAGES = {
|
|
|
322
326
|
IS_INVALID_SYNTAX: "{0} is not a valid syntax",
|
|
323
327
|
IS_NOT_FUNCTION: "{0} is not a function",
|
|
324
328
|
IS_NOT_DEFINED: "{0} is not defined",
|
|
325
|
-
IS_NOT_ALLOWED: "{0} is not allowed"
|
|
329
|
+
IS_NOT_ALLOWED: "{0} is not allowed",
|
|
330
|
+
EXPRESSION_TOO_LONG: "Expression exceeds the maximum length of {0} characters"
|
|
326
331
|
};
|
|
332
|
+
var DEFAULT_MAX_INPUT_LENGTH = 10000;
|
|
333
|
+
var MAX_CONFIGURABLE_INPUT_LENGTH = 100000;
|
|
334
|
+
var DEFAULT_MAX_EVALUATION_STEPS = 10000;
|
|
335
|
+
var MAX_CONFIGURABLE_EVALUATION_STEPS = 100000;
|
|
336
|
+
var MAX_ARRAY_LENGTH = 10000;
|
|
337
|
+
var MAX_BUFFER_BYTES = 1000000;
|
|
338
|
+
var MAX_STRING_LENGTH = 100000;
|
|
339
|
+
var MAX_DATA_NODES = 100000;
|
|
340
|
+
var MAX_BIGINT_EXPONENT = 256n;
|
|
341
|
+
var MAX_BIGINT_BITS = 65536;
|
|
342
|
+
var DEFAULT_MAX_DEPTH = 1000;
|
|
343
|
+
var MAX_CONFIGURABLE_DEPTH = 2000;
|
|
344
|
+
var MAX_REGEXP_SOURCE_LENGTH = 1000;
|
|
345
|
+
var MAX_REGEXP_FLAGS_LENGTH = 32;
|
|
346
|
+
var NON_SANDBOX_GLOBALS = new Set([
|
|
347
|
+
"WeakRef",
|
|
348
|
+
"FinalizationRegistry",
|
|
349
|
+
"Iterator",
|
|
350
|
+
"SharedArrayBuffer",
|
|
351
|
+
"escape",
|
|
352
|
+
"unescape"
|
|
353
|
+
]);
|
|
354
|
+
var TYPED_ARRAY_CONSTRUCTORS = new Set([
|
|
355
|
+
Int8Array,
|
|
356
|
+
Uint8Array,
|
|
357
|
+
Uint8ClampedArray,
|
|
358
|
+
Int16Array,
|
|
359
|
+
Uint16Array,
|
|
360
|
+
Int32Array,
|
|
361
|
+
Uint32Array,
|
|
362
|
+
"function" == typeof Float16Array ? Float16Array : null,
|
|
363
|
+
Float32Array,
|
|
364
|
+
Float64Array,
|
|
365
|
+
"function" == typeof BigInt64Array ? BigInt64Array : null,
|
|
366
|
+
"function" == typeof BigUint64Array ? BigUint64Array : null
|
|
367
|
+
].filter(function(constructor) {
|
|
368
|
+
return "function" == typeof constructor;
|
|
369
|
+
}));
|
|
370
|
+
function isTypedArrayConstructor(value) {
|
|
371
|
+
return TYPED_ARRAY_CONSTRUCTORS.has(value) || "function" == typeof value && "number" == typeof value.BYTES_PER_ELEMENT;
|
|
372
|
+
}
|
|
373
|
+
var TYPED_ARRAY_MUTATORS = function() {
|
|
374
|
+
var map = new Map();
|
|
375
|
+
var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = void 0;
|
|
376
|
+
try {
|
|
377
|
+
for(var _iterator = TYPED_ARRAY_CONSTRUCTORS[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
|
|
378
|
+
var constructor = _step.value;
|
|
379
|
+
for(var _i = 0, _iter = [
|
|
380
|
+
"set",
|
|
381
|
+
"fill",
|
|
382
|
+
"reverse",
|
|
383
|
+
"sort",
|
|
384
|
+
"copyWithin"
|
|
385
|
+
]; _i < _iter.length; _i++){
|
|
386
|
+
var name = _iter[_i];
|
|
387
|
+
var method = constructor.prototype[name];
|
|
388
|
+
if ("function" == typeof method && !map.has(method)) map.set(method, name);
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
} catch (err) {
|
|
392
|
+
_didIteratorError = true;
|
|
393
|
+
_iteratorError = err;
|
|
394
|
+
} finally{
|
|
395
|
+
try {
|
|
396
|
+
if (!_iteratorNormalCompletion && null != _iterator.return) _iterator.return();
|
|
397
|
+
} finally{
|
|
398
|
+
if (_didIteratorError) throw _iteratorError;
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
return map;
|
|
402
|
+
}();
|
|
403
|
+
var NO_OBJECT = Symbol("no-object");
|
|
327
404
|
var renderErrorMessage = function(template) {
|
|
328
405
|
var context = arguments.length > 1 && void 0 !== arguments[1] ? arguments[1] : {};
|
|
329
406
|
return template.replace(/{(\w+)}/g, function(_, key) {
|
|
330
407
|
return String(context[key]);
|
|
331
408
|
});
|
|
332
409
|
};
|
|
410
|
+
function validateLimit(value, name, defaultValue, maximum) {
|
|
411
|
+
if (void 0 === value) return defaultValue;
|
|
412
|
+
if (!Number.isSafeInteger(value) || value < 1 || value > maximum) throw new RangeError("".concat(name, " must be an integer between 1 and ").concat(maximum));
|
|
413
|
+
return value;
|
|
414
|
+
}
|
|
415
|
+
function countLiteralMatches(value, search, all) {
|
|
416
|
+
if ("" === search) return all ? value.length + 1 : 1;
|
|
417
|
+
var count = 0;
|
|
418
|
+
var position = 0;
|
|
419
|
+
while(-1 !== (position = value.indexOf(search, position))){
|
|
420
|
+
count++;
|
|
421
|
+
if (!all) break;
|
|
422
|
+
position += search.length;
|
|
423
|
+
}
|
|
424
|
+
return count;
|
|
425
|
+
}
|
|
426
|
+
function assertBoundedData(value, label) {
|
|
427
|
+
var pending = [
|
|
428
|
+
value
|
|
429
|
+
];
|
|
430
|
+
var seen = new WeakSet();
|
|
431
|
+
var dataSize = 0;
|
|
432
|
+
var dataNodes = 0;
|
|
433
|
+
var enqueueProperties = function(object) {
|
|
434
|
+
var keys = Object.keys(object);
|
|
435
|
+
if (pending.length + keys.length > MAX_DATA_NODES) throw new RangeError("".concat(label, " exceeds the maximum data node count"));
|
|
436
|
+
var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = void 0;
|
|
437
|
+
try {
|
|
438
|
+
for(var _iterator = keys[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
|
|
439
|
+
var key = _step.value;
|
|
440
|
+
dataSize += key.length;
|
|
441
|
+
var descriptor = Object.getOwnPropertyDescriptor(object, key);
|
|
442
|
+
if (!descriptor || !Object.hasOwn(descriptor, "value")) throw new TypeError("".concat(label, " cannot contain accessor properties"));
|
|
443
|
+
pending.push(descriptor.value);
|
|
444
|
+
}
|
|
445
|
+
} catch (err) {
|
|
446
|
+
_didIteratorError = true;
|
|
447
|
+
_iteratorError = err;
|
|
448
|
+
} finally{
|
|
449
|
+
try {
|
|
450
|
+
if (!_iteratorNormalCompletion && null != _iterator.return) _iterator.return();
|
|
451
|
+
} finally{
|
|
452
|
+
if (_didIteratorError) throw _iteratorError;
|
|
453
|
+
}
|
|
454
|
+
}
|
|
455
|
+
};
|
|
456
|
+
while(pending.length > 0){
|
|
457
|
+
var current = pending.pop();
|
|
458
|
+
dataNodes++;
|
|
459
|
+
if (dataNodes > MAX_DATA_NODES) throw new RangeError("".concat(label, " exceeds the maximum data node count"));
|
|
460
|
+
if ("string" == typeof current) {
|
|
461
|
+
if (current.length > MAX_STRING_LENGTH) throw new RangeError("".concat(label, " contains a string that exceeds the maximum length"));
|
|
462
|
+
dataSize += current.length + 8;
|
|
463
|
+
} else if (null === current || (void 0 === current ? "undefined" : _type_of(current)) !== "object" && "function" != typeof current) {
|
|
464
|
+
dataSize += 8;
|
|
465
|
+
continue;
|
|
466
|
+
} else {
|
|
467
|
+
if ("function" == typeof current || seen.has(current)) continue;
|
|
468
|
+
seen.add(current);
|
|
469
|
+
dataSize += 16;
|
|
470
|
+
if (_instanceof(current, ArrayBuffer) || ArrayBuffer.isView(current)) dataSize += current.byteLength;
|
|
471
|
+
else if (Array.isArray(current)) {
|
|
472
|
+
if (current.length > MAX_ARRAY_LENGTH) throw new RangeError("".concat(label, " contains an array that exceeds the maximum length"));
|
|
473
|
+
dataSize += 8 * current.length;
|
|
474
|
+
enqueueProperties(current);
|
|
475
|
+
} else if (_instanceof(current, Map)) {
|
|
476
|
+
if (current.size > MAX_ARRAY_LENGTH) throw new RangeError("".concat(label, " contains a map that exceeds the maximum size"));
|
|
477
|
+
dataSize += 16 * current.size;
|
|
478
|
+
Map.prototype.forEach.call(current, function(item, key) {
|
|
479
|
+
return pending.push(key, item);
|
|
480
|
+
});
|
|
481
|
+
} else if (_instanceof(current, Set)) {
|
|
482
|
+
if (current.size > MAX_ARRAY_LENGTH) throw new RangeError("".concat(label, " contains a set that exceeds the maximum size"));
|
|
483
|
+
dataSize += 8 * current.size;
|
|
484
|
+
Set.prototype.forEach.call(current, function(item) {
|
|
485
|
+
return pending.push(item);
|
|
486
|
+
});
|
|
487
|
+
} else enqueueProperties(current);
|
|
488
|
+
}
|
|
489
|
+
if (dataSize > MAX_BUFFER_BYTES) throw new RangeError("".concat(label, " exceeds the maximum data size"));
|
|
490
|
+
}
|
|
491
|
+
return {
|
|
492
|
+
dataSize: dataSize,
|
|
493
|
+
dataNodes: dataNodes
|
|
494
|
+
};
|
|
495
|
+
}
|
|
333
496
|
var BINARY_OPERATION_MAP = {
|
|
334
497
|
"+": function(a, b) {
|
|
335
498
|
return a + b;
|
|
@@ -401,14 +564,20 @@ var BINARY_OPERATION_MAP = {
|
|
|
401
564
|
function createGlobalScope() {
|
|
402
565
|
var scope = Object.create(null);
|
|
403
566
|
var builtin = globals.builtin;
|
|
404
|
-
for(var key in builtin)
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
567
|
+
for(var key in builtin){
|
|
568
|
+
if (!blockedGlobalBuiltIns.includes(key)) {
|
|
569
|
+
if (!NON_SANDBOX_GLOBALS.has(key)) {
|
|
570
|
+
if (Object.hasOwn(globalThis, key)) {
|
|
571
|
+
var isWritable = builtin[key];
|
|
572
|
+
Object.defineProperty(scope, key, {
|
|
573
|
+
value: globalThis[key],
|
|
574
|
+
writable: isWritable,
|
|
575
|
+
enumerable: false,
|
|
576
|
+
configurable: false
|
|
577
|
+
});
|
|
578
|
+
}
|
|
579
|
+
}
|
|
580
|
+
}
|
|
412
581
|
}
|
|
413
582
|
Object.defineProperty(scope, "globalThis", {
|
|
414
583
|
value: scope,
|
|
@@ -418,6 +587,7 @@ function createGlobalScope() {
|
|
|
418
587
|
});
|
|
419
588
|
return scope;
|
|
420
589
|
}
|
|
590
|
+
var GLOBAL_SCOPE = createGlobalScope();
|
|
421
591
|
var getBlockedMethods = function() {
|
|
422
592
|
var BLOCKED_METHODS = null;
|
|
423
593
|
return function() {
|
|
@@ -468,24 +638,47 @@ var getBlockedMethods = function() {
|
|
|
468
638
|
var Evaluator_Evaluator = /*#__PURE__*/ function() {
|
|
469
639
|
"use strict";
|
|
470
640
|
function Evaluator() {
|
|
471
|
-
var variables = arguments.length > 0 && void 0 !== arguments[0] ? arguments[0] : Object.create(null);
|
|
641
|
+
var variables = arguments.length > 0 && void 0 !== arguments[0] ? arguments[0] : Object.create(null), options = arguments.length > 1 ? arguments[1] : void 0;
|
|
472
642
|
_class_call_check(this, Evaluator);
|
|
643
|
+
this.maxInputLength = validateLimit(null == options ? void 0 : options.maxInputLength, "maxInputLength", DEFAULT_MAX_INPUT_LENGTH, MAX_CONFIGURABLE_INPUT_LENGTH);
|
|
644
|
+
this.maxEvaluationSteps = validateLimit(null == options ? void 0 : options.maxEvaluationSteps, "maxEvaluationSteps", DEFAULT_MAX_EVALUATION_STEPS, MAX_CONFIGURABLE_EVALUATION_STEPS);
|
|
645
|
+
this.maxDepth = validateLimit(null == options ? void 0 : options.maxDepth, "maxDepth", DEFAULT_MAX_DEPTH, MAX_CONFIGURABLE_DEPTH);
|
|
646
|
+
assertBoundedData(variables, "Evaluation context");
|
|
647
|
+
var clonedVariables = structuredClone(variables);
|
|
473
648
|
this.scopes = [
|
|
474
|
-
|
|
475
|
-
|
|
649
|
+
clonedVariables,
|
|
650
|
+
GLOBAL_SCOPE
|
|
476
651
|
].filter(function(scope) {
|
|
477
652
|
return null != scope;
|
|
478
653
|
});
|
|
479
654
|
this.source = void 0;
|
|
655
|
+
this.remainingEvaluationSteps = 0;
|
|
656
|
+
this.remainingDataSize = MAX_BUFFER_BYTES;
|
|
657
|
+
this.remainingDataNodes = MAX_DATA_NODES;
|
|
658
|
+
this.evaluationDepth = 0;
|
|
480
659
|
}
|
|
481
660
|
_create_class(Evaluator, [
|
|
482
661
|
{
|
|
483
662
|
key: "evaluate",
|
|
484
663
|
value: function(expression) {
|
|
664
|
+
if ("string" != typeof expression) throw new TypeError("Expression must be a string");
|
|
665
|
+
if (expression.length > this.maxInputLength) throw new SyntaxError(renderErrorMessage(ERROR_MESSAGES.EXPRESSION_TOO_LONG, [
|
|
666
|
+
this.maxInputLength
|
|
667
|
+
]));
|
|
485
668
|
this.source = expression;
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
669
|
+
this.remainingEvaluationSteps = this.maxEvaluationSteps;
|
|
670
|
+
this.remainingDataSize = MAX_BUFFER_BYTES;
|
|
671
|
+
this.remainingDataNodes = MAX_DATA_NODES;
|
|
672
|
+
this.evaluationDepth = 0;
|
|
673
|
+
var ast;
|
|
674
|
+
try {
|
|
675
|
+
ast = external_acorn_parse(expression, {
|
|
676
|
+
ecmaVersion: "latest"
|
|
677
|
+
});
|
|
678
|
+
} catch (error) {
|
|
679
|
+
if (_instanceof(error, RangeError) && /call stack/i.test(error.message)) throw new SyntaxError("Expression nesting is too deep to parse");
|
|
680
|
+
throw error;
|
|
681
|
+
}
|
|
489
682
|
try {
|
|
490
683
|
return this.execute(ast.body);
|
|
491
684
|
} finally{
|
|
@@ -496,6 +689,11 @@ var Evaluator_Evaluator = /*#__PURE__*/ function() {
|
|
|
496
689
|
{
|
|
497
690
|
key: "execute",
|
|
498
691
|
value: function(body) {
|
|
692
|
+
if (0 === this.remainingEvaluationSteps) {
|
|
693
|
+
this.remainingEvaluationSteps = this.maxEvaluationSteps;
|
|
694
|
+
this.remainingDataSize = MAX_BUFFER_BYTES;
|
|
695
|
+
this.remainingDataNodes = MAX_DATA_NODES;
|
|
696
|
+
}
|
|
499
697
|
var result;
|
|
500
698
|
var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = void 0;
|
|
501
699
|
try {
|
|
@@ -516,11 +714,39 @@ var Evaluator_Evaluator = /*#__PURE__*/ function() {
|
|
|
516
714
|
if ("function" == typeof result) throw new Error(renderErrorMessage(ERROR_MESSAGES.IS_NOT_ALLOWED, [
|
|
517
715
|
"Returning functions from expressions"
|
|
518
716
|
]));
|
|
519
|
-
|
|
717
|
+
assertBoundedData(result, "Evaluation result");
|
|
718
|
+
if (_instanceof(result, Promise)) throw new Error(renderErrorMessage(ERROR_MESSAGES.IS_NOT_ALLOWED, [
|
|
719
|
+
"Returning promises from expressions"
|
|
720
|
+
]));
|
|
721
|
+
try {
|
|
722
|
+
return structuredClone(result);
|
|
723
|
+
} catch (error) {
|
|
724
|
+
if (error && "DataCloneError" === error.name) throw new Error(renderErrorMessage(ERROR_MESSAGES.IS_NOT_ALLOWED, [
|
|
725
|
+
"Returning non-cloneable values from expressions"
|
|
726
|
+
]));
|
|
727
|
+
throw error;
|
|
728
|
+
}
|
|
520
729
|
}
|
|
521
730
|
},
|
|
522
731
|
{
|
|
523
732
|
key: "visit",
|
|
733
|
+
value: function(node) {
|
|
734
|
+
this.remainingEvaluationSteps--;
|
|
735
|
+
if (this.remainingEvaluationSteps < 0) throw new RangeError("Evaluation step limit exceeded");
|
|
736
|
+
this.evaluationDepth++;
|
|
737
|
+
if (this.evaluationDepth > this.maxDepth) {
|
|
738
|
+
this.evaluationDepth--;
|
|
739
|
+
throw new RangeError("Maximum evaluation depth exceeded");
|
|
740
|
+
}
|
|
741
|
+
try {
|
|
742
|
+
return this.visitNode(node);
|
|
743
|
+
} finally{
|
|
744
|
+
this.evaluationDepth--;
|
|
745
|
+
}
|
|
746
|
+
}
|
|
747
|
+
},
|
|
748
|
+
{
|
|
749
|
+
key: "visitNode",
|
|
524
750
|
value: function(node) {
|
|
525
751
|
var _this = this;
|
|
526
752
|
switch(node.type){
|
|
@@ -559,10 +785,14 @@ var Evaluator_Evaluator = /*#__PURE__*/ function() {
|
|
|
559
785
|
if ("Function" === node.callee.name) throw new Error(renderErrorMessage(ERROR_MESSAGES.IS_NOT_ALLOWED, [
|
|
560
786
|
"new Function() constructor"
|
|
561
787
|
]));
|
|
788
|
+
if ("Promise" === node.callee.name) throw new Error(renderErrorMessage(ERROR_MESSAGES.IS_NOT_ALLOWED, [
|
|
789
|
+
"Promise constructor"
|
|
790
|
+
]));
|
|
562
791
|
var Constructor = this.visit(node.callee);
|
|
563
792
|
var args = node.arguments.length ? node.arguments.map(function(arg) {
|
|
564
793
|
return _this.visit(arg);
|
|
565
794
|
}) : [];
|
|
795
|
+
this.assertBoundedConstruction(Constructor, args);
|
|
566
796
|
return _construct(Constructor, Evaluator_to_consumable_array(args));
|
|
567
797
|
case "ChainExpression":
|
|
568
798
|
return this.visit(node.expression);
|
|
@@ -591,10 +821,57 @@ var Evaluator_Evaluator = /*#__PURE__*/ function() {
|
|
|
591
821
|
var op = node.operator;
|
|
592
822
|
var left = this.visit(node.left);
|
|
593
823
|
var right = this.visit(node.right);
|
|
824
|
+
if ("+" === op && ("string" == typeof left || "string" == typeof right)) {
|
|
825
|
+
if (String(left).length + String(right).length > MAX_STRING_LENGTH) throw new RangeError("String result exceeds the maximum allowed length");
|
|
826
|
+
}
|
|
827
|
+
if ((void 0 === left ? "undefined" : _type_of(left)) === "bigint" && (void 0 === right ? "undefined" : _type_of(right)) === "bigint") {
|
|
828
|
+
if ("**" === op && (right > MAX_BIGINT_EXPONENT || right < 0n)) throw new RangeError("BigInt exponent must be between 0 and ".concat(MAX_BIGINT_EXPONENT));
|
|
829
|
+
var leftBits = left.toString(2).length;
|
|
830
|
+
var rightBits = right.toString(2).length;
|
|
831
|
+
if ("**" === op && leftBits * Number(right) > MAX_BIGINT_BITS || "<<" === op && right > BigInt(MAX_BIGINT_BITS) || "<<" === op && right >= 0n && leftBits + Number(right) > MAX_BIGINT_BITS || "*" === op && leftBits + rightBits > MAX_BIGINT_BITS || ("+" === op || "-" === op) && Math.max(leftBits, rightBits) + 1 > MAX_BIGINT_BITS) throw new RangeError("BigInt result exceeds the maximum allowed size");
|
|
832
|
+
}
|
|
594
833
|
if (BINARY_OPERATION_MAP.hasOwnProperty(op)) return BINARY_OPERATION_MAP[op](left, right);
|
|
595
834
|
throw new SyntaxError("Unsupported operator: ".concat(node.operator));
|
|
596
835
|
}
|
|
597
836
|
},
|
|
837
|
+
{
|
|
838
|
+
key: "assertBoundedRegExp",
|
|
839
|
+
value: function(args) {
|
|
840
|
+
if ("string" == typeof args[0] && args[0].length > MAX_REGEXP_SOURCE_LENGTH) throw new RangeError("RegExp source exceeds the maximum allowed length");
|
|
841
|
+
if ("string" == typeof args[1] && args[1].length > MAX_REGEXP_FLAGS_LENGTH) throw new RangeError("RegExp flags exceed the maximum allowed length");
|
|
842
|
+
}
|
|
843
|
+
},
|
|
844
|
+
{
|
|
845
|
+
key: "assertBoundedConstruction",
|
|
846
|
+
value: function(Constructor, args) {
|
|
847
|
+
var _args_;
|
|
848
|
+
if (Constructor === RegExp) this.assertBoundedRegExp(args);
|
|
849
|
+
var size = args[0];
|
|
850
|
+
if (Constructor === Array && 1 === args.length && "number" == typeof size && size > MAX_ARRAY_LENGTH) throw new RangeError("Array length exceeds the maximum allowed length");
|
|
851
|
+
if (Constructor === ArrayBuffer && (size > MAX_BUFFER_BYTES || (null == (_args_ = args[1]) ? void 0 : _args_.maxByteLength) > MAX_BUFFER_BYTES)) throw new RangeError("ArrayBuffer size exceeds the maximum allowed size");
|
|
852
|
+
if (Constructor === DataView && _instanceof(size, ArrayBuffer) && size.byteLength > MAX_BUFFER_BYTES) throw new RangeError("DataView size exceeds the maximum allowed size");
|
|
853
|
+
if (Constructor === Map || Constructor === Set) {
|
|
854
|
+
var _size_size;
|
|
855
|
+
var collectionSize = "string" == typeof size || Array.isArray(size) ? size.length : null != (_size_size = null == size ? void 0 : size.size) ? _size_size : null == size ? void 0 : size.length;
|
|
856
|
+
if ("number" == typeof collectionSize && collectionSize > MAX_ARRAY_LENGTH) throw new RangeError("Collection source exceeds the maximum allowed size");
|
|
857
|
+
}
|
|
858
|
+
if (isTypedArrayConstructor(Constructor)) {
|
|
859
|
+
var byteLength;
|
|
860
|
+
if (_instanceof(size, ArrayBuffer)) {
|
|
861
|
+
var _args_1;
|
|
862
|
+
var offset = null != (_args_1 = args[1]) ? _args_1 : 0;
|
|
863
|
+
var _args_2;
|
|
864
|
+
var elementCount = null != (_args_2 = args[2]) ? _args_2 : Math.floor((size.byteLength - offset) / Constructor.BYTES_PER_ELEMENT);
|
|
865
|
+
byteLength = elementCount * Constructor.BYTES_PER_ELEMENT;
|
|
866
|
+
} else {
|
|
867
|
+
var _size_length;
|
|
868
|
+
var elementCount1 = "number" == typeof size ? size : null != (_size_length = null == size ? void 0 : size.length) ? _size_length : 0;
|
|
869
|
+
byteLength = elementCount1 * Constructor.BYTES_PER_ELEMENT;
|
|
870
|
+
}
|
|
871
|
+
if (byteLength > MAX_BUFFER_BYTES) throw new RangeError("Typed array size exceeds the maximum allowed size");
|
|
872
|
+
}
|
|
873
|
+
}
|
|
874
|
+
},
|
|
598
875
|
{
|
|
599
876
|
key: "handleLogicalExpression",
|
|
600
877
|
value: function(node) {
|
|
@@ -666,10 +943,14 @@ var Evaluator_Evaluator = /*#__PURE__*/ function() {
|
|
|
666
943
|
{
|
|
667
944
|
key: "handleMemberExpression",
|
|
668
945
|
value: function(node) {
|
|
669
|
-
var
|
|
946
|
+
var objectValue = arguments.length > 1 && void 0 !== arguments[1] ? arguments[1] : NO_OBJECT;
|
|
947
|
+
var object = objectValue === NO_OBJECT ? this.visit(node.object) : objectValue;
|
|
670
948
|
var isStaticProperty = "Identifier" === node.property.type && !node.computed;
|
|
671
949
|
var property = isStaticProperty ? node.property.name : this.visit(node.property);
|
|
672
|
-
if (
|
|
950
|
+
if ("stack" === property && _instanceof(object, Error)) throw new Error(renderErrorMessage(ERROR_MESSAGES.IS_NOT_ALLOWED, [
|
|
951
|
+
"Accessing error stack"
|
|
952
|
+
]));
|
|
953
|
+
if (null != object && void 0 !== object.__proto__ && object[property] === object.__proto__) throw new Error(renderErrorMessage(ERROR_MESSAGES.IS_NOT_ALLOWED, [
|
|
673
954
|
"Accessing prototype properties"
|
|
674
955
|
]));
|
|
675
956
|
if (null == object) {
|
|
@@ -692,30 +973,52 @@ var Evaluator_Evaluator = /*#__PURE__*/ function() {
|
|
|
692
973
|
var result = [];
|
|
693
974
|
for(var i = 0; i < node.elements.length; i++){
|
|
694
975
|
var element = node.elements.at(i);
|
|
976
|
+
if (null === element) {
|
|
977
|
+
result.length++;
|
|
978
|
+
continue;
|
|
979
|
+
}
|
|
695
980
|
var value = this.visit(element);
|
|
696
981
|
if ("SpreadElement" === element.type) {
|
|
697
982
|
var _result;
|
|
983
|
+
this.assertBoundedSpread(result.length, value);
|
|
698
984
|
(_result = result).push.apply(_result, Evaluator_to_consumable_array(value));
|
|
699
985
|
} else result.push(value);
|
|
700
986
|
}
|
|
701
987
|
return result;
|
|
702
988
|
}
|
|
703
989
|
},
|
|
990
|
+
{
|
|
991
|
+
key: "assertBoundedSpread",
|
|
992
|
+
value: function(currentLength, value) {
|
|
993
|
+
var size = "string" == typeof value || Array.isArray(value) ? value.length : null == value ? void 0 : value.size;
|
|
994
|
+
if ("number" == typeof size && currentLength + size > MAX_ARRAY_LENGTH) throw new RangeError("Spread value exceeds the maximum allowed length");
|
|
995
|
+
}
|
|
996
|
+
},
|
|
704
997
|
{
|
|
705
998
|
key: "handleObjectExpression",
|
|
706
999
|
value: function(node) {
|
|
707
1000
|
var obj = {};
|
|
1001
|
+
var spreadPropertyCount = 0;
|
|
708
1002
|
var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = void 0;
|
|
709
1003
|
try {
|
|
710
1004
|
for(var _iterator = node.properties[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
|
|
711
1005
|
var prop = _step.value;
|
|
712
1006
|
if ("SpreadElement" === prop.type) {
|
|
713
|
-
|
|
1007
|
+
var spreadValue = this.visit(prop.argument);
|
|
1008
|
+
spreadPropertyCount += Object.keys(spreadValue).length;
|
|
1009
|
+
if (spreadPropertyCount > MAX_ARRAY_LENGTH) throw new RangeError("Object spread exceeds the maximum allowed property count");
|
|
1010
|
+
Object.assign(obj, spreadValue);
|
|
714
1011
|
continue;
|
|
715
1012
|
}
|
|
716
|
-
var key = prop.key.name || prop.key.value;
|
|
1013
|
+
var key = prop.computed ? this.visit(prop.key) : prop.key.name || prop.key.value;
|
|
717
1014
|
var value = this.visit(prop.value);
|
|
718
|
-
obj
|
|
1015
|
+
if (prop.computed) Object.defineProperty(obj, key, {
|
|
1016
|
+
value: value,
|
|
1017
|
+
writable: true,
|
|
1018
|
+
enumerable: true,
|
|
1019
|
+
configurable: true
|
|
1020
|
+
});
|
|
1021
|
+
else obj[key] = value;
|
|
719
1022
|
}
|
|
720
1023
|
} catch (err) {
|
|
721
1024
|
_didIteratorError = true;
|
|
@@ -746,28 +1049,52 @@ var Evaluator_Evaluator = /*#__PURE__*/ function() {
|
|
|
746
1049
|
var paramCount = node.params.length;
|
|
747
1050
|
for(var i = 0; i < paramCount; i++)newScope[node.params[i].name] = args[i];
|
|
748
1051
|
_this.scopes.unshift(newScope);
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
1052
|
+
try {
|
|
1053
|
+
var result = _this.visit(node.body);
|
|
1054
|
+
_this.consumeEvaluationValue(result);
|
|
1055
|
+
return result;
|
|
1056
|
+
} finally{
|
|
1057
|
+
_this.scopes.shift();
|
|
1058
|
+
}
|
|
752
1059
|
};
|
|
753
1060
|
}
|
|
754
1061
|
},
|
|
1062
|
+
{
|
|
1063
|
+
key: "consumeEvaluationValue",
|
|
1064
|
+
value: function(value) {
|
|
1065
|
+
var _assertBoundedData = assertBoundedData(value, "Intermediate evaluation result"), dataSize = _assertBoundedData.dataSize, dataNodes = _assertBoundedData.dataNodes;
|
|
1066
|
+
this.remainingDataSize -= dataSize;
|
|
1067
|
+
this.remainingDataNodes -= dataNodes;
|
|
1068
|
+
if (this.remainingDataSize < 0 || this.remainingDataNodes < 0) throw new RangeError("Evaluation allocation budget exceeded");
|
|
1069
|
+
}
|
|
1070
|
+
},
|
|
755
1071
|
{
|
|
756
1072
|
key: "handleCallExpression",
|
|
757
1073
|
value: function(node) {
|
|
758
1074
|
var _this = this;
|
|
759
|
-
var
|
|
760
|
-
var
|
|
1075
|
+
var isOptional = node.optional || "MemberExpression" === node.callee.type && node.callee.optional;
|
|
1076
|
+
var func;
|
|
1077
|
+
var target = null;
|
|
1078
|
+
if ("MemberExpression" === node.callee.type) {
|
|
1079
|
+
target = this.visit(node.callee.object);
|
|
1080
|
+
func = this.handleMemberExpression(node.callee, target);
|
|
1081
|
+
} else func = this.visit(node.callee);
|
|
761
1082
|
if (null == func && isOptional) return;
|
|
762
1083
|
if (func === Function) throw new Error(renderErrorMessage(ERROR_MESSAGES.IS_NOT_ALLOWED, [
|
|
763
1084
|
"Function constructor"
|
|
764
1085
|
]));
|
|
1086
|
+
if (func === Error.prepareStackTrace) throw new Error(renderErrorMessage(ERROR_MESSAGES.IS_NOT_ALLOWED, [
|
|
1087
|
+
"Error.prepareStackTrace"
|
|
1088
|
+
]));
|
|
765
1089
|
if (getBlockedMethods().has(func)) {
|
|
766
1090
|
var path = getBlockedMethods().get(func);
|
|
767
1091
|
throw new Error(renderErrorMessage(ERROR_MESSAGES.IS_NOT_ALLOWED, [
|
|
768
1092
|
path
|
|
769
1093
|
]));
|
|
770
1094
|
}
|
|
1095
|
+
if (TYPED_ARRAY_MUTATORS.has(func)) throw new Error(renderErrorMessage(ERROR_MESSAGES.IS_NOT_ALLOWED, [
|
|
1096
|
+
"TypedArray.prototype.".concat(TYPED_ARRAY_MUTATORS.get(func))
|
|
1097
|
+
]));
|
|
771
1098
|
var args = function() {
|
|
772
1099
|
if (0 === node.arguments.length) return [];
|
|
773
1100
|
var result = [];
|
|
@@ -776,24 +1103,57 @@ var Evaluator_Evaluator = /*#__PURE__*/ function() {
|
|
|
776
1103
|
var value = _this.visit(element);
|
|
777
1104
|
if ("SpreadElement" === element.type) {
|
|
778
1105
|
var _result;
|
|
1106
|
+
_this.assertBoundedSpread(result.length, value);
|
|
779
1107
|
(_result = result).push.apply(_result, Evaluator_to_consumable_array(value));
|
|
780
1108
|
} else result.push(value);
|
|
781
1109
|
}
|
|
782
1110
|
return result;
|
|
783
1111
|
}();
|
|
784
|
-
var target = "MemberExpression" === node.callee.type ? this.visit(node.callee.object) : null;
|
|
785
1112
|
if (args.some(function(arg) {
|
|
786
1113
|
return arg === Function;
|
|
787
1114
|
})) throw new Error(renderErrorMessage(ERROR_MESSAGES.IS_NOT_ALLOWED, [
|
|
788
1115
|
"Function constructor"
|
|
789
1116
|
]));
|
|
1117
|
+
if ("string" == typeof target) {
|
|
1118
|
+
if (String.prototype.repeat && func === String.prototype.repeat && target.length * Number(args[0]) > MAX_STRING_LENGTH) throw new RangeError("String result exceeds the maximum allowed length");
|
|
1119
|
+
if ((String.prototype.padStart && func === String.prototype.padStart || func === String.prototype.padEnd) && Number(args[0]) > MAX_STRING_LENGTH) throw new RangeError("String result exceeds the maximum allowed length");
|
|
1120
|
+
if (String.prototype.concat && func === String.prototype.concat) {
|
|
1121
|
+
var resultLength = target.length + args.reduce(function(length, value) {
|
|
1122
|
+
return length + String(value).length;
|
|
1123
|
+
}, 0);
|
|
1124
|
+
if (resultLength > MAX_STRING_LENGTH) throw new RangeError("String result exceeds the maximum allowed length");
|
|
1125
|
+
}
|
|
1126
|
+
if (String.prototype.replace && func === String.prototype.replace || String.prototype.replaceAll && func === String.prototype.replaceAll) {
|
|
1127
|
+
if ("string" == typeof args[0]) {
|
|
1128
|
+
if ("function" == typeof args[1] || "string" == typeof args[1] && RegExp("\\$(?:[$&'`])", "u").test(args[1])) throw new Error("Only literal string replacements are allowed");
|
|
1129
|
+
if (target.length * Math.max(1, args[0].length) > 10000000) throw new RangeError("String operation exceeds the maximum work limit");
|
|
1130
|
+
var matchCount = countLiteralMatches(target, args[0], func === String.prototype.replaceAll);
|
|
1131
|
+
if (target.length + matchCount * String(args[1]).length > MAX_STRING_LENGTH) throw new RangeError("String result exceeds the maximum allowed length");
|
|
1132
|
+
}
|
|
1133
|
+
}
|
|
1134
|
+
if (func === String.prototype.split) {
|
|
1135
|
+
if ("" === args[0] && target.length > MAX_ARRAY_LENGTH) throw new RangeError("Split result exceeds the maximum allowed length");
|
|
1136
|
+
if ("string" == typeof args[0] && "" !== args[0] && countLiteralMatches(target, args[0], true) >= MAX_ARRAY_LENGTH) throw new RangeError("Split result exceeds the maximum allowed length");
|
|
1137
|
+
}
|
|
1138
|
+
}
|
|
1139
|
+
if (func === RegExp) this.assertBoundedRegExp(args);
|
|
1140
|
+
if ((target === Array || isTypedArrayConstructor(target)) && func === target.from) {
|
|
1141
|
+
var source = args[0];
|
|
1142
|
+
var _source_size;
|
|
1143
|
+
var size = "string" == typeof source || Array.isArray(source) ? source.length : null != (_source_size = null == source ? void 0 : source.size) ? _source_size : null == source ? void 0 : source.length;
|
|
1144
|
+
if ("number" == typeof size && size > MAX_ARRAY_LENGTH) throw new RangeError("Array.from source exceeds the maximum allowed length");
|
|
1145
|
+
}
|
|
790
1146
|
if ("function" != typeof func) {
|
|
791
1147
|
var calledString = getNodeString(node.callee);
|
|
792
1148
|
throw new TypeError(renderErrorMessage(ERROR_MESSAGES.IS_NOT_FUNCTION, [
|
|
793
1149
|
calledString
|
|
794
1150
|
]));
|
|
795
1151
|
}
|
|
796
|
-
|
|
1152
|
+
var result = func.apply(target, args);
|
|
1153
|
+
if (_instanceof(result, Promise)) throw new Error(renderErrorMessage(ERROR_MESSAGES.IS_NOT_ALLOWED, [
|
|
1154
|
+
"Returning promises from expressions"
|
|
1155
|
+
]));
|
|
1156
|
+
return result;
|
|
797
1157
|
}
|
|
798
1158
|
},
|
|
799
1159
|
{
|
|
@@ -827,7 +1187,7 @@ function getNodeString(node) {
|
|
|
827
1187
|
return node.raw;
|
|
828
1188
|
case "ArrayExpression":
|
|
829
1189
|
return "[".concat(node.elements.map(function(child) {
|
|
830
|
-
return getNodeString(child);
|
|
1190
|
+
return null === child ? "" : getNodeString(child);
|
|
831
1191
|
}).join(","), "]");
|
|
832
1192
|
case "ObjectExpression":
|
|
833
1193
|
if (0 === node.properties.length) return "{}";
|
|
@@ -858,11 +1218,25 @@ function TemplateParser_create_class(Constructor, protoProps, staticProps) {
|
|
|
858
1218
|
if (staticProps) TemplateParser_defineProperties(Constructor, staticProps);
|
|
859
1219
|
return Constructor;
|
|
860
1220
|
}
|
|
1221
|
+
var DEFAULT_MAX_TEMPLATE_LENGTH = 100000;
|
|
1222
|
+
var MAX_CONFIGURABLE_TEMPLATE_LENGTH = 1000000;
|
|
1223
|
+
var DEFAULT_MAX_TOKENS = 1000;
|
|
1224
|
+
var MAX_CONFIGURABLE_TOKENS = 10000;
|
|
1225
|
+
function TemplateParser_validateLimit(value, name, defaultValue, maximum) {
|
|
1226
|
+
if (void 0 === value) return defaultValue;
|
|
1227
|
+
if (!Number.isSafeInteger(value) || value < 1 || value > maximum) throw new RangeError("".concat(name, " must be an integer between 1 and ").concat(maximum));
|
|
1228
|
+
return value;
|
|
1229
|
+
}
|
|
861
1230
|
var TemplateParser_TemplateParser = /*#__PURE__*/ function() {
|
|
862
1231
|
"use strict";
|
|
863
1232
|
function TemplateParser() {
|
|
864
1233
|
var options = arguments.length > 0 && void 0 !== arguments[0] ? arguments[0] : {};
|
|
865
1234
|
TemplateParser_class_call_check(this, TemplateParser);
|
|
1235
|
+
null != options || (options = {});
|
|
1236
|
+
this.maxTemplateLength = TemplateParser_validateLimit(options.maxTemplateLength, "maxTemplateLength", DEFAULT_MAX_TEMPLATE_LENGTH, MAX_CONFIGURABLE_TEMPLATE_LENGTH);
|
|
1237
|
+
this.maxTokens = TemplateParser_validateLimit(options.maxTokens, "maxTokens", DEFAULT_MAX_TOKENS, MAX_CONFIGURABLE_TOKENS);
|
|
1238
|
+
if (void 0 !== options.expressionStart && ("string" != typeof options.expressionStart || 0 === options.expressionStart.length || options.expressionStart.length > 128)) throw new TypeError("expressionStart must be a non-empty string of at most 128 characters");
|
|
1239
|
+
if (void 0 !== options.expressionEnd && ("string" != typeof options.expressionEnd || 0 === options.expressionEnd.length || options.expressionEnd.length > 128)) throw new TypeError("expressionEnd must be a non-empty string of at most 128 characters");
|
|
866
1240
|
this.exprStart = options.expressionStart || "{{";
|
|
867
1241
|
this.exprEnd = options.expressionEnd || "}}";
|
|
868
1242
|
this.startLen = this.exprStart.length;
|
|
@@ -873,13 +1247,20 @@ var TemplateParser_TemplateParser = /*#__PURE__*/ function() {
|
|
|
873
1247
|
{
|
|
874
1248
|
key: "parse",
|
|
875
1249
|
value: function(template) {
|
|
1250
|
+
var _this = this;
|
|
876
1251
|
if ("string" != typeof template) throw new TypeError("模板必须是字符串");
|
|
1252
|
+
if (template.length > this.maxTemplateLength) throw new RangeError("Template exceeds the maximum length of ".concat(this.maxTemplateLength, " characters"));
|
|
877
1253
|
var tokens = [];
|
|
1254
|
+
var pushToken = function(token) {
|
|
1255
|
+
if (tokens.length >= _this.maxTokens) throw new RangeError("Template exceeds the maximum token count of ".concat(_this.maxTokens));
|
|
1256
|
+
tokens.push(token);
|
|
1257
|
+
};
|
|
878
1258
|
var length = template.length;
|
|
879
1259
|
var state = "TEXT";
|
|
880
1260
|
var buffer = "";
|
|
881
1261
|
var exprStartPos = 0;
|
|
882
1262
|
var pos = 0;
|
|
1263
|
+
var prevExprChar = "";
|
|
883
1264
|
while(pos < length){
|
|
884
1265
|
var char = template[pos];
|
|
885
1266
|
var nextChar = template[pos + 1];
|
|
@@ -887,7 +1268,7 @@ var TemplateParser_TemplateParser = /*#__PURE__*/ function() {
|
|
|
887
1268
|
case "TEXT":
|
|
888
1269
|
if (this._isMatch(pos, template, this.exprStart)) {
|
|
889
1270
|
if (buffer.length > 0) {
|
|
890
|
-
|
|
1271
|
+
pushToken({
|
|
891
1272
|
type: "text",
|
|
892
1273
|
value: buffer,
|
|
893
1274
|
start: pos - buffer.length,
|
|
@@ -897,6 +1278,7 @@ var TemplateParser_TemplateParser = /*#__PURE__*/ function() {
|
|
|
897
1278
|
}
|
|
898
1279
|
state = "EXPR";
|
|
899
1280
|
exprStartPos = pos;
|
|
1281
|
+
prevExprChar = "";
|
|
900
1282
|
pos += this.startLen;
|
|
901
1283
|
continue;
|
|
902
1284
|
}
|
|
@@ -906,10 +1288,11 @@ var TemplateParser_TemplateParser = /*#__PURE__*/ function() {
|
|
|
906
1288
|
if ("'" === char) state = "STRING_SQ";
|
|
907
1289
|
else if ('"' === char) state = "STRING_DQ";
|
|
908
1290
|
else if ("`" === char) state = "TEMPLATE";
|
|
1291
|
+
else if ("/" === char && this._isRegexPosition(prevExprChar)) state = "REGEX";
|
|
909
1292
|
else if ("\\" === char) state = "'" === nextChar ? "ESCAPE_SQ" : '"' === nextChar ? "ESCAPE_DQ" : "`" === nextChar ? "ESCAPE_TEMPLATE" : "ESCAPE_EXPR";
|
|
910
1293
|
else if (this._isMatch(pos, template, this.exprEnd)) {
|
|
911
1294
|
var exprValue = this.preserveWhitespace ? buffer : buffer.trim();
|
|
912
|
-
if (exprValue.length > 0)
|
|
1295
|
+
if (exprValue.length > 0) pushToken({
|
|
913
1296
|
type: "expression",
|
|
914
1297
|
value: exprValue,
|
|
915
1298
|
start: exprStartPos,
|
|
@@ -922,6 +1305,7 @@ var TemplateParser_TemplateParser = /*#__PURE__*/ function() {
|
|
|
922
1305
|
pos += this.endLen;
|
|
923
1306
|
continue;
|
|
924
1307
|
}
|
|
1308
|
+
if (!RegExp("\\s", "u").test(char)) prevExprChar = char;
|
|
925
1309
|
buffer += char;
|
|
926
1310
|
break;
|
|
927
1311
|
case "STRING_SQ":
|
|
@@ -939,6 +1323,17 @@ var TemplateParser_TemplateParser = /*#__PURE__*/ function() {
|
|
|
939
1323
|
else if ("`" === char) state = "EXPR";
|
|
940
1324
|
buffer += char;
|
|
941
1325
|
break;
|
|
1326
|
+
case "REGEX":
|
|
1327
|
+
if ("\\" === char) state = "ESCAPE_REGEX";
|
|
1328
|
+
else if ("[" === char) state = "REGEX_CLASS";
|
|
1329
|
+
else if ("/" === char) state = "EXPR";
|
|
1330
|
+
buffer += char;
|
|
1331
|
+
break;
|
|
1332
|
+
case "REGEX_CLASS":
|
|
1333
|
+
if ("\\" === char) state = "ESCAPE_REGEX";
|
|
1334
|
+
else if ("]" === char) state = "REGEX";
|
|
1335
|
+
buffer += char;
|
|
1336
|
+
break;
|
|
942
1337
|
case "ESCAPE_SQ":
|
|
943
1338
|
buffer += char;
|
|
944
1339
|
state = "STRING_SQ";
|
|
@@ -951,6 +1346,10 @@ var TemplateParser_TemplateParser = /*#__PURE__*/ function() {
|
|
|
951
1346
|
buffer += char;
|
|
952
1347
|
state = "TEMPLATE";
|
|
953
1348
|
break;
|
|
1349
|
+
case "ESCAPE_REGEX":
|
|
1350
|
+
buffer += char;
|
|
1351
|
+
state = "REGEX";
|
|
1352
|
+
break;
|
|
954
1353
|
case "ESCAPE_EXPR":
|
|
955
1354
|
buffer += char;
|
|
956
1355
|
state = "EXPR";
|
|
@@ -958,7 +1357,7 @@ var TemplateParser_TemplateParser = /*#__PURE__*/ function() {
|
|
|
958
1357
|
}
|
|
959
1358
|
pos++;
|
|
960
1359
|
}
|
|
961
|
-
if (buffer.length > 0) if ("TEXT" === state)
|
|
1360
|
+
if (buffer.length > 0) if ("TEXT" === state) pushToken({
|
|
962
1361
|
type: "text",
|
|
963
1362
|
value: buffer,
|
|
964
1363
|
start: pos - buffer.length,
|
|
@@ -966,17 +1365,22 @@ var TemplateParser_TemplateParser = /*#__PURE__*/ function() {
|
|
|
966
1365
|
});
|
|
967
1366
|
else {
|
|
968
1367
|
var incompleteExpr = this.exprStart + buffer;
|
|
969
|
-
|
|
1368
|
+
pushToken({
|
|
970
1369
|
type: "text",
|
|
971
1370
|
value: incompleteExpr,
|
|
972
1371
|
start: exprStartPos,
|
|
973
1372
|
end: pos
|
|
974
1373
|
});
|
|
975
|
-
console.warn("警告:在位置 ".concat(exprStartPos, " 开始的表达式未正确结束"));
|
|
976
1374
|
}
|
|
977
1375
|
return tokens;
|
|
978
1376
|
}
|
|
979
1377
|
},
|
|
1378
|
+
{
|
|
1379
|
+
key: "_isRegexPosition",
|
|
1380
|
+
value: function(prev) {
|
|
1381
|
+
return "" === prev || "(,=:[!&|?{};+-*%^~<>".includes(prev);
|
|
1382
|
+
}
|
|
1383
|
+
},
|
|
980
1384
|
{
|
|
981
1385
|
key: "_isMatch",
|
|
982
1386
|
value: function(pos, template, sequence) {
|
|
@@ -1000,18 +1404,36 @@ function src_instanceof(left, right) {
|
|
|
1000
1404
|
if (null != right && "undefined" != typeof Symbol && right[Symbol.hasInstance]) return !!right[Symbol.hasInstance](left);
|
|
1001
1405
|
return left instanceof right;
|
|
1002
1406
|
}
|
|
1407
|
+
var DEFAULT_MAX_TEMPLATE_EXPRESSIONS = 100;
|
|
1408
|
+
var MAX_TEMPLATE_EXPRESSIONS = 1000;
|
|
1409
|
+
var DEFAULT_MAX_TEMPLATE_OUTPUT_LENGTH = 100000;
|
|
1410
|
+
var MAX_TEMPLATE_OUTPUT_LENGTH = 1000000;
|
|
1411
|
+
function src_validateLimit(value, name, defaultValue, maximum) {
|
|
1412
|
+
if (void 0 === value) return defaultValue;
|
|
1413
|
+
if (!Number.isSafeInteger(value) || value < 1 || value > maximum) throw new RangeError("".concat(name, " must be an integer between 1 and ").concat(maximum));
|
|
1414
|
+
return value;
|
|
1415
|
+
}
|
|
1003
1416
|
function evalExpression(expression, context) {
|
|
1004
1417
|
return Evaluator_Evaluator.evaluate(expression, context);
|
|
1005
1418
|
}
|
|
1006
1419
|
function evalTemplate(template, context, templateParserOptions) {
|
|
1420
|
+
var options = null != templateParserOptions ? templateParserOptions : {};
|
|
1421
|
+
var maxExpressions = src_validateLimit(options.maxExpressions, "maxExpressions", DEFAULT_MAX_TEMPLATE_EXPRESSIONS, MAX_TEMPLATE_EXPRESSIONS);
|
|
1422
|
+
var maxOutputLength = src_validateLimit(options.maxOutputLength, "maxOutputLength", DEFAULT_MAX_TEMPLATE_OUTPUT_LENGTH, MAX_TEMPLATE_OUTPUT_LENGTH);
|
|
1423
|
+
var tokens = TemplateParser_TemplateParser.parse(template, options);
|
|
1007
1424
|
var result = "";
|
|
1425
|
+
var expressionCount = 0;
|
|
1426
|
+
var evaluator = new Evaluator_Evaluator(context, {
|
|
1427
|
+
maxInputLength: options.maxExpressionLength,
|
|
1428
|
+
maxEvaluationSteps: options.maxEvaluationSteps
|
|
1429
|
+
});
|
|
1008
1430
|
var typeHandler = {
|
|
1009
1431
|
text: function(token) {
|
|
1010
1432
|
return token.value;
|
|
1011
1433
|
},
|
|
1012
1434
|
expression: function(token) {
|
|
1013
1435
|
try {
|
|
1014
|
-
return
|
|
1436
|
+
return evaluator.evaluate(token.value);
|
|
1015
1437
|
} catch (error) {
|
|
1016
1438
|
if (src_instanceof(error, ReferenceError) && error.message.endsWith("is not defined")) return "undefined";
|
|
1017
1439
|
throw error;
|
|
@@ -1020,11 +1442,17 @@ function evalTemplate(template, context, templateParserOptions) {
|
|
|
1020
1442
|
};
|
|
1021
1443
|
var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = void 0;
|
|
1022
1444
|
try {
|
|
1023
|
-
for(var _iterator =
|
|
1445
|
+
for(var _iterator = tokens[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
|
|
1024
1446
|
var token = _step.value;
|
|
1025
1447
|
var _typeHandler_token_type;
|
|
1026
1448
|
var handler = null != (_typeHandler_token_type = typeHandler[token.type]) ? _typeHandler_token_type : typeHandler["text"];
|
|
1027
|
-
|
|
1449
|
+
if ("expression" === token.type) {
|
|
1450
|
+
expressionCount++;
|
|
1451
|
+
if (expressionCount > maxExpressions) throw new RangeError("Template exceeds the maximum expression count of ".concat(maxExpressions));
|
|
1452
|
+
}
|
|
1453
|
+
var chunk = String(handler(token));
|
|
1454
|
+
if (result.length + chunk.length > maxOutputLength) throw new RangeError("Template output exceeds the maximum length of ".concat(maxOutputLength, " characters"));
|
|
1455
|
+
result += chunk;
|
|
1028
1456
|
}
|
|
1029
1457
|
} catch (err) {
|
|
1030
1458
|
_didIteratorError = true;
|