aboutsummaryrefslogblamecommitdiffstats
path: root/vendor/github.com/robertkrimen/otto/builtin_function.go
blob: 3d07566c6bbf4ec811158508423a712a182829db (plain) (tree)
1
2
3
4


            
             












                                                                                        
                                                                    





                                                                                   
                                                                               














                                                                                 
                                                         

                                                      
                                                     

         
                

                                                                  

                                                       
 
                                                                                                  



                                                                                              









                                                                                              



                                                     
                                                    



                                  
                                                                

                                        
                                  
                                       
                                                                            

                         
                                                    








                                                                              
                                                                    



                                                    
                                                    




                                       
                                                                

                                        
                                                                                       
         
                                                             




                                                    
                                                    






                                           
                                                                



                                                                                              
package otto

import (
    "fmt"
    "regexp"
    "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
}

var matchIdentifier = regexp.MustCompile(`^[$_\p{L}][$_\p{L}\d}]*$`)

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("Function") // 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("length")))
    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))
}