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

290 lines
7.3 KiB
Go
Raw Permalink Normal View History

package otto
import (
"fmt"
)
// Object
func builtinObject(call FunctionCall) Value {
value := call.Argument(0)
switch value.kind {
case valueUndefined, valueNull:
2024-04-04 14:46:14 +00:00
return objectValue(call.runtime.newObject())
}
2024-04-04 14:46:14 +00:00
return objectValue(call.runtime.toObject(value))
}
2024-04-04 14:46:14 +00:00
func builtinNewObject(obj *object, argumentList []Value) Value {
value := valueOfArrayIndex(argumentList, 0)
switch value.kind {
case valueNull, valueUndefined:
case valueNumber, valueString, valueBoolean:
2024-04-04 14:46:14 +00:00
return objectValue(obj.runtime.toObject(value))
case valueObject:
return value
default:
}
2024-04-04 14:46:14 +00:00
return objectValue(obj.runtime.newObject())
}
2024-04-04 14:46:14 +00:00
func builtinObjectValueOf(call FunctionCall) Value {
return objectValue(call.thisObject())
}
2024-04-04 14:46:14 +00:00
func builtinObjectHasOwnProperty(call FunctionCall) Value {
propertyName := call.Argument(0).string()
thisObject := call.thisObject()
2024-04-04 14:46:14 +00:00
return boolValue(thisObject.hasOwnProperty(propertyName))
}
2024-04-04 14:46:14 +00:00
func builtinObjectIsPrototypeOf(call FunctionCall) Value {
value := call.Argument(0)
if !value.IsObject() {
return falseValue
}
prototype := call.toObject(value).prototype
thisObject := call.thisObject()
for prototype != nil {
if thisObject == prototype {
return trueValue
}
prototype = prototype.prototype
}
return falseValue
}
2024-04-04 14:46:14 +00:00
func builtinObjectPropertyIsEnumerable(call FunctionCall) Value {
propertyName := call.Argument(0).string()
thisObject := call.thisObject()
2024-04-04 14:46:14 +00:00
prop := thisObject.getOwnProperty(propertyName)
if prop != nil && prop.enumerable() {
return trueValue
}
return falseValue
}
2024-04-04 14:46:14 +00:00
func builtinObjectToString(call FunctionCall) Value {
var result string
2024-04-04 14:46:14 +00:00
switch {
case call.This.IsUndefined():
result = "[object Undefined]"
2024-04-04 14:46:14 +00:00
case call.This.IsNull():
result = "[object Null]"
2024-04-04 14:46:14 +00:00
default:
result = fmt.Sprintf("[object %s]", call.thisObject().class)
}
2024-04-04 14:46:14 +00:00
return stringValue(result)
}
2024-04-04 14:46:14 +00:00
func builtinObjectToLocaleString(call FunctionCall) Value {
toString := call.thisObject().get("toString")
if !toString.isCallable() {
2024-04-04 14:46:14 +00:00
panic(call.runtime.panicTypeError("Object.toLocaleString %q is not callable", toString))
}
return toString.call(call.runtime, call.This)
}
2024-04-04 14:46:14 +00:00
func builtinObjectGetPrototypeOf(call FunctionCall) Value {
val := call.Argument(0)
obj := val.object()
if obj == nil {
panic(call.runtime.panicTypeError("Object.GetPrototypeOf is nil"))
}
2024-04-04 14:46:14 +00:00
if obj.prototype == nil {
return nullValue
}
2024-04-04 14:46:14 +00:00
return objectValue(obj.prototype)
}
2024-04-04 14:46:14 +00:00
func builtinObjectGetOwnPropertyDescriptor(call FunctionCall) Value {
val := call.Argument(0)
obj := val.object()
if obj == nil {
panic(call.runtime.panicTypeError("Object.GetOwnPropertyDescriptor is nil"))
}
name := call.Argument(1).string()
2024-04-04 14:46:14 +00:00
descriptor := obj.getOwnProperty(name)
if descriptor == nil {
return Value{}
}
2024-04-04 14:46:14 +00:00
return objectValue(call.runtime.fromPropertyDescriptor(*descriptor))
}
2024-04-04 14:46:14 +00:00
func builtinObjectDefineProperty(call FunctionCall) Value {
val := call.Argument(0)
obj := val.object()
if obj == nil {
panic(call.runtime.panicTypeError("Object.DefineProperty is nil"))
}
name := call.Argument(1).string()
descriptor := toPropertyDescriptor(call.runtime, call.Argument(2))
2024-04-04 14:46:14 +00:00
obj.defineOwnProperty(name, descriptor, true)
return val
}
2024-04-04 14:46:14 +00:00
func builtinObjectDefineProperties(call FunctionCall) Value {
val := call.Argument(0)
obj := val.object()
if obj == nil {
panic(call.runtime.panicTypeError("Object.DefineProperties is nil"))
}
properties := call.runtime.toObject(call.Argument(1))
properties.enumerate(false, func(name string) bool {
descriptor := toPropertyDescriptor(call.runtime, properties.get(name))
2024-04-04 14:46:14 +00:00
obj.defineOwnProperty(name, descriptor, true)
return true
})
2024-04-04 14:46:14 +00:00
return val
}
2024-04-04 14:46:14 +00:00
func builtinObjectCreate(call FunctionCall) Value {
prototypeValue := call.Argument(0)
if !prototypeValue.IsNull() && !prototypeValue.IsObject() {
2024-04-04 14:46:14 +00:00
panic(call.runtime.panicTypeError("Object.Create is nil"))
}
2024-04-04 14:46:14 +00:00
obj := call.runtime.newObject()
obj.prototype = prototypeValue.object()
propertiesValue := call.Argument(1)
if propertiesValue.IsDefined() {
properties := call.runtime.toObject(propertiesValue)
properties.enumerate(false, func(name string) bool {
descriptor := toPropertyDescriptor(call.runtime, properties.get(name))
2024-04-04 14:46:14 +00:00
obj.defineOwnProperty(name, descriptor, true)
return true
})
}
2024-04-04 14:46:14 +00:00
return objectValue(obj)
}
2024-04-04 14:46:14 +00:00
func builtinObjectIsExtensible(call FunctionCall) Value {
val := call.Argument(0)
if obj := val.object(); obj != nil {
return boolValue(obj.extensible)
}
2024-04-04 14:46:14 +00:00
panic(call.runtime.panicTypeError("Object.IsExtensible is nil"))
}
2024-04-04 14:46:14 +00:00
func builtinObjectPreventExtensions(call FunctionCall) Value {
val := call.Argument(0)
if obj := val.object(); obj != nil {
obj.extensible = false
return val
}
2024-04-04 14:46:14 +00:00
panic(call.runtime.panicTypeError("Object.PreventExtensions is nil"))
}
2024-04-04 14:46:14 +00:00
func builtinObjectIsSealed(call FunctionCall) Value {
val := call.Argument(0)
if obj := val.object(); obj != nil {
if obj.extensible {
return boolValue(false)
}
result := true
2024-04-04 14:46:14 +00:00
obj.enumerate(true, func(name string) bool {
prop := obj.getProperty(name)
if prop.configurable() {
result = false
}
return true
})
2024-04-04 14:46:14 +00:00
return boolValue(result)
}
2024-04-04 14:46:14 +00:00
panic(call.runtime.panicTypeError("Object.IsSealed is nil"))
}
2024-04-04 14:46:14 +00:00
func builtinObjectSeal(call FunctionCall) Value {
val := call.Argument(0)
if obj := val.object(); obj != nil {
obj.enumerate(true, func(name string) bool {
if prop := obj.getOwnProperty(name); nil != prop && prop.configurable() {
prop.configureOff()
obj.defineOwnProperty(name, *prop, true)
}
return true
})
2024-04-04 14:46:14 +00:00
obj.extensible = false
return val
}
2024-04-04 14:46:14 +00:00
panic(call.runtime.panicTypeError("Object.Seal is nil"))
}
2024-04-04 14:46:14 +00:00
func builtinObjectIsFrozen(call FunctionCall) Value {
val := call.Argument(0)
if obj := val.object(); obj != nil {
if obj.extensible {
return boolValue(false)
}
result := true
2024-04-04 14:46:14 +00:00
obj.enumerate(true, func(name string) bool {
prop := obj.getProperty(name)
if prop.configurable() || prop.writable() {
result = false
}
return true
})
2024-04-04 14:46:14 +00:00
return boolValue(result)
}
2024-04-04 14:46:14 +00:00
panic(call.runtime.panicTypeError("Object.IsFrozen is nil"))
}
2024-04-04 14:46:14 +00:00
func builtinObjectFreeze(call FunctionCall) Value {
val := call.Argument(0)
if obj := val.object(); obj != nil {
obj.enumerate(true, func(name string) bool {
if prop, update := obj.getOwnProperty(name), false; nil != prop {
if prop.isDataDescriptor() && prop.writable() {
prop.writeOff()
update = true
}
2024-04-04 14:46:14 +00:00
if prop.configurable() {
prop.configureOff()
update = true
}
if update {
2024-04-04 14:46:14 +00:00
obj.defineOwnProperty(name, *prop, true)
}
}
return true
})
2024-04-04 14:46:14 +00:00
obj.extensible = false
return val
}
2024-04-04 14:46:14 +00:00
panic(call.runtime.panicTypeError("Object.Freeze is nil"))
}
2024-04-04 14:46:14 +00:00
func builtinObjectKeys(call FunctionCall) Value {
if obj, keys := call.Argument(0).object(), []Value(nil); nil != obj {
obj.enumerate(false, func(name string) bool {
keys = append(keys, stringValue(name))
return true
})
2024-04-04 14:46:14 +00:00
return objectValue(call.runtime.newArrayOf(keys))
}
2024-04-04 14:46:14 +00:00
panic(call.runtime.panicTypeError("Object.Keys is nil"))
}
2024-04-04 14:46:14 +00:00
func builtinObjectGetOwnPropertyNames(call FunctionCall) Value {
if obj, propertyNames := call.Argument(0).object(), []Value(nil); nil != obj {
obj.enumerate(true, func(name string) bool {
if obj.hasOwnProperty(name) {
propertyNames = append(propertyNames, stringValue(name))
}
return true
})
2024-04-04 14:46:14 +00:00
return objectValue(call.runtime.newArrayOf(propertyNames))
}
2024-04-04 14:46:14 +00:00
// Default to empty array for non object types.
return objectValue(call.runtime.newArray(0))
}