|
@@ -69,16 +69,6 @@ type baseObject struct {
|
|
|
propNames []string
|
|
|
}
|
|
|
|
|
|
-type funcObject struct {
|
|
|
- baseObject
|
|
|
-
|
|
|
- nameProp, lenProp valueProperty
|
|
|
-
|
|
|
- stash *stash
|
|
|
- prg *Program
|
|
|
- src string
|
|
|
-}
|
|
|
-
|
|
|
type primitiveValueObject struct {
|
|
|
baseObject
|
|
|
pValue Value
|
|
@@ -104,25 +94,6 @@ func (f FunctionCall) Argument(idx int) Value {
|
|
|
return _undefined
|
|
|
}
|
|
|
|
|
|
-type nativeFuncObject struct {
|
|
|
- baseObject
|
|
|
- nameProp, lenProp valueProperty
|
|
|
- f func(FunctionCall) Value
|
|
|
- construct func(args []Value) *Object
|
|
|
-}
|
|
|
-
|
|
|
-func (f *nativeFuncObject) export() interface{} {
|
|
|
- return f.f
|
|
|
-}
|
|
|
-
|
|
|
-func (f *nativeFuncObject) exportType() reflect.Type {
|
|
|
- return reflect.TypeOf(f.f)
|
|
|
-}
|
|
|
-
|
|
|
-type boundFuncObject struct {
|
|
|
- nativeFuncObject
|
|
|
-}
|
|
|
-
|
|
|
func (o *baseObject) init() {
|
|
|
o.values = make(map[string]Value)
|
|
|
}
|
|
@@ -657,217 +628,7 @@ func (o *baseObject) equal(other objectImpl) bool {
|
|
|
return false
|
|
|
}
|
|
|
|
|
|
-func (f *funcObject) getPropStr(name string) Value {
|
|
|
- switch name {
|
|
|
- case "prototype":
|
|
|
- if _, exists := f.values["prototype"]; !exists {
|
|
|
- return f.addPrototype()
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- return f.baseObject.getPropStr(name)
|
|
|
-}
|
|
|
-
|
|
|
-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) getProp(n Value) Value {
|
|
|
- return f.getPropStr(n.String())
|
|
|
-}
|
|
|
-
|
|
|
-func (f *funcObject) hasOwnProperty(n Value) bool {
|
|
|
- if r := f.baseObject.hasOwnProperty(n); r {
|
|
|
- return true
|
|
|
- }
|
|
|
-
|
|
|
- name := n.String()
|
|
|
- if name == "prototype" {
|
|
|
- return true
|
|
|
- }
|
|
|
- return false
|
|
|
-}
|
|
|
-
|
|
|
-func (f *funcObject) hasOwnPropertyStr(name string) bool {
|
|
|
- if r := f.baseObject.hasOwnPropertyStr(name); r {
|
|
|
- return true
|
|
|
- }
|
|
|
-
|
|
|
- if name == "prototype" {
|
|
|
- return true
|
|
|
- }
|
|
|
- return false
|
|
|
-}
|
|
|
-
|
|
|
-func (f *funcObject) construct(args []Value) *Object {
|
|
|
- proto := f.getStr("prototype")
|
|
|
- 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,
|
|
|
- })
|
|
|
-
|
|
|
- if ret, ok := ret.(*Object); ok {
|
|
|
- return ret
|
|
|
- }
|
|
|
- return obj
|
|
|
-}
|
|
|
-
|
|
|
-func (f *funcObject) Call(call FunctionCall) Value {
|
|
|
- vm := f.val.runtime.vm
|
|
|
- pc := vm.pc
|
|
|
- vm.push(f.val)
|
|
|
- vm.push(call.This)
|
|
|
- for _, arg := range call.Arguments {
|
|
|
- vm.push(arg)
|
|
|
- }
|
|
|
- vm.pc = -1
|
|
|
- vm.pushCtx()
|
|
|
- vm.args = len(call.Arguments)
|
|
|
- vm.prg = f.prg
|
|
|
- vm.stash = f.stash
|
|
|
- vm.pc = 0
|
|
|
- vm.run()
|
|
|
- vm.pc = pc
|
|
|
- vm.halt = false
|
|
|
- return vm.pop()
|
|
|
-}
|
|
|
-
|
|
|
-func (f *funcObject) export() interface{} {
|
|
|
- return f.Call
|
|
|
-}
|
|
|
-
|
|
|
-func (f *funcObject) exportType() reflect.Type {
|
|
|
- return reflect.TypeOf(f.Call)
|
|
|
-}
|
|
|
-
|
|
|
-func (f *funcObject) assertCallable() (func(FunctionCall) Value, bool) {
|
|
|
- return f.Call, true
|
|
|
-}
|
|
|
-
|
|
|
-func (f *funcObject) init(name string, length int) {
|
|
|
- f.baseObject.init()
|
|
|
-
|
|
|
- f.nameProp.configurable = true
|
|
|
- f.nameProp.value = newStringValue(name)
|
|
|
- f.values["name"] = &f.nameProp
|
|
|
-
|
|
|
- f.lenProp.configurable = true
|
|
|
- f.lenProp.value = valueInt(length)
|
|
|
- f.values["length"] = &f.lenProp
|
|
|
-}
|
|
|
-
|
|
|
func (o *baseObject) hasInstance(v Value) bool {
|
|
|
o.val.runtime.typeErrorResult(true, "Expecting a function in instanceof check, but got %s", o.val.ToString())
|
|
|
panic("Unreachable")
|
|
|
}
|
|
|
-
|
|
|
-func (f *funcObject) hasInstance(v Value) bool {
|
|
|
- return f._hasInstance(v)
|
|
|
-}
|
|
|
-
|
|
|
-func (f *nativeFuncObject) hasInstance(v Value) bool {
|
|
|
- return f._hasInstance(v)
|
|
|
-}
|
|
|
-
|
|
|
-func (f *baseObject) _hasInstance(v Value) bool {
|
|
|
- if v, ok := v.(*Object); ok {
|
|
|
- o := f.val.self.getStr("prototype")
|
|
|
- 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(args []Value) Value {
|
|
|
- proto := f.getStr("prototype")
|
|
|
- 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.f(FunctionCall{
|
|
|
- This: obj,
|
|
|
- Arguments: args,
|
|
|
- })
|
|
|
-
|
|
|
- if ret, ok := ret.(*Object); ok {
|
|
|
- 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) init(name string, length int) {
|
|
|
- f.baseObject.init()
|
|
|
-
|
|
|
- f.nameProp.configurable = true
|
|
|
- f.nameProp.value = newStringValue(name)
|
|
|
- f._put("name", &f.nameProp)
|
|
|
-
|
|
|
- f.lenProp.configurable = true
|
|
|
- f.lenProp.value = valueInt(length)
|
|
|
- f._put("length", &f.lenProp)
|
|
|
-}
|
|
|
-
|
|
|
-func (f *boundFuncObject) getProp(n Value) Value {
|
|
|
- return f.getPropStr(n.String())
|
|
|
-}
|
|
|
-
|
|
|
-func (f *boundFuncObject) getPropStr(name string) Value {
|
|
|
- if name == "caller" || name == "arguments" {
|
|
|
- //f.runtime.typeErrorResult(true, "'caller' and 'arguments' are restricted function properties and cannot be accessed in this context.")
|
|
|
- return f.val.runtime.global.throwerProperty
|
|
|
- }
|
|
|
- return f.nativeFuncObject.getPropStr(name)
|
|
|
-}
|
|
|
-
|
|
|
-func (f *boundFuncObject) delete(n Value, throw bool) bool {
|
|
|
- return f.deleteStr(n.String(), throw)
|
|
|
-}
|
|
|
-
|
|
|
-func (f *boundFuncObject) deleteStr(name string, throw bool) bool {
|
|
|
- if name == "caller" || name == "arguments" {
|
|
|
- return true
|
|
|
- }
|
|
|
- return f.nativeFuncObject.deleteStr(name, throw)
|
|
|
-}
|
|
|
-
|
|
|
-func (f *boundFuncObject) putStr(name string, val Value, throw bool) {
|
|
|
- if name == "caller" || name == "arguments" {
|
|
|
- f.val.runtime.typeErrorResult(true, "'caller' and 'arguments' are restricted function properties and cannot be accessed in this context.")
|
|
|
- }
|
|
|
- f.nativeFuncObject.putStr(name, val, throw)
|
|
|
-}
|
|
|
-
|
|
|
-func (f *boundFuncObject) put(n Value, val Value, throw bool) {
|
|
|
- f.putStr(n.String(), val, throw)
|
|
|
-}
|