Engine.cs 50 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Runtime.CompilerServices;
  4. using Esprima;
  5. using Esprima.Ast;
  6. using Jint.Native;
  7. using Jint.Native.Argument;
  8. using Jint.Native.Array;
  9. using Jint.Native.Boolean;
  10. using Jint.Native.Date;
  11. using Jint.Native.Error;
  12. using Jint.Native.Function;
  13. using Jint.Native.Global;
  14. using Jint.Native.Iterator;
  15. using Jint.Native.Json;
  16. using Jint.Native.Map;
  17. using Jint.Native.Math;
  18. using Jint.Native.Number;
  19. using Jint.Native.Object;
  20. using Jint.Native.Proxy;
  21. using Jint.Native.Reflect;
  22. using Jint.Native.RegExp;
  23. using Jint.Native.Set;
  24. using Jint.Native.String;
  25. using Jint.Native.Symbol;
  26. using Jint.Pooling;
  27. using Jint.Runtime;
  28. using Jint.Runtime.CallStack;
  29. using Jint.Runtime.Debugger;
  30. using Jint.Runtime.Descriptors;
  31. using Jint.Runtime.Environments;
  32. using Jint.Runtime.Interop;
  33. using Jint.Runtime.Interop.Reflection;
  34. using Jint.Runtime.Interpreter;
  35. using Jint.Runtime.Interpreter.Expressions;
  36. using Jint.Runtime.References;
  37. namespace Jint
  38. {
  39. public class Engine
  40. {
  41. internal static readonly ParserOptions DefaultParserOptions = new("<anonymous>")
  42. {
  43. AdaptRegexp = true,
  44. Tolerant = true,
  45. Loc = true
  46. };
  47. private static readonly JsString _errorFunctionName = new JsString("Error");
  48. private static readonly JsString _evalErrorFunctionName = new JsString("EvalError");
  49. private static readonly JsString _rangeErrorFunctionName = new JsString("RangeError");
  50. private static readonly JsString _referenceErrorFunctionName = new JsString("ReferenceError");
  51. private static readonly JsString _syntaxErrorFunctionName = new JsString("SyntaxError");
  52. private static readonly JsString _typeErrorFunctionName = new JsString("TypeError");
  53. private static readonly JsString _uriErrorFunctionName = new JsString("URIError");
  54. private readonly ExecutionContextStack _executionContexts;
  55. private JsValue _completionValue = JsValue.Undefined;
  56. internal Node _lastSyntaxNode;
  57. // lazy properties
  58. private ErrorConstructor _error;
  59. private ErrorConstructor _evalError;
  60. private ErrorConstructor _rangeError;
  61. private ErrorConstructor _referenceError;
  62. private ErrorConstructor _syntaxError;
  63. private ErrorConstructor _typeError;
  64. private ErrorConstructor _uriError;
  65. private DebugHandler _debugHandler;
  66. private List<BreakPoint> _breakPoints;
  67. // cached access
  68. private readonly List<IConstraint> _constraints;
  69. private readonly bool _isDebugMode;
  70. internal readonly bool _isStrict;
  71. internal readonly IReferenceResolver _referenceResolver;
  72. internal readonly ReferencePool _referencePool;
  73. internal readonly ArgumentsInstancePool _argumentsInstancePool;
  74. internal readonly JsValueArrayPool _jsValueArrayPool;
  75. public ITypeConverter ClrTypeConverter { get; internal set; }
  76. // cache of types used when resolving CLR type names
  77. internal readonly Dictionary<string, Type> TypeCache = new();
  78. internal static Dictionary<Type, Func<Engine, object, JsValue>> TypeMappers = new()
  79. {
  80. { typeof(bool), (engine, v) => (bool) v ? JsBoolean.True : JsBoolean.False },
  81. { typeof(byte), (engine, v) => JsNumber.Create((byte)v) },
  82. { typeof(char), (engine, v) => JsString.Create((char)v) },
  83. { typeof(DateTime), (engine, v) => engine.Date.Construct((DateTime)v) },
  84. { typeof(DateTimeOffset), (engine, v) => engine.Date.Construct((DateTimeOffset)v) },
  85. { typeof(decimal), (engine, v) => (JsValue) (double)(decimal)v },
  86. { typeof(double), (engine, v) => (JsValue)(double)v },
  87. { typeof(Int16), (engine, v) => JsNumber.Create((Int16)v) },
  88. { typeof(Int32), (engine, v) => JsNumber.Create((Int32)v) },
  89. { typeof(Int64), (engine, v) => (JsValue)(Int64)v },
  90. { typeof(SByte), (engine, v) => JsNumber.Create((SByte)v) },
  91. { typeof(Single), (engine, v) => (JsValue)(Single)v },
  92. { typeof(string), (engine, v) => JsString.Create((string) v) },
  93. { typeof(UInt16), (engine, v) => JsNumber.Create((UInt16)v) },
  94. { typeof(UInt32), (engine, v) => JsNumber.Create((UInt32)v) },
  95. { typeof(UInt64), (engine, v) => JsNumber.Create((UInt64)v) },
  96. { typeof(System.Text.RegularExpressions.Regex), (engine, v) => engine.RegExp.Construct((System.Text.RegularExpressions.Regex)v, "") }
  97. };
  98. // shared frozen version
  99. internal readonly PropertyDescriptor _callerCalleeArgumentsThrowerConfigurable;
  100. internal readonly PropertyDescriptor _callerCalleeArgumentsThrowerNonConfigurable;
  101. internal static Dictionary<ClrPropertyDescriptorFactoriesKey, ReflectionAccessor> ReflectionAccessors = new();
  102. internal readonly JintCallStack CallStack;
  103. /// <summary>
  104. /// Constructs a new engine instance.
  105. /// </summary>
  106. public Engine() : this((Action<Options>) null)
  107. {
  108. }
  109. /// <summary>
  110. /// Constructs a new engine instance and allows customizing options.
  111. /// </summary>
  112. public Engine(Action<Options> options)
  113. : this((engine, opts) => options?.Invoke(opts))
  114. {
  115. }
  116. /// <summary>
  117. /// Constructs a new engine with a custom <see cref="Options"/> instance.
  118. /// </summary>
  119. public Engine(Options options) : this((e, o) => e.Options = options)
  120. {
  121. }
  122. /// <summary>
  123. /// Constructs a new engine instance and allows customizing options.
  124. /// </summary>
  125. /// <remarks>The provided engine instance in callback is not guaranteed to be fully configured</remarks>
  126. public Engine(Action<Engine, Options> options)
  127. {
  128. _executionContexts = new ExecutionContextStack(2);
  129. Global = GlobalObject.CreateGlobalObject(this);
  130. Object = ObjectConstructor.CreateObjectConstructor(this);
  131. Function = FunctionConstructor.CreateFunctionConstructor(this);
  132. _callerCalleeArgumentsThrowerConfigurable = new GetSetPropertyDescriptor.ThrowerPropertyDescriptor(this, PropertyFlag.Configurable | PropertyFlag.CustomJsValue, "'caller', 'callee', and 'arguments' properties may not be accessed on strict mode functions or the arguments objects for calls to them");
  133. _callerCalleeArgumentsThrowerNonConfigurable = new GetSetPropertyDescriptor.ThrowerPropertyDescriptor(this, PropertyFlag.CustomJsValue, "'caller', 'callee', and 'arguments' properties may not be accessed on strict mode functions or the arguments objects for calls to them");
  134. Symbol = SymbolConstructor.CreateSymbolConstructor(this);
  135. Array = ArrayConstructor.CreateArrayConstructor(this);
  136. Map = MapConstructor.CreateMapConstructor(this);
  137. Set = SetConstructor.CreateSetConstructor(this);
  138. Iterator = IteratorConstructor.CreateIteratorConstructor(this);
  139. String = StringConstructor.CreateStringConstructor(this);
  140. RegExp = RegExpConstructor.CreateRegExpConstructor(this);
  141. Number = NumberConstructor.CreateNumberConstructor(this);
  142. Boolean = BooleanConstructor.CreateBooleanConstructor(this);
  143. Date = DateConstructor.CreateDateConstructor(this);
  144. Math = MathInstance.CreateMathObject(this);
  145. Json = JsonInstance.CreateJsonObject(this);
  146. Proxy = ProxyConstructor.CreateProxyConstructor(this);
  147. Reflect = ReflectInstance.CreateReflectObject(this);
  148. GlobalSymbolRegistry = new GlobalSymbolRegistry();
  149. // Because the properties might need some of the built-in object
  150. // their configuration is delayed to a later step
  151. // trigger initialization
  152. Global.EnsureInitialized();
  153. // this is implementation dependent, and only to pass some unit tests
  154. Global._prototype = Object.PrototypeObject;
  155. Object._prototype = Function.PrototypeObject;
  156. // create the global environment http://www.ecma-international.org/ecma-262/5.1/#sec-10.2.3
  157. GlobalEnvironment = LexicalEnvironment.NewGlobalEnvironment(this, Global);
  158. // create the global execution context http://www.ecma-international.org/ecma-262/5.1/#sec-10.4.1.1
  159. EnterExecutionContext(GlobalEnvironment, GlobalEnvironment);
  160. Eval = new EvalFunctionInstance(this);
  161. Global.SetProperty(CommonProperties.Eval, new PropertyDescriptor(Eval, PropertyFlag.Configurable | PropertyFlag.Writable));
  162. Options = new Options();
  163. options?.Invoke(this, Options);
  164. // gather some options as fields for faster checks
  165. _isDebugMode = Options.IsDebugMode;
  166. _isStrict = Options.IsStrict;
  167. _constraints = Options._Constraints;
  168. _referenceResolver = Options.ReferenceResolver;
  169. CallStack = new JintCallStack(Options.MaxRecursionDepth >= 0);
  170. _referencePool = new ReferencePool();
  171. _argumentsInstancePool = new ArgumentsInstancePool(this);
  172. _jsValueArrayPool = new JsValueArrayPool();
  173. Options.Apply(this);
  174. }
  175. internal LexicalEnvironment GlobalEnvironment { get; }
  176. public GlobalObject Global { get; }
  177. public ObjectConstructor Object { get; }
  178. public FunctionConstructor Function { get; }
  179. public ArrayConstructor Array { get; }
  180. public MapConstructor Map { get; }
  181. public SetConstructor Set { get; }
  182. public IteratorConstructor Iterator { get; }
  183. public StringConstructor String { get; }
  184. public RegExpConstructor RegExp { get; }
  185. public BooleanConstructor Boolean { get; }
  186. public NumberConstructor Number { get; }
  187. public DateConstructor Date { get; }
  188. public MathInstance Math { get; }
  189. public JsonInstance Json { get; }
  190. public ProxyConstructor Proxy { get; }
  191. public ReflectInstance Reflect { get; }
  192. public SymbolConstructor Symbol { get; }
  193. public EvalFunctionInstance Eval { get; }
  194. public ErrorConstructor Error => _error ??= ErrorConstructor.CreateErrorConstructor(this, _errorFunctionName);
  195. public ErrorConstructor EvalError => _evalError ??= ErrorConstructor.CreateErrorConstructor(this, _evalErrorFunctionName);
  196. public ErrorConstructor SyntaxError => _syntaxError ??= ErrorConstructor.CreateErrorConstructor(this, _syntaxErrorFunctionName);
  197. public ErrorConstructor TypeError => _typeError ??= ErrorConstructor.CreateErrorConstructor(this, _typeErrorFunctionName);
  198. public ErrorConstructor RangeError => _rangeError ??= ErrorConstructor.CreateErrorConstructor(this, _rangeErrorFunctionName);
  199. public ErrorConstructor ReferenceError => _referenceError ??= ErrorConstructor.CreateErrorConstructor(this, _referenceErrorFunctionName);
  200. public ErrorConstructor UriError => _uriError ??= ErrorConstructor.CreateErrorConstructor(this, _uriErrorFunctionName);
  201. public ref readonly ExecutionContext ExecutionContext
  202. {
  203. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  204. get => ref _executionContexts.Peek();
  205. }
  206. public GlobalSymbolRegistry GlobalSymbolRegistry { get; }
  207. internal long CurrentMemoryUsage { get; private set; }
  208. internal Options Options { [MethodImpl(MethodImplOptions.AggressiveInlining)] get; private set; }
  209. #region Debugger
  210. public delegate StepMode DebugStepDelegate(object sender, DebugInformation e);
  211. public delegate StepMode BreakDelegate(object sender, DebugInformation e);
  212. public event DebugStepDelegate Step;
  213. public event BreakDelegate Break;
  214. internal DebugHandler DebugHandler => _debugHandler ??= new DebugHandler(this);
  215. public List<BreakPoint> BreakPoints => _breakPoints ??= new List<BreakPoint>();
  216. internal StepMode? InvokeStepEvent(DebugInformation info)
  217. {
  218. return Step?.Invoke(this, info);
  219. }
  220. internal StepMode? InvokeBreakEvent(DebugInformation info)
  221. {
  222. return Break?.Invoke(this, info);
  223. }
  224. #endregion
  225. public ExecutionContext EnterExecutionContext(
  226. LexicalEnvironment lexicalEnvironment,
  227. LexicalEnvironment variableEnvironment)
  228. {
  229. var context = new ExecutionContext(
  230. lexicalEnvironment,
  231. variableEnvironment);
  232. _executionContexts.Push(context);
  233. return context;
  234. }
  235. public Engine SetValue(JsValue name, Delegate value)
  236. {
  237. Global.FastAddProperty(name, new DelegateWrapper(this, value), true, false, true);
  238. return this;
  239. }
  240. public Engine SetValue(JsValue name, string value)
  241. {
  242. return SetValue(name, new JsString(value));
  243. }
  244. public Engine SetValue(JsValue name, double value)
  245. {
  246. return SetValue(name, JsNumber.Create(value));
  247. }
  248. public Engine SetValue(JsValue name, int value)
  249. {
  250. return SetValue(name, JsNumber.Create(value));
  251. }
  252. public Engine SetValue(JsValue name, bool value)
  253. {
  254. return SetValue(name, value ? JsBoolean.True : JsBoolean.False);
  255. }
  256. public Engine SetValue(JsValue name, JsValue value)
  257. {
  258. Global.Set(name, value, Global);
  259. return this;
  260. }
  261. public Engine SetValue(JsValue name, object obj)
  262. {
  263. return SetValue(name, JsValue.FromObject(this, obj));
  264. }
  265. public void LeaveExecutionContext()
  266. {
  267. _executionContexts.Pop();
  268. }
  269. /// <summary>
  270. /// Initializes the statements count
  271. /// </summary>
  272. public void ResetConstraints()
  273. {
  274. for (var i = 0; i < _constraints.Count; i++)
  275. {
  276. _constraints[i].Reset();
  277. }
  278. }
  279. /// <summary>
  280. /// Initializes list of references of called functions
  281. /// </summary>
  282. public void ResetCallStack()
  283. {
  284. CallStack.Clear();
  285. }
  286. public Engine Execute(string source)
  287. {
  288. return Execute(source, DefaultParserOptions);
  289. }
  290. public Engine Execute(string source, ParserOptions parserOptions)
  291. {
  292. var parser = new JavaScriptParser(source, parserOptions);
  293. return Execute(parser.ParseScript());
  294. }
  295. public Engine Execute(Script script)
  296. {
  297. return Execute(script, true);
  298. }
  299. internal Engine Execute(Script script, bool resetState)
  300. {
  301. if (resetState)
  302. {
  303. ResetConstraints();
  304. ResetLastStatement();
  305. ResetCallStack();
  306. }
  307. using (new StrictModeScope(_isStrict || script.Strict))
  308. {
  309. GlobalDeclarationInstantiation(
  310. script,
  311. GlobalEnvironment);
  312. var list = new JintStatementList(this, null, script.Body);
  313. var result = list.Execute();
  314. if (result.Type == CompletionType.Throw)
  315. {
  316. var ex = new JavaScriptException(result.GetValueOrDefault()).SetCallstack(this, result.Location);
  317. throw ex;
  318. }
  319. _completionValue = result.GetValueOrDefault();
  320. }
  321. return this;
  322. }
  323. private void ResetLastStatement()
  324. {
  325. _lastSyntaxNode = null;
  326. }
  327. /// <summary>
  328. /// Gets the last evaluated statement completion value
  329. /// </summary>
  330. public JsValue GetCompletionValue()
  331. {
  332. return _completionValue;
  333. }
  334. internal void RunBeforeExecuteStatementChecks(Statement statement)
  335. {
  336. // Avoid allocating the enumerator because we run this loop very often.
  337. for (var i = 0; i < _constraints.Count; i++)
  338. {
  339. _constraints[i].Check();
  340. }
  341. if (_isDebugMode)
  342. {
  343. DebugHandler.OnStep(statement);
  344. }
  345. }
  346. /// <summary>
  347. /// http://www.ecma-international.org/ecma-262/5.1/#sec-8.7.1
  348. /// </summary>
  349. public JsValue GetValue(object value)
  350. {
  351. return GetValue(value, false);
  352. }
  353. internal JsValue GetValue(object value, bool returnReferenceToPool)
  354. {
  355. if (value is JsValue jsValue)
  356. {
  357. return jsValue;
  358. }
  359. if (!(value is Reference reference))
  360. {
  361. return ((Completion) value).Value;
  362. }
  363. return GetValue(reference, returnReferenceToPool);
  364. }
  365. internal JsValue GetValue(Reference reference, bool returnReferenceToPool)
  366. {
  367. var baseValue = reference.GetBase();
  368. if (baseValue._type == InternalTypes.Undefined)
  369. {
  370. if (_referenceResolver.TryUnresolvableReference(this, reference, out JsValue val))
  371. {
  372. return val;
  373. }
  374. ExceptionHelper.ThrowReferenceError(this, reference);
  375. }
  376. if ((baseValue._type & InternalTypes.ObjectEnvironmentRecord) == 0
  377. && _referenceResolver.TryPropertyReference(this, reference, ref baseValue))
  378. {
  379. return baseValue;
  380. }
  381. if (reference.IsPropertyReference())
  382. {
  383. var property = reference.GetReferencedName();
  384. if (returnReferenceToPool)
  385. {
  386. _referencePool.Return(reference);
  387. }
  388. if (baseValue.IsObject())
  389. {
  390. var o = TypeConverter.ToObject(this, baseValue);
  391. var v = o.Get(property, reference.GetThisValue());
  392. return v;
  393. }
  394. else
  395. {
  396. // check if we are accessing a string, boxing operation can be costly to do index access
  397. // we have good chance to have fast path with integer or string indexer
  398. ObjectInstance o = null;
  399. if ((property._type & (InternalTypes.String | InternalTypes.Integer)) != 0
  400. && baseValue is JsString s
  401. && TryHandleStringValue(property, s, ref o, out var jsValue))
  402. {
  403. return jsValue;
  404. }
  405. if (o is null)
  406. {
  407. o = TypeConverter.ToObject(this, baseValue);
  408. }
  409. var desc = o.GetProperty(property);
  410. if (desc == PropertyDescriptor.Undefined)
  411. {
  412. return JsValue.Undefined;
  413. }
  414. if (desc.IsDataDescriptor())
  415. {
  416. return desc.Value;
  417. }
  418. var getter = desc.Get;
  419. if (getter.IsUndefined())
  420. {
  421. return Undefined.Instance;
  422. }
  423. var callable = (ICallable) getter.AsObject();
  424. return callable.Call(baseValue, Arguments.Empty);
  425. }
  426. }
  427. if (!(baseValue is EnvironmentRecord record))
  428. {
  429. return ExceptionHelper.ThrowArgumentException<JsValue>();
  430. }
  431. var bindingValue = record.GetBindingValue(reference.GetReferencedName().ToString(), reference.IsStrictReference());
  432. if (returnReferenceToPool)
  433. {
  434. _referencePool.Return(reference);
  435. }
  436. return bindingValue;
  437. }
  438. private bool TryHandleStringValue(JsValue property, JsString s, ref ObjectInstance o, out JsValue jsValue)
  439. {
  440. if (property == CommonProperties.Length)
  441. {
  442. jsValue = JsNumber.Create((uint) s.Length);
  443. return true;
  444. }
  445. if (property is JsNumber number && number.IsInteger())
  446. {
  447. var index = number.AsInteger();
  448. var str = s._value;
  449. if (index < 0 || index >= str.Length)
  450. {
  451. jsValue = JsValue.Undefined;
  452. return true;
  453. }
  454. jsValue = JsString.Create(str[index]);
  455. return true;
  456. }
  457. if (property is JsString propertyString
  458. && propertyString._value.Length > 0
  459. && char.IsLower(propertyString._value[0]))
  460. {
  461. // trying to find property that's always in prototype
  462. o = String.PrototypeObject;
  463. }
  464. jsValue = JsValue.Undefined;
  465. return false;
  466. }
  467. /// <summary>
  468. /// https://tc39.es/ecma262/#sec-putvalue
  469. /// </summary>
  470. internal void PutValue(Reference reference, JsValue value)
  471. {
  472. var baseValue = reference.GetBase();
  473. if (reference.IsUnresolvableReference())
  474. {
  475. if (reference.IsStrictReference())
  476. {
  477. ExceptionHelper.ThrowReferenceError(this, reference);
  478. }
  479. Global.Set(reference.GetReferencedName(), value, throwOnError: false);
  480. }
  481. else if (reference.IsPropertyReference())
  482. {
  483. if (reference.HasPrimitiveBase())
  484. {
  485. baseValue = TypeConverter.ToObject(this, baseValue);
  486. }
  487. var succeeded = baseValue.Set(reference.GetReferencedName(), value, reference.GetThisValue());
  488. if (!succeeded && reference.IsStrictReference())
  489. {
  490. ExceptionHelper.ThrowTypeError(this);
  491. }
  492. }
  493. else
  494. {
  495. ((EnvironmentRecord) baseValue).SetMutableBinding(TypeConverter.ToString(reference.GetReferencedName()), value, reference.IsStrictReference());
  496. }
  497. }
  498. /// <summary>
  499. /// http://www.ecma-international.org/ecma-262/6.0/#sec-initializereferencedbinding
  500. /// </summary>
  501. public void InitializeReferenceBinding(Reference reference, JsValue value)
  502. {
  503. var baseValue = (EnvironmentRecord) reference.GetBase();
  504. baseValue.InitializeBinding(TypeConverter.ToString(reference.GetReferencedName()), value);
  505. }
  506. /// <summary>
  507. /// Invoke the current value as function.
  508. /// </summary>
  509. /// <param name="propertyName">The name of the function to call.</param>
  510. /// <param name="arguments">The arguments of the function call.</param>
  511. /// <returns>The value returned by the function call.</returns>
  512. public JsValue Invoke(string propertyName, params object[] arguments)
  513. {
  514. return Invoke(propertyName, null, arguments);
  515. }
  516. /// <summary>
  517. /// Invoke the current value as function.
  518. /// </summary>
  519. /// <param name="propertyName">The name of the function to call.</param>
  520. /// <param name="thisObj">The this value inside the function call.</param>
  521. /// <param name="arguments">The arguments of the function call.</param>
  522. /// <returns>The value returned by the function call.</returns>
  523. public JsValue Invoke(string propertyName, object thisObj, object[] arguments)
  524. {
  525. var value = GetValue(propertyName);
  526. return Invoke(value, thisObj, arguments);
  527. }
  528. /// <summary>
  529. /// Invoke the current value as function.
  530. /// </summary>
  531. /// <param name="value">The function to call.</param>
  532. /// <param name="arguments">The arguments of the function call.</param>
  533. /// <returns>The value returned by the function call.</returns>
  534. public JsValue Invoke(JsValue value, params object[] arguments)
  535. {
  536. return Invoke(value, null, arguments);
  537. }
  538. /// <summary>
  539. /// Invoke the current value as function.
  540. /// </summary>
  541. /// <param name="value">The function to call.</param>
  542. /// <param name="thisObj">The this value inside the function call.</param>
  543. /// <param name="arguments">The arguments of the function call.</param>
  544. /// <returns>The value returned by the function call.</returns>
  545. public JsValue Invoke(JsValue value, object thisObj, object[] arguments)
  546. {
  547. var callable = value as ICallable ?? ExceptionHelper.ThrowTypeError<ICallable>(this, "Can only invoke functions");
  548. var items = _jsValueArrayPool.RentArray(arguments.Length);
  549. for (int i = 0; i < arguments.Length; ++i)
  550. {
  551. items[i] = JsValue.FromObject(this, arguments[i]);
  552. }
  553. var result = callable.Call(JsValue.FromObject(this, thisObj), items);
  554. _jsValueArrayPool.ReturnArray(items);
  555. return result;
  556. }
  557. /// <summary>
  558. /// Gets a named value from the Global scope.
  559. /// </summary>
  560. /// <param name="propertyName">The name of the property to return.</param>
  561. public JsValue GetValue(string propertyName)
  562. {
  563. return GetValue(Global, new JsString(propertyName));
  564. }
  565. /// <summary>
  566. /// Gets the last evaluated <see cref="Node"/>.
  567. /// </summary>
  568. internal Node GetLastSyntaxNode()
  569. {
  570. return _lastSyntaxNode;
  571. }
  572. /// <summary>
  573. /// Gets a named value from the specified scope.
  574. /// </summary>
  575. /// <param name="scope">The scope to get the property from.</param>
  576. /// <param name="property">The name of the property to return.</param>
  577. public JsValue GetValue(JsValue scope, JsValue property)
  578. {
  579. var reference = _referencePool.Rent(scope, property, _isStrict, thisValue: null);
  580. var jsValue = GetValue(reference, false);
  581. _referencePool.Return(reference);
  582. return jsValue;
  583. }
  584. /// <summary>
  585. /// https://tc39.es/ecma262/#sec-resolvebinding
  586. /// </summary>
  587. internal Reference ResolveBinding(string name, LexicalEnvironment env = null)
  588. {
  589. env ??= ExecutionContext.LexicalEnvironment;
  590. return GetIdentifierReference(env, name, StrictModeScope.IsStrictModeCode);
  591. }
  592. private Reference GetIdentifierReference(LexicalEnvironment env, string name, bool strict)
  593. {
  594. if (env is null)
  595. {
  596. return new Reference(JsValue.Undefined, name, strict);
  597. }
  598. var envRec = env._record;
  599. if (envRec.HasBinding(name))
  600. {
  601. return new Reference(envRec, name, strict);
  602. }
  603. return GetIdentifierReference(env._outer, name, strict);
  604. }
  605. /// <summary>
  606. /// https://tc39.es/ecma262/#sec-getthisenvironment
  607. /// </summary>
  608. internal EnvironmentRecord GetThisEnvironment()
  609. {
  610. // The loop will always terminate because the list of environments always
  611. // ends with the global environment which has a this binding.
  612. var lex = ExecutionContext.LexicalEnvironment;
  613. while (true)
  614. {
  615. var envRec = lex._record;
  616. var exists = envRec.HasThisBinding();
  617. if (exists)
  618. {
  619. return envRec;
  620. }
  621. var outer = lex._outer;
  622. lex = outer;
  623. }
  624. }
  625. /// <summary>
  626. /// https://tc39.es/ecma262/#sec-resolvethisbinding
  627. /// </summary>
  628. internal JsValue ResolveThisBinding()
  629. {
  630. var envRec = GetThisEnvironment();
  631. return envRec.GetThisBinding();
  632. }
  633. /// <summary>
  634. /// https://tc39.es/ecma262/#sec-globaldeclarationinstantiation
  635. /// </summary>
  636. private void GlobalDeclarationInstantiation(
  637. Script script,
  638. LexicalEnvironment env)
  639. {
  640. var envRec = (GlobalEnvironmentRecord) env._record;
  641. var hoistingScope = HoistingScope.GetProgramLevelDeclarations(script);
  642. var functionDeclarations = hoistingScope._functionDeclarations;
  643. var varDeclarations = hoistingScope._variablesDeclarations;
  644. var lexDeclarations = hoistingScope._lexicalDeclarations;
  645. var functionToInitialize = new LinkedList<FunctionDeclaration>();
  646. var declaredFunctionNames = new HashSet<string>();
  647. var declaredVarNames = new List<string>();
  648. if (functionDeclarations != null)
  649. {
  650. for (var i = functionDeclarations.Count - 1; i >= 0; i--)
  651. {
  652. var d = functionDeclarations[i];
  653. var fn = d.Id.Name;
  654. if (!declaredFunctionNames.Contains(fn))
  655. {
  656. var fnDefinable = envRec.CanDeclareGlobalFunction(fn);
  657. if (!fnDefinable)
  658. {
  659. ExceptionHelper.ThrowTypeError(this);
  660. }
  661. declaredFunctionNames.Add(fn);
  662. functionToInitialize.AddFirst(d);
  663. }
  664. }
  665. }
  666. var boundNames = new List<string>();
  667. if (varDeclarations != null)
  668. {
  669. for (var i = 0; i < varDeclarations.Count; i++)
  670. {
  671. var d = varDeclarations[i];
  672. boundNames.Clear();
  673. d.GetBoundNames(boundNames);
  674. for (var j = 0; j < boundNames.Count; j++)
  675. {
  676. var vn = boundNames[j];
  677. if (envRec.HasLexicalDeclaration(vn))
  678. {
  679. ExceptionHelper.ThrowSyntaxError(this, $"Identifier '{vn}' has already been declared");
  680. }
  681. if (!declaredFunctionNames.Contains(vn))
  682. {
  683. var vnDefinable = envRec.CanDeclareGlobalVar(vn);
  684. if (!vnDefinable)
  685. {
  686. ExceptionHelper.ThrowTypeError(this);
  687. }
  688. declaredVarNames.Add(vn);
  689. }
  690. }
  691. }
  692. }
  693. if (lexDeclarations != null)
  694. {
  695. for (var i = 0; i < lexDeclarations.Count; i++)
  696. {
  697. var d = lexDeclarations[i];
  698. boundNames.Clear();
  699. d.GetBoundNames(boundNames);
  700. for (var j = 0; j < boundNames.Count; j++)
  701. {
  702. var dn = boundNames[j];
  703. if (envRec.HasVarDeclaration(dn)
  704. || envRec.HasLexicalDeclaration(dn)
  705. || envRec.HasRestrictedGlobalProperty(dn))
  706. {
  707. ExceptionHelper.ThrowSyntaxError(this, $"Identifier '{dn}' has already been declared");
  708. }
  709. if (d.Kind == VariableDeclarationKind.Const)
  710. {
  711. envRec.CreateImmutableBinding(dn, strict: true);
  712. }
  713. else
  714. {
  715. envRec.CreateMutableBinding(dn, canBeDeleted: false);
  716. }
  717. }
  718. }
  719. }
  720. foreach (var f in functionToInitialize)
  721. {
  722. var fn = f.Id!.Name;
  723. if (envRec.HasLexicalDeclaration(fn))
  724. {
  725. ExceptionHelper.ThrowSyntaxError(this, $"Identifier '{fn}' has already been declared");
  726. }
  727. var fo = Function.CreateFunctionObject(f, env);
  728. envRec.CreateGlobalFunctionBinding(fn, fo, canBeDeleted: false);
  729. }
  730. for (var i = 0; i < declaredVarNames.Count; i++)
  731. {
  732. var vn = declaredVarNames[i];
  733. envRec.CreateGlobalVarBinding(vn, canBeDeleted: false);
  734. }
  735. }
  736. /// <summary>
  737. /// https://tc39.es/ecma262/#sec-functiondeclarationinstantiation
  738. /// </summary>
  739. internal ArgumentsInstance FunctionDeclarationInstantiation(
  740. FunctionInstance functionInstance,
  741. JsValue[] argumentsList,
  742. LexicalEnvironment env)
  743. {
  744. var func = functionInstance._functionDefinition;
  745. var envRec = (FunctionEnvironmentRecord) env._record;
  746. var strict = StrictModeScope.IsStrictModeCode;
  747. var configuration = func.Initialize(this, functionInstance);
  748. var parameterNames = configuration.ParameterNames;
  749. var hasDuplicates = configuration.HasDuplicates;
  750. var simpleParameterList = configuration.IsSimpleParameterList;
  751. var hasParameterExpressions = configuration.HasParameterExpressions;
  752. var canInitializeParametersOnDeclaration = simpleParameterList && !configuration.HasDuplicates;
  753. envRec.InitializeParameters(parameterNames, hasDuplicates, canInitializeParametersOnDeclaration ? argumentsList : null);
  754. ArgumentsInstance ao = null;
  755. if (configuration.ArgumentsObjectNeeded)
  756. {
  757. if (strict || !simpleParameterList)
  758. {
  759. ao = CreateUnmappedArgumentsObject(argumentsList);
  760. }
  761. else
  762. {
  763. // NOTE: mapped argument object is only provided for non-strict functions that don't have a rest parameter,
  764. // any parameter default value initializers, or any destructured parameters.
  765. ao = CreateMappedArgumentsObject(functionInstance, parameterNames, argumentsList, envRec, configuration.HasRestParameter);
  766. }
  767. if (strict)
  768. {
  769. envRec.CreateImmutableBindingAndInitialize(KnownKeys.Arguments, strict: false, ao);
  770. }
  771. else
  772. {
  773. envRec.CreateMutableBindingAndInitialize(KnownKeys.Arguments, canBeDeleted: false, ao);
  774. }
  775. }
  776. if (!canInitializeParametersOnDeclaration)
  777. {
  778. // slower set
  779. envRec.AddFunctionParameters(func.Function, argumentsList);
  780. }
  781. // Let iteratorRecord be CreateListIteratorRecord(argumentsList).
  782. // If hasDuplicates is true, then
  783. // Perform ? IteratorBindingInitialization for formals with iteratorRecord and undefined as arguments.
  784. // Else,
  785. // Perform ? IteratorBindingInitialization for formals with iteratorRecord and env as arguments.
  786. LexicalEnvironment varEnv;
  787. DeclarativeEnvironmentRecord varEnvRec;
  788. if (!hasParameterExpressions)
  789. {
  790. // NOTE: Only a single lexical environment is needed for the parameters and top-level vars.
  791. for (var i = 0; i < configuration.VarsToInitialize.Count; i++)
  792. {
  793. var pair = configuration.VarsToInitialize[i];
  794. envRec.CreateMutableBindingAndInitialize(pair.Name, canBeDeleted: false, JsValue.Undefined);
  795. }
  796. varEnv = env;
  797. varEnvRec = envRec;
  798. }
  799. else
  800. {
  801. // NOTE: A separate Environment Record is needed to ensure that closures created by expressions
  802. // in the formal parameter list do not have visibility of declarations in the function body.
  803. varEnv = LexicalEnvironment.NewDeclarativeEnvironment(this, env);
  804. varEnvRec = (DeclarativeEnvironmentRecord) varEnv._record;
  805. UpdateVariableEnvironment(varEnv);
  806. for (var i = 0; i < configuration.VarsToInitialize.Count; i++)
  807. {
  808. var pair = configuration.VarsToInitialize[i];
  809. var initialValue = pair.InitialValue ?? envRec.GetBindingValue(pair.Name, strict: false);
  810. varEnvRec.CreateMutableBindingAndInitialize(pair.Name, canBeDeleted: false, initialValue);
  811. }
  812. }
  813. // NOTE: Annex B.3.3.1 adds additional steps at this point.
  814. // A https://tc39.es/ecma262/#sec-web-compat-functiondeclarationinstantiation
  815. LexicalEnvironment lexEnv;
  816. if (!strict)
  817. {
  818. lexEnv = LexicalEnvironment.NewDeclarativeEnvironment(this, varEnv);
  819. // NOTE: Non-strict functions use a separate lexical Environment Record for top-level lexical declarations
  820. // so that a direct eval can determine whether any var scoped declarations introduced by the eval code conflict
  821. // with pre-existing top-level lexically scoped declarations. This is not needed for strict functions
  822. // because a strict direct eval always places all declarations into a new Environment Record.
  823. }
  824. else
  825. {
  826. lexEnv = varEnv;
  827. }
  828. var lexEnvRec = lexEnv._record;
  829. UpdateLexicalEnvironment(lexEnv);
  830. if (configuration.LexicalDeclarations.Length > 0)
  831. {
  832. InitializeLexicalDeclarations(configuration.LexicalDeclarations, lexEnvRec);
  833. }
  834. if (configuration.FunctionsToInitialize != null)
  835. {
  836. InitializeFunctions(configuration.FunctionsToInitialize, lexEnv, varEnvRec);
  837. }
  838. return ao;
  839. }
  840. private void InitializeFunctions(
  841. LinkedList<FunctionDeclaration> functionsToInitialize,
  842. LexicalEnvironment lexEnv,
  843. DeclarativeEnvironmentRecord varEnvRec)
  844. {
  845. foreach (var f in functionsToInitialize)
  846. {
  847. var fn = f.Id.Name;
  848. var fo = Function.CreateFunctionObject(f, lexEnv);
  849. varEnvRec.SetMutableBinding(fn, fo, strict: false);
  850. }
  851. }
  852. private static void InitializeLexicalDeclarations(
  853. JintFunctionDefinition.State.LexicalVariableDeclaration[] lexicalDeclarations,
  854. EnvironmentRecord lexEnvRec)
  855. {
  856. foreach (var d in lexicalDeclarations)
  857. {
  858. for (var j = 0; j < d.BoundNames.Count; j++)
  859. {
  860. var dn = d.BoundNames[j];
  861. if (d.Kind == VariableDeclarationKind.Const)
  862. {
  863. lexEnvRec.CreateImmutableBinding(dn, strict: true);
  864. }
  865. else
  866. {
  867. lexEnvRec.CreateMutableBinding(dn, canBeDeleted: false);
  868. }
  869. }
  870. }
  871. }
  872. private ArgumentsInstance CreateMappedArgumentsObject(
  873. FunctionInstance func,
  874. Key[] formals,
  875. JsValue[] argumentsList,
  876. DeclarativeEnvironmentRecord envRec,
  877. bool hasRestParameter)
  878. {
  879. return _argumentsInstancePool.Rent(func, formals, argumentsList, envRec, hasRestParameter);
  880. }
  881. private ArgumentsInstance CreateUnmappedArgumentsObject(JsValue[] argumentsList)
  882. {
  883. return _argumentsInstancePool.Rent(argumentsList);
  884. }
  885. /// <summary>
  886. /// https://tc39.es/ecma262/#sec-evaldeclarationinstantiation
  887. /// </summary>
  888. internal void EvalDeclarationInstantiation(
  889. Script script,
  890. LexicalEnvironment varEnv,
  891. LexicalEnvironment lexEnv,
  892. bool strict)
  893. {
  894. var hoistingScope = HoistingScope.GetProgramLevelDeclarations(script);
  895. var lexEnvRec = (DeclarativeEnvironmentRecord) lexEnv._record;
  896. var varEnvRec = varEnv._record;
  897. if (!strict && hoistingScope._variablesDeclarations != null)
  898. {
  899. if (varEnvRec is GlobalEnvironmentRecord globalEnvironmentRecord)
  900. {
  901. ref readonly var nodes = ref hoistingScope._variablesDeclarations;
  902. for (var i = 0; i < nodes.Count; i++)
  903. {
  904. var variablesDeclaration = nodes[i];
  905. var identifier = (Identifier) variablesDeclaration.Declarations[0].Id;
  906. if (globalEnvironmentRecord.HasLexicalDeclaration(identifier.Name))
  907. {
  908. ExceptionHelper.ThrowSyntaxError(this, "Identifier '" + identifier.Name + "' has already been declared");
  909. }
  910. }
  911. }
  912. var thisLex = lexEnv;
  913. while (thisLex != varEnv)
  914. {
  915. var thisEnvRec = thisLex._record;
  916. if (!(thisEnvRec is ObjectEnvironmentRecord))
  917. {
  918. ref readonly var nodes = ref hoistingScope._variablesDeclarations;
  919. for (var i = 0; i < nodes.Count; i++)
  920. {
  921. var variablesDeclaration = nodes[i];
  922. var identifier = (Identifier) variablesDeclaration.Declarations[0].Id;
  923. if (thisEnvRec.HasBinding(identifier.Name))
  924. {
  925. ExceptionHelper.ThrowSyntaxError(this);
  926. }
  927. }
  928. }
  929. thisLex = thisLex._outer;
  930. }
  931. }
  932. var functionDeclarations = hoistingScope._functionDeclarations;
  933. var functionsToInitialize = new LinkedList<FunctionDeclaration>();
  934. var declaredFunctionNames = new HashSet<string>();
  935. if (functionDeclarations != null)
  936. {
  937. for (var i = functionDeclarations.Count - 1; i >= 0; i--)
  938. {
  939. var d = functionDeclarations[i];
  940. var fn = d.Id.Name;
  941. if (!declaredFunctionNames.Contains(fn))
  942. {
  943. if (varEnvRec is GlobalEnvironmentRecord ger)
  944. {
  945. var fnDefinable = ger.CanDeclareGlobalFunction(fn);
  946. if (!fnDefinable)
  947. {
  948. ExceptionHelper.ThrowTypeError(this);
  949. }
  950. }
  951. declaredFunctionNames.Add(fn);
  952. functionsToInitialize.AddFirst(d);
  953. }
  954. }
  955. }
  956. var boundNames = new List<string>();
  957. var declaredVarNames = new List<string>();
  958. var variableDeclarations = hoistingScope._variablesDeclarations;
  959. var variableDeclarationsCount = variableDeclarations?.Count;
  960. for (var i = 0; i < variableDeclarationsCount; i++)
  961. {
  962. var variableDeclaration = variableDeclarations[i];
  963. boundNames.Clear();
  964. variableDeclaration.GetBoundNames(boundNames);
  965. for (var j = 0; j < boundNames.Count; j++)
  966. {
  967. var vn = boundNames[j];
  968. if (!declaredFunctionNames.Contains(vn))
  969. {
  970. if (varEnvRec is GlobalEnvironmentRecord ger)
  971. {
  972. var vnDefinable = ger.CanDeclareGlobalFunction(vn);
  973. if (!vnDefinable)
  974. {
  975. ExceptionHelper.ThrowTypeError(this);
  976. }
  977. }
  978. declaredVarNames.Add(vn);
  979. }
  980. }
  981. }
  982. var lexicalDeclarations = hoistingScope._lexicalDeclarations;
  983. var lexicalDeclarationsCount = lexicalDeclarations?.Count;
  984. for (var i = 0; i < lexicalDeclarationsCount; i++)
  985. {
  986. boundNames.Clear();
  987. var d = lexicalDeclarations[i];
  988. d.GetBoundNames(boundNames);
  989. for (var j = 0; j < boundNames.Count; j++)
  990. {
  991. var dn = boundNames[j];
  992. if (d.Kind == VariableDeclarationKind.Const)
  993. {
  994. lexEnvRec.CreateImmutableBinding(dn, strict: true);
  995. }
  996. else
  997. {
  998. lexEnvRec.CreateMutableBinding(dn, canBeDeleted: false);
  999. }
  1000. }
  1001. }
  1002. foreach (var f in functionsToInitialize)
  1003. {
  1004. var fn = f.Id.Name;
  1005. var fo = Function.CreateFunctionObject(f, lexEnv);
  1006. if (varEnvRec is GlobalEnvironmentRecord ger)
  1007. {
  1008. ger.CreateGlobalFunctionBinding(fn, fo, canBeDeleted: true);
  1009. }
  1010. else
  1011. {
  1012. var bindingExists = varEnvRec.HasBinding(fn);
  1013. if (!bindingExists)
  1014. {
  1015. varEnvRec.CreateMutableBinding(fn, canBeDeleted: true);
  1016. varEnvRec.InitializeBinding(fn, fo);
  1017. }
  1018. else
  1019. {
  1020. varEnvRec.SetMutableBinding(fn, fo, strict: false);
  1021. }
  1022. }
  1023. }
  1024. foreach (var vn in declaredVarNames)
  1025. {
  1026. if (varEnvRec is GlobalEnvironmentRecord ger)
  1027. {
  1028. ger.CreateGlobalVarBinding(vn, true);
  1029. }
  1030. else
  1031. {
  1032. var bindingExists = varEnvRec.HasBinding(vn);
  1033. if (!bindingExists)
  1034. {
  1035. varEnvRec.CreateMutableBinding(vn, canBeDeleted: true);
  1036. varEnvRec.InitializeBinding(vn, JsValue.Undefined);
  1037. }
  1038. }
  1039. }
  1040. }
  1041. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  1042. internal void UpdateLexicalEnvironment(LexicalEnvironment newEnv)
  1043. {
  1044. _executionContexts.ReplaceTopLexicalEnvironment(newEnv);
  1045. }
  1046. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  1047. internal void UpdateVariableEnvironment(LexicalEnvironment newEnv)
  1048. {
  1049. _executionContexts.ReplaceTopVariableEnvironment(newEnv);
  1050. }
  1051. internal JsValue Call(ICallable callable, JsValue thisObject, JsValue[] arguments, JintExpression expression)
  1052. {
  1053. if (callable is FunctionInstance functionInstance)
  1054. {
  1055. return Call(functionInstance, thisObject, arguments, expression);
  1056. }
  1057. return callable.Call(thisObject, arguments);
  1058. }
  1059. internal JsValue Construct(IConstructor constructor, JsValue[] arguments, JsValue newTarget, JintExpression expression)
  1060. {
  1061. if (constructor is FunctionInstance functionInstance)
  1062. {
  1063. return Construct(functionInstance, arguments, newTarget, expression);
  1064. }
  1065. return constructor.Construct(arguments, newTarget);
  1066. }
  1067. internal JsValue Call(
  1068. FunctionInstance functionInstance,
  1069. JsValue thisObject,
  1070. JsValue[] arguments,
  1071. JintExpression expression)
  1072. {
  1073. var callStackElement = new CallStackElement(functionInstance, expression);
  1074. var recursionDepth = CallStack.Push(callStackElement);
  1075. if (recursionDepth > Options.MaxRecursionDepth)
  1076. {
  1077. // pop the current element as it was never reached
  1078. CallStack.Pop();
  1079. ExceptionHelper.ThrowRecursionDepthOverflowException(CallStack, callStackElement.ToString());
  1080. }
  1081. if (_isDebugMode)
  1082. {
  1083. DebugHandler.AddToDebugCallStack(functionInstance);
  1084. }
  1085. var result = functionInstance.Call(thisObject, arguments);
  1086. if (_isDebugMode)
  1087. {
  1088. DebugHandler.PopDebugCallStack();
  1089. }
  1090. CallStack.Pop();
  1091. return result;
  1092. }
  1093. internal JsValue Construct(
  1094. FunctionInstance functionInstance,
  1095. JsValue[] arguments,
  1096. JsValue newTarget,
  1097. JintExpression expression)
  1098. {
  1099. var callStackElement = new CallStackElement(functionInstance, expression);
  1100. var recursionDepth = CallStack.Push(callStackElement);
  1101. if (recursionDepth > Options.MaxRecursionDepth)
  1102. {
  1103. // pop the current element as it was never reached
  1104. CallStack.Pop();
  1105. ExceptionHelper.ThrowRecursionDepthOverflowException(CallStack, callStackElement.ToString());
  1106. }
  1107. if (_isDebugMode)
  1108. {
  1109. DebugHandler.AddToDebugCallStack(functionInstance);
  1110. }
  1111. var result = ((IConstructor) functionInstance).Construct(arguments, newTarget);
  1112. if (_isDebugMode)
  1113. {
  1114. DebugHandler.PopDebugCallStack();
  1115. }
  1116. CallStack.Pop();
  1117. return result;
  1118. }
  1119. }
  1120. }