github.com/nuvolaris/goja@v0.0.0-20230825100449-967811910c6d/builtin_function.go (about)

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