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/esm/index.mjs
CHANGED
|
@@ -144,8 +144,6 @@ var mutableMethods = [
|
|
|
144
144
|
"DataView.prototype.setFloat64",
|
|
145
145
|
"DataView.prototype.setBigInt64",
|
|
146
146
|
"DataView.prototype.setBigUint64",
|
|
147
|
-
"Promise.prototype.catch",
|
|
148
|
-
"Promise.prototype.finally",
|
|
149
147
|
"Generator.prototype.next",
|
|
150
148
|
"Generator.prototype.return",
|
|
151
149
|
"Generator.prototype.throw",
|
|
@@ -180,7 +178,8 @@ var dangerousMethods = [
|
|
|
180
178
|
"Object.getOwnPropertyDescriptors",
|
|
181
179
|
"Object.getOwnPropertyNames",
|
|
182
180
|
"Object.getOwnPropertySymbols",
|
|
183
|
-
"
|
|
181
|
+
"Error.captureStackTrace",
|
|
182
|
+
"Error.prepareStackTrace"
|
|
184
183
|
];
|
|
185
184
|
mutableMethods.push("Object.prototype.__proto__");
|
|
186
185
|
var blockedMethods = _to_consumable_array(mutableMethods).concat(_to_consumable_array(dangerousMethods));
|
|
@@ -227,6 +226,10 @@ var blockedGlobalBuiltIns = [
|
|
|
227
226
|
"Reflect",
|
|
228
227
|
"Atomics",
|
|
229
228
|
"WebAssembly",
|
|
229
|
+
"SharedArrayBuffer",
|
|
230
|
+
"queueMicrotask",
|
|
231
|
+
"AbortSignal",
|
|
232
|
+
"Promise",
|
|
230
233
|
"console",
|
|
231
234
|
"Intl",
|
|
232
235
|
"Deno"
|
|
@@ -322,14 +325,127 @@ var ERROR_MESSAGES = {
|
|
|
322
325
|
IS_INVALID_SYNTAX: "{0} is not a valid syntax",
|
|
323
326
|
IS_NOT_FUNCTION: "{0} is not a function",
|
|
324
327
|
IS_NOT_DEFINED: "{0} is not defined",
|
|
325
|
-
IS_NOT_ALLOWED: "{0} is not allowed"
|
|
328
|
+
IS_NOT_ALLOWED: "{0} is not allowed",
|
|
329
|
+
EXPRESSION_TOO_LONG: "Expression exceeds the maximum length of {0} characters"
|
|
326
330
|
};
|
|
331
|
+
var DEFAULT_MAX_INPUT_LENGTH = 10000;
|
|
332
|
+
var MAX_CONFIGURABLE_INPUT_LENGTH = 100000;
|
|
333
|
+
var DEFAULT_MAX_EVALUATION_STEPS = 10000;
|
|
334
|
+
var MAX_CONFIGURABLE_EVALUATION_STEPS = 100000;
|
|
335
|
+
var MAX_ARRAY_LENGTH = 10000;
|
|
336
|
+
var MAX_BUFFER_BYTES = 1000000;
|
|
337
|
+
var MAX_STRING_LENGTH = 100000;
|
|
338
|
+
var MAX_DATA_NODES = 100000;
|
|
339
|
+
var MAX_BIGINT_EXPONENT = 256n;
|
|
340
|
+
var MAX_BIGINT_BITS = 65536;
|
|
341
|
+
var TYPED_ARRAY_CONSTRUCTORS = new Set([
|
|
342
|
+
Int8Array,
|
|
343
|
+
Uint8Array,
|
|
344
|
+
Uint8ClampedArray,
|
|
345
|
+
Int16Array,
|
|
346
|
+
Uint16Array,
|
|
347
|
+
Int32Array,
|
|
348
|
+
Uint32Array,
|
|
349
|
+
Float32Array,
|
|
350
|
+
Float64Array,
|
|
351
|
+
"function" == typeof BigInt64Array ? BigInt64Array : null,
|
|
352
|
+
"function" == typeof BigUint64Array ? BigUint64Array : null
|
|
353
|
+
].filter(function(constructor) {
|
|
354
|
+
return "function" == typeof constructor;
|
|
355
|
+
}));
|
|
356
|
+
var NO_OBJECT = Symbol("no-object");
|
|
327
357
|
var renderErrorMessage = function(template) {
|
|
328
358
|
var context = arguments.length > 1 && void 0 !== arguments[1] ? arguments[1] : {};
|
|
329
359
|
return template.replace(/{(\w+)}/g, function(_, key) {
|
|
330
360
|
return String(context[key]);
|
|
331
361
|
});
|
|
332
362
|
};
|
|
363
|
+
function validateLimit(value, name, defaultValue, maximum) {
|
|
364
|
+
if (void 0 === value) return defaultValue;
|
|
365
|
+
if (!Number.isSafeInteger(value) || value < 1 || value > maximum) throw new RangeError("".concat(name, " must be an integer between 1 and ").concat(maximum));
|
|
366
|
+
return value;
|
|
367
|
+
}
|
|
368
|
+
function countLiteralMatches(value, search, all) {
|
|
369
|
+
if ("" === search) return all ? value.length + 1 : 1;
|
|
370
|
+
var count = 0;
|
|
371
|
+
var position = 0;
|
|
372
|
+
while(-1 !== (position = value.indexOf(search, position))){
|
|
373
|
+
count++;
|
|
374
|
+
if (!all) break;
|
|
375
|
+
position += search.length;
|
|
376
|
+
}
|
|
377
|
+
return count;
|
|
378
|
+
}
|
|
379
|
+
function assertBoundedData(value, label) {
|
|
380
|
+
var pending = [
|
|
381
|
+
value
|
|
382
|
+
];
|
|
383
|
+
var seen = new WeakSet();
|
|
384
|
+
var dataSize = 0;
|
|
385
|
+
var dataNodes = 0;
|
|
386
|
+
var enqueueProperties = function(object) {
|
|
387
|
+
var keys = Object.keys(object);
|
|
388
|
+
if (pending.length + keys.length > MAX_DATA_NODES) throw new RangeError("".concat(label, " exceeds the maximum data node count"));
|
|
389
|
+
var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = void 0;
|
|
390
|
+
try {
|
|
391
|
+
for(var _iterator = keys[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
|
|
392
|
+
var key = _step.value;
|
|
393
|
+
dataSize += key.length;
|
|
394
|
+
var descriptor = Object.getOwnPropertyDescriptor(object, key);
|
|
395
|
+
if (!descriptor || !Object.hasOwn(descriptor, "value")) throw new TypeError("".concat(label, " cannot contain accessor properties"));
|
|
396
|
+
pending.push(descriptor.value);
|
|
397
|
+
}
|
|
398
|
+
} catch (err) {
|
|
399
|
+
_didIteratorError = true;
|
|
400
|
+
_iteratorError = err;
|
|
401
|
+
} finally{
|
|
402
|
+
try {
|
|
403
|
+
if (!_iteratorNormalCompletion && null != _iterator.return) _iterator.return();
|
|
404
|
+
} finally{
|
|
405
|
+
if (_didIteratorError) throw _iteratorError;
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
};
|
|
409
|
+
while(pending.length > 0){
|
|
410
|
+
var current = pending.pop();
|
|
411
|
+
dataNodes++;
|
|
412
|
+
if (dataNodes > MAX_DATA_NODES) throw new RangeError("".concat(label, " exceeds the maximum data node count"));
|
|
413
|
+
if ("string" == typeof current) {
|
|
414
|
+
if (current.length > MAX_STRING_LENGTH) throw new RangeError("".concat(label, " contains a string that exceeds the maximum length"));
|
|
415
|
+
dataSize += current.length + 8;
|
|
416
|
+
} else if (null === current || (void 0 === current ? "undefined" : _type_of(current)) !== "object" && "function" != typeof current) {
|
|
417
|
+
dataSize += 8;
|
|
418
|
+
continue;
|
|
419
|
+
} else {
|
|
420
|
+
if ("function" == typeof current || seen.has(current)) continue;
|
|
421
|
+
seen.add(current);
|
|
422
|
+
dataSize += 16;
|
|
423
|
+
if (_instanceof(current, ArrayBuffer) || ArrayBuffer.isView(current)) dataSize += current.byteLength;
|
|
424
|
+
else if (Array.isArray(current)) {
|
|
425
|
+
if (current.length > MAX_ARRAY_LENGTH) throw new RangeError("".concat(label, " contains an array that exceeds the maximum length"));
|
|
426
|
+
dataSize += 8 * current.length;
|
|
427
|
+
enqueueProperties(current);
|
|
428
|
+
} else if (_instanceof(current, Map)) {
|
|
429
|
+
if (current.size > MAX_ARRAY_LENGTH) throw new RangeError("".concat(label, " contains a map that exceeds the maximum size"));
|
|
430
|
+
dataSize += 16 * current.size;
|
|
431
|
+
Map.prototype.forEach.call(current, function(item, key) {
|
|
432
|
+
return pending.push(key, item);
|
|
433
|
+
});
|
|
434
|
+
} else if (_instanceof(current, Set)) {
|
|
435
|
+
if (current.size > MAX_ARRAY_LENGTH) throw new RangeError("".concat(label, " contains a set that exceeds the maximum size"));
|
|
436
|
+
dataSize += 8 * current.size;
|
|
437
|
+
Set.prototype.forEach.call(current, function(item) {
|
|
438
|
+
return pending.push(item);
|
|
439
|
+
});
|
|
440
|
+
} else enqueueProperties(current);
|
|
441
|
+
}
|
|
442
|
+
if (dataSize > MAX_BUFFER_BYTES) throw new RangeError("".concat(label, " exceeds the maximum data size"));
|
|
443
|
+
}
|
|
444
|
+
return {
|
|
445
|
+
dataSize: dataSize,
|
|
446
|
+
dataNodes: dataNodes
|
|
447
|
+
};
|
|
448
|
+
}
|
|
333
449
|
var BINARY_OPERATION_MAP = {
|
|
334
450
|
"+": function(a, b) {
|
|
335
451
|
return a + b;
|
|
@@ -468,21 +584,35 @@ var getBlockedMethods = function() {
|
|
|
468
584
|
var Evaluator_Evaluator = /*#__PURE__*/ function() {
|
|
469
585
|
"use strict";
|
|
470
586
|
function Evaluator() {
|
|
471
|
-
var variables = arguments.length > 0 && void 0 !== arguments[0] ? arguments[0] : Object.create(null);
|
|
587
|
+
var variables = arguments.length > 0 && void 0 !== arguments[0] ? arguments[0] : Object.create(null), options = arguments.length > 1 ? arguments[1] : void 0;
|
|
472
588
|
_class_call_check(this, Evaluator);
|
|
589
|
+
this.maxInputLength = validateLimit(null == options ? void 0 : options.maxInputLength, "maxInputLength", DEFAULT_MAX_INPUT_LENGTH, MAX_CONFIGURABLE_INPUT_LENGTH);
|
|
590
|
+
this.maxEvaluationSteps = validateLimit(null == options ? void 0 : options.maxEvaluationSteps, "maxEvaluationSteps", DEFAULT_MAX_EVALUATION_STEPS, MAX_CONFIGURABLE_EVALUATION_STEPS);
|
|
591
|
+
assertBoundedData(variables, "Evaluation context");
|
|
592
|
+
var clonedVariables = structuredClone(variables);
|
|
473
593
|
this.scopes = [
|
|
474
|
-
|
|
594
|
+
clonedVariables,
|
|
475
595
|
createGlobalScope()
|
|
476
596
|
].filter(function(scope) {
|
|
477
597
|
return null != scope;
|
|
478
598
|
});
|
|
479
599
|
this.source = void 0;
|
|
600
|
+
this.remainingEvaluationSteps = 0;
|
|
601
|
+
this.remainingDataSize = MAX_BUFFER_BYTES;
|
|
602
|
+
this.remainingDataNodes = MAX_DATA_NODES;
|
|
480
603
|
}
|
|
481
604
|
_create_class(Evaluator, [
|
|
482
605
|
{
|
|
483
606
|
key: "evaluate",
|
|
484
607
|
value: function(expression) {
|
|
608
|
+
if ("string" != typeof expression) throw new TypeError("Expression must be a string");
|
|
609
|
+
if (expression.length > this.maxInputLength) throw new SyntaxError(renderErrorMessage(ERROR_MESSAGES.EXPRESSION_TOO_LONG, [
|
|
610
|
+
this.maxInputLength
|
|
611
|
+
]));
|
|
485
612
|
this.source = expression;
|
|
613
|
+
this.remainingEvaluationSteps = this.maxEvaluationSteps;
|
|
614
|
+
this.remainingDataSize = MAX_BUFFER_BYTES;
|
|
615
|
+
this.remainingDataNodes = MAX_DATA_NODES;
|
|
486
616
|
var ast = external_acorn_parse(expression, {
|
|
487
617
|
ecmaVersion: "latest"
|
|
488
618
|
});
|
|
@@ -496,6 +626,11 @@ var Evaluator_Evaluator = /*#__PURE__*/ function() {
|
|
|
496
626
|
{
|
|
497
627
|
key: "execute",
|
|
498
628
|
value: function(body) {
|
|
629
|
+
if (0 === this.remainingEvaluationSteps) {
|
|
630
|
+
this.remainingEvaluationSteps = this.maxEvaluationSteps;
|
|
631
|
+
this.remainingDataSize = MAX_BUFFER_BYTES;
|
|
632
|
+
this.remainingDataNodes = MAX_DATA_NODES;
|
|
633
|
+
}
|
|
499
634
|
var result;
|
|
500
635
|
var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = void 0;
|
|
501
636
|
try {
|
|
@@ -516,13 +651,26 @@ var Evaluator_Evaluator = /*#__PURE__*/ function() {
|
|
|
516
651
|
if ("function" == typeof result) throw new Error(renderErrorMessage(ERROR_MESSAGES.IS_NOT_ALLOWED, [
|
|
517
652
|
"Returning functions from expressions"
|
|
518
653
|
]));
|
|
519
|
-
|
|
654
|
+
assertBoundedData(result, "Evaluation result");
|
|
655
|
+
if (_instanceof(result, Promise)) throw new Error(renderErrorMessage(ERROR_MESSAGES.IS_NOT_ALLOWED, [
|
|
656
|
+
"Returning promises from expressions"
|
|
657
|
+
]));
|
|
658
|
+
try {
|
|
659
|
+
return structuredClone(result);
|
|
660
|
+
} catch (error) {
|
|
661
|
+
if (error && "DataCloneError" === error.name) throw new Error(renderErrorMessage(ERROR_MESSAGES.IS_NOT_ALLOWED, [
|
|
662
|
+
"Returning non-cloneable values from expressions"
|
|
663
|
+
]));
|
|
664
|
+
throw error;
|
|
665
|
+
}
|
|
520
666
|
}
|
|
521
667
|
},
|
|
522
668
|
{
|
|
523
669
|
key: "visit",
|
|
524
670
|
value: function(node) {
|
|
525
671
|
var _this = this;
|
|
672
|
+
this.remainingEvaluationSteps--;
|
|
673
|
+
if (this.remainingEvaluationSteps < 0) throw new RangeError("Evaluation step limit exceeded");
|
|
526
674
|
switch(node.type){
|
|
527
675
|
case "ExpressionStatement":
|
|
528
676
|
return this.visit(node.expression);
|
|
@@ -559,10 +707,14 @@ var Evaluator_Evaluator = /*#__PURE__*/ function() {
|
|
|
559
707
|
if ("Function" === node.callee.name) throw new Error(renderErrorMessage(ERROR_MESSAGES.IS_NOT_ALLOWED, [
|
|
560
708
|
"new Function() constructor"
|
|
561
709
|
]));
|
|
710
|
+
if ("Promise" === node.callee.name) throw new Error(renderErrorMessage(ERROR_MESSAGES.IS_NOT_ALLOWED, [
|
|
711
|
+
"Promise constructor"
|
|
712
|
+
]));
|
|
562
713
|
var Constructor = this.visit(node.callee);
|
|
563
714
|
var args = node.arguments.length ? node.arguments.map(function(arg) {
|
|
564
715
|
return _this.visit(arg);
|
|
565
716
|
}) : [];
|
|
717
|
+
this.assertBoundedConstruction(Constructor, args);
|
|
566
718
|
return _construct(Constructor, Evaluator_to_consumable_array(args));
|
|
567
719
|
case "ChainExpression":
|
|
568
720
|
return this.visit(node.expression);
|
|
@@ -591,10 +743,49 @@ var Evaluator_Evaluator = /*#__PURE__*/ function() {
|
|
|
591
743
|
var op = node.operator;
|
|
592
744
|
var left = this.visit(node.left);
|
|
593
745
|
var right = this.visit(node.right);
|
|
746
|
+
if ("+" === op && ("string" == typeof left || "string" == typeof right)) {
|
|
747
|
+
if (String(left).length + String(right).length > MAX_STRING_LENGTH) throw new RangeError("String result exceeds the maximum allowed length");
|
|
748
|
+
}
|
|
749
|
+
if ((void 0 === left ? "undefined" : _type_of(left)) === "bigint" && (void 0 === right ? "undefined" : _type_of(right)) === "bigint") {
|
|
750
|
+
if ("**" === op && (right > MAX_BIGINT_EXPONENT || right < 0n)) throw new RangeError("BigInt exponent must be between 0 and ".concat(MAX_BIGINT_EXPONENT));
|
|
751
|
+
var leftBits = left.toString(2).length;
|
|
752
|
+
var rightBits = right.toString(2).length;
|
|
753
|
+
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");
|
|
754
|
+
}
|
|
594
755
|
if (BINARY_OPERATION_MAP.hasOwnProperty(op)) return BINARY_OPERATION_MAP[op](left, right);
|
|
595
756
|
throw new SyntaxError("Unsupported operator: ".concat(node.operator));
|
|
596
757
|
}
|
|
597
758
|
},
|
|
759
|
+
{
|
|
760
|
+
key: "assertBoundedConstruction",
|
|
761
|
+
value: function(Constructor, args) {
|
|
762
|
+
var _args_;
|
|
763
|
+
var size = args[0];
|
|
764
|
+
if (Constructor === Array && 1 === args.length && "number" == typeof size && size > MAX_ARRAY_LENGTH) throw new RangeError("Array length exceeds the maximum allowed length");
|
|
765
|
+
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");
|
|
766
|
+
if (Constructor === DataView && _instanceof(size, ArrayBuffer) && size.byteLength > MAX_BUFFER_BYTES) throw new RangeError("DataView size exceeds the maximum allowed size");
|
|
767
|
+
if (Constructor === Map || Constructor === Set) {
|
|
768
|
+
var _size_size;
|
|
769
|
+
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;
|
|
770
|
+
if ("number" == typeof collectionSize && collectionSize > MAX_ARRAY_LENGTH) throw new RangeError("Collection source exceeds the maximum allowed size");
|
|
771
|
+
}
|
|
772
|
+
if (TYPED_ARRAY_CONSTRUCTORS.has(Constructor)) {
|
|
773
|
+
var byteLength;
|
|
774
|
+
if (_instanceof(size, ArrayBuffer)) {
|
|
775
|
+
var _args_1;
|
|
776
|
+
var offset = null != (_args_1 = args[1]) ? _args_1 : 0;
|
|
777
|
+
var _args_2;
|
|
778
|
+
var elementCount = null != (_args_2 = args[2]) ? _args_2 : Math.floor((size.byteLength - offset) / Constructor.BYTES_PER_ELEMENT);
|
|
779
|
+
byteLength = elementCount * Constructor.BYTES_PER_ELEMENT;
|
|
780
|
+
} else {
|
|
781
|
+
var _size_length;
|
|
782
|
+
var elementCount1 = "number" == typeof size ? size : null != (_size_length = null == size ? void 0 : size.length) ? _size_length : 0;
|
|
783
|
+
byteLength = elementCount1 * Constructor.BYTES_PER_ELEMENT;
|
|
784
|
+
}
|
|
785
|
+
if (byteLength > MAX_BUFFER_BYTES) throw new RangeError("Typed array size exceeds the maximum allowed size");
|
|
786
|
+
}
|
|
787
|
+
}
|
|
788
|
+
},
|
|
598
789
|
{
|
|
599
790
|
key: "handleLogicalExpression",
|
|
600
791
|
value: function(node) {
|
|
@@ -666,9 +857,13 @@ var Evaluator_Evaluator = /*#__PURE__*/ function() {
|
|
|
666
857
|
{
|
|
667
858
|
key: "handleMemberExpression",
|
|
668
859
|
value: function(node) {
|
|
669
|
-
var
|
|
860
|
+
var objectValue = arguments.length > 1 && void 0 !== arguments[1] ? arguments[1] : NO_OBJECT;
|
|
861
|
+
var object = objectValue === NO_OBJECT ? this.visit(node.object) : objectValue;
|
|
670
862
|
var isStaticProperty = "Identifier" === node.property.type && !node.computed;
|
|
671
863
|
var property = isStaticProperty ? node.property.name : this.visit(node.property);
|
|
864
|
+
if ("stack" === property && _instanceof(object, Error)) throw new Error(renderErrorMessage(ERROR_MESSAGES.IS_NOT_ALLOWED, [
|
|
865
|
+
"Accessing error stack"
|
|
866
|
+
]));
|
|
672
867
|
if (null != object && object[property] === (null == object ? void 0 : object.__proto__)) throw new Error(renderErrorMessage(ERROR_MESSAGES.IS_NOT_ALLOWED, [
|
|
673
868
|
"Accessing prototype properties"
|
|
674
869
|
]));
|
|
@@ -679,7 +874,11 @@ var Evaluator_Evaluator = /*#__PURE__*/ function() {
|
|
|
679
874
|
property
|
|
680
875
|
]));
|
|
681
876
|
}
|
|
682
|
-
|
|
877
|
+
var result = object[property];
|
|
878
|
+
if (result === Function || result === Function.prototype) throw new Error(renderErrorMessage(ERROR_MESSAGES.IS_NOT_ALLOWED, [
|
|
879
|
+
"Function constructor"
|
|
880
|
+
]));
|
|
881
|
+
return result;
|
|
683
882
|
}
|
|
684
883
|
},
|
|
685
884
|
{
|
|
@@ -688,30 +887,52 @@ var Evaluator_Evaluator = /*#__PURE__*/ function() {
|
|
|
688
887
|
var result = [];
|
|
689
888
|
for(var i = 0; i < node.elements.length; i++){
|
|
690
889
|
var element = node.elements.at(i);
|
|
890
|
+
if (null === element) {
|
|
891
|
+
result.length++;
|
|
892
|
+
continue;
|
|
893
|
+
}
|
|
691
894
|
var value = this.visit(element);
|
|
692
895
|
if ("SpreadElement" === element.type) {
|
|
693
896
|
var _result;
|
|
897
|
+
this.assertBoundedSpread(result.length, value);
|
|
694
898
|
(_result = result).push.apply(_result, Evaluator_to_consumable_array(value));
|
|
695
899
|
} else result.push(value);
|
|
696
900
|
}
|
|
697
901
|
return result;
|
|
698
902
|
}
|
|
699
903
|
},
|
|
904
|
+
{
|
|
905
|
+
key: "assertBoundedSpread",
|
|
906
|
+
value: function(currentLength, value) {
|
|
907
|
+
var size = "string" == typeof value || Array.isArray(value) ? value.length : null == value ? void 0 : value.size;
|
|
908
|
+
if ("number" == typeof size && currentLength + size > MAX_ARRAY_LENGTH) throw new RangeError("Spread value exceeds the maximum allowed length");
|
|
909
|
+
}
|
|
910
|
+
},
|
|
700
911
|
{
|
|
701
912
|
key: "handleObjectExpression",
|
|
702
913
|
value: function(node) {
|
|
703
914
|
var obj = {};
|
|
915
|
+
var spreadPropertyCount = 0;
|
|
704
916
|
var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = void 0;
|
|
705
917
|
try {
|
|
706
918
|
for(var _iterator = node.properties[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
|
|
707
919
|
var prop = _step.value;
|
|
708
920
|
if ("SpreadElement" === prop.type) {
|
|
709
|
-
|
|
921
|
+
var spreadValue = this.visit(prop.argument);
|
|
922
|
+
spreadPropertyCount += Object.keys(spreadValue).length;
|
|
923
|
+
if (spreadPropertyCount > MAX_ARRAY_LENGTH) throw new RangeError("Object spread exceeds the maximum allowed property count");
|
|
924
|
+
Object.assign(obj, spreadValue);
|
|
710
925
|
continue;
|
|
711
926
|
}
|
|
712
|
-
var key = prop.key.name || prop.key.value;
|
|
927
|
+
var key = prop.computed ? this.visit(prop.key) : prop.key.name || prop.key.value;
|
|
713
928
|
var value = this.visit(prop.value);
|
|
714
|
-
obj
|
|
929
|
+
if (prop.computed) Object.defineProperty(obj, key, {
|
|
930
|
+
value: value,
|
|
931
|
+
writable: true,
|
|
932
|
+
enumerable: true,
|
|
933
|
+
configurable: true
|
|
934
|
+
});
|
|
935
|
+
else obj[key] = value;
|
|
715
936
|
}
|
|
716
937
|
} catch (err) {
|
|
717
938
|
_didIteratorError = true;
|
|
@@ -742,22 +963,43 @@ var Evaluator_Evaluator = /*#__PURE__*/ function() {
|
|
|
742
963
|
var paramCount = node.params.length;
|
|
743
964
|
for(var i = 0; i < paramCount; i++)newScope[node.params[i].name] = args[i];
|
|
744
965
|
_this.scopes.unshift(newScope);
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
966
|
+
try {
|
|
967
|
+
var result = _this.visit(node.body);
|
|
968
|
+
_this.consumeEvaluationValue(result);
|
|
969
|
+
return result;
|
|
970
|
+
} finally{
|
|
971
|
+
_this.scopes.shift();
|
|
972
|
+
}
|
|
748
973
|
};
|
|
749
974
|
}
|
|
750
975
|
},
|
|
976
|
+
{
|
|
977
|
+
key: "consumeEvaluationValue",
|
|
978
|
+
value: function(value) {
|
|
979
|
+
var _assertBoundedData = assertBoundedData(value, "Intermediate evaluation result"), dataSize = _assertBoundedData.dataSize, dataNodes = _assertBoundedData.dataNodes;
|
|
980
|
+
this.remainingDataSize -= dataSize;
|
|
981
|
+
this.remainingDataNodes -= dataNodes;
|
|
982
|
+
if (this.remainingDataSize < 0 || this.remainingDataNodes < 0) throw new RangeError("Evaluation allocation budget exceeded");
|
|
983
|
+
}
|
|
984
|
+
},
|
|
751
985
|
{
|
|
752
986
|
key: "handleCallExpression",
|
|
753
987
|
value: function(node) {
|
|
754
988
|
var _this = this;
|
|
755
|
-
var
|
|
756
|
-
var
|
|
989
|
+
var isOptional = node.optional || "MemberExpression" === node.callee.type && node.callee.optional;
|
|
990
|
+
var func;
|
|
991
|
+
var target = null;
|
|
992
|
+
if ("MemberExpression" === node.callee.type) {
|
|
993
|
+
target = this.visit(node.callee.object);
|
|
994
|
+
func = this.handleMemberExpression(node.callee, target);
|
|
995
|
+
} else func = this.visit(node.callee);
|
|
757
996
|
if (null == func && isOptional) return;
|
|
758
997
|
if (func === Function) throw new Error(renderErrorMessage(ERROR_MESSAGES.IS_NOT_ALLOWED, [
|
|
759
998
|
"Function constructor"
|
|
760
999
|
]));
|
|
1000
|
+
if (func === Error.prepareStackTrace) throw new Error(renderErrorMessage(ERROR_MESSAGES.IS_NOT_ALLOWED, [
|
|
1001
|
+
"Error.prepareStackTrace"
|
|
1002
|
+
]));
|
|
761
1003
|
if (getBlockedMethods().has(func)) {
|
|
762
1004
|
var path = getBlockedMethods().get(func);
|
|
763
1005
|
throw new Error(renderErrorMessage(ERROR_MESSAGES.IS_NOT_ALLOWED, [
|
|
@@ -772,19 +1014,56 @@ var Evaluator_Evaluator = /*#__PURE__*/ function() {
|
|
|
772
1014
|
var value = _this.visit(element);
|
|
773
1015
|
if ("SpreadElement" === element.type) {
|
|
774
1016
|
var _result;
|
|
1017
|
+
_this.assertBoundedSpread(result.length, value);
|
|
775
1018
|
(_result = result).push.apply(_result, Evaluator_to_consumable_array(value));
|
|
776
1019
|
} else result.push(value);
|
|
777
1020
|
}
|
|
778
1021
|
return result;
|
|
779
1022
|
}();
|
|
780
|
-
|
|
1023
|
+
if (args.some(function(arg) {
|
|
1024
|
+
return arg === Function;
|
|
1025
|
+
})) throw new Error(renderErrorMessage(ERROR_MESSAGES.IS_NOT_ALLOWED, [
|
|
1026
|
+
"Function constructor"
|
|
1027
|
+
]));
|
|
1028
|
+
if ("string" == typeof target) {
|
|
1029
|
+
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");
|
|
1030
|
+
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");
|
|
1031
|
+
if (String.prototype.concat && func === String.prototype.concat) {
|
|
1032
|
+
var resultLength = target.length + args.reduce(function(length, value) {
|
|
1033
|
+
return length + String(value).length;
|
|
1034
|
+
}, 0);
|
|
1035
|
+
if (resultLength > MAX_STRING_LENGTH) throw new RangeError("String result exceeds the maximum allowed length");
|
|
1036
|
+
}
|
|
1037
|
+
if (String.prototype.replace && func === String.prototype.replace || String.prototype.replaceAll && func === String.prototype.replaceAll) {
|
|
1038
|
+
if ("string" == typeof args[0]) {
|
|
1039
|
+
if ("function" == typeof args[1] || "string" == typeof args[1] && RegExp("\\$(?:[$&'`])", "u").test(args[1])) throw new Error("Only literal string replacements are allowed");
|
|
1040
|
+
if (target.length * Math.max(1, args[0].length) > 10000000) throw new RangeError("String operation exceeds the maximum work limit");
|
|
1041
|
+
var matchCount = countLiteralMatches(target, args[0], func === String.prototype.replaceAll);
|
|
1042
|
+
if (target.length + matchCount * String(args[1]).length > MAX_STRING_LENGTH) throw new RangeError("String result exceeds the maximum allowed length");
|
|
1043
|
+
}
|
|
1044
|
+
}
|
|
1045
|
+
if (func === String.prototype.split) {
|
|
1046
|
+
if ("" === args[0] && target.length > MAX_ARRAY_LENGTH) throw new RangeError("Split result exceeds the maximum allowed length");
|
|
1047
|
+
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");
|
|
1048
|
+
}
|
|
1049
|
+
}
|
|
1050
|
+
if ((target === Array || TYPED_ARRAY_CONSTRUCTORS.has(target)) && func === target.from) {
|
|
1051
|
+
var source = args[0];
|
|
1052
|
+
var _source_size;
|
|
1053
|
+
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;
|
|
1054
|
+
if ("number" == typeof size && size > MAX_ARRAY_LENGTH) throw new RangeError("Array.from source exceeds the maximum allowed length");
|
|
1055
|
+
}
|
|
781
1056
|
if ("function" != typeof func) {
|
|
782
1057
|
var calledString = getNodeString(node.callee);
|
|
783
1058
|
throw new TypeError(renderErrorMessage(ERROR_MESSAGES.IS_NOT_FUNCTION, [
|
|
784
1059
|
calledString
|
|
785
1060
|
]));
|
|
786
1061
|
}
|
|
787
|
-
|
|
1062
|
+
var result = func.apply(target, args);
|
|
1063
|
+
if (_instanceof(result, Promise)) throw new Error(renderErrorMessage(ERROR_MESSAGES.IS_NOT_ALLOWED, [
|
|
1064
|
+
"Returning promises from expressions"
|
|
1065
|
+
]));
|
|
1066
|
+
return result;
|
|
788
1067
|
}
|
|
789
1068
|
},
|
|
790
1069
|
{
|
|
@@ -849,11 +1128,25 @@ function TemplateParser_create_class(Constructor, protoProps, staticProps) {
|
|
|
849
1128
|
if (staticProps) TemplateParser_defineProperties(Constructor, staticProps);
|
|
850
1129
|
return Constructor;
|
|
851
1130
|
}
|
|
1131
|
+
var DEFAULT_MAX_TEMPLATE_LENGTH = 100000;
|
|
1132
|
+
var MAX_CONFIGURABLE_TEMPLATE_LENGTH = 1000000;
|
|
1133
|
+
var DEFAULT_MAX_TOKENS = 1000;
|
|
1134
|
+
var MAX_CONFIGURABLE_TOKENS = 10000;
|
|
1135
|
+
function TemplateParser_validateLimit(value, name, defaultValue, maximum) {
|
|
1136
|
+
if (void 0 === value) return defaultValue;
|
|
1137
|
+
if (!Number.isSafeInteger(value) || value < 1 || value > maximum) throw new RangeError("".concat(name, " must be an integer between 1 and ").concat(maximum));
|
|
1138
|
+
return value;
|
|
1139
|
+
}
|
|
852
1140
|
var TemplateParser_TemplateParser = /*#__PURE__*/ function() {
|
|
853
1141
|
"use strict";
|
|
854
1142
|
function TemplateParser() {
|
|
855
1143
|
var options = arguments.length > 0 && void 0 !== arguments[0] ? arguments[0] : {};
|
|
856
1144
|
TemplateParser_class_call_check(this, TemplateParser);
|
|
1145
|
+
null != options || (options = {});
|
|
1146
|
+
this.maxTemplateLength = TemplateParser_validateLimit(options.maxTemplateLength, "maxTemplateLength", DEFAULT_MAX_TEMPLATE_LENGTH, MAX_CONFIGURABLE_TEMPLATE_LENGTH);
|
|
1147
|
+
this.maxTokens = TemplateParser_validateLimit(options.maxTokens, "maxTokens", DEFAULT_MAX_TOKENS, MAX_CONFIGURABLE_TOKENS);
|
|
1148
|
+
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");
|
|
1149
|
+
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");
|
|
857
1150
|
this.exprStart = options.expressionStart || "{{";
|
|
858
1151
|
this.exprEnd = options.expressionEnd || "}}";
|
|
859
1152
|
this.startLen = this.exprStart.length;
|
|
@@ -864,8 +1157,14 @@ var TemplateParser_TemplateParser = /*#__PURE__*/ function() {
|
|
|
864
1157
|
{
|
|
865
1158
|
key: "parse",
|
|
866
1159
|
value: function(template) {
|
|
1160
|
+
var _this = this;
|
|
867
1161
|
if ("string" != typeof template) throw new TypeError("模板必须是字符串");
|
|
1162
|
+
if (template.length > this.maxTemplateLength) throw new RangeError("Template exceeds the maximum length of ".concat(this.maxTemplateLength, " characters"));
|
|
868
1163
|
var tokens = [];
|
|
1164
|
+
var pushToken = function(token) {
|
|
1165
|
+
if (tokens.length >= _this.maxTokens) throw new RangeError("Template exceeds the maximum token count of ".concat(_this.maxTokens));
|
|
1166
|
+
tokens.push(token);
|
|
1167
|
+
};
|
|
869
1168
|
var length = template.length;
|
|
870
1169
|
var state = "TEXT";
|
|
871
1170
|
var buffer = "";
|
|
@@ -878,7 +1177,7 @@ var TemplateParser_TemplateParser = /*#__PURE__*/ function() {
|
|
|
878
1177
|
case "TEXT":
|
|
879
1178
|
if (this._isMatch(pos, template, this.exprStart)) {
|
|
880
1179
|
if (buffer.length > 0) {
|
|
881
|
-
|
|
1180
|
+
pushToken({
|
|
882
1181
|
type: "text",
|
|
883
1182
|
value: buffer,
|
|
884
1183
|
start: pos - buffer.length,
|
|
@@ -900,7 +1199,7 @@ var TemplateParser_TemplateParser = /*#__PURE__*/ function() {
|
|
|
900
1199
|
else if ("\\" === char) state = "'" === nextChar ? "ESCAPE_SQ" : '"' === nextChar ? "ESCAPE_DQ" : "`" === nextChar ? "ESCAPE_TEMPLATE" : "ESCAPE_EXPR";
|
|
901
1200
|
else if (this._isMatch(pos, template, this.exprEnd)) {
|
|
902
1201
|
var exprValue = this.preserveWhitespace ? buffer : buffer.trim();
|
|
903
|
-
if (exprValue.length > 0)
|
|
1202
|
+
if (exprValue.length > 0) pushToken({
|
|
904
1203
|
type: "expression",
|
|
905
1204
|
value: exprValue,
|
|
906
1205
|
start: exprStartPos,
|
|
@@ -949,7 +1248,7 @@ var TemplateParser_TemplateParser = /*#__PURE__*/ function() {
|
|
|
949
1248
|
}
|
|
950
1249
|
pos++;
|
|
951
1250
|
}
|
|
952
|
-
if (buffer.length > 0) if ("TEXT" === state)
|
|
1251
|
+
if (buffer.length > 0) if ("TEXT" === state) pushToken({
|
|
953
1252
|
type: "text",
|
|
954
1253
|
value: buffer,
|
|
955
1254
|
start: pos - buffer.length,
|
|
@@ -957,13 +1256,12 @@ var TemplateParser_TemplateParser = /*#__PURE__*/ function() {
|
|
|
957
1256
|
});
|
|
958
1257
|
else {
|
|
959
1258
|
var incompleteExpr = this.exprStart + buffer;
|
|
960
|
-
|
|
1259
|
+
pushToken({
|
|
961
1260
|
type: "text",
|
|
962
1261
|
value: incompleteExpr,
|
|
963
1262
|
start: exprStartPos,
|
|
964
1263
|
end: pos
|
|
965
1264
|
});
|
|
966
|
-
console.warn("警告:在位置 ".concat(exprStartPos, " 开始的表达式未正确结束"));
|
|
967
1265
|
}
|
|
968
1266
|
return tokens;
|
|
969
1267
|
}
|
|
@@ -991,18 +1289,36 @@ function src_instanceof(left, right) {
|
|
|
991
1289
|
if (null != right && "undefined" != typeof Symbol && right[Symbol.hasInstance]) return !!right[Symbol.hasInstance](left);
|
|
992
1290
|
return left instanceof right;
|
|
993
1291
|
}
|
|
1292
|
+
var DEFAULT_MAX_TEMPLATE_EXPRESSIONS = 100;
|
|
1293
|
+
var MAX_TEMPLATE_EXPRESSIONS = 1000;
|
|
1294
|
+
var DEFAULT_MAX_TEMPLATE_OUTPUT_LENGTH = 100000;
|
|
1295
|
+
var MAX_TEMPLATE_OUTPUT_LENGTH = 1000000;
|
|
1296
|
+
function src_validateLimit(value, name, defaultValue, maximum) {
|
|
1297
|
+
if (void 0 === value) return defaultValue;
|
|
1298
|
+
if (!Number.isSafeInteger(value) || value < 1 || value > maximum) throw new RangeError("".concat(name, " must be an integer between 1 and ").concat(maximum));
|
|
1299
|
+
return value;
|
|
1300
|
+
}
|
|
994
1301
|
function evalExpression(expression, context) {
|
|
995
1302
|
return Evaluator_Evaluator.evaluate(expression, context);
|
|
996
1303
|
}
|
|
997
1304
|
function evalTemplate(template, context, templateParserOptions) {
|
|
1305
|
+
var options = null != templateParserOptions ? templateParserOptions : {};
|
|
1306
|
+
var maxExpressions = src_validateLimit(options.maxExpressions, "maxExpressions", DEFAULT_MAX_TEMPLATE_EXPRESSIONS, MAX_TEMPLATE_EXPRESSIONS);
|
|
1307
|
+
var maxOutputLength = src_validateLimit(options.maxOutputLength, "maxOutputLength", DEFAULT_MAX_TEMPLATE_OUTPUT_LENGTH, MAX_TEMPLATE_OUTPUT_LENGTH);
|
|
1308
|
+
var tokens = TemplateParser_TemplateParser.parse(template, options);
|
|
998
1309
|
var result = "";
|
|
1310
|
+
var expressionCount = 0;
|
|
1311
|
+
var evaluator = new Evaluator_Evaluator(context, {
|
|
1312
|
+
maxInputLength: options.maxExpressionLength,
|
|
1313
|
+
maxEvaluationSteps: options.maxEvaluationSteps
|
|
1314
|
+
});
|
|
999
1315
|
var typeHandler = {
|
|
1000
1316
|
text: function(token) {
|
|
1001
1317
|
return token.value;
|
|
1002
1318
|
},
|
|
1003
1319
|
expression: function(token) {
|
|
1004
1320
|
try {
|
|
1005
|
-
return
|
|
1321
|
+
return evaluator.evaluate(token.value);
|
|
1006
1322
|
} catch (error) {
|
|
1007
1323
|
if (src_instanceof(error, ReferenceError) && error.message.endsWith("is not defined")) return "undefined";
|
|
1008
1324
|
throw error;
|
|
@@ -1011,11 +1327,17 @@ function evalTemplate(template, context, templateParserOptions) {
|
|
|
1011
1327
|
};
|
|
1012
1328
|
var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = void 0;
|
|
1013
1329
|
try {
|
|
1014
|
-
for(var _iterator =
|
|
1330
|
+
for(var _iterator = tokens[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
|
|
1015
1331
|
var token = _step.value;
|
|
1016
1332
|
var _typeHandler_token_type;
|
|
1017
1333
|
var handler = null != (_typeHandler_token_type = typeHandler[token.type]) ? _typeHandler_token_type : typeHandler["text"];
|
|
1018
|
-
|
|
1334
|
+
if ("expression" === token.type) {
|
|
1335
|
+
expressionCount++;
|
|
1336
|
+
if (expressionCount > maxExpressions) throw new RangeError("Template exceeds the maximum expression count of ".concat(maxExpressions));
|
|
1337
|
+
}
|
|
1338
|
+
var chunk = String(handler(token));
|
|
1339
|
+
if (result.length + chunk.length > maxOutputLength) throw new RangeError("Template output exceeds the maximum length of ".concat(maxOutputLength, " characters"));
|
|
1340
|
+
result += chunk;
|
|
1019
1341
|
}
|
|
1020
1342
|
} catch (err) {
|
|
1021
1343
|
_didIteratorError = true;
|