ArrowFunctionInstance.cs 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
  1. using System.Runtime.CompilerServices;
  2. using Esprima.Ast;
  3. using Jint.Runtime;
  4. using Jint.Runtime.Descriptors;
  5. using Jint.Runtime.Descriptors.Specialized;
  6. using Jint.Runtime.Environments;
  7. using Jint.Runtime.Interpreter;
  8. namespace Jint.Native.Function
  9. {
  10. public sealed class ArrowFunctionInstance : FunctionInstance
  11. {
  12. private readonly JintFunctionDefinition _function;
  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, function, scope, strict ? FunctionThisMode.Strict : FunctionThisMode.Lexical)
  30. {
  31. _function = function;
  32. PreventExtensions();
  33. _prototype = Engine.Function.PrototypeObject;
  34. _length = new LazyPropertyDescriptor(() => JsNumber.Create(function.Initialize(engine, this).Length), PropertyFlag.Configurable);
  35. }
  36. // for example RavenDB wants to inspect this
  37. public IFunction FunctionDeclaration => _function.Function;
  38. /// <summary>
  39. /// http://www.ecma-international.org/ecma-262/5.1/#sec-13.2.1
  40. /// </summary>
  41. public override JsValue Call(JsValue thisArg, JsValue[] arguments)
  42. {
  43. var strict = Strict || _engine._isStrict;
  44. using (new StrictModeScope(strict, true))
  45. {
  46. var localEnv = LexicalEnvironment.NewFunctionEnvironment(_engine, this, Undefined);
  47. _engine.EnterExecutionContext(localEnv, localEnv);
  48. try
  49. {
  50. _engine.FunctionDeclarationInstantiation(
  51. functionInstance: this,
  52. arguments,
  53. localEnv);
  54. var result = _function.Body.Execute();
  55. var value = result.GetValueOrDefault().Clone();
  56. if (result.Type == CompletionType.Throw)
  57. {
  58. ExceptionHelper.ThrowJavaScriptException(_engine, value, result);
  59. }
  60. if (result.Type == CompletionType.Return)
  61. {
  62. return value;
  63. }
  64. }
  65. finally
  66. {
  67. _engine.LeaveExecutionContext();
  68. }
  69. return Undefined;
  70. }
  71. }
  72. public override bool Set(JsValue property, JsValue value, JsValue receiver)
  73. {
  74. AssertValidPropertyName(property);
  75. return base.Set(property, value, receiver);
  76. }
  77. public override JsValue Get(JsValue property, JsValue receiver)
  78. {
  79. AssertValidPropertyName(property);
  80. return base.Get(property, receiver);
  81. }
  82. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  83. private void AssertValidPropertyName(JsValue property)
  84. {
  85. if (property == CommonProperties.Caller
  86. || property == CommonProperties.Callee
  87. || property == CommonProperties.Arguments)
  88. {
  89. ExceptionHelper.ThrowTypeError(_engine, "'caller', 'callee', and 'arguments' properties may not be accessed on strict mode functions or the arguments objects for calls to them");
  90. }
  91. }
  92. }
  93. }