forked from robertkrimen/otto
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Split builtin.go out to builtin_*.go
- Loading branch information
1 parent
4e4e89c
commit ec902a6
Showing
11 changed files
with
1,288 additions
and
1,252 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
package otto | ||
|
||
// Boolean | ||
|
||
func builtinBoolean(call FunctionCall) Value { | ||
return toValue(toBoolean(call.Argument(0))) | ||
} | ||
|
||
func builtinNewBoolean(self *_object, _ Value, argumentList []Value) Value { | ||
return toValue(self.runtime.newBoolean(valueOfArrayIndex(argumentList, 0))) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
package otto | ||
|
||
import ( | ||
time_ "time" | ||
) | ||
|
||
// Date | ||
|
||
func builtinDate(call FunctionCall) Value { | ||
return toValue(call.runtime.newDate(newDateTime(call.ArgumentList))) | ||
} | ||
|
||
func builtinNewDate(self *_object, _ Value, argumentList []Value) Value { | ||
return toValue(self.runtime.newDate(newDateTime(argumentList))) | ||
} | ||
|
||
func builtinDate_toString(call FunctionCall) Value { | ||
date := dateObjectOf(call.thisObject()) | ||
if date.isNaN { | ||
return toValue("Invalid Date") | ||
} | ||
return toValue(date.Time().Local().Format(time_.RFC1123)) | ||
} | ||
|
||
func builtinDate_toUTCString(call FunctionCall) Value { | ||
date := dateObjectOf(call.thisObject()) | ||
if date.isNaN { | ||
return toValue("Invalid Date") | ||
} | ||
return toValue(date.Time().Format(time_.RFC1123)) | ||
} | ||
|
||
func builtinDate_getTime(call FunctionCall) Value { | ||
date := dateObjectOf(call.thisObject()) | ||
if date.isNaN { | ||
return NaNValue() | ||
} | ||
// We do this (convert away from a float) so the user | ||
// does not get something back in exponential notation | ||
return toValue(int64(date.Epoch())) | ||
} | ||
|
||
func builtinDate_setTime(call FunctionCall) Value { | ||
date := dateObjectOf(call.thisObject()) | ||
date.Set(toFloat(call.Argument(0))) | ||
return date.Value() | ||
} | ||
|
||
func _builtinDate_set(call FunctionCall, argumentCap int, dateLocal bool) (*_dateObject, *_ecmaTime) { | ||
date := dateObjectOf(call.thisObject()) | ||
if date.isNaN { | ||
return nil, nil | ||
} | ||
for index := 0; index < len(call.ArgumentList) && index < argumentCap; index++ { | ||
value := call.Argument(index) | ||
if value.IsNaN() { | ||
date.SetNaN() | ||
return date, nil | ||
} | ||
} | ||
baseTime := date.Time() | ||
if dateLocal { | ||
baseTime = baseTime.Local() | ||
} | ||
ecmaTime := ecmaTime(baseTime) | ||
return date, &ecmaTime | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
package otto | ||
|
||
// Function | ||
|
||
func builtinFunction(call FunctionCall) Value { | ||
return toValue(builtinNewFunctionNative(call.runtime, call.ArgumentList)) | ||
} | ||
|
||
func builtinNewFunction(self *_object, _ Value, argumentList []Value) Value { | ||
return toValue(builtinNewFunctionNative(self.runtime, argumentList)) | ||
} | ||
|
||
func builtinNewFunctionNative(runtime *_runtime, argumentList []Value) *_object { | ||
parameterList := []string{} | ||
bodySource := "" | ||
argumentCount := len(argumentList) | ||
if argumentCount > 0 { | ||
bodySource = toString(argumentList[argumentCount-1]) | ||
argumentList = argumentList[0 : argumentCount-1] | ||
for _, value := range argumentList { | ||
parameterList = append(parameterList, toString(value)) | ||
} | ||
} | ||
|
||
parser := newParser() | ||
parser.lexer.Source = bodySource | ||
_programNode := parser.ParseAsFunction() | ||
return runtime.newNodeFunction(_programNode.toFunction(parameterList), runtime.GlobalEnvironment) | ||
} | ||
|
||
func builtinFunction_apply(call FunctionCall) Value { | ||
if !call.This.isCallable() { | ||
panic(newTypeError()) | ||
} | ||
this := call.Argument(0) | ||
if this.IsUndefined() { | ||
// FIXME Not ECMA5 | ||
this = toValue(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 := uint(toUint32(arrayObject.get("length"))) | ||
valueArray := make([]Value, length) | ||
for index := uint(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(call.runtime.GlobalObject) | ||
} | ||
if len(call.ArgumentList) >= 1 { | ||
return thisObject.Call(this, call.ArgumentList[1:]) | ||
} | ||
return thisObject.Call(this, []Value{}) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,79 @@ | ||
package otto | ||
|
||
import ( | ||
"math" | ||
"math/rand" | ||
) | ||
|
||
// Math | ||
|
||
func builtinMath_max(call FunctionCall) Value { | ||
switch len(call.ArgumentList) { | ||
case 0: | ||
return negativeInfinityValue() | ||
case 1: | ||
return toValue(toFloat(call.ArgumentList[0])) | ||
default: | ||
result := toFloat(call.ArgumentList[0]) | ||
if math.IsNaN(result) { | ||
return NaNValue() | ||
} | ||
for _, value := range call.ArgumentList[1:] { | ||
value := toFloat(value) | ||
if math.IsNaN(value) { | ||
return NaNValue() | ||
} | ||
result = math.Max(result, value) | ||
} | ||
return toValue(result) | ||
} | ||
return UndefinedValue() | ||
} | ||
|
||
func builtinMath_min(call FunctionCall) Value { | ||
switch len(call.ArgumentList) { | ||
case 0: | ||
return positiveInfinityValue() | ||
case 1: | ||
return toValue(toFloat(call.ArgumentList[0])) | ||
default: | ||
result := toFloat(call.ArgumentList[0]) | ||
if math.IsNaN(result) { | ||
return NaNValue() | ||
} | ||
for _, value := range call.ArgumentList[1:] { | ||
value := toFloat(value) | ||
if math.IsNaN(value) { | ||
return NaNValue() | ||
} | ||
result = math.Min(result, value) | ||
} | ||
return toValue(result) | ||
} | ||
return UndefinedValue() | ||
} | ||
|
||
func builtinMath_ceil(call FunctionCall) Value { | ||
number := toFloat(call.Argument(0)) | ||
if math.IsNaN(number) { | ||
return NaNValue() | ||
} | ||
return toValue(math.Ceil(number)) | ||
} | ||
|
||
func builtinMath_floor(call FunctionCall) Value { | ||
number := toFloat(call.Argument(0)) | ||
if math.IsNaN(number) { | ||
return NaNValue() | ||
} | ||
return toValue(math.Floor(number)) | ||
} | ||
|
||
func builtinMath_random(call FunctionCall) Value { | ||
return toValue(rand.Float64()) | ||
} | ||
|
||
func builtinMath_pow(call FunctionCall) Value { | ||
// TODO Make sure this works according to the specification (15.8.2.13) | ||
return toValue(math.Pow(toFloat(call.Argument(0)), toFloat(call.Argument(1)))) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
package otto | ||
|
||
// Number | ||
|
||
func numberValueFromNumberArgumentList(argumentList []Value) Value { | ||
if len(argumentList) > 0 { | ||
return toValue(toNumber(argumentList[0])) | ||
} | ||
return toValue(0) | ||
} | ||
|
||
func builtinNumber(call FunctionCall) Value { | ||
return numberValueFromNumberArgumentList(call.ArgumentList) | ||
} | ||
|
||
func builtinNewNumber(self *_object, _ Value, argumentList []Value) Value { | ||
return toValue(self.runtime.newNumber(numberValueFromNumberArgumentList(argumentList))) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,97 @@ | ||
package otto | ||
|
||
import ( | ||
"fmt" | ||
) | ||
|
||
// Object | ||
|
||
func builtinObject(call FunctionCall) Value { | ||
value := call.Argument(0) | ||
switch value._valueType { | ||
case valueUndefined, valueNull: | ||
return toValue(call.runtime.newObject()) | ||
} | ||
|
||
return toValue(call.runtime.toObject(value)) | ||
} | ||
|
||
func builtinNewObject(self *_object, _ Value, _ []Value) Value { | ||
return toValue(self.runtime.newObject()) | ||
} | ||
|
||
func builtinObject_toString(call FunctionCall) Value { | ||
result := "" | ||
if call.This.IsUndefined() { | ||
result = "[object Undefined]" | ||
} else if call.This.IsNull() { | ||
result = "[object Null]" | ||
} else { | ||
result = fmt.Sprintf("[object %s]", call.thisObject().class) | ||
} | ||
return toValue(result) | ||
} | ||
|
||
func builtinObject_getOwnPropertyDescriptor(call FunctionCall) Value { | ||
objectValue := call.Argument(0) | ||
object := objectValue._object() | ||
if object == nil { | ||
panic(newTypeError()) | ||
} | ||
|
||
name := toString(call.Argument(1)) | ||
descriptor := object.getOwnProperty(name) | ||
if descriptor == nil { | ||
return UndefinedValue() | ||
} | ||
return toValue(call.runtime.fromPropertyDescriptor(*descriptor)) | ||
} | ||
|
||
func builtinObject_defineProperty(call FunctionCall) Value { | ||
objectValue := call.Argument(0) | ||
object := objectValue._object() | ||
if object == nil { | ||
panic(newTypeError()) | ||
} | ||
name := toString(call.Argument(1)) | ||
descriptor := toPropertyDescriptor(call.Argument(2)) | ||
object.defineOwnProperty(name, descriptor, true) | ||
return objectValue | ||
} | ||
|
||
func builtinObject_defineProperties(call FunctionCall) Value { | ||
objectValue := call.Argument(0) | ||
object := objectValue._object() | ||
if object == nil { | ||
panic(newTypeError()) | ||
} | ||
|
||
properties := call.runtime.toObject(call.Argument(1)) | ||
properties.enumerate(func(name string) { | ||
descriptor := toPropertyDescriptor(properties.get(name)) | ||
object.defineOwnProperty(name, descriptor, true) | ||
}) | ||
|
||
return objectValue | ||
} | ||
|
||
func builtinObject_create(call FunctionCall) Value { | ||
prototypeValue := call.Argument(0) | ||
prototype := prototypeValue._object() | ||
if prototype == nil { | ||
panic(newTypeError()) | ||
} | ||
|
||
object := call.runtime.newObject() | ||
|
||
propertiesValue := call.Argument(1) | ||
if propertiesValue.IsDefined() { | ||
properties := call.runtime.toObject(propertiesValue) | ||
properties.enumerate(func(name string) { | ||
descriptor := toPropertyDescriptor(properties.get(name)) | ||
object.defineOwnProperty(name, descriptor, true) | ||
}) | ||
} | ||
|
||
return toValue(object) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
package otto | ||
|
||
import ( | ||
"fmt" | ||
) | ||
|
||
// RegExp | ||
|
||
func builtinRegExp(call FunctionCall) Value { | ||
return toValue(call.runtime.newRegExp(call.Argument(0), call.Argument(1))) | ||
} | ||
|
||
func builtinNewRegExp(self *_object, _ Value, argumentList []Value) Value { | ||
return toValue(self.runtime.newRegExp(valueOfArrayIndex(argumentList, 0), valueOfArrayIndex(argumentList, 1))) | ||
} | ||
|
||
func builtinRegExp_toString(call FunctionCall) Value { | ||
thisObject := call.thisObject() | ||
source := toString(thisObject.get("source")) | ||
flags := []byte{} | ||
if toBoolean(thisObject.get("global")) { | ||
flags = append(flags, 'g') | ||
} | ||
if toBoolean(thisObject.get("ignoreCase")) { | ||
flags = append(flags, 'i') | ||
} | ||
if toBoolean(thisObject.get("multiline")) { | ||
flags = append(flags, 'm') | ||
} | ||
return toValue(fmt.Sprintf("/%s/%s", source, flags)) | ||
} | ||
|
||
func builtinRegExp_exec(call FunctionCall) Value { | ||
thisObject := call.thisObject() | ||
target := toString(call.Argument(0)) | ||
match, result := execRegExp(thisObject, target) | ||
if !match { | ||
return NullValue() | ||
} | ||
return toValue(execResultToArray(call.runtime, target, result)) | ||
} | ||
|
||
func builtinRegExp_test(call FunctionCall) Value { | ||
thisObject := call.thisObject() | ||
target := toString(call.Argument(0)) | ||
match, _ := execRegExp(thisObject, target) | ||
return toValue(match) | ||
} |
Oops, something went wrong.