ArrowFunctionInstance.cs 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124
  1. using System.Runtime.CompilerServices;
  2. using Esprima.Ast;
  3. using Jint.Runtime;
  4. using Jint.Runtime.Descriptors;
  5. using Jint.Runtime.Environments;
  6. using Jint.Runtime.Interpreter;
  7. namespace Jint.Native.Function
  8. {
  9. public sealed class ArrowFunctionInstance : FunctionInstance
  10. {
  11. private readonly JintFunctionDefinition _function;
  12. private readonly JsValue _thisBinding;
  13. /// <summary>
  14. /// http://www.ecma-international.org/ecma-262/6.0/#sec-arrow-function-definitions
  15. /// </summary>
  16. public ArrowFunctionInstance(
  17. Engine engine,
  18. IFunction functionDeclaration,
  19. LexicalEnvironment scope,
  20. bool strict)
  21. : this(engine, new JintFunctionDefinition(engine, functionDeclaration), scope, strict)
  22. {
  23. }
  24. internal ArrowFunctionInstance(
  25. Engine engine,
  26. JintFunctionDefinition function,
  27. LexicalEnvironment scope,
  28. bool strict)
  29. : base(engine, (string) null, function._parameterNames, scope, strict)
  30. {
  31. _function = function;
  32. PreventExtensions();
  33. _prototype = Engine.Function.PrototypeObject;
  34. _length = new PropertyDescriptor(JsNumber.Create(function._length), PropertyFlag.Configurable);
  35. _thisBinding = _engine.ExecutionContext.ThisBinding;
  36. }
  37. // for example RavenDB wants to inspect this
  38. public IFunction FunctionDeclaration => _function._function;
  39. /// <summary>
  40. /// http://www.ecma-international.org/ecma-262/5.1/#sec-13.2.1
  41. /// </summary>
  42. /// <param name="thisArg"></param>
  43. /// <param name="arguments"></param>
  44. /// <returns></returns>
  45. public override JsValue Call(JsValue thisArg, JsValue[] arguments)
  46. {
  47. var localEnv = LexicalEnvironment.NewDeclarativeEnvironment(_engine, _scope);
  48. var strict = Strict || _engine._isStrict;
  49. using (new StrictModeScope(strict, true))
  50. {
  51. _engine.EnterExecutionContext(
  52. localEnv,
  53. localEnv,
  54. _thisBinding);
  55. try
  56. {
  57. var argumentInstanceRented = _engine.DeclarationBindingInstantiation(
  58. DeclarationBindingType.FunctionCode,
  59. _function._hoistingScope,
  60. functionInstance: this,
  61. arguments);
  62. var result = _function._body.Execute();
  63. var value = result.GetValueOrDefault();
  64. if (argumentInstanceRented)
  65. {
  66. _engine.ExecutionContext.LexicalEnvironment?._record?.FunctionWasCalled();
  67. _engine.ExecutionContext.VariableEnvironment?._record?.FunctionWasCalled();
  68. }
  69. if (result.Type == CompletionType.Throw)
  70. {
  71. ExceptionHelper.ThrowJavaScriptException(_engine, value, result);
  72. }
  73. if (result.Type == CompletionType.Return)
  74. {
  75. return value;
  76. }
  77. }
  78. finally
  79. {
  80. _engine.LeaveExecutionContext();
  81. }
  82. return Undefined;
  83. }
  84. }
  85. public override bool Set(in Key propertyName, JsValue value, JsValue receiver)
  86. {
  87. AssertValidPropertyName(propertyName);
  88. return base.Set(propertyName, value, receiver);
  89. }
  90. public override JsValue Get(in Key propertyName, JsValue receiver)
  91. {
  92. AssertValidPropertyName(propertyName);
  93. return base.Get(propertyName, receiver);
  94. }
  95. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  96. private void AssertValidPropertyName(in Key propertyName)
  97. {
  98. if (propertyName == KnownKeys.Caller
  99. || propertyName == KnownKeys.Callee
  100. || propertyName == KnownKeys.Arguments)
  101. {
  102. ExceptionHelper.ThrowTypeError(_engine, "'caller', 'callee', and 'arguments' properties may not be accessed on strict mode functions or the arguments objects for calls to them");
  103. }
  104. }
  105. }
  106. }