Engine.cs 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using Jint.Native;
  5. using Jint.Native.Argument;
  6. using Jint.Native.Array;
  7. using Jint.Native.Boolean;
  8. using Jint.Native.Date;
  9. using Jint.Native.Error;
  10. using Jint.Native.Function;
  11. using Jint.Native.Global;
  12. using Jint.Native.Json;
  13. using Jint.Native.Math;
  14. using Jint.Native.Number;
  15. using Jint.Native.Object;
  16. using Jint.Native.RegExp;
  17. using Jint.Native.String;
  18. using Jint.Parser;
  19. using Jint.Parser.Ast;
  20. using Jint.Runtime;
  21. using Jint.Runtime.Descriptors;
  22. using Jint.Runtime.Environments;
  23. using Jint.Runtime.Interop;
  24. using Jint.Runtime.References;
  25. namespace Jint
  26. {
  27. public class Engine
  28. {
  29. private readonly ExpressionInterpreter _expressions;
  30. private readonly StatementInterpreter _statements;
  31. private readonly Stack<ExecutionContext> _executionContexts;
  32. private JsValue _completionValue = JsValue.Undefined;
  33. private int _statementsCount;
  34. private SyntaxNode _lastSyntaxNode = null;
  35. // cache of types used when resolving CLR type names
  36. internal Dictionary<string, Type> TypeCache = new Dictionary<string, Type>();
  37. public Engine() : this(null)
  38. {
  39. }
  40. public Engine(Action<Options> options)
  41. {
  42. _executionContexts = new Stack<ExecutionContext>();
  43. Global = GlobalObject.CreateGlobalObject(this);
  44. Object = ObjectConstructor.CreateObjectConstructor(this);
  45. Function = FunctionConstructor.CreateFunctionConstructor(this);
  46. Array = ArrayConstructor.CreateArrayConstructor(this);
  47. String = StringConstructor.CreateStringConstructor(this);
  48. RegExp = RegExpConstructor.CreateRegExpConstructor(this);
  49. Number = NumberConstructor.CreateNumberConstructor(this);
  50. Boolean = BooleanConstructor.CreateBooleanConstructor(this);
  51. Date = DateConstructor.CreateDateConstructor(this);
  52. Math = MathInstance.CreateMathObject(this);
  53. Json = JsonInstance.CreateJsonObject(this);
  54. Error = ErrorConstructor.CreateErrorConstructor(this, "Error");
  55. EvalError = ErrorConstructor.CreateErrorConstructor(this, "EvalError");
  56. RangeError = ErrorConstructor.CreateErrorConstructor(this, "RangeError");
  57. ReferenceError = ErrorConstructor.CreateErrorConstructor(this, "ReferenceError");
  58. SyntaxError = ErrorConstructor.CreateErrorConstructor(this, "SyntaxError");
  59. TypeError = ErrorConstructor.CreateErrorConstructor(this, "TypeError");
  60. UriError = ErrorConstructor.CreateErrorConstructor(this, "URIError");
  61. // Because the properties might need some of the built-in object
  62. // their configuration is delayed to a later step
  63. Global.Configure();
  64. Object.Configure();
  65. Object.PrototypeObject.Configure();
  66. Function.Configure();
  67. Function.PrototypeObject.Configure();
  68. Array.Configure();
  69. Array.PrototypeObject.Configure();
  70. String.Configure();
  71. String.PrototypeObject.Configure();
  72. RegExp.Configure();
  73. RegExp.PrototypeObject.Configure();
  74. Number.Configure();
  75. Number.PrototypeObject.Configure();
  76. Boolean.Configure();
  77. Boolean.PrototypeObject.Configure();
  78. Date.Configure();
  79. Date.PrototypeObject.Configure();
  80. Math.Configure();
  81. Json.Configure();
  82. Error.Configure();
  83. Error.PrototypeObject.Configure();
  84. // create the global environment http://www.ecma-international.org/ecma-262/5.1/#sec-10.2.3
  85. GlobalEnvironment = LexicalEnvironment.NewObjectEnvironment(this, Global, null, false);
  86. // create the global execution context http://www.ecma-international.org/ecma-262/5.1/#sec-10.4.1.1
  87. EnterExecutionContext(GlobalEnvironment, GlobalEnvironment, Global);
  88. Options = new Options();
  89. if (options != null)
  90. {
  91. options(Options);
  92. }
  93. Eval = new EvalFunctionInstance(this, new string[0], LexicalEnvironment.NewDeclarativeEnvironment(this, ExecutionContext.LexicalEnvironment), StrictModeScope.IsStrictModeCode);
  94. Global.FastAddProperty("eval", Eval, true, false, true);
  95. _statements = new StatementInterpreter(this);
  96. _expressions = new ExpressionInterpreter(this);
  97. if (Options.IsClrAllowed())
  98. {
  99. Global.FastAddProperty("System", new NamespaceReference(this, "System"), false, false, false);
  100. Global.FastAddProperty("importNamespace", new ClrFunctionInstance(this, (thisObj, arguments) =>
  101. {
  102. return new NamespaceReference(this, TypeConverter.ToString(arguments.At(0)));
  103. }), false, false, false);
  104. }
  105. }
  106. public LexicalEnvironment GlobalEnvironment;
  107. public GlobalObject Global { get; private set; }
  108. public ObjectConstructor Object { get; private set; }
  109. public FunctionConstructor Function { get; private set; }
  110. public ArrayConstructor Array { get; private set; }
  111. public StringConstructor String { get; private set; }
  112. public RegExpConstructor RegExp { get; private set; }
  113. public BooleanConstructor Boolean { get; private set; }
  114. public NumberConstructor Number { get; private set; }
  115. public DateConstructor Date { get; private set; }
  116. public MathInstance Math { get; private set; }
  117. public JsonInstance Json { get; private set; }
  118. public EvalFunctionInstance Eval { get; private set; }
  119. public ErrorConstructor Error { get; private set; }
  120. public ErrorConstructor EvalError { get; private set; }
  121. public ErrorConstructor SyntaxError { get; private set; }
  122. public ErrorConstructor TypeError { get; private set; }
  123. public ErrorConstructor RangeError { get; private set; }
  124. public ErrorConstructor ReferenceError { get; private set; }
  125. public ErrorConstructor UriError { get; private set; }
  126. public ExecutionContext ExecutionContext { get { return _executionContexts.Peek(); } }
  127. internal Options Options { get; private set; }
  128. public ExecutionContext EnterExecutionContext(LexicalEnvironment lexicalEnvironment, LexicalEnvironment variableEnvironment, JsValue thisBinding)
  129. {
  130. var executionContext = new ExecutionContext
  131. {
  132. LexicalEnvironment = lexicalEnvironment,
  133. VariableEnvironment = variableEnvironment,
  134. ThisBinding = thisBinding
  135. };
  136. _executionContexts.Push(executionContext);
  137. return executionContext;
  138. }
  139. public Engine SetValue(string name, Delegate value)
  140. {
  141. Global.FastAddProperty(name, new DelegateWrapper(this, value), true, false, true);
  142. return this;
  143. }
  144. public Engine SetValue(string name, string value)
  145. {
  146. return SetValue(name, new JsValue(value));
  147. }
  148. public Engine SetValue(string name, double value)
  149. {
  150. return SetValue(name, new JsValue(value));
  151. }
  152. public Engine SetValue(string name, bool value)
  153. {
  154. return SetValue(name, new JsValue(value));
  155. }
  156. public Engine SetValue(string name, JsValue value)
  157. {
  158. Global.Put(name, value, false);
  159. return this;
  160. }
  161. public Engine SetValue(string name, Object obj)
  162. {
  163. return SetValue(name, JsValue.FromObject(this, obj));
  164. }
  165. public void LeaveExecutionContext()
  166. {
  167. _executionContexts.Pop();
  168. }
  169. /// <summary>
  170. /// Initializes the statements count
  171. /// </summary>
  172. public void ResetStatementsCount()
  173. {
  174. _statementsCount = 0;
  175. }
  176. public Engine Execute(string source)
  177. {
  178. var parser = new JavaScriptParser();
  179. return Execute(parser.Parse(source));
  180. }
  181. public Engine Execute(string source, ParserOptions parserOptions)
  182. {
  183. var parser = new JavaScriptParser();
  184. return Execute(parser.Parse(source, parserOptions));
  185. }
  186. public Engine Execute(Program program)
  187. {
  188. ResetStatementsCount();
  189. ResetLastStatement();
  190. using (new StrictModeScope(Options.IsStrict() || program.Strict))
  191. {
  192. DeclarationBindingInstantiation(DeclarationBindingType.GlobalCode, program.FunctionDeclarations, program.VariableDeclarations, null, null);
  193. var result = _statements.ExecuteProgram(program);
  194. if (result.Type == Completion.Throw)
  195. {
  196. throw new JavaScriptException(result.GetValueOrDefault());
  197. }
  198. _completionValue = result.GetValueOrDefault();
  199. }
  200. return this;
  201. }
  202. private void ResetLastStatement()
  203. {
  204. _lastSyntaxNode = null;
  205. }
  206. /// <summary>
  207. /// Gets the last evaluated statement completion value
  208. /// </summary>
  209. public JsValue GetCompletionValue()
  210. {
  211. return _completionValue;
  212. }
  213. public Completion ExecuteStatement(Statement statement)
  214. {
  215. var maxStatements = Options.GetMaxStatements();
  216. if (maxStatements > 0 && _statementsCount++ > maxStatements)
  217. {
  218. throw new StatementsCountOverflowException();
  219. }
  220. _lastSyntaxNode = statement;
  221. switch (statement.Type)
  222. {
  223. case SyntaxNodes.BlockStatement:
  224. return _statements.ExecuteBlockStatement(statement.As<BlockStatement>());
  225. case SyntaxNodes.BreakStatement:
  226. return _statements.ExecuteBreakStatement(statement.As<BreakStatement>());
  227. case SyntaxNodes.ContinueStatement:
  228. return _statements.ExecuteContinueStatement(statement.As<ContinueStatement>());
  229. case SyntaxNodes.DoWhileStatement:
  230. return _statements.ExecuteDoWhileStatement(statement.As<DoWhileStatement>());
  231. case SyntaxNodes.DebuggerStatement:
  232. return _statements.ExecuteDebuggerStatement(statement.As<DebuggerStatement>());
  233. case SyntaxNodes.EmptyStatement:
  234. return _statements.ExecuteEmptyStatement(statement.As<EmptyStatement>());
  235. case SyntaxNodes.ExpressionStatement:
  236. return _statements.ExecuteExpressionStatement(statement.As<ExpressionStatement>());
  237. case SyntaxNodes.ForStatement:
  238. return _statements.ExecuteForStatement(statement.As<ForStatement>());
  239. case SyntaxNodes.ForInStatement:
  240. return _statements.ExecuteForInStatement(statement.As<ForInStatement>());
  241. case SyntaxNodes.FunctionDeclaration:
  242. return new Completion(Completion.Normal, null, null);
  243. case SyntaxNodes.IfStatement:
  244. return _statements.ExecuteIfStatement(statement.As<IfStatement>());
  245. case SyntaxNodes.LabeledStatement:
  246. return _statements.ExecuteLabelledStatement(statement.As<LabelledStatement>());
  247. case SyntaxNodes.ReturnStatement:
  248. return _statements.ExecuteReturnStatement(statement.As<ReturnStatement>());
  249. case SyntaxNodes.SwitchStatement:
  250. return _statements.ExecuteSwitchStatement(statement.As<SwitchStatement>());
  251. case SyntaxNodes.ThrowStatement:
  252. return _statements.ExecuteThrowStatement(statement.As<ThrowStatement>());
  253. case SyntaxNodes.TryStatement:
  254. return _statements.ExecuteTryStatement(statement.As<TryStatement>());
  255. case SyntaxNodes.VariableDeclaration:
  256. return _statements.ExecuteVariableDeclaration(statement.As<VariableDeclaration>());
  257. case SyntaxNodes.WhileStatement:
  258. return _statements.ExecuteWhileStatement(statement.As<WhileStatement>());
  259. case SyntaxNodes.WithStatement:
  260. return _statements.ExecuteWithStatement(statement.As<WithStatement>());
  261. case SyntaxNodes.Program:
  262. return _statements.ExecuteProgram(statement.As<Program>());
  263. default:
  264. throw new ArgumentOutOfRangeException();
  265. }
  266. }
  267. public object EvaluateExpression(Expression expression)
  268. {
  269. _lastSyntaxNode = expression;
  270. switch (expression.Type)
  271. {
  272. case SyntaxNodes.AssignmentExpression:
  273. return _expressions.EvaluateAssignmentExpression(expression.As<AssignmentExpression>());
  274. case SyntaxNodes.ArrayExpression:
  275. return _expressions.EvaluateArrayExpression(expression.As<ArrayExpression>());
  276. case SyntaxNodes.BinaryExpression:
  277. return _expressions.EvaluateBinaryExpression(expression.As<BinaryExpression>());
  278. case SyntaxNodes.CallExpression:
  279. return _expressions.EvaluateCallExpression(expression.As<CallExpression>());
  280. case SyntaxNodes.ConditionalExpression:
  281. return _expressions.EvaluateConditionalExpression(expression.As<ConditionalExpression>());
  282. case SyntaxNodes.FunctionExpression:
  283. return _expressions.EvaluateFunctionExpression(expression.As<FunctionExpression>());
  284. case SyntaxNodes.Identifier:
  285. return _expressions.EvaluateIdentifier(expression.As<Identifier>());
  286. case SyntaxNodes.Literal:
  287. return _expressions.EvaluateLiteral(expression.As<Literal>());
  288. case SyntaxNodes.RegularExpressionLiteral:
  289. return _expressions.EvaluateLiteral(expression.As<Literal>());
  290. case SyntaxNodes.LogicalExpression:
  291. return _expressions.EvaluateLogicalExpression(expression.As<LogicalExpression>());
  292. case SyntaxNodes.MemberExpression:
  293. return _expressions.EvaluateMemberExpression(expression.As<MemberExpression>());
  294. case SyntaxNodes.NewExpression:
  295. return _expressions.EvaluateNewExpression(expression.As<NewExpression>());
  296. case SyntaxNodes.ObjectExpression:
  297. return _expressions.EvaluateObjectExpression(expression.As<ObjectExpression>());
  298. case SyntaxNodes.SequenceExpression:
  299. return _expressions.EvaluateSequenceExpression(expression.As<SequenceExpression>());
  300. case SyntaxNodes.ThisExpression:
  301. return _expressions.EvaluateThisExpression(expression.As<ThisExpression>());
  302. case SyntaxNodes.UpdateExpression:
  303. return _expressions.EvaluateUpdateExpression(expression.As<UpdateExpression>());
  304. case SyntaxNodes.UnaryExpression:
  305. return _expressions.EvaluateUnaryExpression(expression.As<UnaryExpression>());
  306. default:
  307. throw new ArgumentOutOfRangeException();
  308. }
  309. }
  310. /// <summary>
  311. /// http://www.ecma-international.org/ecma-262/5.1/#sec-8.7.1
  312. /// </summary>
  313. /// <param name="value"></param>
  314. /// <returns></returns>
  315. public JsValue GetValue(object value)
  316. {
  317. var reference = value as Reference;
  318. if (reference == null)
  319. {
  320. var completion = value as Completion;
  321. if (completion != null)
  322. {
  323. return GetValue(completion.Value);
  324. }
  325. return (JsValue)value;
  326. }
  327. if (reference.IsUnresolvableReference())
  328. {
  329. throw new JavaScriptException(ReferenceError, reference.GetReferencedName() + " is not defined");
  330. }
  331. var baseValue = reference.GetBase();
  332. if (reference.IsPropertyReference())
  333. {
  334. if (reference.HasPrimitiveBase() == false)
  335. {
  336. var o = TypeConverter.ToObject(this, baseValue);
  337. return o.Get(reference.GetReferencedName());
  338. }
  339. else
  340. {
  341. var o = TypeConverter.ToObject(this, baseValue);
  342. var desc = o.GetProperty(reference.GetReferencedName());
  343. if (desc == PropertyDescriptor.Undefined)
  344. {
  345. return JsValue.Undefined;
  346. }
  347. if (desc.IsDataDescriptor())
  348. {
  349. return desc.Value.Value;
  350. }
  351. var getter = desc.Get.Value;
  352. if (getter == Undefined.Instance)
  353. {
  354. return Undefined.Instance;
  355. }
  356. var callable = (ICallable)getter.AsObject();
  357. return callable.Call(baseValue, Arguments.Empty);
  358. }
  359. }
  360. else
  361. {
  362. var record = baseValue.As<EnvironmentRecord>();
  363. if (record == null)
  364. {
  365. throw new ArgumentException();
  366. }
  367. return record.GetBindingValue(reference.GetReferencedName(), reference.IsStrict());
  368. }
  369. }
  370. /// <summary>
  371. /// http://www.ecma-international.org/ecma-262/5.1/#sec-8.7.2
  372. /// </summary>
  373. /// <param name="reference"></param>
  374. /// <param name="value"></param>
  375. public void PutValue(Reference reference, JsValue value)
  376. {
  377. if (reference.IsUnresolvableReference())
  378. {
  379. if (reference.IsStrict())
  380. {
  381. throw new JavaScriptException(ReferenceError);
  382. }
  383. Global.Put(reference.GetReferencedName(), value, false);
  384. }
  385. else if (reference.IsPropertyReference())
  386. {
  387. var baseValue = reference.GetBase();
  388. if (!reference.HasPrimitiveBase())
  389. {
  390. baseValue.AsObject().Put(reference.GetReferencedName(), value, reference.IsStrict());
  391. }
  392. else
  393. {
  394. PutPrimitiveBase(baseValue, reference.GetReferencedName(), value, reference.IsStrict());
  395. }
  396. }
  397. else
  398. {
  399. var baseValue = reference.GetBase();
  400. var record = baseValue.As<EnvironmentRecord>();
  401. if (record == null)
  402. {
  403. throw new ArgumentNullException();
  404. }
  405. record.SetMutableBinding(reference.GetReferencedName(), value, reference.IsStrict());
  406. }
  407. }
  408. /// <summary>
  409. /// Used by PutValue when the reference has a primitive base value
  410. /// </summary>
  411. /// <param name="b"></param>
  412. /// <param name="name"></param>
  413. /// <param name="value"></param>
  414. /// <param name="throwOnError"></param>
  415. public void PutPrimitiveBase(JsValue b, string name, JsValue value, bool throwOnError)
  416. {
  417. var o = TypeConverter.ToObject(this, b);
  418. if (!o.CanPut(name))
  419. {
  420. if (throwOnError)
  421. {
  422. throw new JavaScriptException(TypeError);
  423. }
  424. return;
  425. }
  426. var ownDesc = o.GetOwnProperty(name);
  427. if (ownDesc.IsDataDescriptor())
  428. {
  429. if (throwOnError)
  430. {
  431. throw new JavaScriptException(TypeError);
  432. }
  433. return;
  434. }
  435. var desc = o.GetProperty(name);
  436. if (desc.IsAccessorDescriptor())
  437. {
  438. var setter = (ICallable)desc.Set.Value.AsObject();
  439. setter.Call(b, new[] { value });
  440. }
  441. else
  442. {
  443. if (throwOnError)
  444. {
  445. throw new JavaScriptException(TypeError);
  446. }
  447. }
  448. }
  449. /// <summary>
  450. /// Invoke the current value as function.
  451. /// </summary>
  452. /// <param name="propertyName">The arguments of the function call.</param>
  453. /// <returns>The value returned by the function call.</returns>
  454. public JsValue Invoke(string propertyName, params object[] arguments)
  455. {
  456. return Invoke(propertyName, null, arguments);
  457. }
  458. /// <summary>
  459. /// Invoke the current value as function.
  460. /// </summary>
  461. /// <param name="propertyName">The name of the function to call.</param>
  462. /// <param name="thisObj">The this value inside the function call.</param>
  463. /// <param name="arguments">The arguments of the function call.</param>
  464. /// <returns>The value returned by the function call.</returns>
  465. public JsValue Invoke(string propertyName, object thisObj, object[] arguments)
  466. {
  467. var value = GetValue(propertyName);
  468. var callable = value.TryCast<ICallable>();
  469. if (callable == null)
  470. {
  471. throw new ArgumentException("Can only invoke functions");
  472. }
  473. return callable.Call(JsValue.FromObject(this, thisObj), arguments.Select(x => JsValue.FromObject(this, x)).ToArray());
  474. }
  475. /// <summary>
  476. /// Gets a named value from the Global scope.
  477. /// </summary>
  478. /// <param name="propertyName">The name of the property to return.</param>
  479. public JsValue GetValue(string propertyName)
  480. {
  481. return GetValue(Global, propertyName);
  482. }
  483. /// <summary>
  484. /// Gets the last evaluated <see cref="SyntaxNode"/>.
  485. /// </summary>
  486. public SyntaxNode GetLastSyntaxNode()
  487. {
  488. return _lastSyntaxNode;
  489. }
  490. /// <summary>
  491. /// Gets a named value from the specified scope.
  492. /// </summary>
  493. /// <param name="scope">The scope to get the property from.</param>
  494. /// <param name="propertyName">The name of the property to return.</param>
  495. public JsValue GetValue(JsValue scope, string propertyName)
  496. {
  497. if (System.String.IsNullOrEmpty(propertyName))
  498. {
  499. throw new ArgumentException("propertyName");
  500. }
  501. var reference = new Reference(scope, propertyName, Options.IsStrict());
  502. return GetValue(reference);
  503. }
  504. // http://www.ecma-international.org/ecma-262/5.1/#sec-10.5
  505. public void DeclarationBindingInstantiation(DeclarationBindingType declarationBindingType, IList<FunctionDeclaration> functionDeclarations, IList<VariableDeclaration> variableDeclarations, FunctionInstance functionInstance, JsValue[] arguments)
  506. {
  507. var env = ExecutionContext.VariableEnvironment.Record;
  508. bool configurableBindings = declarationBindingType == DeclarationBindingType.EvalCode;
  509. var strict = StrictModeScope.IsStrictModeCode;
  510. if (declarationBindingType == DeclarationBindingType.FunctionCode)
  511. {
  512. var argCount = arguments.Length;
  513. var n = 0;
  514. foreach (var argName in functionInstance.FormalParameters)
  515. {
  516. n++;
  517. var v = n > argCount ? Undefined.Instance : arguments[n - 1];
  518. var argAlreadyDeclared = env.HasBinding(argName);
  519. if (!argAlreadyDeclared)
  520. {
  521. env.CreateMutableBinding(argName);
  522. }
  523. env.SetMutableBinding(argName, v, strict);
  524. }
  525. }
  526. foreach (var f in functionDeclarations)
  527. {
  528. var fn = f.Id.Name;
  529. var fo = Function.CreateFunctionObject(f);
  530. var funcAlreadyDeclared = env.HasBinding(fn);
  531. if (!funcAlreadyDeclared)
  532. {
  533. env.CreateMutableBinding(fn, configurableBindings);
  534. }
  535. else
  536. {
  537. if (env == GlobalEnvironment.Record)
  538. {
  539. var go = Global;
  540. var existingProp = go.GetProperty(fn);
  541. if (existingProp.Configurable.Value.AsBoolean())
  542. {
  543. go.DefineOwnProperty(fn,
  544. new PropertyDescriptor(
  545. value: Undefined.Instance,
  546. writable: true,
  547. enumerable: true,
  548. configurable: configurableBindings
  549. ), true);
  550. }
  551. else
  552. {
  553. if (existingProp.IsAccessorDescriptor() || (!existingProp.Enumerable.Value.AsBoolean()))
  554. {
  555. throw new JavaScriptException(TypeError);
  556. }
  557. }
  558. }
  559. }
  560. env.SetMutableBinding(fn, fo, strict);
  561. }
  562. var argumentsAlreadyDeclared = env.HasBinding("arguments");
  563. if (declarationBindingType == DeclarationBindingType.FunctionCode && !argumentsAlreadyDeclared)
  564. {
  565. var argsObj = ArgumentsInstance.CreateArgumentsObject(this, functionInstance, functionInstance.FormalParameters, arguments, env, strict);
  566. if (strict)
  567. {
  568. var declEnv = env as DeclarativeEnvironmentRecord;
  569. if (declEnv == null)
  570. {
  571. throw new ArgumentException();
  572. }
  573. declEnv.CreateImmutableBinding("arguments");
  574. declEnv.InitializeImmutableBinding("arguments", argsObj);
  575. }
  576. else
  577. {
  578. env.CreateMutableBinding("arguments");
  579. env.SetMutableBinding("arguments", argsObj, false);
  580. }
  581. }
  582. // process all variable declarations in the current parser scope
  583. foreach (var d in variableDeclarations.SelectMany(x => x.Declarations))
  584. {
  585. var dn = d.Id.Name;
  586. var varAlreadyDeclared = env.HasBinding(dn);
  587. if (!varAlreadyDeclared)
  588. {
  589. env.CreateMutableBinding(dn, configurableBindings);
  590. env.SetMutableBinding(dn, Undefined.Instance, strict);
  591. }
  592. }
  593. }
  594. }
  595. }