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

219 lines
5.2 KiB
Go
Raw Normal View History

package otto
// property
2024-04-04 14:46:14 +00:00
type propertyMode int
const (
2024-04-04 14:46:14 +00:00
modeWriteMask propertyMode = 0o700
modeEnumerateMask propertyMode = 0o070
modeConfigureMask propertyMode = 0o007
modeOnMask propertyMode = 0o111
modeSetMask propertyMode = 0o222 // If value is 2, then mode is neither "On" nor "Off"
)
2024-04-04 14:46:14 +00:00
type propertyGetSet [2]*object
2024-04-04 14:46:14 +00:00
var nilGetSetObject = object{}
2024-04-04 14:46:14 +00:00
type property struct {
value interface{}
2024-04-04 14:46:14 +00:00
mode propertyMode
}
2024-04-04 14:46:14 +00:00
func (p property) writable() bool {
return p.mode&modeWriteMask == modeWriteMask&modeOnMask
}
2024-04-04 14:46:14 +00:00
func (p *property) writeOn() {
p.mode = (p.mode & ^modeWriteMask) | (modeWriteMask & modeOnMask)
}
2024-04-04 14:46:14 +00:00
func (p *property) writeOff() {
p.mode &= ^modeWriteMask
}
2024-04-04 14:46:14 +00:00
func (p *property) writeClear() {
p.mode = (p.mode & ^modeWriteMask) | (modeWriteMask & modeSetMask)
}
2024-04-04 14:46:14 +00:00
func (p property) writeSet() bool {
return p.mode&modeWriteMask&modeSetMask == 0
}
2024-04-04 14:46:14 +00:00
func (p property) enumerable() bool {
return p.mode&modeEnumerateMask == modeEnumerateMask&modeOnMask
}
2024-04-04 14:46:14 +00:00
func (p *property) enumerateOn() {
p.mode = (p.mode & ^modeEnumerateMask) | (modeEnumerateMask & modeOnMask)
}
2024-04-04 14:46:14 +00:00
func (p *property) enumerateOff() {
p.mode &= ^modeEnumerateMask
}
2024-04-04 14:46:14 +00:00
func (p property) enumerateSet() bool {
return p.mode&modeEnumerateMask&modeSetMask == 0
}
2024-04-04 14:46:14 +00:00
func (p property) configurable() bool {
return p.mode&modeConfigureMask == modeConfigureMask&modeOnMask
}
2024-04-04 14:46:14 +00:00
func (p *property) configureOn() {
p.mode = (p.mode & ^modeConfigureMask) | (modeConfigureMask & modeOnMask)
}
2024-04-04 14:46:14 +00:00
func (p *property) configureOff() {
p.mode &= ^modeConfigureMask
}
2024-04-04 14:46:14 +00:00
func (p property) configureSet() bool { //nolint: unused
return p.mode&modeConfigureMask&modeSetMask == 0
}
2024-04-04 14:46:14 +00:00
func (p property) copy() *property { //nolint: unused
cpy := p
return &cpy
}
2024-04-04 14:46:14 +00:00
func (p property) get(this *object) Value {
switch value := p.value.(type) {
case Value:
return value
2024-04-04 14:46:14 +00:00
case propertyGetSet:
if value[0] != nil {
return value[0].call(toValue(this), nil, false, nativeFrame)
}
}
return Value{}
}
2024-04-04 14:46:14 +00:00
func (p property) isAccessorDescriptor() bool {
setGet, test := p.value.(propertyGetSet)
return test && (setGet[0] != nil || setGet[1] != nil)
}
2024-04-04 14:46:14 +00:00
func (p property) isDataDescriptor() bool {
if p.writeSet() { // Either "On" or "Off"
return true
}
2024-04-04 14:46:14 +00:00
value, valid := p.value.(Value)
return valid && !value.isEmpty()
}
2024-04-04 14:46:14 +00:00
func (p property) isGenericDescriptor() bool {
return !(p.isDataDescriptor() || p.isAccessorDescriptor())
}
2024-04-04 14:46:14 +00:00
func (p property) isEmpty() bool {
return p.mode == 0o222 && p.isGenericDescriptor()
}
// _enumerableValue, _enumerableTrue, _enumerableFalse?
// .enumerableValue() .enumerableExists()
2024-04-04 14:46:14 +00:00
func toPropertyDescriptor(rt *runtime, value Value) property {
objectDescriptor := value.object()
if objectDescriptor == nil {
2024-04-04 14:46:14 +00:00
panic(rt.panicTypeError("toPropertyDescriptor on nil"))
}
2024-04-04 14:46:14 +00:00
var descriptor property
descriptor.mode = modeSetMask // Initially nothing is set
if objectDescriptor.hasProperty("enumerable") {
if objectDescriptor.get("enumerable").bool() {
descriptor.enumerateOn()
} else {
descriptor.enumerateOff()
}
2024-04-04 14:46:14 +00:00
}
2024-04-04 14:46:14 +00:00
if objectDescriptor.hasProperty("configurable") {
if objectDescriptor.get("configurable").bool() {
descriptor.configureOn()
} else {
descriptor.configureOff()
}
2024-04-04 14:46:14 +00:00
}
2024-04-04 14:46:14 +00:00
if objectDescriptor.hasProperty("writable") {
if objectDescriptor.get("writable").bool() {
descriptor.writeOn()
} else {
descriptor.writeOff()
}
}
2024-04-04 14:46:14 +00:00
var getter, setter *object
getterSetter := false
if objectDescriptor.hasProperty("get") {
value := objectDescriptor.get("get")
if value.IsDefined() {
if !value.isCallable() {
2024-04-04 14:46:14 +00:00
panic(rt.panicTypeError("toPropertyDescriptor get not callable"))
}
2024-04-04 14:46:14 +00:00
getter = value.object()
getterSetter = true
} else {
2024-04-04 14:46:14 +00:00
getter = &nilGetSetObject
getterSetter = true
}
}
if objectDescriptor.hasProperty("set") {
value := objectDescriptor.get("set")
if value.IsDefined() {
if !value.isCallable() {
2024-04-04 14:46:14 +00:00
panic(rt.panicTypeError("toPropertyDescriptor set not callable"))
}
2024-04-04 14:46:14 +00:00
setter = value.object()
getterSetter = true
} else {
2024-04-04 14:46:14 +00:00
setter = &nilGetSetObject
getterSetter = true
}
}
if getterSetter {
if descriptor.writeSet() {
2024-04-04 14:46:14 +00:00
panic(rt.panicTypeError("toPropertyDescriptor descriptor writeSet"))
}
2024-04-04 14:46:14 +00:00
descriptor.value = propertyGetSet{getter, setter}
}
if objectDescriptor.hasProperty("value") {
if getterSetter {
2024-04-04 14:46:14 +00:00
panic(rt.panicTypeError("toPropertyDescriptor value getterSetter"))
}
descriptor.value = objectDescriptor.get("value")
}
2024-04-04 14:46:14 +00:00
return descriptor
}
2024-04-04 14:46:14 +00:00
func (rt *runtime) fromPropertyDescriptor(descriptor property) *object {
obj := rt.newObject()
if descriptor.isDataDescriptor() {
2024-04-04 14:46:14 +00:00
obj.defineProperty("value", descriptor.value.(Value), 0o111, false)
obj.defineProperty("writable", boolValue(descriptor.writable()), 0o111, false)
} else if descriptor.isAccessorDescriptor() {
2024-04-04 14:46:14 +00:00
getSet := descriptor.value.(propertyGetSet)
get := Value{}
if getSet[0] != nil {
2024-04-04 14:46:14 +00:00
get = objectValue(getSet[0])
}
set := Value{}
if getSet[1] != nil {
2024-04-04 14:46:14 +00:00
set = objectValue(getSet[1])
}
2024-04-04 14:46:14 +00:00
obj.defineProperty("get", get, 0o111, false)
obj.defineProperty("set", set, 0o111, false)
}
2024-04-04 14:46:14 +00:00
obj.defineProperty("enumerable", boolValue(descriptor.enumerable()), 0o111, false)
obj.defineProperty("configurable", boolValue(descriptor.configurable()), 0o111, false)
return obj
}