ecma-evaluator 2.0.8 → 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 +349 -27
- 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 +349 -27
- 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
|
]));
|
|
@@ -720,7 +915,11 @@ var Evaluator_Evaluator = /*#__PURE__*/ function() {
|
|
|
720
915
|
property
|
|
721
916
|
]));
|
|
722
917
|
}
|
|
723
|
-
|
|
918
|
+
var result = object[property];
|
|
919
|
+
if (result === Function || result === Function.prototype) throw new Error(renderErrorMessage(ERROR_MESSAGES.IS_NOT_ALLOWED, [
|
|
920
|
+
"Function constructor"
|
|
921
|
+
]));
|
|
922
|
+
return result;
|
|
724
923
|
}
|
|
725
924
|
},
|
|
726
925
|
{
|
|
@@ -729,30 +928,52 @@ var Evaluator_Evaluator = /*#__PURE__*/ function() {
|
|
|
729
928
|
var result = [];
|
|
730
929
|
for(var i = 0; i < node.elements.length; i++){
|
|
731
930
|
var element = node.elements.at(i);
|
|
931
|
+
if (null === element) {
|
|
932
|
+
result.length++;
|
|
933
|
+
continue;
|
|
934
|
+
}
|
|
732
935
|
var value = this.visit(element);
|
|
733
936
|
if ("SpreadElement" === element.type) {
|
|
734
937
|
var _result;
|
|
938
|
+
this.assertBoundedSpread(result.length, value);
|
|
735
939
|
(_result = result).push.apply(_result, Evaluator_to_consumable_array(value));
|
|
736
940
|
} else result.push(value);
|
|
737
941
|
}
|
|
738
942
|
return result;
|
|
739
943
|
}
|
|
740
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
|
+
},
|
|
741
952
|
{
|
|
742
953
|
key: "handleObjectExpression",
|
|
743
954
|
value: function(node) {
|
|
744
955
|
var obj = {};
|
|
956
|
+
var spreadPropertyCount = 0;
|
|
745
957
|
var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = void 0;
|
|
746
958
|
try {
|
|
747
959
|
for(var _iterator = node.properties[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
|
|
748
960
|
var prop = _step.value;
|
|
749
961
|
if ("SpreadElement" === prop.type) {
|
|
750
|
-
|
|
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);
|
|
751
966
|
continue;
|
|
752
967
|
}
|
|
753
|
-
var key = prop.key.name || prop.key.value;
|
|
968
|
+
var key = prop.computed ? this.visit(prop.key) : prop.key.name || prop.key.value;
|
|
754
969
|
var value = this.visit(prop.value);
|
|
755
|
-
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;
|
|
756
977
|
}
|
|
757
978
|
} catch (err) {
|
|
758
979
|
_didIteratorError = true;
|
|
@@ -783,22 +1004,43 @@ var Evaluator_Evaluator = /*#__PURE__*/ function() {
|
|
|
783
1004
|
var paramCount = node.params.length;
|
|
784
1005
|
for(var i = 0; i < paramCount; i++)newScope[node.params[i].name] = args[i];
|
|
785
1006
|
_this.scopes.unshift(newScope);
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
1007
|
+
try {
|
|
1008
|
+
var result = _this.visit(node.body);
|
|
1009
|
+
_this.consumeEvaluationValue(result);
|
|
1010
|
+
return result;
|
|
1011
|
+
} finally{
|
|
1012
|
+
_this.scopes.shift();
|
|
1013
|
+
}
|
|
789
1014
|
};
|
|
790
1015
|
}
|
|
791
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
|
+
},
|
|
792
1026
|
{
|
|
793
1027
|
key: "handleCallExpression",
|
|
794
1028
|
value: function(node) {
|
|
795
1029
|
var _this = this;
|
|
796
|
-
var
|
|
797
|
-
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);
|
|
798
1037
|
if (null == func && isOptional) return;
|
|
799
1038
|
if (func === Function) throw new Error(renderErrorMessage(ERROR_MESSAGES.IS_NOT_ALLOWED, [
|
|
800
1039
|
"Function constructor"
|
|
801
1040
|
]));
|
|
1041
|
+
if (func === Error.prepareStackTrace) throw new Error(renderErrorMessage(ERROR_MESSAGES.IS_NOT_ALLOWED, [
|
|
1042
|
+
"Error.prepareStackTrace"
|
|
1043
|
+
]));
|
|
802
1044
|
if (getBlockedMethods().has(func)) {
|
|
803
1045
|
var path = getBlockedMethods().get(func);
|
|
804
1046
|
throw new Error(renderErrorMessage(ERROR_MESSAGES.IS_NOT_ALLOWED, [
|
|
@@ -813,19 +1055,56 @@ var Evaluator_Evaluator = /*#__PURE__*/ function() {
|
|
|
813
1055
|
var value = _this.visit(element);
|
|
814
1056
|
if ("SpreadElement" === element.type) {
|
|
815
1057
|
var _result;
|
|
1058
|
+
_this.assertBoundedSpread(result.length, value);
|
|
816
1059
|
(_result = result).push.apply(_result, Evaluator_to_consumable_array(value));
|
|
817
1060
|
} else result.push(value);
|
|
818
1061
|
}
|
|
819
1062
|
return result;
|
|
820
1063
|
}();
|
|
821
|
-
|
|
1064
|
+
if (args.some(function(arg) {
|
|
1065
|
+
return arg === Function;
|
|
1066
|
+
})) throw new Error(renderErrorMessage(ERROR_MESSAGES.IS_NOT_ALLOWED, [
|
|
1067
|
+
"Function constructor"
|
|
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
|
+
}
|
|
822
1097
|
if ("function" != typeof func) {
|
|
823
1098
|
var calledString = getNodeString(node.callee);
|
|
824
1099
|
throw new TypeError(renderErrorMessage(ERROR_MESSAGES.IS_NOT_FUNCTION, [
|
|
825
1100
|
calledString
|
|
826
1101
|
]));
|
|
827
1102
|
}
|
|
828
|
-
|
|
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;
|
|
829
1108
|
}
|
|
830
1109
|
},
|
|
831
1110
|
{
|
|
@@ -890,11 +1169,25 @@ function TemplateParser_create_class(Constructor, protoProps, staticProps) {
|
|
|
890
1169
|
if (staticProps) TemplateParser_defineProperties(Constructor, staticProps);
|
|
891
1170
|
return Constructor;
|
|
892
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
|
+
}
|
|
893
1181
|
var TemplateParser_TemplateParser = /*#__PURE__*/ function() {
|
|
894
1182
|
"use strict";
|
|
895
1183
|
function TemplateParser() {
|
|
896
1184
|
var options = arguments.length > 0 && void 0 !== arguments[0] ? arguments[0] : {};
|
|
897
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");
|
|
898
1191
|
this.exprStart = options.expressionStart || "{{";
|
|
899
1192
|
this.exprEnd = options.expressionEnd || "}}";
|
|
900
1193
|
this.startLen = this.exprStart.length;
|
|
@@ -905,8 +1198,14 @@ var TemplateParser_TemplateParser = /*#__PURE__*/ function() {
|
|
|
905
1198
|
{
|
|
906
1199
|
key: "parse",
|
|
907
1200
|
value: function(template) {
|
|
1201
|
+
var _this = this;
|
|
908
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"));
|
|
909
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
|
+
};
|
|
910
1209
|
var length = template.length;
|
|
911
1210
|
var state = "TEXT";
|
|
912
1211
|
var buffer = "";
|
|
@@ -919,7 +1218,7 @@ var TemplateParser_TemplateParser = /*#__PURE__*/ function() {
|
|
|
919
1218
|
case "TEXT":
|
|
920
1219
|
if (this._isMatch(pos, template, this.exprStart)) {
|
|
921
1220
|
if (buffer.length > 0) {
|
|
922
|
-
|
|
1221
|
+
pushToken({
|
|
923
1222
|
type: "text",
|
|
924
1223
|
value: buffer,
|
|
925
1224
|
start: pos - buffer.length,
|
|
@@ -941,7 +1240,7 @@ var TemplateParser_TemplateParser = /*#__PURE__*/ function() {
|
|
|
941
1240
|
else if ("\\" === char) state = "'" === nextChar ? "ESCAPE_SQ" : '"' === nextChar ? "ESCAPE_DQ" : "`" === nextChar ? "ESCAPE_TEMPLATE" : "ESCAPE_EXPR";
|
|
942
1241
|
else if (this._isMatch(pos, template, this.exprEnd)) {
|
|
943
1242
|
var exprValue = this.preserveWhitespace ? buffer : buffer.trim();
|
|
944
|
-
if (exprValue.length > 0)
|
|
1243
|
+
if (exprValue.length > 0) pushToken({
|
|
945
1244
|
type: "expression",
|
|
946
1245
|
value: exprValue,
|
|
947
1246
|
start: exprStartPos,
|
|
@@ -990,7 +1289,7 @@ var TemplateParser_TemplateParser = /*#__PURE__*/ function() {
|
|
|
990
1289
|
}
|
|
991
1290
|
pos++;
|
|
992
1291
|
}
|
|
993
|
-
if (buffer.length > 0) if ("TEXT" === state)
|
|
1292
|
+
if (buffer.length > 0) if ("TEXT" === state) pushToken({
|
|
994
1293
|
type: "text",
|
|
995
1294
|
value: buffer,
|
|
996
1295
|
start: pos - buffer.length,
|
|
@@ -998,13 +1297,12 @@ var TemplateParser_TemplateParser = /*#__PURE__*/ function() {
|
|
|
998
1297
|
});
|
|
999
1298
|
else {
|
|
1000
1299
|
var incompleteExpr = this.exprStart + buffer;
|
|
1001
|
-
|
|
1300
|
+
pushToken({
|
|
1002
1301
|
type: "text",
|
|
1003
1302
|
value: incompleteExpr,
|
|
1004
1303
|
start: exprStartPos,
|
|
1005
1304
|
end: pos
|
|
1006
1305
|
});
|
|
1007
|
-
console.warn("警告:在位置 ".concat(exprStartPos, " 开始的表达式未正确结束"));
|
|
1008
1306
|
}
|
|
1009
1307
|
return tokens;
|
|
1010
1308
|
}
|
|
@@ -1032,18 +1330,36 @@ function src_instanceof(left, right) {
|
|
|
1032
1330
|
if (null != right && "undefined" != typeof Symbol && right[Symbol.hasInstance]) return !!right[Symbol.hasInstance](left);
|
|
1033
1331
|
return left instanceof right;
|
|
1034
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
|
+
}
|
|
1035
1342
|
function evalExpression(expression, context) {
|
|
1036
1343
|
return Evaluator_Evaluator.evaluate(expression, context);
|
|
1037
1344
|
}
|
|
1038
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);
|
|
1039
1350
|
var result = "";
|
|
1351
|
+
var expressionCount = 0;
|
|
1352
|
+
var evaluator = new Evaluator_Evaluator(context, {
|
|
1353
|
+
maxInputLength: options.maxExpressionLength,
|
|
1354
|
+
maxEvaluationSteps: options.maxEvaluationSteps
|
|
1355
|
+
});
|
|
1040
1356
|
var typeHandler = {
|
|
1041
1357
|
text: function(token) {
|
|
1042
1358
|
return token.value;
|
|
1043
1359
|
},
|
|
1044
1360
|
expression: function(token) {
|
|
1045
1361
|
try {
|
|
1046
|
-
return
|
|
1362
|
+
return evaluator.evaluate(token.value);
|
|
1047
1363
|
} catch (error) {
|
|
1048
1364
|
if (src_instanceof(error, ReferenceError) && error.message.endsWith("is not defined")) return "undefined";
|
|
1049
1365
|
throw error;
|
|
@@ -1052,11 +1368,17 @@ function evalTemplate(template, context, templateParserOptions) {
|
|
|
1052
1368
|
};
|
|
1053
1369
|
var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = void 0;
|
|
1054
1370
|
try {
|
|
1055
|
-
for(var _iterator =
|
|
1371
|
+
for(var _iterator = tokens[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
|
|
1056
1372
|
var token = _step.value;
|
|
1057
1373
|
var _typeHandler_token_type;
|
|
1058
1374
|
var handler = null != (_typeHandler_token_type = typeHandler[token.type]) ? _typeHandler_token_type : typeHandler["text"];
|
|
1059
|
-
|
|
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;
|
|
1060
1382
|
}
|
|
1061
1383
|
} catch (err) {
|
|
1062
1384
|
_didIteratorError = true;
|