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