1package goja 2 3import ( 4 "reflect" 5 6 "github.com/dop251/goja/unistring" 7) 8 9type baseFuncObject struct { 10 baseObject 11 12 lenProp valueProperty 13} 14 15type baseJsFuncObject struct { 16 baseFuncObject 17 18 stash *stash 19 prg *Program 20 src string 21 strict bool 22} 23 24type funcObject struct { 25 baseJsFuncObject 26} 27 28type arrowFuncObject struct { 29 baseJsFuncObject 30 this Value 31 newTarget Value 32} 33 34type nativeFuncObject struct { 35 baseFuncObject 36 37 f func(FunctionCall) Value 38 construct func(args []Value, newTarget *Object) *Object 39} 40 41type boundFuncObject struct { 42 nativeFuncObject 43 wrapped *Object 44} 45 46func (f *nativeFuncObject) export(*objectExportCtx) interface{} { 47 return f.f 48} 49 50func (f *nativeFuncObject) exportType() reflect.Type { 51 return reflect.TypeOf(f.f) 52} 53 54func (f *funcObject) _addProto(n unistring.String) Value { 55 if n == "prototype" { 56 if _, exists := f.values[n]; !exists { 57 return f.addPrototype() 58 } 59 } 60 return nil 61} 62 63func (f *funcObject) getStr(p unistring.String, receiver Value) Value { 64 return f.getStrWithOwnProp(f.getOwnPropStr(p), p, receiver) 65} 66 67func (f *funcObject) getOwnPropStr(name unistring.String) Value { 68 if v := f._addProto(name); v != nil { 69 return v 70 } 71 72 return f.baseObject.getOwnPropStr(name) 73} 74 75func (f *funcObject) setOwnStr(name unistring.String, val Value, throw bool) bool { 76 f._addProto(name) 77 return f.baseObject.setOwnStr(name, val, throw) 78} 79 80func (f *funcObject) setForeignStr(name unistring.String, val, receiver Value, throw bool) (bool, bool) { 81 return f._setForeignStr(name, f.getOwnPropStr(name), val, receiver, throw) 82} 83 84func (f *funcObject) deleteStr(name unistring.String, throw bool) bool { 85 f._addProto(name) 86 return f.baseObject.deleteStr(name, throw) 87} 88 89func (f *funcObject) addPrototype() Value { 90 proto := f.val.runtime.NewObject() 91 proto.self._putProp("constructor", f.val, true, false, true) 92 return f._putProp("prototype", proto, true, false, false) 93} 94 95func (f *funcObject) hasOwnPropertyStr(name unistring.String) bool { 96 if r := f.baseObject.hasOwnPropertyStr(name); r { 97 return true 98 } 99 100 if name == "prototype" { 101 return true 102 } 103 return false 104} 105 106func (f *funcObject) ownKeys(all bool, accum []Value) []Value { 107 if all { 108 if _, exists := f.values["prototype"]; !exists { 109 accum = append(accum, asciiString("prototype")) 110 } 111 } 112 return f.baseFuncObject.ownKeys(all, accum) 113} 114 115func (f *funcObject) construct(args []Value, newTarget *Object) *Object { 116 if newTarget == nil { 117 newTarget = f.val 118 } 119 proto := newTarget.self.getStr("prototype", nil) 120 var protoObj *Object 121 if p, ok := proto.(*Object); ok { 122 protoObj = p 123 } else { 124 protoObj = f.val.runtime.global.ObjectPrototype 125 } 126 127 obj := f.val.runtime.newBaseObject(protoObj, classObject).val 128 ret := f.call(FunctionCall{ 129 This: obj, 130 Arguments: args, 131 }, newTarget) 132 133 if ret, ok := ret.(*Object); ok { 134 return ret 135 } 136 return obj 137} 138 139func (f *funcObject) Call(call FunctionCall) Value { 140 return f.call(call, nil) 141} 142 143func (f *arrowFuncObject) Call(call FunctionCall) Value { 144 return f._call(call, f.newTarget, f.this) 145} 146 147func (f *baseJsFuncObject) _call(call FunctionCall, newTarget, this Value) Value { 148 vm := f.val.runtime.vm 149 pc := vm.pc 150 151 vm.stack.expand(vm.sp + len(call.Arguments) + 1) 152 vm.stack[vm.sp] = f.val 153 vm.sp++ 154 vm.stack[vm.sp] = this 155 vm.sp++ 156 for _, arg := range call.Arguments { 157 if arg != nil { 158 vm.stack[vm.sp] = arg 159 } else { 160 vm.stack[vm.sp] = _undefined 161 } 162 vm.sp++ 163 } 164 165 vm.pc = -1 166 vm.pushCtx() 167 vm.args = len(call.Arguments) 168 vm.prg = f.prg 169 vm.stash = f.stash 170 vm.newTarget = newTarget 171 vm.pc = 0 172 vm.run() 173 vm.pc = pc 174 vm.halt = false 175 return vm.pop() 176 177} 178 179func (f *funcObject) call(call FunctionCall, newTarget Value) Value { 180 return f._call(call, newTarget, nilSafe(call.This)) 181} 182 183func (f *funcObject) export(*objectExportCtx) interface{} { 184 return f.Call 185} 186 187func (f *funcObject) exportType() reflect.Type { 188 return reflect.TypeOf(f.Call) 189} 190 191func (f *funcObject) assertCallable() (func(FunctionCall) Value, bool) { 192 return f.Call, true 193} 194 195func (f *funcObject) assertConstructor() func(args []Value, newTarget *Object) *Object { 196 return f.construct 197} 198 199func (f *arrowFuncObject) exportType() reflect.Type { 200 return reflect.TypeOf(f.Call) 201} 202 203func (f *arrowFuncObject) assertCallable() (func(FunctionCall) Value, bool) { 204 return f.Call, true 205} 206 207func (f *baseFuncObject) init(name unistring.String, length int) { 208 f.baseObject.init() 209 210 f._putProp("name", stringValueFromRaw(name), false, false, true) 211 212 f.lenProp.configurable = true 213 f.lenProp.value = valueInt(length) 214 f._put("length", &f.lenProp) 215} 216 217func (f *baseFuncObject) hasInstance(v Value) bool { 218 if v, ok := v.(*Object); ok { 219 o := f.val.self.getStr("prototype", nil) 220 if o1, ok := o.(*Object); ok { 221 for { 222 v = v.self.proto() 223 if v == nil { 224 return false 225 } 226 if o1 == v { 227 return true 228 } 229 } 230 } else { 231 f.val.runtime.typeErrorResult(true, "prototype is not an object") 232 } 233 } 234 235 return false 236} 237 238func (f *nativeFuncObject) defaultConstruct(ccall func(ConstructorCall) *Object, args []Value, newTarget *Object) *Object { 239 proto := f.getStr("prototype", nil) 240 var protoObj *Object 241 if p, ok := proto.(*Object); ok { 242 protoObj = p 243 } else { 244 protoObj = f.val.runtime.global.ObjectPrototype 245 } 246 obj := f.val.runtime.newBaseObject(protoObj, classObject).val 247 ret := ccall(ConstructorCall{ 248 This: obj, 249 Arguments: args, 250 NewTarget: newTarget, 251 }) 252 253 if ret != nil { 254 return ret 255 } 256 return obj 257} 258 259func (f *nativeFuncObject) assertCallable() (func(FunctionCall) Value, bool) { 260 if f.f != nil { 261 return f.f, true 262 } 263 return nil, false 264} 265 266func (f *nativeFuncObject) assertConstructor() func(args []Value, newTarget *Object) *Object { 267 return f.construct 268} 269 270func (f *boundFuncObject) getStr(p unistring.String, receiver Value) Value { 271 return f.getStrWithOwnProp(f.getOwnPropStr(p), p, receiver) 272} 273 274func (f *boundFuncObject) getOwnPropStr(name unistring.String) Value { 275 if name == "caller" || name == "arguments" { 276 return f.val.runtime.global.throwerProperty 277 } 278 279 return f.nativeFuncObject.getOwnPropStr(name) 280} 281 282func (f *boundFuncObject) deleteStr(name unistring.String, throw bool) bool { 283 if name == "caller" || name == "arguments" { 284 return true 285 } 286 return f.nativeFuncObject.deleteStr(name, throw) 287} 288 289func (f *boundFuncObject) setOwnStr(name unistring.String, val Value, throw bool) bool { 290 if name == "caller" || name == "arguments" { 291 panic(f.val.runtime.NewTypeError("'caller' and 'arguments' are restricted function properties and cannot be accessed in this context.")) 292 } 293 return f.nativeFuncObject.setOwnStr(name, val, throw) 294} 295 296func (f *boundFuncObject) setForeignStr(name unistring.String, val, receiver Value, throw bool) (bool, bool) { 297 return f._setForeignStr(name, f.getOwnPropStr(name), val, receiver, throw) 298} 299 300func (f *boundFuncObject) hasInstance(v Value) bool { 301 return instanceOfOperator(v, f.wrapped) 302} 303