aboutsummaryrefslogtreecommitdiffstats
path: root/Godeps/_workspace/src/github.com/obscuren/otto/builtin_function.go
diff options
context:
space:
mode:
Diffstat (limited to 'Godeps/_workspace/src/github.com/obscuren/otto/builtin_function.go')
-rw-r--r--Godeps/_workspace/src/github.com/obscuren/otto/builtin_function.go117
1 files changed, 117 insertions, 0 deletions
diff --git a/Godeps/_workspace/src/github.com/obscuren/otto/builtin_function.go b/Godeps/_workspace/src/github.com/obscuren/otto/builtin_function.go
new file mode 100644
index 000000000..80442104d
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/obscuren/otto/builtin_function.go
@@ -0,0 +1,117 @@
+package otto
+
+import (
+ "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, _ Value, 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(toString(value), 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, toString(value))
+ }
+ parameterList = strings.Join(tmp, ",")
+ body = toString(argumentList[count-1])
+ }
+
+ function, err := parser.ParseFunction(parameterList, body)
+ runtime.parseThrow(err) // Will panic/throw appropriately
+ cmpl_function := parseExpression(function)
+
+ return runtime.newNodeFunction(cmpl_function.(*_nodeFunctionLiteral), runtime.GlobalEnvironment)
+}
+
+func builtinFunction_toString(call FunctionCall) Value {
+ object := call.thisClassObject("Function") // Should throw a TypeError unless Function
+ return toValue_string(object.value.(_functionObject).source(object))
+}
+
+func builtinFunction_apply(call FunctionCall) Value {
+ if !call.This.isCallable() {
+ panic(newTypeError())
+ }
+ this := call.Argument(0)
+ if this.IsUndefined() {
+ // FIXME Not ECMA5
+ this = toValue_object(call.runtime.GlobalObject)
+ }
+ argumentList := call.Argument(1)
+ switch argumentList._valueType {
+ case valueUndefined, valueNull:
+ return call.thisObject().Call(this, []Value{})
+ case valueObject:
+ default:
+ panic(newTypeError())
+ }
+
+ 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)
+}
+
+func builtinFunction_call(call FunctionCall) Value {
+ if !call.This.isCallable() {
+ panic(newTypeError())
+ }
+ 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:])
+ }
+ return thisObject.Call(this, []Value{})
+}
+
+func builtinFunction_bind(call FunctionCall) Value {
+ target := call.This
+ if !target.isCallable() {
+ panic(newTypeError())
+ }
+ 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))
+}