123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319 |
- package goja
- import (
- "reflect"
- "github.com/dop251/goja/unistring"
- )
- type baseFuncObject struct {
- baseObject
- lenProp valueProperty
- }
- type baseJsFuncObject struct {
- baseFuncObject
- stash *stash
- prg *Program
- src string
- strict bool
- }
- type funcObject struct {
- baseJsFuncObject
- }
- type methodFuncObject struct {
- baseJsFuncObject
- }
- type arrowFuncObject struct {
- baseJsFuncObject
- this Value
- newTarget Value
- }
- type nativeFuncObject struct {
- baseFuncObject
- f func(FunctionCall) Value
- construct func(args []Value, newTarget *Object) *Object
- }
- type boundFuncObject struct {
- nativeFuncObject
- wrapped *Object
- }
- func (f *nativeFuncObject) export(*objectExportCtx) interface{} {
- return f.f
- }
- func (f *nativeFuncObject) exportType() reflect.Type {
- return reflect.TypeOf(f.f)
- }
- func (f *funcObject) _addProto(n unistring.String) Value {
- if n == "prototype" {
- if _, exists := f.values[n]; !exists {
- return f.addPrototype()
- }
- }
- return nil
- }
- func (f *funcObject) getStr(p unistring.String, receiver Value) Value {
- return f.getStrWithOwnProp(f.getOwnPropStr(p), p, receiver)
- }
- func (f *funcObject) getOwnPropStr(name unistring.String) Value {
- if v := f._addProto(name); v != nil {
- return v
- }
- return f.baseObject.getOwnPropStr(name)
- }
- func (f *funcObject) setOwnStr(name unistring.String, val Value, throw bool) bool {
- f._addProto(name)
- return f.baseObject.setOwnStr(name, val, throw)
- }
- func (f *funcObject) setForeignStr(name unistring.String, val, receiver Value, throw bool) (bool, bool) {
- return f._setForeignStr(name, f.getOwnPropStr(name), val, receiver, throw)
- }
- func (f *funcObject) defineOwnPropertyStr(name unistring.String, descr PropertyDescriptor, throw bool) bool {
- f._addProto(name)
- return f.baseObject.defineOwnPropertyStr(name, descr, throw)
- }
- func (f *funcObject) deleteStr(name unistring.String, throw bool) bool {
- f._addProto(name)
- return f.baseObject.deleteStr(name, throw)
- }
- func (f *funcObject) addPrototype() Value {
- proto := f.val.runtime.NewObject()
- proto.self._putProp("constructor", f.val, true, false, true)
- return f._putProp("prototype", proto, true, false, false)
- }
- func (f *funcObject) hasOwnPropertyStr(name unistring.String) bool {
- if r := f.baseObject.hasOwnPropertyStr(name); r {
- return true
- }
- if name == "prototype" {
- return true
- }
- return false
- }
- func (f *funcObject) stringKeys(all bool, accum []Value) []Value {
- if all {
- if _, exists := f.values["prototype"]; !exists {
- accum = append(accum, asciiString("prototype"))
- }
- }
- return f.baseFuncObject.stringKeys(all, accum)
- }
- func (f *funcObject) iterateStringKeys() iterNextFunc {
- if _, exists := f.values["prototype"]; !exists {
- f.addPrototype()
- }
- return f.baseFuncObject.iterateStringKeys()
- }
- func (f *funcObject) construct(args []Value, newTarget *Object) *Object {
- if newTarget == nil {
- newTarget = f.val
- }
- proto := newTarget.self.getStr("prototype", nil)
- var protoObj *Object
- if p, ok := proto.(*Object); ok {
- protoObj = p
- } else {
- protoObj = f.val.runtime.global.ObjectPrototype
- }
- obj := f.val.runtime.newBaseObject(protoObj, classObject).val
- ret := f.call(FunctionCall{
- This: obj,
- Arguments: args,
- }, newTarget)
- if ret, ok := ret.(*Object); ok {
- return ret
- }
- return obj
- }
- func (f *baseJsFuncObject) Call(call FunctionCall) Value {
- return f.call(call, nil)
- }
- func (f *arrowFuncObject) Call(call FunctionCall) Value {
- return f._call(call, f.newTarget, f.this)
- }
- func (f *baseJsFuncObject) _call(call FunctionCall, newTarget, this Value) Value {
- vm := f.val.runtime.vm
- pc := vm.pc
- vm.stack.expand(vm.sp + len(call.Arguments) + 1)
- vm.stack[vm.sp] = f.val
- vm.sp++
- vm.stack[vm.sp] = this
- vm.sp++
- for _, arg := range call.Arguments {
- if arg != nil {
- vm.stack[vm.sp] = arg
- } else {
- vm.stack[vm.sp] = _undefined
- }
- vm.sp++
- }
- vm.pc = -1
- vm.pushCtx()
- vm.args = len(call.Arguments)
- vm.prg = f.prg
- vm.stash = f.stash
- vm.newTarget = newTarget
- vm.pc = 0
- vm.run()
- vm.pc = pc
- vm.halt = false
- return vm.pop()
- }
- func (f *baseJsFuncObject) call(call FunctionCall, newTarget Value) Value {
- return f._call(call, newTarget, nilSafe(call.This))
- }
- func (f *funcObject) export(*objectExportCtx) interface{} {
- return f.Call
- }
- func (f *funcObject) exportType() reflect.Type {
- return reflect.TypeOf(f.Call)
- }
- func (f *baseJsFuncObject) assertCallable() (func(FunctionCall) Value, bool) {
- return f.Call, true
- }
- func (f *funcObject) assertConstructor() func(args []Value, newTarget *Object) *Object {
- return f.construct
- }
- func (f *arrowFuncObject) exportType() reflect.Type {
- return reflect.TypeOf(f.Call)
- }
- func (f *arrowFuncObject) assertCallable() (func(FunctionCall) Value, bool) {
- return f.Call, true
- }
- func (f *baseFuncObject) init(name unistring.String, length Value) {
- f.baseObject.init()
- f.lenProp.configurable = true
- f.lenProp.value = length
- f._put("length", &f.lenProp)
- f._putProp("name", stringValueFromRaw(name), false, false, true)
- }
- func (f *baseFuncObject) hasInstance(v Value) bool {
- if v, ok := v.(*Object); ok {
- o := f.val.self.getStr("prototype", nil)
- if o1, ok := o.(*Object); ok {
- for {
- v = v.self.proto()
- if v == nil {
- return false
- }
- if o1 == v {
- return true
- }
- }
- } else {
- f.val.runtime.typeErrorResult(true, "prototype is not an object")
- }
- }
- return false
- }
- func (f *nativeFuncObject) defaultConstruct(ccall func(ConstructorCall) *Object, args []Value, newTarget *Object) *Object {
- proto := f.getStr("prototype", nil)
- var protoObj *Object
- if p, ok := proto.(*Object); ok {
- protoObj = p
- } else {
- protoObj = f.val.runtime.global.ObjectPrototype
- }
- obj := f.val.runtime.newBaseObject(protoObj, classObject).val
- ret := ccall(ConstructorCall{
- This: obj,
- Arguments: args,
- NewTarget: newTarget,
- })
- if ret != nil {
- return ret
- }
- return obj
- }
- func (f *nativeFuncObject) assertCallable() (func(FunctionCall) Value, bool) {
- if f.f != nil {
- return f.f, true
- }
- return nil, false
- }
- func (f *nativeFuncObject) assertConstructor() func(args []Value, newTarget *Object) *Object {
- return f.construct
- }
- /*func (f *boundFuncObject) getStr(p unistring.String, receiver Value) Value {
- return f.getStrWithOwnProp(f.getOwnPropStr(p), p, receiver)
- }
- func (f *boundFuncObject) getOwnPropStr(name unistring.String) Value {
- if name == "caller" || name == "arguments" {
- return f.val.runtime.global.throwerProperty
- }
- return f.nativeFuncObject.getOwnPropStr(name)
- }
- func (f *boundFuncObject) deleteStr(name unistring.String, throw bool) bool {
- if name == "caller" || name == "arguments" {
- return true
- }
- return f.nativeFuncObject.deleteStr(name, throw)
- }
- func (f *boundFuncObject) setOwnStr(name unistring.String, val Value, throw bool) bool {
- if name == "caller" || name == "arguments" {
- panic(f.val.runtime.NewTypeError("'caller' and 'arguments' are restricted function properties and cannot be accessed in this context."))
- }
- return f.nativeFuncObject.setOwnStr(name, val, throw)
- }
- func (f *boundFuncObject) setForeignStr(name unistring.String, val, receiver Value, throw bool) (bool, bool) {
- return f._setForeignStr(name, f.getOwnPropStr(name), val, receiver, throw)
- }
- */
- func (f *boundFuncObject) hasInstance(v Value) bool {
- return instanceOfOperator(v, f.wrapped)
- }
|