func.go 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240
  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) *Object
  17. }
  18. type boundFuncObject struct {
  19. nativeFuncObject
  20. }
  21. func (f *nativeFuncObject) export() interface{} {
  22. return f.f
  23. }
  24. func (f *nativeFuncObject) exportType() reflect.Type {
  25. return reflect.TypeOf(f.f)
  26. }
  27. func (f *funcObject) getPropStr(name string) Value {
  28. switch name {
  29. case "prototype":
  30. if _, exists := f.values["prototype"]; !exists {
  31. return f.addPrototype()
  32. }
  33. }
  34. return f.baseObject.getPropStr(name)
  35. }
  36. func (f *funcObject) addPrototype() Value {
  37. proto := f.val.runtime.NewObject()
  38. proto.self._putProp("constructor", f.val, true, false, true)
  39. return f._putProp("prototype", proto, true, false, false)
  40. }
  41. func (f *funcObject) getProp(n Value) Value {
  42. return f.getPropStr(n.String())
  43. }
  44. func (f *funcObject) hasOwnProperty(n Value) bool {
  45. if r := f.baseObject.hasOwnProperty(n); r {
  46. return true
  47. }
  48. name := n.String()
  49. if name == "prototype" {
  50. return true
  51. }
  52. return false
  53. }
  54. func (f *funcObject) hasOwnPropertyStr(name string) bool {
  55. if r := f.baseObject.hasOwnPropertyStr(name); r {
  56. return true
  57. }
  58. if name == "prototype" {
  59. return true
  60. }
  61. return false
  62. }
  63. func (f *funcObject) construct(args []Value) *Object {
  64. proto := f.getStr("prototype")
  65. var protoObj *Object
  66. if p, ok := proto.(*Object); ok {
  67. protoObj = p
  68. } else {
  69. protoObj = f.val.runtime.global.ObjectPrototype
  70. }
  71. obj := f.val.runtime.newBaseObject(protoObj, classObject).val
  72. ret := f.Call(FunctionCall{
  73. This: obj,
  74. Arguments: args,
  75. })
  76. if ret, ok := ret.(*Object); ok {
  77. return ret
  78. }
  79. return obj
  80. }
  81. func (f *funcObject) Call(call FunctionCall) Value {
  82. vm := f.val.runtime.vm
  83. pc := vm.pc
  84. vm.stack.expand(vm.sp + len(call.Arguments) + 1)
  85. vm.stack[vm.sp] = f.val
  86. vm.sp++
  87. if call.This != nil {
  88. vm.stack[vm.sp] = call.This
  89. } else {
  90. vm.stack[vm.sp] = _undefined
  91. }
  92. vm.sp++
  93. for _, arg := range call.Arguments {
  94. if arg != nil {
  95. vm.stack[vm.sp] = arg
  96. } else {
  97. vm.stack[vm.sp] = _undefined
  98. }
  99. vm.sp++
  100. }
  101. vm.pc = -1
  102. vm.pushCtx()
  103. vm.args = len(call.Arguments)
  104. vm.prg = f.prg
  105. vm.stash = f.stash
  106. vm.pc = 0
  107. vm.run()
  108. vm.pc = pc
  109. vm.halt = false
  110. return vm.pop()
  111. }
  112. func (f *funcObject) export() interface{} {
  113. return f.Call
  114. }
  115. func (f *funcObject) exportType() reflect.Type {
  116. return reflect.TypeOf(f.Call)
  117. }
  118. func (f *funcObject) assertCallable() (func(FunctionCall) Value, bool) {
  119. return f.Call, true
  120. }
  121. func (f *baseFuncObject) init(name string, length int) {
  122. f.baseObject.init()
  123. f.nameProp.configurable = true
  124. f.nameProp.value = newStringValue(name)
  125. f._put("name", &f.nameProp)
  126. f.lenProp.configurable = true
  127. f.lenProp.value = valueInt(length)
  128. f._put("length", &f.lenProp)
  129. }
  130. func (f *baseFuncObject) hasInstance(v Value) bool {
  131. if v, ok := v.(*Object); ok {
  132. o := f.val.self.getStr("prototype")
  133. if o1, ok := o.(*Object); ok {
  134. for {
  135. v = v.self.proto()
  136. if v == nil {
  137. return false
  138. }
  139. if o1 == v {
  140. return true
  141. }
  142. }
  143. } else {
  144. f.val.runtime.typeErrorResult(true, "prototype is not an object")
  145. }
  146. }
  147. return false
  148. }
  149. func (f *nativeFuncObject) defaultConstruct(ccall func(ConstructorCall) *Object, args []Value) *Object {
  150. proto := f.getStr("prototype")
  151. var protoObj *Object
  152. if p, ok := proto.(*Object); ok {
  153. protoObj = p
  154. } else {
  155. protoObj = f.val.runtime.global.ObjectPrototype
  156. }
  157. obj := f.val.runtime.newBaseObject(protoObj, classObject).val
  158. ret := ccall(ConstructorCall{
  159. This: obj,
  160. Arguments: args,
  161. })
  162. if ret != nil {
  163. return ret
  164. }
  165. return obj
  166. }
  167. func (f *nativeFuncObject) assertCallable() (func(FunctionCall) Value, bool) {
  168. if f.f != nil {
  169. return f.f, true
  170. }
  171. return nil, false
  172. }
  173. func (f *boundFuncObject) getProp(n Value) Value {
  174. return f.getPropStr(n.String())
  175. }
  176. func (f *boundFuncObject) getPropStr(name string) Value {
  177. if name == "caller" || name == "arguments" {
  178. //f.runtime.typeErrorResult(true, "'caller' and 'arguments' are restricted function properties and cannot be accessed in this context.")
  179. return f.val.runtime.global.throwerProperty
  180. }
  181. return f.nativeFuncObject.getPropStr(name)
  182. }
  183. func (f *boundFuncObject) delete(n Value, throw bool) bool {
  184. return f.deleteStr(n.String(), throw)
  185. }
  186. func (f *boundFuncObject) deleteStr(name string, throw bool) bool {
  187. if name == "caller" || name == "arguments" {
  188. return true
  189. }
  190. return f.nativeFuncObject.deleteStr(name, throw)
  191. }
  192. func (f *boundFuncObject) putStr(name string, val Value, throw bool) {
  193. if name == "caller" || name == "arguments" {
  194. f.val.runtime.typeErrorResult(true, "'caller' and 'arguments' are restricted function properties and cannot be accessed in this context.")
  195. }
  196. f.nativeFuncObject.putStr(name, val, throw)
  197. }
  198. func (f *boundFuncObject) put(n Value, val Value, throw bool) {
  199. f.putStr(n.String(), val, throw)
  200. }