forked from robertkrimen/otto
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathbuiltin.go
143 lines (122 loc) · 3.41 KB
/
builtin.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
package otto
import (
"fmt"
"math"
"net/url"
"regexp"
"strconv"
"strings"
)
// Global
func builtinGlobal_eval(call FunctionCall) Value {
source := call.Argument(0)
if !source.IsString() {
return source
}
program, err := parse(toString(source))
if err != nil {
switch err := err.(type) {
case *_syntaxError, *_error, _error:
panic(err)
default:
panic(&_syntaxError{Message: fmt.Sprintf("%v", err)})
}
}
runtime := call.runtime
if call.evalHint {
runtime.EnterEvalExecutionContext(call)
defer runtime.LeaveExecutionContext()
}
returnValue := runtime.evaluate(program)
if returnValue.isEmpty() {
return UndefinedValue()
}
return returnValue
}
func builtinGlobal_isNaN(call FunctionCall) Value {
value := toFloat(call.Argument(0))
return toValue(math.IsNaN(value))
}
func builtinGlobal_isFinite(call FunctionCall) Value {
value := toFloat(call.Argument(0))
return toValue(!math.IsNaN(value) && !math.IsInf(value, 0))
}
func builtinGlobal_parseInt(call FunctionCall) Value {
// Caveat emptor: This implementation does NOT match the specification
string_ := strings.TrimSpace(toString(call.Argument(0)))
radix := call.Argument(1)
radixValue := 0
if radix.IsDefined() {
radixValue = int(toInt32(radix))
}
value, err := strconv.ParseInt(string_, radixValue, 64)
if err != nil {
return NaNValue()
}
return toValue(value)
}
func builtinGlobal_parseFloat(call FunctionCall) Value {
// Caveat emptor: This implementation does NOT match the specification
string_ := strings.TrimSpace(toString(call.Argument(0)))
value, err := strconv.ParseFloat(string_, 64)
if err != nil {
return NaNValue()
}
return toValue(value)
}
func _builtinGlobal_encodeURI(call FunctionCall, characterRegexp *regexp.Regexp) Value {
value := []byte(toString(call.Argument(0)))
value = characterRegexp.ReplaceAllFunc(value, func(target []byte) []byte {
// Probably a better way of doing this
if target[0] == ' ' {
return []byte("%20")
}
return []byte(url.QueryEscape(string(target)))
})
return toValue(string(value))
}
var encodeURI_Regexp = regexp.MustCompile(`([^~!@#$&*()=:/,;?+'])`)
func builtinGlobal_encodeURI(call FunctionCall) Value {
return _builtinGlobal_encodeURI(call, encodeURI_Regexp)
}
var encodeURIComponent_Regexp = regexp.MustCompile(`([^~!*()'])`)
func builtinGlobal_encodeURIComponent(call FunctionCall) Value {
return _builtinGlobal_encodeURI(call, encodeURIComponent_Regexp)
}
func builtinGlobal_decodeURI_decodeURIComponent(call FunctionCall) Value {
value, err := url.QueryUnescape(toString(call.Argument(0)))
if err != nil {
panic(newURIError("URI malformed"))
}
return toValue(value)
}
// Error
func builtinError(call FunctionCall) Value {
return toValue(call.runtime.newError("", call.Argument(0)))
}
func builtinNewError(self *_object, _ Value, argumentList []Value) Value {
return toValue(self.runtime.newError("", valueOfArrayIndex(argumentList, 0)))
}
func builtinError_toString(call FunctionCall) Value {
thisObject := call.thisObject()
if thisObject == nil {
panic(newTypeError())
}
name := "Error"
nameValue := thisObject.get("name")
if nameValue.IsDefined() {
name = toString(nameValue)
}
message := ""
messageValue := thisObject.get("message")
if messageValue.IsDefined() {
message = toString(messageValue)
}
if len(name) == 0 {
return toValue(message)
}
if len(message) == 0 {
return toValue(name)
}
return toValue(fmt.Sprintf("%s: %s", name, message))
}