mirror of
https://github.com/robertkrimen/otto
synced 2025-10-12 20:27:30 +08:00
142 lines
2.9 KiB
Go
142 lines
2.9 KiB
Go
package otto
|
|
|
|
type _stash interface {
|
|
test(string) bool
|
|
get(string) Value
|
|
property(string) *_property
|
|
index(string) (_property, bool)
|
|
enumerate(func(string))
|
|
|
|
canPut(string) bool
|
|
put(string, Value)
|
|
set(string, Value, _propertyMode)
|
|
defineProperty(string, interface{}, _propertyMode)
|
|
|
|
delete(string)
|
|
|
|
extensible() bool
|
|
lock()
|
|
unlock()
|
|
}
|
|
|
|
type _objectStash struct {
|
|
_extensible bool
|
|
propertyMap map[string]_property
|
|
}
|
|
|
|
func newObjectStash(extensible bool) *_objectStash {
|
|
return &_objectStash{
|
|
_extensible: extensible,
|
|
propertyMap: make(map[string]_property),
|
|
}
|
|
}
|
|
|
|
func (self *_objectStash) test(name string) bool {
|
|
_, exists := self.propertyMap[name]
|
|
return exists
|
|
}
|
|
|
|
func (self *_objectStash) get(name string) Value {
|
|
property, exists := self.propertyMap[name]
|
|
|
|
if !exists {
|
|
return UndefinedValue()
|
|
}
|
|
|
|
switch value := property.value.(type) {
|
|
case Value:
|
|
return value
|
|
case _propertyGetSet:
|
|
if value[0] == nil {
|
|
return UndefinedValue()
|
|
}
|
|
return value[0].CallGet(name)
|
|
}
|
|
|
|
panic(hereBeDragons())
|
|
}
|
|
|
|
func (self *_objectStash) property(name string) *_property {
|
|
property, exists := self.propertyMap[name]
|
|
if !exists {
|
|
return nil
|
|
}
|
|
return &property
|
|
}
|
|
|
|
func (self _objectStash) index(name string) (_property, bool) {
|
|
property := self.property(name)
|
|
if property == nil {
|
|
return _property{}, false
|
|
}
|
|
return *property, true
|
|
}
|
|
|
|
func (self *_objectStash) enumerate(each func(string)) {
|
|
for name, property := range self.propertyMap {
|
|
if property.enumerable() {
|
|
each(name)
|
|
}
|
|
}
|
|
}
|
|
|
|
func (self *_objectStash) canPut(name string) bool {
|
|
property, exists := self.propertyMap[name]
|
|
if !exists {
|
|
return self.extensible()
|
|
}
|
|
switch propertyValue := property.value.(type) {
|
|
case Value:
|
|
return property.writable()
|
|
case _propertyGetSet:
|
|
return propertyValue[1] != nil
|
|
}
|
|
panic(hereBeDragons())
|
|
}
|
|
|
|
func (self *_objectStash) put(name string, value Value) {
|
|
property, exists := self.propertyMap[name]
|
|
if exists {
|
|
switch propertyValue := property.value.(type) {
|
|
case Value:
|
|
if property.writable() {
|
|
property.value = value
|
|
self.propertyMap[name] = property
|
|
}
|
|
case _propertyGetSet:
|
|
if propertyValue[1] != nil {
|
|
propertyValue[1].CallSet(name, value)
|
|
}
|
|
}
|
|
} else if self.extensible() {
|
|
self.propertyMap[name] = _property{value, 0111} // Write, Enumerate, Configure
|
|
}
|
|
}
|
|
|
|
func (self *_objectStash) set(name string, value Value, mode _propertyMode) {
|
|
self.propertyMap[name] = _property{value, mode}
|
|
}
|
|
|
|
func (self *_objectStash) defineProperty(name string, value interface{}, mode _propertyMode) {
|
|
if value == nil {
|
|
value = UndefinedValue()
|
|
}
|
|
self.propertyMap[name] = _property{value, mode}
|
|
}
|
|
|
|
func (self *_objectStash) delete(name string) {
|
|
delete(self.propertyMap, name)
|
|
}
|
|
|
|
func (self _objectStash) extensible() bool {
|
|
return self._extensible
|
|
}
|
|
|
|
func (self *_objectStash) lock() {
|
|
self._extensible = false
|
|
}
|
|
|
|
func (self *_objectStash) unlock() {
|
|
self._extensible = true
|
|
}
|