builtin_function.go 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418
  1. package goja
  2. import (
  3. "math"
  4. "sync"
  5. )
  6. func (r *Runtime) functionCtor(args []Value, proto *Object, async, generator bool) *Object {
  7. var sb StringBuilder
  8. if async {
  9. if generator {
  10. sb.WriteString(asciiString("(async function* anonymous("))
  11. } else {
  12. sb.WriteString(asciiString("(async function anonymous("))
  13. }
  14. } else {
  15. if generator {
  16. sb.WriteString(asciiString("(function* anonymous("))
  17. } else {
  18. sb.WriteString(asciiString("(function anonymous("))
  19. }
  20. }
  21. if len(args) > 1 {
  22. ar := args[:len(args)-1]
  23. for i, arg := range ar {
  24. sb.WriteString(arg.toString())
  25. if i < len(ar)-1 {
  26. sb.WriteRune(',')
  27. }
  28. }
  29. }
  30. sb.WriteString(asciiString("\n) {\n"))
  31. if len(args) > 0 {
  32. sb.WriteString(args[len(args)-1].toString())
  33. }
  34. sb.WriteString(asciiString("\n})"))
  35. ret := r.toObject(r.eval(sb.String(), false, false))
  36. ret.self.setProto(proto, true)
  37. return ret
  38. }
  39. func (r *Runtime) builtin_Function(args []Value, proto *Object) *Object {
  40. return r.functionCtor(args, proto, false, false)
  41. }
  42. func (r *Runtime) builtin_asyncFunction(args []Value, proto *Object) *Object {
  43. return r.functionCtor(args, proto, true, false)
  44. }
  45. func (r *Runtime) builtin_generatorFunction(args []Value, proto *Object) *Object {
  46. return r.functionCtor(args, proto, false, true)
  47. }
  48. func (r *Runtime) functionproto_toString(call FunctionCall) Value {
  49. obj := r.toObject(call.This)
  50. switch f := obj.self.(type) {
  51. case funcObjectImpl:
  52. return f.source()
  53. case *proxyObject:
  54. if _, ok := f.target.self.(funcObjectImpl); ok {
  55. return asciiString("function () { [native code] }")
  56. }
  57. }
  58. panic(r.NewTypeError("Function.prototype.toString requires that 'this' be a Function"))
  59. }
  60. func (r *Runtime) functionproto_hasInstance(call FunctionCall) Value {
  61. if o, ok := call.This.(*Object); ok {
  62. if _, ok = o.self.assertCallable(); ok {
  63. return r.toBoolean(o.self.hasInstance(call.Argument(0)))
  64. }
  65. }
  66. return valueFalse
  67. }
  68. func (r *Runtime) createListFromArrayLike(a Value) []Value {
  69. o := r.toObject(a)
  70. if arr := r.checkStdArrayObj(o); arr != nil {
  71. return arr.values
  72. }
  73. l := toLength(o.self.getStr("length", nil))
  74. res := make([]Value, 0, l)
  75. for k := int64(0); k < l; k++ {
  76. res = append(res, nilSafe(o.self.getIdx(valueInt(k), nil)))
  77. }
  78. return res
  79. }
  80. func (r *Runtime) functionproto_apply(call FunctionCall) Value {
  81. var args []Value
  82. argArray := call.Argument(1)
  83. if !IsUndefined(argArray) && !IsNull(argArray) {
  84. args = r.createListFromArrayLike(argArray)
  85. }
  86. f := r.toCallable(call.This)
  87. return f(FunctionCall{
  88. This: call.Argument(0),
  89. Arguments: args,
  90. })
  91. }
  92. func (r *Runtime) functionproto_call(call FunctionCall) Value {
  93. var args []Value
  94. if len(call.Arguments) > 0 {
  95. args = call.Arguments[1:]
  96. }
  97. f := r.toCallable(call.This)
  98. return f(FunctionCall{
  99. This: call.Argument(0),
  100. Arguments: args,
  101. })
  102. }
  103. func (r *Runtime) boundCallable(target func(FunctionCall) Value, boundArgs []Value) func(FunctionCall) Value {
  104. var this Value
  105. var args []Value
  106. if len(boundArgs) > 0 {
  107. this = boundArgs[0]
  108. args = make([]Value, len(boundArgs)-1)
  109. copy(args, boundArgs[1:])
  110. } else {
  111. this = _undefined
  112. }
  113. return func(call FunctionCall) Value {
  114. a := append(args, call.Arguments...)
  115. return target(FunctionCall{
  116. This: this,
  117. Arguments: a,
  118. })
  119. }
  120. }
  121. func (r *Runtime) boundConstruct(f *Object, target func([]Value, *Object) *Object, boundArgs []Value) func([]Value, *Object) *Object {
  122. if target == nil {
  123. return nil
  124. }
  125. var args []Value
  126. if len(boundArgs) > 1 {
  127. args = make([]Value, len(boundArgs)-1)
  128. copy(args, boundArgs[1:])
  129. }
  130. return func(fargs []Value, newTarget *Object) *Object {
  131. a := append(args, fargs...)
  132. if newTarget == f {
  133. newTarget = nil
  134. }
  135. return target(a, newTarget)
  136. }
  137. }
  138. func (r *Runtime) functionproto_bind(call FunctionCall) Value {
  139. obj := r.toObject(call.This)
  140. fcall := r.toCallable(call.This)
  141. construct := obj.self.assertConstructor()
  142. var l = _positiveZero
  143. if obj.self.hasOwnPropertyStr("length") {
  144. var li int64
  145. switch lenProp := nilSafe(obj.self.getStr("length", nil)).(type) {
  146. case valueInt:
  147. li = lenProp.ToInteger()
  148. case valueFloat:
  149. switch lenProp {
  150. case _positiveInf:
  151. l = lenProp
  152. goto lenNotInt
  153. case _negativeInf:
  154. goto lenNotInt
  155. case _negativeZero:
  156. // no-op, li == 0
  157. default:
  158. if !math.IsNaN(float64(lenProp)) {
  159. li = int64(math.Abs(float64(lenProp)))
  160. } // else li = 0
  161. }
  162. }
  163. if len(call.Arguments) > 1 {
  164. li -= int64(len(call.Arguments)) - 1
  165. }
  166. if li < 0 {
  167. li = 0
  168. }
  169. l = intToValue(li)
  170. }
  171. lenNotInt:
  172. name := obj.self.getStr("name", nil)
  173. nameStr := stringBound_
  174. if s, ok := name.(String); ok {
  175. nameStr = nameStr.Concat(s)
  176. }
  177. v := &Object{runtime: r}
  178. ff := r.newNativeFuncAndConstruct(v, r.boundCallable(fcall, call.Arguments), r.boundConstruct(v, construct, call.Arguments), nil, nameStr.string(), l)
  179. bf := &boundFuncObject{
  180. nativeFuncObject: *ff,
  181. wrapped: obj,
  182. }
  183. bf.prototype = obj.self.proto()
  184. v.self = bf
  185. return v
  186. }
  187. func (r *Runtime) getThrower() *Object {
  188. ret := r.global.thrower
  189. if ret == nil {
  190. ret = r.newNativeFunc(r.builtin_thrower, "", 0)
  191. r.global.thrower = ret
  192. r.object_freeze(FunctionCall{Arguments: []Value{ret}})
  193. }
  194. return ret
  195. }
  196. func (r *Runtime) newThrowerProperty(configurable bool) Value {
  197. thrower := r.getThrower()
  198. return &valueProperty{
  199. getterFunc: thrower,
  200. setterFunc: thrower,
  201. accessor: true,
  202. configurable: configurable,
  203. }
  204. }
  205. func createFunctionProtoTemplate() *objectTemplate {
  206. t := newObjectTemplate()
  207. t.protoFactory = func(r *Runtime) *Object {
  208. return r.global.ObjectPrototype
  209. }
  210. t.putStr("constructor", func(r *Runtime) Value { return valueProp(r.getFunction(), true, false, true) })
  211. t.putStr("length", func(r *Runtime) Value { return valueProp(_positiveZero, false, false, true) })
  212. t.putStr("name", func(r *Runtime) Value { return valueProp(stringEmpty, false, false, true) })
  213. t.putStr("apply", func(r *Runtime) Value { return r.methodProp(r.functionproto_apply, "apply", 2) })
  214. t.putStr("bind", func(r *Runtime) Value { return r.methodProp(r.functionproto_bind, "bind", 1) })
  215. t.putStr("call", func(r *Runtime) Value { return r.methodProp(r.functionproto_call, "call", 1) })
  216. t.putStr("toString", func(r *Runtime) Value { return r.methodProp(r.functionproto_toString, "toString", 0) })
  217. t.putStr("caller", func(r *Runtime) Value { return r.newThrowerProperty(true) })
  218. t.putStr("arguments", func(r *Runtime) Value { return r.newThrowerProperty(true) })
  219. t.putSym(SymHasInstance, func(r *Runtime) Value {
  220. return valueProp(r.newNativeFunc(r.functionproto_hasInstance, "[Symbol.hasInstance]", 1), false, false, false)
  221. })
  222. return t
  223. }
  224. var functionProtoTemplate *objectTemplate
  225. var functionProtoTemplateOnce sync.Once
  226. func getFunctionProtoTemplate() *objectTemplate {
  227. functionProtoTemplateOnce.Do(func() {
  228. functionProtoTemplate = createFunctionProtoTemplate()
  229. })
  230. return functionProtoTemplate
  231. }
  232. func (r *Runtime) getFunctionPrototype() *Object {
  233. ret := r.global.FunctionPrototype
  234. if ret == nil {
  235. ret = &Object{runtime: r}
  236. r.global.FunctionPrototype = ret
  237. r.newTemplatedFuncObject(getFunctionProtoTemplate(), ret, func(FunctionCall) Value {
  238. return _undefined
  239. }, nil)
  240. }
  241. return ret
  242. }
  243. func (r *Runtime) createFunction(v *Object) objectImpl {
  244. return r.newNativeFuncConstructObj(v, r.builtin_Function, "Function", r.getFunctionPrototype(), 1)
  245. }
  246. func (r *Runtime) createAsyncFunctionProto(val *Object) objectImpl {
  247. o := &baseObject{
  248. class: classObject,
  249. val: val,
  250. extensible: true,
  251. prototype: r.getFunctionPrototype(),
  252. }
  253. o.init()
  254. o._putProp("constructor", r.getAsyncFunction(), true, false, true)
  255. o._putSym(SymToStringTag, valueProp(asciiString(classAsyncFunction), false, false, true))
  256. return o
  257. }
  258. func (r *Runtime) getAsyncFunctionPrototype() *Object {
  259. var o *Object
  260. if o = r.global.AsyncFunctionPrototype; o == nil {
  261. o = &Object{runtime: r}
  262. r.global.AsyncFunctionPrototype = o
  263. o.self = r.createAsyncFunctionProto(o)
  264. }
  265. return o
  266. }
  267. func (r *Runtime) createAsyncFunction(val *Object) objectImpl {
  268. o := r.newNativeFuncConstructObj(val, r.builtin_asyncFunction, "AsyncFunction", r.getAsyncFunctionPrototype(), 1)
  269. return o
  270. }
  271. func (r *Runtime) getAsyncFunction() *Object {
  272. var o *Object
  273. if o = r.global.AsyncFunction; o == nil {
  274. o = &Object{runtime: r}
  275. r.global.AsyncFunction = o
  276. o.self = r.createAsyncFunction(o)
  277. }
  278. return o
  279. }
  280. func (r *Runtime) builtin_genproto_next(call FunctionCall) Value {
  281. if o, ok := call.This.(*Object); ok {
  282. if gen, ok := o.self.(*generatorObject); ok {
  283. return gen.next(call.Argument(0))
  284. }
  285. }
  286. panic(r.NewTypeError("Method [Generator].prototype.next called on incompatible receiver"))
  287. }
  288. func (r *Runtime) builtin_genproto_return(call FunctionCall) Value {
  289. if o, ok := call.This.(*Object); ok {
  290. if gen, ok := o.self.(*generatorObject); ok {
  291. return gen._return(call.Argument(0))
  292. }
  293. }
  294. panic(r.NewTypeError("Method [Generator].prototype.return called on incompatible receiver"))
  295. }
  296. func (r *Runtime) builtin_genproto_throw(call FunctionCall) Value {
  297. if o, ok := call.This.(*Object); ok {
  298. if gen, ok := o.self.(*generatorObject); ok {
  299. return gen.throw(call.Argument(0))
  300. }
  301. }
  302. panic(r.NewTypeError("Method [Generator].prototype.throw called on incompatible receiver"))
  303. }
  304. func (r *Runtime) createGeneratorFunctionProto(val *Object) objectImpl {
  305. o := newBaseObjectObj(val, r.getFunctionPrototype(), classObject)
  306. o._putProp("constructor", r.getGeneratorFunction(), false, false, true)
  307. o._putProp("prototype", r.getGeneratorPrototype(), false, false, true)
  308. o._putSym(SymToStringTag, valueProp(asciiString(classGeneratorFunction), false, false, true))
  309. return o
  310. }
  311. func (r *Runtime) getGeneratorFunctionPrototype() *Object {
  312. var o *Object
  313. if o = r.global.GeneratorFunctionPrototype; o == nil {
  314. o = &Object{runtime: r}
  315. r.global.GeneratorFunctionPrototype = o
  316. o.self = r.createGeneratorFunctionProto(o)
  317. }
  318. return o
  319. }
  320. func (r *Runtime) createGeneratorFunction(val *Object) objectImpl {
  321. o := r.newNativeFuncConstructObj(val, r.builtin_generatorFunction, "GeneratorFunction", r.getGeneratorFunctionPrototype(), 1)
  322. return o
  323. }
  324. func (r *Runtime) getGeneratorFunction() *Object {
  325. var o *Object
  326. if o = r.global.GeneratorFunction; o == nil {
  327. o = &Object{runtime: r}
  328. r.global.GeneratorFunction = o
  329. o.self = r.createGeneratorFunction(o)
  330. }
  331. return o
  332. }
  333. func (r *Runtime) createGeneratorProto(val *Object) objectImpl {
  334. o := newBaseObjectObj(val, r.getIteratorPrototype(), classObject)
  335. o._putProp("constructor", r.getGeneratorFunctionPrototype(), false, false, true)
  336. o._putProp("next", r.newNativeFunc(r.builtin_genproto_next, "next", 1), true, false, true)
  337. o._putProp("return", r.newNativeFunc(r.builtin_genproto_return, "return", 1), true, false, true)
  338. o._putProp("throw", r.newNativeFunc(r.builtin_genproto_throw, "throw", 1), true, false, true)
  339. o._putSym(SymToStringTag, valueProp(asciiString(classGenerator), false, false, true))
  340. return o
  341. }
  342. func (r *Runtime) getGeneratorPrototype() *Object {
  343. var o *Object
  344. if o = r.global.GeneratorPrototype; o == nil {
  345. o = &Object{runtime: r}
  346. r.global.GeneratorPrototype = o
  347. o.self = r.createGeneratorProto(o)
  348. }
  349. return o
  350. }
  351. func (r *Runtime) getFunction() *Object {
  352. ret := r.global.Function
  353. if ret == nil {
  354. ret = &Object{runtime: r}
  355. r.global.Function = ret
  356. ret.self = r.createFunction(ret)
  357. }
  358. return ret
  359. }