...

Source file src/github.com/dop251/goja/builtin_function.go

Documentation: github.com/dop251/goja

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

View as plain text