github.com/dop251/goja@v0.0.0-20240220182346-e401ed450204/builtin_function.go (about) 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 // no-op, li == 0 175 default: 176 if !math.IsNaN(float64(lenProp)) { 177 li = int64(math.Abs(float64(lenProp))) 178 } // else li = 0 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 }