ecma-evaluator 2.0.9 → 2.0.10
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 +10 -494
- package/README.zh-CN.md +10 -493
- package/dist/cjs/Evaluator.d.cts +15 -2
- package/dist/cjs/TemplateParser.d.cts +12 -0
- package/dist/cjs/index.cjs +339 -26
- package/dist/cjs/index.cjs.map +1 -1
- package/dist/esm/Evaluator.d.mts +15 -2
- package/dist/esm/TemplateParser.d.mts +12 -0
- package/dist/esm/index.mjs +339 -26
- package/dist/esm/index.mjs.map +1 -1
- package/package.json +74 -67
package/dist/cjs/index.cjs
CHANGED
|
@@ -185,8 +185,6 @@ var mutableMethods = [
|
|
|
185
185
|
"DataView.prototype.setFloat64",
|
|
186
186
|
"DataView.prototype.setBigInt64",
|
|
187
187
|
"DataView.prototype.setBigUint64",
|
|
188
|
-
"Promise.prototype.catch",
|
|
189
|
-
"Promise.prototype.finally",
|
|
190
188
|
"Generator.prototype.next",
|
|
191
189
|
"Generator.prototype.return",
|
|
192
190
|
"Generator.prototype.throw",
|
|
@@ -221,7 +219,8 @@ var dangerousMethods = [
|
|
|
221
219
|
"Object.getOwnPropertyDescriptors",
|
|
222
220
|
"Object.getOwnPropertyNames",
|
|
223
221
|
"Object.getOwnPropertySymbols",
|
|
224
|
-
"
|
|
222
|
+
"Error.captureStackTrace",
|
|
223
|
+
"Error.prepareStackTrace"
|
|
225
224
|
];
|
|
226
225
|
mutableMethods.push("Object.prototype.__proto__");
|
|
227
226
|
var blockedMethods = _to_consumable_array(mutableMethods).concat(_to_consumable_array(dangerousMethods));
|
|
@@ -268,6 +267,10 @@ var blockedGlobalBuiltIns = [
|
|
|
268
267
|
"Reflect",
|
|
269
268
|
"Atomics",
|
|
270
269
|
"WebAssembly",
|
|
270
|
+
"SharedArrayBuffer",
|
|
271
|
+
"queueMicrotask",
|
|
272
|
+
"AbortSignal",
|
|
273
|
+
"Promise",
|
|
271
274
|
"console",
|
|
272
275
|
"Intl",
|
|
273
276
|
"Deno"
|
|
@@ -363,14 +366,127 @@ var ERROR_MESSAGES = {
|
|
|
363
366
|
IS_INVALID_SYNTAX: "{0} is not a valid syntax",
|
|
364
367
|
IS_NOT_FUNCTION: "{0} is not a function",
|
|
365
368
|
IS_NOT_DEFINED: "{0} is not defined",
|
|
366
|
-
IS_NOT_ALLOWED: "{0} is not allowed"
|
|
369
|
+
IS_NOT_ALLOWED: "{0} is not allowed",
|
|
370
|
+
EXPRESSION_TOO_LONG: "Expression exceeds the maximum length of {0} characters"
|
|
367
371
|
};
|
|
372
|
+
var DEFAULT_MAX_INPUT_LENGTH = 10000;
|
|
373
|
+
var MAX_CONFIGURABLE_INPUT_LENGTH = 100000;
|
|
374
|
+
var DEFAULT_MAX_EVALUATION_STEPS = 10000;
|
|
375
|
+
var MAX_CONFIGURABLE_EVALUATION_STEPS = 100000;
|
|
376
|
+
var MAX_ARRAY_LENGTH = 10000;
|
|
377
|
+
var MAX_BUFFER_BYTES = 1000000;
|
|
378
|
+
var MAX_STRING_LENGTH = 100000;
|
|
379
|
+
var MAX_DATA_NODES = 100000;
|
|
380
|
+
var MAX_BIGINT_EXPONENT = 256n;
|
|
381
|
+
var MAX_BIGINT_BITS = 65536;
|
|
382
|
+
var TYPED_ARRAY_CONSTRUCTORS = new Set([
|
|
383
|
+
Int8Array,
|
|
384
|
+
Uint8Array,
|
|
385
|
+
Uint8ClampedArray,
|
|
386
|
+
Int16Array,
|
|
387
|
+
Uint16Array,
|
|
388
|
+
Int32Array,
|
|
389
|
+
Uint32Array,
|
|
390
|
+
Float32Array,
|
|
391
|
+
Float64Array,
|
|
392
|
+
"function" == typeof BigInt64Array ? BigInt64Array : null,
|
|
393
|
+
"function" == typeof BigUint64Array ? BigUint64Array : null
|
|
394
|
+
].filter(function(constructor) {
|
|
395
|
+
return "function" == typeof constructor;
|
|
396
|
+
}));
|
|
397
|
+
var NO_OBJECT = Symbol("no-object");
|
|
368
398
|
var renderErrorMessage = function(template) {
|
|
369
399
|
var context = arguments.length > 1 && void 0 !== arguments[1] ? arguments[1] : {};
|
|
370
400
|
return template.replace(/{(\w+)}/g, function(_, key) {
|
|
371
401
|
return String(context[key]);
|
|
372
402
|
});
|
|
373
403
|
};
|
|
404
|
+
function validateLimit(value, name, defaultValue, maximum) {
|
|
405
|
+
if (void 0 === value) return defaultValue;
|
|
406
|
+
if (!Number.isSafeInteger(value) || value < 1 || value > maximum) throw new RangeError("".concat(name, " must be an integer between 1 and ").concat(maximum));
|
|
407
|
+
return value;
|
|
408
|
+
}
|
|
409
|
+
function countLiteralMatches(value, search, all) {
|
|
410
|
+
if ("" === search) return all ? value.length + 1 : 1;
|
|
411
|
+
var count = 0;
|
|
412
|
+
var position = 0;
|
|
413
|
+
while(-1 !== (position = value.indexOf(search, position))){
|
|
414
|
+
count++;
|
|
415
|
+
if (!all) break;
|
|
416
|
+
position += search.length;
|
|
417
|
+
}
|
|
418
|
+
return count;
|
|
419
|
+
}
|
|
420
|
+
function assertBoundedData(value, label) {
|
|
421
|
+
var pending = [
|
|
422
|
+
value
|
|
423
|
+
];
|
|
424
|
+
var seen = new WeakSet();
|
|
425
|
+
var dataSize = 0;
|
|
426
|
+
var dataNodes = 0;
|
|
427
|
+
var enqueueProperties = function(object) {
|
|
428
|
+
var keys = Object.keys(object);
|
|
429
|
+
if (pending.length + keys.length > MAX_DATA_NODES) throw new RangeError("".concat(label, " exceeds the maximum data node count"));
|
|
430
|
+
var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = void 0;
|
|
431
|
+
try {
|
|
432
|
+
for(var _iterator = keys[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
|
|
433
|
+
var key = _step.value;
|
|
434
|
+
dataSize += key.length;
|
|
435
|
+
var descriptor = Object.getOwnPropertyDescriptor(object, key);
|
|
436
|
+
if (!descriptor || !Object.hasOwn(descriptor, "value")) throw new TypeError("".concat(label, " cannot contain accessor properties"));
|
|
437
|
+
pending.push(descriptor.value);
|
|
438
|
+
}
|
|
439
|
+
} catch (err) {
|
|
440
|
+
_didIteratorError = true;
|
|
441
|
+
_iteratorError = err;
|
|
442
|
+
} finally{
|
|
443
|
+
try {
|
|
444
|
+
if (!_iteratorNormalCompletion && null != _iterator.return) _iterator.return();
|
|
445
|
+
} finally{
|
|
446
|
+
if (_didIteratorError) throw _iteratorError;
|
|
447
|
+
}
|
|
448
|
+
}
|
|
449
|
+
};
|
|
450
|
+
while(pending.length > 0){
|
|
451
|
+
var current = pending.pop();
|
|
452
|
+
dataNodes++;
|
|
453
|
+
if (dataNodes > MAX_DATA_NODES) throw new RangeError("".concat(label, " exceeds the maximum data node count"));
|
|
454
|
+
if ("string" == typeof current) {
|
|
455
|
+
if (current.length > MAX_STRING_LENGTH) throw new RangeError("".concat(label, " contains a string that exceeds the maximum length"));
|
|
456
|
+
dataSize += current.length + 8;
|
|
457
|
+
} else if (null === current || (void 0 === current ? "undefined" : _type_of(current)) !== "object" && "function" != typeof current) {
|
|
458
|
+
dataSize += 8;
|
|
459
|
+
continue;
|
|
460
|
+
} else {
|
|
461
|
+
if ("function" == typeof current || seen.has(current)) continue;
|
|
462
|
+
seen.add(current);
|
|
463
|
+
dataSize += 16;
|
|
464
|
+
if (_instanceof(current, ArrayBuffer) || ArrayBuffer.isView(current)) dataSize += current.byteLength;
|
|
465
|
+
else if (Array.isArray(current)) {
|
|
466
|
+
if (current.length > MAX_ARRAY_LENGTH) throw new RangeError("".concat(label, " contains an array that exceeds the maximum length"));
|
|
467
|
+
dataSize += 8 * current.length;
|
|
468
|
+
enqueueProperties(current);
|
|
469
|
+
} else if (_instanceof(current, Map)) {
|
|
470
|
+
if (current.size > MAX_ARRAY_LENGTH) throw new RangeError("".concat(label, " contains a map that exceeds the maximum size"));
|
|
471
|
+
dataSize += 16 * current.size;
|
|
472
|
+
Map.prototype.forEach.call(current, function(item, key) {
|
|
473
|
+
return pending.push(key, item);
|
|
474
|
+
});
|
|
475
|
+
} else if (_instanceof(current, Set)) {
|
|
476
|
+
if (current.size > MAX_ARRAY_LENGTH) throw new RangeError("".concat(label, " contains a set that exceeds the maximum size"));
|
|
477
|
+
dataSize += 8 * current.size;
|
|
478
|
+
Set.prototype.forEach.call(current, function(item) {
|
|
479
|
+
return pending.push(item);
|
|
480
|
+
});
|
|
481
|
+
} else enqueueProperties(current);
|
|
482
|
+
}
|
|
483
|
+
if (dataSize > MAX_BUFFER_BYTES) throw new RangeError("".concat(label, " exceeds the maximum data size"));
|
|
484
|
+
}
|
|
485
|
+
return {
|
|
486
|
+
dataSize: dataSize,
|
|
487
|
+
dataNodes: dataNodes
|
|
488
|
+
};
|
|
489
|
+
}
|
|
374
490
|
var BINARY_OPERATION_MAP = {
|
|
375
491
|
"+": function(a, b) {
|
|
376
492
|
return a + b;
|
|
@@ -509,21 +625,35 @@ var getBlockedMethods = function() {
|
|
|
509
625
|
var Evaluator_Evaluator = /*#__PURE__*/ function() {
|
|
510
626
|
"use strict";
|
|
511
627
|
function Evaluator() {
|
|
512
|
-
var variables = arguments.length > 0 && void 0 !== arguments[0] ? arguments[0] : Object.create(null);
|
|
628
|
+
var variables = arguments.length > 0 && void 0 !== arguments[0] ? arguments[0] : Object.create(null), options = arguments.length > 1 ? arguments[1] : void 0;
|
|
513
629
|
_class_call_check(this, Evaluator);
|
|
630
|
+
this.maxInputLength = validateLimit(null == options ? void 0 : options.maxInputLength, "maxInputLength", DEFAULT_MAX_INPUT_LENGTH, MAX_CONFIGURABLE_INPUT_LENGTH);
|
|
631
|
+
this.maxEvaluationSteps = validateLimit(null == options ? void 0 : options.maxEvaluationSteps, "maxEvaluationSteps", DEFAULT_MAX_EVALUATION_STEPS, MAX_CONFIGURABLE_EVALUATION_STEPS);
|
|
632
|
+
assertBoundedData(variables, "Evaluation context");
|
|
633
|
+
var clonedVariables = structuredClone(variables);
|
|
514
634
|
this.scopes = [
|
|
515
|
-
|
|
635
|
+
clonedVariables,
|
|
516
636
|
createGlobalScope()
|
|
517
637
|
].filter(function(scope) {
|
|
518
638
|
return null != scope;
|
|
519
639
|
});
|
|
520
640
|
this.source = void 0;
|
|
641
|
+
this.remainingEvaluationSteps = 0;
|
|
642
|
+
this.remainingDataSize = MAX_BUFFER_BYTES;
|
|
643
|
+
this.remainingDataNodes = MAX_DATA_NODES;
|
|
521
644
|
}
|
|
522
645
|
_create_class(Evaluator, [
|
|
523
646
|
{
|
|
524
647
|
key: "evaluate",
|
|
525
648
|
value: function(expression) {
|
|
649
|
+
if ("string" != typeof expression) throw new TypeError("Expression must be a string");
|
|
650
|
+
if (expression.length > this.maxInputLength) throw new SyntaxError(renderErrorMessage(ERROR_MESSAGES.EXPRESSION_TOO_LONG, [
|
|
651
|
+
this.maxInputLength
|
|
652
|
+
]));
|
|
526
653
|
this.source = expression;
|
|
654
|
+
this.remainingEvaluationSteps = this.maxEvaluationSteps;
|
|
655
|
+
this.remainingDataSize = MAX_BUFFER_BYTES;
|
|
656
|
+
this.remainingDataNodes = MAX_DATA_NODES;
|
|
527
657
|
var ast = external_acorn_namespaceObject.parse(expression, {
|
|
528
658
|
ecmaVersion: "latest"
|
|
529
659
|
});
|
|
@@ -537,6 +667,11 @@ var Evaluator_Evaluator = /*#__PURE__*/ function() {
|
|
|
537
667
|
{
|
|
538
668
|
key: "execute",
|
|
539
669
|
value: function(body) {
|
|
670
|
+
if (0 === this.remainingEvaluationSteps) {
|
|
671
|
+
this.remainingEvaluationSteps = this.maxEvaluationSteps;
|
|
672
|
+
this.remainingDataSize = MAX_BUFFER_BYTES;
|
|
673
|
+
this.remainingDataNodes = MAX_DATA_NODES;
|
|
674
|
+
}
|
|
540
675
|
var result;
|
|
541
676
|
var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = void 0;
|
|
542
677
|
try {
|
|
@@ -557,13 +692,26 @@ var Evaluator_Evaluator = /*#__PURE__*/ function() {
|
|
|
557
692
|
if ("function" == typeof result) throw new Error(renderErrorMessage(ERROR_MESSAGES.IS_NOT_ALLOWED, [
|
|
558
693
|
"Returning functions from expressions"
|
|
559
694
|
]));
|
|
560
|
-
|
|
695
|
+
assertBoundedData(result, "Evaluation result");
|
|
696
|
+
if (_instanceof(result, Promise)) throw new Error(renderErrorMessage(ERROR_MESSAGES.IS_NOT_ALLOWED, [
|
|
697
|
+
"Returning promises from expressions"
|
|
698
|
+
]));
|
|
699
|
+
try {
|
|
700
|
+
return structuredClone(result);
|
|
701
|
+
} catch (error) {
|
|
702
|
+
if (error && "DataCloneError" === error.name) throw new Error(renderErrorMessage(ERROR_MESSAGES.IS_NOT_ALLOWED, [
|
|
703
|
+
"Returning non-cloneable values from expressions"
|
|
704
|
+
]));
|
|
705
|
+
throw error;
|
|
706
|
+
}
|
|
561
707
|
}
|
|
562
708
|
},
|
|
563
709
|
{
|
|
564
710
|
key: "visit",
|
|
565
711
|
value: function(node) {
|
|
566
712
|
var _this = this;
|
|
713
|
+
this.remainingEvaluationSteps--;
|
|
714
|
+
if (this.remainingEvaluationSteps < 0) throw new RangeError("Evaluation step limit exceeded");
|
|
567
715
|
switch(node.type){
|
|
568
716
|
case "ExpressionStatement":
|
|
569
717
|
return this.visit(node.expression);
|
|
@@ -600,10 +748,14 @@ var Evaluator_Evaluator = /*#__PURE__*/ function() {
|
|
|
600
748
|
if ("Function" === node.callee.name) throw new Error(renderErrorMessage(ERROR_MESSAGES.IS_NOT_ALLOWED, [
|
|
601
749
|
"new Function() constructor"
|
|
602
750
|
]));
|
|
751
|
+
if ("Promise" === node.callee.name) throw new Error(renderErrorMessage(ERROR_MESSAGES.IS_NOT_ALLOWED, [
|
|
752
|
+
"Promise constructor"
|
|
753
|
+
]));
|
|
603
754
|
var Constructor = this.visit(node.callee);
|
|
604
755
|
var args = node.arguments.length ? node.arguments.map(function(arg) {
|
|
605
756
|
return _this.visit(arg);
|
|
606
757
|
}) : [];
|
|
758
|
+
this.assertBoundedConstruction(Constructor, args);
|
|
607
759
|
return _construct(Constructor, Evaluator_to_consumable_array(args));
|
|
608
760
|
case "ChainExpression":
|
|
609
761
|
return this.visit(node.expression);
|
|
@@ -632,10 +784,49 @@ var Evaluator_Evaluator = /*#__PURE__*/ function() {
|
|
|
632
784
|
var op = node.operator;
|
|
633
785
|
var left = this.visit(node.left);
|
|
634
786
|
var right = this.visit(node.right);
|
|
787
|
+
if ("+" === op && ("string" == typeof left || "string" == typeof right)) {
|
|
788
|
+
if (String(left).length + String(right).length > MAX_STRING_LENGTH) throw new RangeError("String result exceeds the maximum allowed length");
|
|
789
|
+
}
|
|
790
|
+
if ((void 0 === left ? "undefined" : _type_of(left)) === "bigint" && (void 0 === right ? "undefined" : _type_of(right)) === "bigint") {
|
|
791
|
+
if ("**" === op && (right > MAX_BIGINT_EXPONENT || right < 0n)) throw new RangeError("BigInt exponent must be between 0 and ".concat(MAX_BIGINT_EXPONENT));
|
|
792
|
+
var leftBits = left.toString(2).length;
|
|
793
|
+
var rightBits = right.toString(2).length;
|
|
794
|
+
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");
|
|
795
|
+
}
|
|
635
796
|
if (BINARY_OPERATION_MAP.hasOwnProperty(op)) return BINARY_OPERATION_MAP[op](left, right);
|
|
636
797
|
throw new SyntaxError("Unsupported operator: ".concat(node.operator));
|
|
637
798
|
}
|
|
638
799
|
},
|
|
800
|
+
{
|
|
801
|
+
key: "assertBoundedConstruction",
|
|
802
|
+
value: function(Constructor, args) {
|
|
803
|
+
var _args_;
|
|
804
|
+
var size = args[0];
|
|
805
|
+
if (Constructor === Array && 1 === args.length && "number" == typeof size && size > MAX_ARRAY_LENGTH) throw new RangeError("Array length exceeds the maximum allowed length");
|
|
806
|
+
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");
|
|
807
|
+
if (Constructor === DataView && _instanceof(size, ArrayBuffer) && size.byteLength > MAX_BUFFER_BYTES) throw new RangeError("DataView size exceeds the maximum allowed size");
|
|
808
|
+
if (Constructor === Map || Constructor === Set) {
|
|
809
|
+
var _size_size;
|
|
810
|
+
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;
|
|
811
|
+
if ("number" == typeof collectionSize && collectionSize > MAX_ARRAY_LENGTH) throw new RangeError("Collection source exceeds the maximum allowed size");
|
|
812
|
+
}
|
|
813
|
+
if (TYPED_ARRAY_CONSTRUCTORS.has(Constructor)) {
|
|
814
|
+
var byteLength;
|
|
815
|
+
if (_instanceof(size, ArrayBuffer)) {
|
|
816
|
+
var _args_1;
|
|
817
|
+
var offset = null != (_args_1 = args[1]) ? _args_1 : 0;
|
|
818
|
+
var _args_2;
|
|
819
|
+
var elementCount = null != (_args_2 = args[2]) ? _args_2 : Math.floor((size.byteLength - offset) / Constructor.BYTES_PER_ELEMENT);
|
|
820
|
+
byteLength = elementCount * Constructor.BYTES_PER_ELEMENT;
|
|
821
|
+
} else {
|
|
822
|
+
var _size_length;
|
|
823
|
+
var elementCount1 = "number" == typeof size ? size : null != (_size_length = null == size ? void 0 : size.length) ? _size_length : 0;
|
|
824
|
+
byteLength = elementCount1 * Constructor.BYTES_PER_ELEMENT;
|
|
825
|
+
}
|
|
826
|
+
if (byteLength > MAX_BUFFER_BYTES) throw new RangeError("Typed array size exceeds the maximum allowed size");
|
|
827
|
+
}
|
|
828
|
+
}
|
|
829
|
+
},
|
|
639
830
|
{
|
|
640
831
|
key: "handleLogicalExpression",
|
|
641
832
|
value: function(node) {
|
|
@@ -707,9 +898,13 @@ var Evaluator_Evaluator = /*#__PURE__*/ function() {
|
|
|
707
898
|
{
|
|
708
899
|
key: "handleMemberExpression",
|
|
709
900
|
value: function(node) {
|
|
710
|
-
var
|
|
901
|
+
var objectValue = arguments.length > 1 && void 0 !== arguments[1] ? arguments[1] : NO_OBJECT;
|
|
902
|
+
var object = objectValue === NO_OBJECT ? this.visit(node.object) : objectValue;
|
|
711
903
|
var isStaticProperty = "Identifier" === node.property.type && !node.computed;
|
|
712
904
|
var property = isStaticProperty ? node.property.name : this.visit(node.property);
|
|
905
|
+
if ("stack" === property && _instanceof(object, Error)) throw new Error(renderErrorMessage(ERROR_MESSAGES.IS_NOT_ALLOWED, [
|
|
906
|
+
"Accessing error stack"
|
|
907
|
+
]));
|
|
713
908
|
if (null != object && object[property] === (null == object ? void 0 : object.__proto__)) throw new Error(renderErrorMessage(ERROR_MESSAGES.IS_NOT_ALLOWED, [
|
|
714
909
|
"Accessing prototype properties"
|
|
715
910
|
]));
|
|
@@ -733,30 +928,52 @@ var Evaluator_Evaluator = /*#__PURE__*/ function() {
|
|
|
733
928
|
var result = [];
|
|
734
929
|
for(var i = 0; i < node.elements.length; i++){
|
|
735
930
|
var element = node.elements.at(i);
|
|
931
|
+
if (null === element) {
|
|
932
|
+
result.length++;
|
|
933
|
+
continue;
|
|
934
|
+
}
|
|
736
935
|
var value = this.visit(element);
|
|
737
936
|
if ("SpreadElement" === element.type) {
|
|
738
937
|
var _result;
|
|
938
|
+
this.assertBoundedSpread(result.length, value);
|
|
739
939
|
(_result = result).push.apply(_result, Evaluator_to_consumable_array(value));
|
|
740
940
|
} else result.push(value);
|
|
741
941
|
}
|
|
742
942
|
return result;
|
|
743
943
|
}
|
|
744
944
|
},
|
|
945
|
+
{
|
|
946
|
+
key: "assertBoundedSpread",
|
|
947
|
+
value: function(currentLength, value) {
|
|
948
|
+
var size = "string" == typeof value || Array.isArray(value) ? value.length : null == value ? void 0 : value.size;
|
|
949
|
+
if ("number" == typeof size && currentLength + size > MAX_ARRAY_LENGTH) throw new RangeError("Spread value exceeds the maximum allowed length");
|
|
950
|
+
}
|
|
951
|
+
},
|
|
745
952
|
{
|
|
746
953
|
key: "handleObjectExpression",
|
|
747
954
|
value: function(node) {
|
|
748
955
|
var obj = {};
|
|
956
|
+
var spreadPropertyCount = 0;
|
|
749
957
|
var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = void 0;
|
|
750
958
|
try {
|
|
751
959
|
for(var _iterator = node.properties[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
|
|
752
960
|
var prop = _step.value;
|
|
753
961
|
if ("SpreadElement" === prop.type) {
|
|
754
|
-
|
|
962
|
+
var spreadValue = this.visit(prop.argument);
|
|
963
|
+
spreadPropertyCount += Object.keys(spreadValue).length;
|
|
964
|
+
if (spreadPropertyCount > MAX_ARRAY_LENGTH) throw new RangeError("Object spread exceeds the maximum allowed property count");
|
|
965
|
+
Object.assign(obj, spreadValue);
|
|
755
966
|
continue;
|
|
756
967
|
}
|
|
757
|
-
var key = prop.key.name || prop.key.value;
|
|
968
|
+
var key = prop.computed ? this.visit(prop.key) : prop.key.name || prop.key.value;
|
|
758
969
|
var value = this.visit(prop.value);
|
|
759
|
-
obj
|
|
970
|
+
if (prop.computed) Object.defineProperty(obj, key, {
|
|
971
|
+
value: value,
|
|
972
|
+
writable: true,
|
|
973
|
+
enumerable: true,
|
|
974
|
+
configurable: true
|
|
975
|
+
});
|
|
976
|
+
else obj[key] = value;
|
|
760
977
|
}
|
|
761
978
|
} catch (err) {
|
|
762
979
|
_didIteratorError = true;
|
|
@@ -787,22 +1004,43 @@ var Evaluator_Evaluator = /*#__PURE__*/ function() {
|
|
|
787
1004
|
var paramCount = node.params.length;
|
|
788
1005
|
for(var i = 0; i < paramCount; i++)newScope[node.params[i].name] = args[i];
|
|
789
1006
|
_this.scopes.unshift(newScope);
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
1007
|
+
try {
|
|
1008
|
+
var result = _this.visit(node.body);
|
|
1009
|
+
_this.consumeEvaluationValue(result);
|
|
1010
|
+
return result;
|
|
1011
|
+
} finally{
|
|
1012
|
+
_this.scopes.shift();
|
|
1013
|
+
}
|
|
793
1014
|
};
|
|
794
1015
|
}
|
|
795
1016
|
},
|
|
1017
|
+
{
|
|
1018
|
+
key: "consumeEvaluationValue",
|
|
1019
|
+
value: function(value) {
|
|
1020
|
+
var _assertBoundedData = assertBoundedData(value, "Intermediate evaluation result"), dataSize = _assertBoundedData.dataSize, dataNodes = _assertBoundedData.dataNodes;
|
|
1021
|
+
this.remainingDataSize -= dataSize;
|
|
1022
|
+
this.remainingDataNodes -= dataNodes;
|
|
1023
|
+
if (this.remainingDataSize < 0 || this.remainingDataNodes < 0) throw new RangeError("Evaluation allocation budget exceeded");
|
|
1024
|
+
}
|
|
1025
|
+
},
|
|
796
1026
|
{
|
|
797
1027
|
key: "handleCallExpression",
|
|
798
1028
|
value: function(node) {
|
|
799
1029
|
var _this = this;
|
|
800
|
-
var
|
|
801
|
-
var
|
|
1030
|
+
var isOptional = node.optional || "MemberExpression" === node.callee.type && node.callee.optional;
|
|
1031
|
+
var func;
|
|
1032
|
+
var target = null;
|
|
1033
|
+
if ("MemberExpression" === node.callee.type) {
|
|
1034
|
+
target = this.visit(node.callee.object);
|
|
1035
|
+
func = this.handleMemberExpression(node.callee, target);
|
|
1036
|
+
} else func = this.visit(node.callee);
|
|
802
1037
|
if (null == func && isOptional) return;
|
|
803
1038
|
if (func === Function) throw new Error(renderErrorMessage(ERROR_MESSAGES.IS_NOT_ALLOWED, [
|
|
804
1039
|
"Function constructor"
|
|
805
1040
|
]));
|
|
1041
|
+
if (func === Error.prepareStackTrace) throw new Error(renderErrorMessage(ERROR_MESSAGES.IS_NOT_ALLOWED, [
|
|
1042
|
+
"Error.prepareStackTrace"
|
|
1043
|
+
]));
|
|
806
1044
|
if (getBlockedMethods().has(func)) {
|
|
807
1045
|
var path = getBlockedMethods().get(func);
|
|
808
1046
|
throw new Error(renderErrorMessage(ERROR_MESSAGES.IS_NOT_ALLOWED, [
|
|
@@ -817,24 +1055,56 @@ var Evaluator_Evaluator = /*#__PURE__*/ function() {
|
|
|
817
1055
|
var value = _this.visit(element);
|
|
818
1056
|
if ("SpreadElement" === element.type) {
|
|
819
1057
|
var _result;
|
|
1058
|
+
_this.assertBoundedSpread(result.length, value);
|
|
820
1059
|
(_result = result).push.apply(_result, Evaluator_to_consumable_array(value));
|
|
821
1060
|
} else result.push(value);
|
|
822
1061
|
}
|
|
823
1062
|
return result;
|
|
824
1063
|
}();
|
|
825
|
-
var target = "MemberExpression" === node.callee.type ? this.visit(node.callee.object) : null;
|
|
826
1064
|
if (args.some(function(arg) {
|
|
827
1065
|
return arg === Function;
|
|
828
1066
|
})) throw new Error(renderErrorMessage(ERROR_MESSAGES.IS_NOT_ALLOWED, [
|
|
829
1067
|
"Function constructor"
|
|
830
1068
|
]));
|
|
1069
|
+
if ("string" == typeof target) {
|
|
1070
|
+
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");
|
|
1071
|
+
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");
|
|
1072
|
+
if (String.prototype.concat && func === String.prototype.concat) {
|
|
1073
|
+
var resultLength = target.length + args.reduce(function(length, value) {
|
|
1074
|
+
return length + String(value).length;
|
|
1075
|
+
}, 0);
|
|
1076
|
+
if (resultLength > MAX_STRING_LENGTH) throw new RangeError("String result exceeds the maximum allowed length");
|
|
1077
|
+
}
|
|
1078
|
+
if (String.prototype.replace && func === String.prototype.replace || String.prototype.replaceAll && func === String.prototype.replaceAll) {
|
|
1079
|
+
if ("string" == typeof args[0]) {
|
|
1080
|
+
if ("function" == typeof args[1] || "string" == typeof args[1] && RegExp("\\$(?:[$&'`])", "u").test(args[1])) throw new Error("Only literal string replacements are allowed");
|
|
1081
|
+
if (target.length * Math.max(1, args[0].length) > 10000000) throw new RangeError("String operation exceeds the maximum work limit");
|
|
1082
|
+
var matchCount = countLiteralMatches(target, args[0], func === String.prototype.replaceAll);
|
|
1083
|
+
if (target.length + matchCount * String(args[1]).length > MAX_STRING_LENGTH) throw new RangeError("String result exceeds the maximum allowed length");
|
|
1084
|
+
}
|
|
1085
|
+
}
|
|
1086
|
+
if (func === String.prototype.split) {
|
|
1087
|
+
if ("" === args[0] && target.length > MAX_ARRAY_LENGTH) throw new RangeError("Split result exceeds the maximum allowed length");
|
|
1088
|
+
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");
|
|
1089
|
+
}
|
|
1090
|
+
}
|
|
1091
|
+
if ((target === Array || TYPED_ARRAY_CONSTRUCTORS.has(target)) && func === target.from) {
|
|
1092
|
+
var source = args[0];
|
|
1093
|
+
var _source_size;
|
|
1094
|
+
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;
|
|
1095
|
+
if ("number" == typeof size && size > MAX_ARRAY_LENGTH) throw new RangeError("Array.from source exceeds the maximum allowed length");
|
|
1096
|
+
}
|
|
831
1097
|
if ("function" != typeof func) {
|
|
832
1098
|
var calledString = getNodeString(node.callee);
|
|
833
1099
|
throw new TypeError(renderErrorMessage(ERROR_MESSAGES.IS_NOT_FUNCTION, [
|
|
834
1100
|
calledString
|
|
835
1101
|
]));
|
|
836
1102
|
}
|
|
837
|
-
|
|
1103
|
+
var result = func.apply(target, args);
|
|
1104
|
+
if (_instanceof(result, Promise)) throw new Error(renderErrorMessage(ERROR_MESSAGES.IS_NOT_ALLOWED, [
|
|
1105
|
+
"Returning promises from expressions"
|
|
1106
|
+
]));
|
|
1107
|
+
return result;
|
|
838
1108
|
}
|
|
839
1109
|
},
|
|
840
1110
|
{
|
|
@@ -899,11 +1169,25 @@ function TemplateParser_create_class(Constructor, protoProps, staticProps) {
|
|
|
899
1169
|
if (staticProps) TemplateParser_defineProperties(Constructor, staticProps);
|
|
900
1170
|
return Constructor;
|
|
901
1171
|
}
|
|
1172
|
+
var DEFAULT_MAX_TEMPLATE_LENGTH = 100000;
|
|
1173
|
+
var MAX_CONFIGURABLE_TEMPLATE_LENGTH = 1000000;
|
|
1174
|
+
var DEFAULT_MAX_TOKENS = 1000;
|
|
1175
|
+
var MAX_CONFIGURABLE_TOKENS = 10000;
|
|
1176
|
+
function TemplateParser_validateLimit(value, name, defaultValue, maximum) {
|
|
1177
|
+
if (void 0 === value) return defaultValue;
|
|
1178
|
+
if (!Number.isSafeInteger(value) || value < 1 || value > maximum) throw new RangeError("".concat(name, " must be an integer between 1 and ").concat(maximum));
|
|
1179
|
+
return value;
|
|
1180
|
+
}
|
|
902
1181
|
var TemplateParser_TemplateParser = /*#__PURE__*/ function() {
|
|
903
1182
|
"use strict";
|
|
904
1183
|
function TemplateParser() {
|
|
905
1184
|
var options = arguments.length > 0 && void 0 !== arguments[0] ? arguments[0] : {};
|
|
906
1185
|
TemplateParser_class_call_check(this, TemplateParser);
|
|
1186
|
+
null != options || (options = {});
|
|
1187
|
+
this.maxTemplateLength = TemplateParser_validateLimit(options.maxTemplateLength, "maxTemplateLength", DEFAULT_MAX_TEMPLATE_LENGTH, MAX_CONFIGURABLE_TEMPLATE_LENGTH);
|
|
1188
|
+
this.maxTokens = TemplateParser_validateLimit(options.maxTokens, "maxTokens", DEFAULT_MAX_TOKENS, MAX_CONFIGURABLE_TOKENS);
|
|
1189
|
+
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");
|
|
1190
|
+
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");
|
|
907
1191
|
this.exprStart = options.expressionStart || "{{";
|
|
908
1192
|
this.exprEnd = options.expressionEnd || "}}";
|
|
909
1193
|
this.startLen = this.exprStart.length;
|
|
@@ -914,8 +1198,14 @@ var TemplateParser_TemplateParser = /*#__PURE__*/ function() {
|
|
|
914
1198
|
{
|
|
915
1199
|
key: "parse",
|
|
916
1200
|
value: function(template) {
|
|
1201
|
+
var _this = this;
|
|
917
1202
|
if ("string" != typeof template) throw new TypeError("模板必须是字符串");
|
|
1203
|
+
if (template.length > this.maxTemplateLength) throw new RangeError("Template exceeds the maximum length of ".concat(this.maxTemplateLength, " characters"));
|
|
918
1204
|
var tokens = [];
|
|
1205
|
+
var pushToken = function(token) {
|
|
1206
|
+
if (tokens.length >= _this.maxTokens) throw new RangeError("Template exceeds the maximum token count of ".concat(_this.maxTokens));
|
|
1207
|
+
tokens.push(token);
|
|
1208
|
+
};
|
|
919
1209
|
var length = template.length;
|
|
920
1210
|
var state = "TEXT";
|
|
921
1211
|
var buffer = "";
|
|
@@ -928,7 +1218,7 @@ var TemplateParser_TemplateParser = /*#__PURE__*/ function() {
|
|
|
928
1218
|
case "TEXT":
|
|
929
1219
|
if (this._isMatch(pos, template, this.exprStart)) {
|
|
930
1220
|
if (buffer.length > 0) {
|
|
931
|
-
|
|
1221
|
+
pushToken({
|
|
932
1222
|
type: "text",
|
|
933
1223
|
value: buffer,
|
|
934
1224
|
start: pos - buffer.length,
|
|
@@ -950,7 +1240,7 @@ var TemplateParser_TemplateParser = /*#__PURE__*/ function() {
|
|
|
950
1240
|
else if ("\\" === char) state = "'" === nextChar ? "ESCAPE_SQ" : '"' === nextChar ? "ESCAPE_DQ" : "`" === nextChar ? "ESCAPE_TEMPLATE" : "ESCAPE_EXPR";
|
|
951
1241
|
else if (this._isMatch(pos, template, this.exprEnd)) {
|
|
952
1242
|
var exprValue = this.preserveWhitespace ? buffer : buffer.trim();
|
|
953
|
-
if (exprValue.length > 0)
|
|
1243
|
+
if (exprValue.length > 0) pushToken({
|
|
954
1244
|
type: "expression",
|
|
955
1245
|
value: exprValue,
|
|
956
1246
|
start: exprStartPos,
|
|
@@ -999,7 +1289,7 @@ var TemplateParser_TemplateParser = /*#__PURE__*/ function() {
|
|
|
999
1289
|
}
|
|
1000
1290
|
pos++;
|
|
1001
1291
|
}
|
|
1002
|
-
if (buffer.length > 0) if ("TEXT" === state)
|
|
1292
|
+
if (buffer.length > 0) if ("TEXT" === state) pushToken({
|
|
1003
1293
|
type: "text",
|
|
1004
1294
|
value: buffer,
|
|
1005
1295
|
start: pos - buffer.length,
|
|
@@ -1007,13 +1297,12 @@ var TemplateParser_TemplateParser = /*#__PURE__*/ function() {
|
|
|
1007
1297
|
});
|
|
1008
1298
|
else {
|
|
1009
1299
|
var incompleteExpr = this.exprStart + buffer;
|
|
1010
|
-
|
|
1300
|
+
pushToken({
|
|
1011
1301
|
type: "text",
|
|
1012
1302
|
value: incompleteExpr,
|
|
1013
1303
|
start: exprStartPos,
|
|
1014
1304
|
end: pos
|
|
1015
1305
|
});
|
|
1016
|
-
console.warn("警告:在位置 ".concat(exprStartPos, " 开始的表达式未正确结束"));
|
|
1017
1306
|
}
|
|
1018
1307
|
return tokens;
|
|
1019
1308
|
}
|
|
@@ -1041,18 +1330,36 @@ function src_instanceof(left, right) {
|
|
|
1041
1330
|
if (null != right && "undefined" != typeof Symbol && right[Symbol.hasInstance]) return !!right[Symbol.hasInstance](left);
|
|
1042
1331
|
return left instanceof right;
|
|
1043
1332
|
}
|
|
1333
|
+
var DEFAULT_MAX_TEMPLATE_EXPRESSIONS = 100;
|
|
1334
|
+
var MAX_TEMPLATE_EXPRESSIONS = 1000;
|
|
1335
|
+
var DEFAULT_MAX_TEMPLATE_OUTPUT_LENGTH = 100000;
|
|
1336
|
+
var MAX_TEMPLATE_OUTPUT_LENGTH = 1000000;
|
|
1337
|
+
function src_validateLimit(value, name, defaultValue, maximum) {
|
|
1338
|
+
if (void 0 === value) return defaultValue;
|
|
1339
|
+
if (!Number.isSafeInteger(value) || value < 1 || value > maximum) throw new RangeError("".concat(name, " must be an integer between 1 and ").concat(maximum));
|
|
1340
|
+
return value;
|
|
1341
|
+
}
|
|
1044
1342
|
function evalExpression(expression, context) {
|
|
1045
1343
|
return Evaluator_Evaluator.evaluate(expression, context);
|
|
1046
1344
|
}
|
|
1047
1345
|
function evalTemplate(template, context, templateParserOptions) {
|
|
1346
|
+
var options = null != templateParserOptions ? templateParserOptions : {};
|
|
1347
|
+
var maxExpressions = src_validateLimit(options.maxExpressions, "maxExpressions", DEFAULT_MAX_TEMPLATE_EXPRESSIONS, MAX_TEMPLATE_EXPRESSIONS);
|
|
1348
|
+
var maxOutputLength = src_validateLimit(options.maxOutputLength, "maxOutputLength", DEFAULT_MAX_TEMPLATE_OUTPUT_LENGTH, MAX_TEMPLATE_OUTPUT_LENGTH);
|
|
1349
|
+
var tokens = TemplateParser_TemplateParser.parse(template, options);
|
|
1048
1350
|
var result = "";
|
|
1351
|
+
var expressionCount = 0;
|
|
1352
|
+
var evaluator = new Evaluator_Evaluator(context, {
|
|
1353
|
+
maxInputLength: options.maxExpressionLength,
|
|
1354
|
+
maxEvaluationSteps: options.maxEvaluationSteps
|
|
1355
|
+
});
|
|
1049
1356
|
var typeHandler = {
|
|
1050
1357
|
text: function(token) {
|
|
1051
1358
|
return token.value;
|
|
1052
1359
|
},
|
|
1053
1360
|
expression: function(token) {
|
|
1054
1361
|
try {
|
|
1055
|
-
return
|
|
1362
|
+
return evaluator.evaluate(token.value);
|
|
1056
1363
|
} catch (error) {
|
|
1057
1364
|
if (src_instanceof(error, ReferenceError) && error.message.endsWith("is not defined")) return "undefined";
|
|
1058
1365
|
throw error;
|
|
@@ -1061,11 +1368,17 @@ function evalTemplate(template, context, templateParserOptions) {
|
|
|
1061
1368
|
};
|
|
1062
1369
|
var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = void 0;
|
|
1063
1370
|
try {
|
|
1064
|
-
for(var _iterator =
|
|
1371
|
+
for(var _iterator = tokens[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
|
|
1065
1372
|
var token = _step.value;
|
|
1066
1373
|
var _typeHandler_token_type;
|
|
1067
1374
|
var handler = null != (_typeHandler_token_type = typeHandler[token.type]) ? _typeHandler_token_type : typeHandler["text"];
|
|
1068
|
-
|
|
1375
|
+
if ("expression" === token.type) {
|
|
1376
|
+
expressionCount++;
|
|
1377
|
+
if (expressionCount > maxExpressions) throw new RangeError("Template exceeds the maximum expression count of ".concat(maxExpressions));
|
|
1378
|
+
}
|
|
1379
|
+
var chunk = String(handler(token));
|
|
1380
|
+
if (result.length + chunk.length > maxOutputLength) throw new RangeError("Template output exceeds the maximum length of ".concat(maxOutputLength, " characters"));
|
|
1381
|
+
result += chunk;
|
|
1069
1382
|
}
|
|
1070
1383
|
} catch (err) {
|
|
1071
1384
|
_didIteratorError = true;
|