123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126 |
- package otto
- import (
- "fmt"
- "strings"
- "unicode"
- "github.com/robertkrimen/otto/parser"
- )
- // Function
- func builtinFunction(call FunctionCall) Value {
- return toValue_object(builtinNewFunctionNative(call.runtime, call.ArgumentList))
- }
- func builtinNewFunction(self *_object, argumentList []Value) Value {
- return toValue_object(builtinNewFunctionNative(self.runtime, argumentList))
- }
- func argumentList2parameterList(argumentList []Value) []string {
- parameterList := make([]string, 0, len(argumentList))
- for _, value := range argumentList {
- tmp := strings.FieldsFunc(value.string(), func(chr rune) bool {
- return chr == ',' || unicode.IsSpace(chr)
- })
- parameterList = append(parameterList, tmp...)
- }
- return parameterList
- }
- func builtinNewFunctionNative(runtime *_runtime, argumentList []Value) *_object {
- var parameterList, body string
- count := len(argumentList)
- if count > 0 {
- tmp := make([]string, 0, count-1)
- for _, value := range argumentList[0 : count-1] {
- tmp = append(tmp, value.string())
- }
- parameterList = strings.Join(tmp, ",")
- body = argumentList[count-1].string()
- }
- // FIXME
- function, err := parser.ParseFunction(parameterList, body)
- runtime.parseThrow(err) // Will panic/throw appropriately
- cmpl := _compiler{}
- cmpl_function := cmpl.parseExpression(function)
- return runtime.newNodeFunction(cmpl_function.(*_nodeFunctionLiteral), runtime.globalStash)
- }
- func builtinFunction_toString(call FunctionCall) Value {
- object := call.thisClassObject(classFunction) // Should throw a TypeError unless Function
- switch fn := object.value.(type) {
- case _nativeFunctionObject:
- return toValue_string(fmt.Sprintf("function %s() { [native code] }", fn.name))
- case _nodeFunctionObject:
- return toValue_string(fn.node.source)
- case _bindFunctionObject:
- return toValue_string("function () { [native code] }")
- }
- panic(call.runtime.panicTypeError("Function.toString()"))
- }
- func builtinFunction_apply(call FunctionCall) Value {
- if !call.This.isCallable() {
- panic(call.runtime.panicTypeError())
- }
- this := call.Argument(0)
- if this.IsUndefined() {
- // FIXME Not ECMA5
- this = toValue_object(call.runtime.globalObject)
- }
- argumentList := call.Argument(1)
- switch argumentList.kind {
- case valueUndefined, valueNull:
- return call.thisObject().call(this, nil, false, nativeFrame)
- case valueObject:
- default:
- panic(call.runtime.panicTypeError())
- }
- arrayObject := argumentList._object()
- thisObject := call.thisObject()
- length := int64(toUint32(arrayObject.get(propertyLength)))
- valueArray := make([]Value, length)
- for index := int64(0); index < length; index++ {
- valueArray[index] = arrayObject.get(arrayIndexToString(index))
- }
- return thisObject.call(this, valueArray, false, nativeFrame)
- }
- func builtinFunction_call(call FunctionCall) Value {
- if !call.This.isCallable() {
- panic(call.runtime.panicTypeError())
- }
- thisObject := call.thisObject()
- this := call.Argument(0)
- if this.IsUndefined() {
- // FIXME Not ECMA5
- this = toValue_object(call.runtime.globalObject)
- }
- if len(call.ArgumentList) >= 1 {
- return thisObject.call(this, call.ArgumentList[1:], false, nativeFrame)
- }
- return thisObject.call(this, nil, false, nativeFrame)
- }
- func builtinFunction_bind(call FunctionCall) Value {
- target := call.This
- if !target.isCallable() {
- panic(call.runtime.panicTypeError())
- }
- targetObject := target._object()
- this := call.Argument(0)
- argumentList := call.slice(1)
- if this.IsUndefined() {
- // FIXME Do this elsewhere?
- this = toValue_object(call.runtime.globalObject)
- }
- return toValue_object(call.runtime.newBoundFunction(targetObject, this, argumentList))
- }
|