1
- using Esprima ;
1
+ using System ;
2
+ using Esprima ;
2
3
using Esprima . Ast ;
4
+ using Jint . Native . Generator ;
3
5
using Jint . Native . Object ;
4
6
using Jint . Runtime ;
5
7
using Jint . Runtime . Descriptors ;
6
8
using Jint . Runtime . Environments ;
9
+ using Jint . Runtime . Interpreter ;
7
10
8
11
namespace Jint . Native . Function
9
12
{
@@ -32,43 +35,116 @@ public override JsValue Call(JsValue thisObject, JsValue[] arguments)
32
35
return Construct ( arguments , thisObject ) ;
33
36
}
34
37
38
+ public ObjectInstance Construct ( JsValue [ ] arguments , JsValue newTarget )
39
+ {
40
+ var function = CreateDynamicFunction (
41
+ _engine ,
42
+ this ,
43
+ newTarget ,
44
+ FunctionKind . Normal ,
45
+ arguments ) ;
46
+
47
+ return function ;
48
+ }
49
+
35
50
/// <summary>
36
51
/// https://tc39.es/ecma262/#sec-createdynamicfunction
37
52
/// </summary>
38
- public ObjectInstance Construct ( JsValue [ ] arguments , JsValue newTarget )
53
+ internal static FunctionInstance CreateDynamicFunction (
54
+ Engine engine ,
55
+ ObjectInstance constructor ,
56
+ JsValue newTarget ,
57
+ FunctionKind kind ,
58
+ JsValue [ ] args )
39
59
{
40
- var argCount = arguments . Length ;
41
- string p = "" ;
42
- string body = "" ;
60
+ if ( newTarget . IsUndefined ( ) )
61
+ {
62
+ newTarget = constructor ;
63
+ }
64
+
65
+ Func < Intrinsics , ObjectInstance > fallbackProto = null ;
66
+ switch ( kind )
67
+ {
68
+ case FunctionKind . Normal :
69
+ fallbackProto = intrinsics => intrinsics . Function . PrototypeObject ;
70
+ break ;
71
+ case FunctionKind . Generator :
72
+ fallbackProto = intrinsics => intrinsics . GeneratorFunction . PrototypeObject ;
73
+ break ;
74
+ case FunctionKind . AsyncGenerator :
75
+ case FunctionKind . Async :
76
+ default :
77
+ ExceptionHelper . ThrowArgumentOutOfRangeException ( nameof ( kind ) , kind . ToString ( ) ) ;
78
+ break ;
79
+ }
80
+
81
+ var argCount = args . Length ;
82
+ var p = "" ;
83
+ var body = "" ;
43
84
44
85
if ( argCount == 1 )
45
86
{
46
- body = TypeConverter . ToString ( arguments [ 0 ] ) ;
87
+ body = TypeConverter . ToString ( args [ 0 ] ) ;
47
88
}
48
89
else if ( argCount > 1 )
49
90
{
50
- var firstArg = arguments [ 0 ] ;
91
+ var firstArg = args [ 0 ] ;
51
92
p = TypeConverter . ToString ( firstArg ) ;
52
93
for ( var k = 1 ; k < argCount - 1 ; k ++ )
53
94
{
54
- var nextArg = arguments [ k ] ;
95
+ var nextArg = args [ k ] ;
55
96
p += "," + TypeConverter . ToString ( nextArg ) ;
56
97
}
57
98
58
- body = TypeConverter . ToString ( arguments [ argCount - 1 ] ) ;
99
+ body = TypeConverter . ToString ( args [ argCount - 1 ] ) ;
59
100
}
60
101
61
102
IFunction function = null ;
62
103
try
63
104
{
64
- string functionExpression ;
105
+ string functionExpression = null ;
65
106
if ( argCount == 0 )
66
107
{
67
- functionExpression = "function f(){}" ;
108
+ switch ( kind )
109
+ {
110
+ case FunctionKind . Normal :
111
+ functionExpression = "function f(){}" ;
112
+ break ;
113
+ case FunctionKind . Generator :
114
+ functionExpression = "function* f(){}" ;
115
+ break ;
116
+ case FunctionKind . Async :
117
+ ExceptionHelper . ThrowNotImplementedException ( "Async functions not implemented" ) ;
118
+ break ;
119
+ case FunctionKind . AsyncGenerator :
120
+ ExceptionHelper . ThrowNotImplementedException ( "Async generators not implemented" ) ;
121
+ break ;
122
+ default :
123
+ ExceptionHelper . ThrowArgumentOutOfRangeException ( nameof ( kind ) , kind . ToString ( ) ) ;
124
+ break ;
125
+ }
68
126
}
69
127
else
70
128
{
71
- functionExpression = "function f(" ;
129
+ switch ( kind )
130
+ {
131
+ case FunctionKind . Normal :
132
+ functionExpression = "function f(" ;
133
+ break ;
134
+ case FunctionKind . Generator :
135
+ functionExpression = "function* f(" ;
136
+ break ;
137
+ case FunctionKind . Async :
138
+ ExceptionHelper . ThrowNotImplementedException ( "Async functions not implemented" ) ;
139
+ break ;
140
+ case FunctionKind . AsyncGenerator :
141
+ ExceptionHelper . ThrowNotImplementedException ( "Async generators not implemented" ) ;
142
+ break ;
143
+ default :
144
+ ExceptionHelper . ThrowArgumentOutOfRangeException ( nameof ( kind ) , kind . ToString ( ) ) ;
145
+ break ;
146
+ }
147
+
72
148
if ( p . IndexOf ( '/' ) != - 1 )
73
149
{
74
150
// ensure comments don't screw up things
@@ -95,49 +171,70 @@ public ObjectInstance Construct(JsValue[] arguments, JsValue newTarget)
95
171
var parser = new JavaScriptParser ( functionExpression , ParserOptions ) ;
96
172
function = ( IFunction ) parser . ParseScript ( ) . Body [ 0 ] ;
97
173
}
98
- catch ( ParserException )
174
+ catch ( ParserException ex )
99
175
{
100
- ExceptionHelper . ThrowSyntaxError ( _realm ) ;
176
+ ExceptionHelper . ThrowSyntaxError ( engine . Realm , ex . Message ) ;
101
177
}
102
178
103
- // TODO generators etc, rewrite logic
104
- var proto = GetPrototypeFromConstructor ( newTarget , static intrinsics => intrinsics . Function . PrototypeObject ) ;
105
-
106
- var functionObject = new ScriptFunctionInstance (
107
- Engine ,
108
- function ,
109
- _realm . GlobalEnv ,
110
- function . Strict ,
111
- proto )
112
- {
113
- _realm = _realm
114
- } ;
179
+ var proto = GetPrototypeFromConstructor ( engine , newTarget , fallbackProto ) ;
180
+ var thisMode = function . Strict
181
+ ? FunctionThisMode . Strict
182
+ : FunctionThisMode . Global ;
115
183
116
- functionObject . MakeConstructor ( ) ;
184
+ FunctionInstance F = new ScriptFunctionInstance (
185
+ engine ,
186
+ new JintFunctionDefinition ( engine , function ) ,
187
+ engine . Realm . GlobalEnv ,
188
+ thisMode ,
189
+ proto ) ;
117
190
118
- // the function is not actually a named function
119
- functionObject . SetFunctionName ( _functionNameAnonymous , force : true ) ;
191
+ if ( kind == FunctionKind . Generator )
192
+ {
193
+ F = new GeneratorFunctionInstance ( engine , engine . Realm , F ) ;
194
+ }
195
+ else if ( kind == FunctionKind . AsyncGenerator )
196
+ {
197
+ // TODO
198
+ // Let prototype be ! OrdinaryObjectCreate(%AsyncGeneratorFunction.prototype.prototype%).
199
+ // Perform DefinePropertyOrThrow(F, "prototype", PropertyDescriptor { [[Value]]: prototype, [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: false }).
200
+ ExceptionHelper . ThrowNotImplementedException ( ) ;
201
+ }
202
+ else if ( kind == FunctionKind . Normal )
203
+ {
204
+ F . MakeConstructor ( ) ;
205
+ }
120
206
121
- return functionObject ;
207
+ F . SetFunctionName ( _functionNameAnonymous , force : true ) ;
208
+ return F ;
122
209
}
123
210
124
211
/// <summary>
125
212
/// https://tc39.es/ecma262/#sec-runtime-semantics-instantiatefunctionobject
126
213
/// </summary>
127
- internal FunctionInstance InstantiateFunctionObject ( FunctionDeclaration functionDeclaration , EnvironmentRecord env )
214
+ internal FunctionInstance InstantiateFunctionObject ( FunctionDeclaration functionDeclaration , EnvironmentRecord scope )
128
215
{
129
- var functionObject = new ScriptFunctionInstance (
216
+ var strict = functionDeclaration . Strict || _engine . _isStrict ;
217
+ FunctionInstance F = new ScriptFunctionInstance (
130
218
Engine ,
131
219
functionDeclaration ,
132
- env ,
133
- functionDeclaration . Strict || _engine . _isStrict )
134
- {
135
- _realm = _realm
136
- } ;
220
+ scope ,
221
+ strict ,
222
+ _realm . Intrinsics . Function . PrototypeObject ) ; ;
137
223
138
- functionObject . MakeConstructor ( ) ;
224
+ var name = functionDeclaration . Id ? . Name ?? "default" ;
225
+ if ( functionDeclaration . Generator )
226
+ {
227
+ // https://tc39.es/ecma262/#sec-generator-function-definitions-runtime-semantics-instantiatefunctionobject
228
+ F = new GeneratorFunctionInstance ( _engine , _realm , F ) ;
229
+ }
230
+ else
231
+ {
232
+ // https://tc39.es/ecma262/#sec-function-definitions-runtime-semantics-instantiatefunctionobject
233
+ F . MakeConstructor ( ) ;
234
+ }
139
235
140
- return functionObject ;
236
+ F . SetFunctionName ( name ) ;
237
+ return F ;
141
238
}
142
239
}
143
240
}
0 commit comments