rum-goggles/v1/vendor/github.com/robertkrimen/otto/global.go

218 lines
5.3 KiB
Go
Raw Permalink Normal View History

package otto
import (
"strconv"
"time"
)
var (
prototypeValueObject = interface{}(nil)
2024-04-04 14:46:14 +00:00
prototypeValueFunction = nativeFunctionObject{
call: func(_ FunctionCall) Value {
return Value{}
},
}
2024-04-04 14:46:14 +00:00
prototypeValueString = stringASCII("")
// TODO Make this just false?
prototypeValueBoolean = Value{
kind: valueBoolean,
value: false,
}
prototypeValueNumber = Value{
kind: valueNumber,
value: 0,
}
2024-04-04 14:46:14 +00:00
prototypeValueDate = dateObject{
epoch: 0,
isNaN: false,
time: time.Unix(0, 0).UTC(),
value: Value{
kind: valueNumber,
value: 0,
},
}
2024-04-04 14:46:14 +00:00
prototypeValueRegExp = regExpObject{
regularExpression: nil,
global: false,
ignoreCase: false,
multiline: false,
source: "",
flags: "",
}
)
2024-04-04 14:46:14 +00:00
func newContext() *runtime {
rt := &runtime{}
2024-04-04 14:46:14 +00:00
rt.globalStash = rt.newObjectStash(nil, nil)
rt.globalObject = rt.globalStash.object
2024-04-04 14:46:14 +00:00
rt.newContext()
2024-04-04 14:46:14 +00:00
rt.eval = rt.globalObject.property["eval"].value.(Value).value.(*object)
rt.globalObject.prototype = rt.global.ObjectPrototype
2024-04-04 14:46:14 +00:00
return rt
}
2024-04-04 14:46:14 +00:00
func (rt *runtime) newBaseObject() *object {
return newObject(rt, "")
}
2024-04-04 14:46:14 +00:00
func (rt *runtime) newClassObject(class string) *object {
return newObject(rt, class)
}
2024-04-04 14:46:14 +00:00
func (rt *runtime) newPrimitiveObject(class string, value Value) *object {
o := rt.newClassObject(class)
o.value = value
return o
}
2024-04-04 14:46:14 +00:00
func (o *object) primitiveValue() Value {
switch value := o.value.(type) {
case Value:
return value
2024-04-04 14:46:14 +00:00
case stringObjecter:
return stringValue(value.String())
}
return Value{}
}
2024-04-04 14:46:14 +00:00
func (o *object) hasPrimitive() bool { //nolint: unused
switch o.value.(type) {
case Value, stringObjecter:
return true
}
return false
}
2024-04-04 14:46:14 +00:00
func (rt *runtime) newObject() *object {
o := rt.newClassObject(classObjectName)
o.prototype = rt.global.ObjectPrototype
return o
}
2024-04-04 14:46:14 +00:00
func (rt *runtime) newArray(length uint32) *object {
o := rt.newArrayObject(length)
o.prototype = rt.global.ArrayPrototype
return o
}
2024-04-04 14:46:14 +00:00
func (rt *runtime) newArrayOf(valueArray []Value) *object {
o := rt.newArray(uint32(len(valueArray)))
for index, value := range valueArray {
if value.isEmpty() {
continue
}
2024-04-04 14:46:14 +00:00
o.defineProperty(strconv.FormatInt(int64(index), 10), value, 0o111, false)
}
2024-04-04 14:46:14 +00:00
return o
}
2024-04-04 14:46:14 +00:00
func (rt *runtime) newString(value Value) *object {
o := rt.newStringObject(value)
o.prototype = rt.global.StringPrototype
return o
}
2024-04-04 14:46:14 +00:00
func (rt *runtime) newBoolean(value Value) *object {
o := rt.newBooleanObject(value)
o.prototype = rt.global.BooleanPrototype
return o
}
2024-04-04 14:46:14 +00:00
func (rt *runtime) newNumber(value Value) *object {
o := rt.newNumberObject(value)
o.prototype = rt.global.NumberPrototype
return o
}
2024-04-04 14:46:14 +00:00
func (rt *runtime) newRegExp(patternValue Value, flagsValue Value) *object {
pattern := ""
flags := ""
2024-04-04 14:46:14 +00:00
if obj := patternValue.object(); obj != nil && obj.class == classRegExpName {
if flagsValue.IsDefined() {
2024-04-04 14:46:14 +00:00
panic(rt.panicTypeError("Cannot supply flags when constructing one RegExp from another"))
}
2024-04-04 14:46:14 +00:00
regExp := obj.regExpValue()
pattern = regExp.source
flags = regExp.flags
} else {
if patternValue.IsDefined() {
pattern = patternValue.string()
}
if flagsValue.IsDefined() {
flags = flagsValue.string()
}
}
2024-04-04 14:46:14 +00:00
return rt.newRegExpDirect(pattern, flags)
}
2024-04-04 14:46:14 +00:00
func (rt *runtime) newRegExpDirect(pattern string, flags string) *object {
o := rt.newRegExpObject(pattern, flags)
o.prototype = rt.global.RegExpPrototype
return o
}
2024-04-04 14:46:14 +00:00
// TODO Should (probably) be one argument, right? This is redundant.
func (rt *runtime) newDate(epoch float64) *object {
o := rt.newDateObject(epoch)
o.prototype = rt.global.DatePrototype
return o
}
2024-04-04 14:46:14 +00:00
func (rt *runtime) newError(name string, message Value, stackFramesToPop int) *object {
switch name {
case "EvalError":
2024-04-04 14:46:14 +00:00
return rt.newEvalError(message)
case "TypeError":
2024-04-04 14:46:14 +00:00
return rt.newTypeError(message)
case "RangeError":
2024-04-04 14:46:14 +00:00
return rt.newRangeError(message)
case "ReferenceError":
2024-04-04 14:46:14 +00:00
return rt.newReferenceError(message)
case "SyntaxError":
2024-04-04 14:46:14 +00:00
return rt.newSyntaxError(message)
case "URIError":
2024-04-04 14:46:14 +00:00
return rt.newURIError(message)
}
2024-04-04 14:46:14 +00:00
obj := rt.newErrorObject(name, message, stackFramesToPop)
obj.prototype = rt.global.ErrorPrototype
if name != "" {
2024-04-04 14:46:14 +00:00
obj.defineProperty("name", stringValue(name), 0o111, false)
}
2024-04-04 14:46:14 +00:00
return obj
}
2024-04-04 14:46:14 +00:00
func (rt *runtime) newNativeFunction(name, file string, line int, fn nativeFunction) *object {
o := rt.newNativeFunctionObject(name, file, line, fn, 0)
o.prototype = rt.global.FunctionPrototype
prototype := rt.newObject()
o.defineProperty("prototype", objectValue(prototype), 0o100, false)
prototype.defineProperty("constructor", objectValue(o), 0o100, false)
return o
}
2024-04-04 14:46:14 +00:00
func (rt *runtime) newNodeFunction(node *nodeFunctionLiteral, scopeEnvironment stasher) *object {
// TODO Implement 13.2 fully
2024-04-04 14:46:14 +00:00
o := rt.newNodeFunctionObject(node, scopeEnvironment)
o.prototype = rt.global.FunctionPrototype
prototype := rt.newObject()
o.defineProperty("prototype", objectValue(prototype), 0o100, false)
prototype.defineProperty("constructor", objectValue(o), 0o101, false)
return o
}
// FIXME Only in one place...
2024-04-04 14:46:14 +00:00
func (rt *runtime) newBoundFunction(target *object, this Value, argumentList []Value) *object {
o := rt.newBoundFunctionObject(target, this, argumentList)
o.prototype = rt.global.FunctionPrototype
prototype := rt.newObject()
o.defineProperty("prototype", objectValue(prototype), 0o100, false)
prototype.defineProperty("constructor", objectValue(o), 0o100, false)
return o
}