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.
@@ -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
- "Object.getOwnPropertyDescriptors"
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
- structuredClone(variables),
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
- return result;
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 object = this.visit(node.object);
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
  ]));
@@ -692,30 +887,52 @@ var Evaluator_Evaluator = /*#__PURE__*/ function() {
692
887
  var result = [];
693
888
  for(var i = 0; i < node.elements.length; i++){
694
889
  var element = node.elements.at(i);
890
+ if (null === element) {
891
+ result.length++;
892
+ continue;
893
+ }
695
894
  var value = this.visit(element);
696
895
  if ("SpreadElement" === element.type) {
697
896
  var _result;
897
+ this.assertBoundedSpread(result.length, value);
698
898
  (_result = result).push.apply(_result, Evaluator_to_consumable_array(value));
699
899
  } else result.push(value);
700
900
  }
701
901
  return result;
702
902
  }
703
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
+ },
704
911
  {
705
912
  key: "handleObjectExpression",
706
913
  value: function(node) {
707
914
  var obj = {};
915
+ var spreadPropertyCount = 0;
708
916
  var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = void 0;
709
917
  try {
710
918
  for(var _iterator = node.properties[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
711
919
  var prop = _step.value;
712
920
  if ("SpreadElement" === prop.type) {
713
- Object.assign(obj, this.visit(prop.argument));
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);
714
925
  continue;
715
926
  }
716
- var key = prop.key.name || prop.key.value;
927
+ var key = prop.computed ? this.visit(prop.key) : prop.key.name || prop.key.value;
717
928
  var value = this.visit(prop.value);
718
- obj[key] = value;
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;
719
936
  }
720
937
  } catch (err) {
721
938
  _didIteratorError = true;
@@ -746,22 +963,43 @@ var Evaluator_Evaluator = /*#__PURE__*/ function() {
746
963
  var paramCount = node.params.length;
747
964
  for(var i = 0; i < paramCount; i++)newScope[node.params[i].name] = args[i];
748
965
  _this.scopes.unshift(newScope);
749
- var result = _this.visit(node.body);
750
- _this.scopes.shift();
751
- return result;
966
+ try {
967
+ var result = _this.visit(node.body);
968
+ _this.consumeEvaluationValue(result);
969
+ return result;
970
+ } finally{
971
+ _this.scopes.shift();
972
+ }
752
973
  };
753
974
  }
754
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
+ },
755
985
  {
756
986
  key: "handleCallExpression",
757
987
  value: function(node) {
758
988
  var _this = this;
759
- var func = this.visit(node.callee);
760
- var isOptional = node.optional || node.callee.optional;
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);
761
996
  if (null == func && isOptional) return;
762
997
  if (func === Function) throw new Error(renderErrorMessage(ERROR_MESSAGES.IS_NOT_ALLOWED, [
763
998
  "Function constructor"
764
999
  ]));
1000
+ if (func === Error.prepareStackTrace) throw new Error(renderErrorMessage(ERROR_MESSAGES.IS_NOT_ALLOWED, [
1001
+ "Error.prepareStackTrace"
1002
+ ]));
765
1003
  if (getBlockedMethods().has(func)) {
766
1004
  var path = getBlockedMethods().get(func);
767
1005
  throw new Error(renderErrorMessage(ERROR_MESSAGES.IS_NOT_ALLOWED, [
@@ -776,24 +1014,56 @@ var Evaluator_Evaluator = /*#__PURE__*/ function() {
776
1014
  var value = _this.visit(element);
777
1015
  if ("SpreadElement" === element.type) {
778
1016
  var _result;
1017
+ _this.assertBoundedSpread(result.length, value);
779
1018
  (_result = result).push.apply(_result, Evaluator_to_consumable_array(value));
780
1019
  } else result.push(value);
781
1020
  }
782
1021
  return result;
783
1022
  }();
784
- var target = "MemberExpression" === node.callee.type ? this.visit(node.callee.object) : null;
785
1023
  if (args.some(function(arg) {
786
1024
  return arg === Function;
787
1025
  })) throw new Error(renderErrorMessage(ERROR_MESSAGES.IS_NOT_ALLOWED, [
788
1026
  "Function constructor"
789
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
+ }
790
1056
  if ("function" != typeof func) {
791
1057
  var calledString = getNodeString(node.callee);
792
1058
  throw new TypeError(renderErrorMessage(ERROR_MESSAGES.IS_NOT_FUNCTION, [
793
1059
  calledString
794
1060
  ]));
795
1061
  }
796
- return func.apply(target, args);
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;
797
1067
  }
798
1068
  },
799
1069
  {
@@ -858,11 +1128,25 @@ function TemplateParser_create_class(Constructor, protoProps, staticProps) {
858
1128
  if (staticProps) TemplateParser_defineProperties(Constructor, staticProps);
859
1129
  return Constructor;
860
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
+ }
861
1140
  var TemplateParser_TemplateParser = /*#__PURE__*/ function() {
862
1141
  "use strict";
863
1142
  function TemplateParser() {
864
1143
  var options = arguments.length > 0 && void 0 !== arguments[0] ? arguments[0] : {};
865
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");
866
1150
  this.exprStart = options.expressionStart || "{{";
867
1151
  this.exprEnd = options.expressionEnd || "}}";
868
1152
  this.startLen = this.exprStart.length;
@@ -873,8 +1157,14 @@ var TemplateParser_TemplateParser = /*#__PURE__*/ function() {
873
1157
  {
874
1158
  key: "parse",
875
1159
  value: function(template) {
1160
+ var _this = this;
876
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"));
877
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
+ };
878
1168
  var length = template.length;
879
1169
  var state = "TEXT";
880
1170
  var buffer = "";
@@ -887,7 +1177,7 @@ var TemplateParser_TemplateParser = /*#__PURE__*/ function() {
887
1177
  case "TEXT":
888
1178
  if (this._isMatch(pos, template, this.exprStart)) {
889
1179
  if (buffer.length > 0) {
890
- tokens.push({
1180
+ pushToken({
891
1181
  type: "text",
892
1182
  value: buffer,
893
1183
  start: pos - buffer.length,
@@ -909,7 +1199,7 @@ var TemplateParser_TemplateParser = /*#__PURE__*/ function() {
909
1199
  else if ("\\" === char) state = "'" === nextChar ? "ESCAPE_SQ" : '"' === nextChar ? "ESCAPE_DQ" : "`" === nextChar ? "ESCAPE_TEMPLATE" : "ESCAPE_EXPR";
910
1200
  else if (this._isMatch(pos, template, this.exprEnd)) {
911
1201
  var exprValue = this.preserveWhitespace ? buffer : buffer.trim();
912
- if (exprValue.length > 0) tokens.push({
1202
+ if (exprValue.length > 0) pushToken({
913
1203
  type: "expression",
914
1204
  value: exprValue,
915
1205
  start: exprStartPos,
@@ -958,7 +1248,7 @@ var TemplateParser_TemplateParser = /*#__PURE__*/ function() {
958
1248
  }
959
1249
  pos++;
960
1250
  }
961
- if (buffer.length > 0) if ("TEXT" === state) tokens.push({
1251
+ if (buffer.length > 0) if ("TEXT" === state) pushToken({
962
1252
  type: "text",
963
1253
  value: buffer,
964
1254
  start: pos - buffer.length,
@@ -966,13 +1256,12 @@ var TemplateParser_TemplateParser = /*#__PURE__*/ function() {
966
1256
  });
967
1257
  else {
968
1258
  var incompleteExpr = this.exprStart + buffer;
969
- tokens.push({
1259
+ pushToken({
970
1260
  type: "text",
971
1261
  value: incompleteExpr,
972
1262
  start: exprStartPos,
973
1263
  end: pos
974
1264
  });
975
- console.warn("警告:在位置 ".concat(exprStartPos, " 开始的表达式未正确结束"));
976
1265
  }
977
1266
  return tokens;
978
1267
  }
@@ -1000,18 +1289,36 @@ function src_instanceof(left, right) {
1000
1289
  if (null != right && "undefined" != typeof Symbol && right[Symbol.hasInstance]) return !!right[Symbol.hasInstance](left);
1001
1290
  return left instanceof right;
1002
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
+ }
1003
1301
  function evalExpression(expression, context) {
1004
1302
  return Evaluator_Evaluator.evaluate(expression, context);
1005
1303
  }
1006
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);
1007
1309
  var result = "";
1310
+ var expressionCount = 0;
1311
+ var evaluator = new Evaluator_Evaluator(context, {
1312
+ maxInputLength: options.maxExpressionLength,
1313
+ maxEvaluationSteps: options.maxEvaluationSteps
1314
+ });
1008
1315
  var typeHandler = {
1009
1316
  text: function(token) {
1010
1317
  return token.value;
1011
1318
  },
1012
1319
  expression: function(token) {
1013
1320
  try {
1014
- return Evaluator_Evaluator.evaluate(token.value, context);
1321
+ return evaluator.evaluate(token.value);
1015
1322
  } catch (error) {
1016
1323
  if (src_instanceof(error, ReferenceError) && error.message.endsWith("is not defined")) return "undefined";
1017
1324
  throw error;
@@ -1020,11 +1327,17 @@ function evalTemplate(template, context, templateParserOptions) {
1020
1327
  };
1021
1328
  var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = void 0;
1022
1329
  try {
1023
- for(var _iterator = TemplateParser_TemplateParser.parse(template, templateParserOptions)[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
1330
+ for(var _iterator = tokens[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
1024
1331
  var token = _step.value;
1025
1332
  var _typeHandler_token_type;
1026
1333
  var handler = null != (_typeHandler_token_type = typeHandler[token.type]) ? _typeHandler_token_type : typeHandler["text"];
1027
- result += handler(token);
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;
1028
1341
  }
1029
1342
  } catch (err) {
1030
1343
  _didIteratorError = true;