func.go 6.1 KB

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