1 package goja
2
3 import (
4 "math"
5 "sync"
6 )
7
8 func (r *Runtime) functionCtor(args []Value, proto *Object, async, generator bool) *Object {
9 var sb StringBuilder
10 if async {
11 if generator {
12 sb.WriteString(asciiString("(async function* anonymous("))
13 } else {
14 sb.WriteString(asciiString("(async function anonymous("))
15 }
16 } else {
17 if generator {
18 sb.WriteString(asciiString("(function* anonymous("))
19 } else {
20 sb.WriteString(asciiString("(function anonymous("))
21 }
22 }
23 if len(args) > 1 {
24 ar := args[:len(args)-1]
25 for i, arg := range ar {
26 sb.WriteString(arg.toString())
27 if i < len(ar)-1 {
28 sb.WriteRune(',')
29 }
30 }
31 }
32 sb.WriteString(asciiString("\n) {\n"))
33 if len(args) > 0 {
34 sb.WriteString(args[len(args)-1].toString())
35 }
36 sb.WriteString(asciiString("\n})"))
37
38 ret := r.toObject(r.eval(sb.String(), false, false))
39 ret.self.setProto(proto, true)
40 return ret
41 }
42
43 func (r *Runtime) builtin_Function(args []Value, proto *Object) *Object {
44 return r.functionCtor(args, proto, false, false)
45 }
46
47 func (r *Runtime) builtin_asyncFunction(args []Value, proto *Object) *Object {
48 return r.functionCtor(args, proto, true, false)
49 }
50
51 func (r *Runtime) builtin_generatorFunction(args []Value, proto *Object) *Object {
52 return r.functionCtor(args, proto, false, true)
53 }
54
55 func (r *Runtime) functionproto_toString(call FunctionCall) Value {
56 obj := r.toObject(call.This)
57 switch f := obj.self.(type) {
58 case funcObjectImpl:
59 return f.source()
60 case *proxyObject:
61 if _, ok := f.target.self.(funcObjectImpl); ok {
62 return asciiString("function () { [native code] }")
63 }
64 }
65 panic(r.NewTypeError("Function.prototype.toString requires that 'this' be a Function"))
66 }
67
68 func (r *Runtime) functionproto_hasInstance(call FunctionCall) Value {
69 if o, ok := call.This.(*Object); ok {
70 if _, ok = o.self.assertCallable(); ok {
71 return r.toBoolean(o.self.hasInstance(call.Argument(0)))
72 }
73 }
74
75 return valueFalse
76 }
77
78 func (r *Runtime) createListFromArrayLike(a Value) []Value {
79 o := r.toObject(a)
80 if arr := r.checkStdArrayObj(o); arr != nil {
81 return arr.values
82 }
83 l := toLength(o.self.getStr("length", nil))
84 res := make([]Value, 0, l)
85 for k := int64(0); k < l; k++ {
86 res = append(res, nilSafe(o.self.getIdx(valueInt(k), nil)))
87 }
88 return res
89 }
90
91 func (r *Runtime) functionproto_apply(call FunctionCall) Value {
92 var args []Value
93 if len(call.Arguments) >= 2 {
94 args = r.createListFromArrayLike(call.Arguments[1])
95 }
96
97 f := r.toCallable(call.This)
98 return f(FunctionCall{
99 This: call.Argument(0),
100 Arguments: args,
101 })
102 }
103
104 func (r *Runtime) functionproto_call(call FunctionCall) Value {
105 var args []Value
106 if len(call.Arguments) > 0 {
107 args = call.Arguments[1:]
108 }
109
110 f := r.toCallable(call.This)
111 return f(FunctionCall{
112 This: call.Argument(0),
113 Arguments: args,
114 })
115 }
116
117 func (r *Runtime) boundCallable(target func(FunctionCall) Value, boundArgs []Value) func(FunctionCall) Value {
118 var this Value
119 var args []Value
120 if len(boundArgs) > 0 {
121 this = boundArgs[0]
122 args = make([]Value, len(boundArgs)-1)
123 copy(args, boundArgs[1:])
124 } else {
125 this = _undefined
126 }
127 return func(call FunctionCall) Value {
128 a := append(args, call.Arguments...)
129 return target(FunctionCall{
130 This: this,
131 Arguments: a,
132 })
133 }
134 }
135
136 func (r *Runtime) boundConstruct(f *Object, target func([]Value, *Object) *Object, boundArgs []Value) func([]Value, *Object) *Object {
137 if target == nil {
138 return nil
139 }
140 var args []Value
141 if len(boundArgs) > 1 {
142 args = make([]Value, len(boundArgs)-1)
143 copy(args, boundArgs[1:])
144 }
145 return func(fargs []Value, newTarget *Object) *Object {
146 a := append(args, fargs...)
147 if newTarget == f {
148 newTarget = nil
149 }
150 return target(a, newTarget)
151 }
152 }
153
154 func (r *Runtime) functionproto_bind(call FunctionCall) Value {
155 obj := r.toObject(call.This)
156
157 fcall := r.toCallable(call.This)
158 construct := obj.self.assertConstructor()
159
160 var l = _positiveZero
161 if obj.self.hasOwnPropertyStr("length") {
162 var li int64
163 switch lenProp := nilSafe(obj.self.getStr("length", nil)).(type) {
164 case valueInt:
165 li = lenProp.ToInteger()
166 case valueFloat:
167 switch lenProp {
168 case _positiveInf:
169 l = lenProp
170 goto lenNotInt
171 case _negativeInf:
172 goto lenNotInt
173 case _negativeZero:
174
175 default:
176 if !math.IsNaN(float64(lenProp)) {
177 li = int64(math.Abs(float64(lenProp)))
178 }
179 }
180 }
181 if len(call.Arguments) > 1 {
182 li -= int64(len(call.Arguments)) - 1
183 }
184 if li < 0 {
185 li = 0
186 }
187 l = intToValue(li)
188 }
189 lenNotInt:
190 name := obj.self.getStr("name", nil)
191 nameStr := stringBound_
192 if s, ok := name.(String); ok {
193 nameStr = nameStr.Concat(s)
194 }
195
196 v := &Object{runtime: r}
197 ff := r.newNativeFuncAndConstruct(v, r.boundCallable(fcall, call.Arguments), r.boundConstruct(v, construct, call.Arguments), nil, nameStr.string(), l)
198 bf := &boundFuncObject{
199 nativeFuncObject: *ff,
200 wrapped: obj,
201 }
202 bf.prototype = obj.self.proto()
203 v.self = bf
204
205 return v
206 }
207
208 func (r *Runtime) getThrower() *Object {
209 ret := r.global.thrower
210 if ret == nil {
211 ret = r.newNativeFunc(r.builtin_thrower, "", 0)
212 r.global.thrower = ret
213 r.object_freeze(FunctionCall{Arguments: []Value{ret}})
214 }
215 return ret
216 }
217
218 func (r *Runtime) newThrowerProperty(configurable bool) Value {
219 thrower := r.getThrower()
220 return &valueProperty{
221 getterFunc: thrower,
222 setterFunc: thrower,
223 accessor: true,
224 configurable: configurable,
225 }
226 }
227
228 func createFunctionProtoTemplate() *objectTemplate {
229 t := newObjectTemplate()
230 t.protoFactory = func(r *Runtime) *Object {
231 return r.global.ObjectPrototype
232 }
233
234 t.putStr("constructor", func(r *Runtime) Value { return valueProp(r.getFunction(), true, false, true) })
235
236 t.putStr("length", func(r *Runtime) Value { return valueProp(_positiveZero, false, false, true) })
237 t.putStr("name", func(r *Runtime) Value { return valueProp(stringEmpty, false, false, true) })
238
239 t.putStr("apply", func(r *Runtime) Value { return r.methodProp(r.functionproto_apply, "apply", 2) })
240 t.putStr("bind", func(r *Runtime) Value { return r.methodProp(r.functionproto_bind, "bind", 1) })
241 t.putStr("call", func(r *Runtime) Value { return r.methodProp(r.functionproto_call, "call", 1) })
242 t.putStr("toString", func(r *Runtime) Value { return r.methodProp(r.functionproto_toString, "toString", 0) })
243
244 t.putStr("caller", func(r *Runtime) Value { return r.newThrowerProperty(true) })
245 t.putStr("arguments", func(r *Runtime) Value { return r.newThrowerProperty(true) })
246
247 t.putSym(SymHasInstance, func(r *Runtime) Value {
248 return valueProp(r.newNativeFunc(r.functionproto_hasInstance, "[Symbol.hasInstance]", 1), false, false, false)
249 })
250
251 return t
252 }
253
254 var functionProtoTemplate *objectTemplate
255 var functionProtoTemplateOnce sync.Once
256
257 func getFunctionProtoTemplate() *objectTemplate {
258 functionProtoTemplateOnce.Do(func() {
259 functionProtoTemplate = createFunctionProtoTemplate()
260 })
261 return functionProtoTemplate
262 }
263
264 func (r *Runtime) getFunctionPrototype() *Object {
265 ret := r.global.FunctionPrototype
266 if ret == nil {
267 ret = &Object{runtime: r}
268 r.global.FunctionPrototype = ret
269 r.newTemplatedFuncObject(getFunctionProtoTemplate(), ret, func(FunctionCall) Value {
270 return _undefined
271 }, nil)
272 }
273 return ret
274 }
275
276 func (r *Runtime) createFunction(v *Object) objectImpl {
277 return r.newNativeFuncConstructObj(v, r.builtin_Function, "Function", r.getFunctionPrototype(), 1)
278 }
279
280 func (r *Runtime) createAsyncFunctionProto(val *Object) objectImpl {
281 o := &baseObject{
282 class: classObject,
283 val: val,
284 extensible: true,
285 prototype: r.getFunctionPrototype(),
286 }
287 o.init()
288
289 o._putProp("constructor", r.getAsyncFunction(), true, false, true)
290
291 o._putSym(SymToStringTag, valueProp(asciiString(classAsyncFunction), false, false, true))
292
293 return o
294 }
295
296 func (r *Runtime) getAsyncFunctionPrototype() *Object {
297 var o *Object
298 if o = r.global.AsyncFunctionPrototype; o == nil {
299 o = &Object{runtime: r}
300 r.global.AsyncFunctionPrototype = o
301 o.self = r.createAsyncFunctionProto(o)
302 }
303 return o
304 }
305
306 func (r *Runtime) createAsyncFunction(val *Object) objectImpl {
307 o := r.newNativeFuncConstructObj(val, r.builtin_asyncFunction, "AsyncFunction", r.getAsyncFunctionPrototype(), 1)
308
309 return o
310 }
311
312 func (r *Runtime) getAsyncFunction() *Object {
313 var o *Object
314 if o = r.global.AsyncFunction; o == nil {
315 o = &Object{runtime: r}
316 r.global.AsyncFunction = o
317 o.self = r.createAsyncFunction(o)
318 }
319 return o
320 }
321
322 func (r *Runtime) builtin_genproto_next(call FunctionCall) Value {
323 if o, ok := call.This.(*Object); ok {
324 if gen, ok := o.self.(*generatorObject); ok {
325 return gen.next(call.Argument(0))
326 }
327 }
328 panic(r.NewTypeError("Method [Generator].prototype.next called on incompatible receiver"))
329 }
330
331 func (r *Runtime) builtin_genproto_return(call FunctionCall) Value {
332 if o, ok := call.This.(*Object); ok {
333 if gen, ok := o.self.(*generatorObject); ok {
334 return gen._return(call.Argument(0))
335 }
336 }
337 panic(r.NewTypeError("Method [Generator].prototype.return called on incompatible receiver"))
338 }
339
340 func (r *Runtime) builtin_genproto_throw(call FunctionCall) Value {
341 if o, ok := call.This.(*Object); ok {
342 if gen, ok := o.self.(*generatorObject); ok {
343 return gen.throw(call.Argument(0))
344 }
345 }
346 panic(r.NewTypeError("Method [Generator].prototype.throw called on incompatible receiver"))
347 }
348
349 func (r *Runtime) createGeneratorFunctionProto(val *Object) objectImpl {
350 o := newBaseObjectObj(val, r.getFunctionPrototype(), classObject)
351
352 o._putProp("constructor", r.getGeneratorFunction(), false, false, true)
353 o._putProp("prototype", r.getGeneratorPrototype(), false, false, true)
354 o._putSym(SymToStringTag, valueProp(asciiString(classGeneratorFunction), false, false, true))
355
356 return o
357 }
358
359 func (r *Runtime) getGeneratorFunctionPrototype() *Object {
360 var o *Object
361 if o = r.global.GeneratorFunctionPrototype; o == nil {
362 o = &Object{runtime: r}
363 r.global.GeneratorFunctionPrototype = o
364 o.self = r.createGeneratorFunctionProto(o)
365 }
366 return o
367 }
368
369 func (r *Runtime) createGeneratorFunction(val *Object) objectImpl {
370 o := r.newNativeFuncConstructObj(val, r.builtin_generatorFunction, "GeneratorFunction", r.getGeneratorFunctionPrototype(), 1)
371 return o
372 }
373
374 func (r *Runtime) getGeneratorFunction() *Object {
375 var o *Object
376 if o = r.global.GeneratorFunction; o == nil {
377 o = &Object{runtime: r}
378 r.global.GeneratorFunction = o
379 o.self = r.createGeneratorFunction(o)
380 }
381 return o
382 }
383
384 func (r *Runtime) createGeneratorProto(val *Object) objectImpl {
385 o := newBaseObjectObj(val, r.getIteratorPrototype(), classObject)
386
387 o._putProp("constructor", r.getGeneratorFunctionPrototype(), false, false, true)
388 o._putProp("next", r.newNativeFunc(r.builtin_genproto_next, "next", 1), true, false, true)
389 o._putProp("return", r.newNativeFunc(r.builtin_genproto_return, "return", 1), true, false, true)
390 o._putProp("throw", r.newNativeFunc(r.builtin_genproto_throw, "throw", 1), true, false, true)
391
392 o._putSym(SymToStringTag, valueProp(asciiString(classGenerator), false, false, true))
393
394 return o
395 }
396
397 func (r *Runtime) getGeneratorPrototype() *Object {
398 var o *Object
399 if o = r.global.GeneratorPrototype; o == nil {
400 o = &Object{runtime: r}
401 r.global.GeneratorPrototype = o
402 o.self = r.createGeneratorProto(o)
403 }
404 return o
405 }
406
407 func (r *Runtime) getFunction() *Object {
408 ret := r.global.Function
409 if ret == nil {
410 ret = &Object{runtime: r}
411 r.global.Function = ret
412 ret.self = r.createFunction(ret)
413 }
414
415 return ret
416 }
417
View as plain text