mirror of
https://github.com/robertkrimen/otto
synced 2025-10-26 20:28:49 +08:00
Enumerate (consistently) in definition order
This commit is contained in:
parent
d68cd0afe2
commit
bef32b9223
47
stash.go
47
stash.go
|
|
@ -21,23 +21,24 @@ type _stash interface {
|
||||||
|
|
||||||
type _objectStash struct {
|
type _objectStash struct {
|
||||||
_extensible bool
|
_extensible bool
|
||||||
propertyMap map[string]_property
|
_property map[string]_property
|
||||||
|
_order []string
|
||||||
}
|
}
|
||||||
|
|
||||||
func newObjectStash(extensible bool) *_objectStash {
|
func newObjectStash(extensible bool) *_objectStash {
|
||||||
return &_objectStash{
|
return &_objectStash{
|
||||||
_extensible: extensible,
|
_extensible: extensible,
|
||||||
propertyMap: make(map[string]_property),
|
_property: make(map[string]_property),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *_objectStash) test(name string) bool {
|
func (self *_objectStash) test(name string) bool {
|
||||||
_, exists := self.propertyMap[name]
|
_, exists := self._property[name]
|
||||||
return exists
|
return exists
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *_objectStash) get(name string) Value {
|
func (self *_objectStash) get(name string) Value {
|
||||||
property, exists := self.propertyMap[name]
|
property, exists := self._property[name]
|
||||||
|
|
||||||
if !exists {
|
if !exists {
|
||||||
return UndefinedValue()
|
return UndefinedValue()
|
||||||
|
|
@ -57,7 +58,7 @@ func (self *_objectStash) get(name string) Value {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *_objectStash) property(name string) *_property {
|
func (self *_objectStash) property(name string) *_property {
|
||||||
property, exists := self.propertyMap[name]
|
property, exists := self._property[name]
|
||||||
if !exists {
|
if !exists {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
@ -73,15 +74,15 @@ func (self _objectStash) index(name string) (_property, bool) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *_objectStash) enumerate(each func(string)) {
|
func (self *_objectStash) enumerate(each func(string)) {
|
||||||
for name, property := range self.propertyMap {
|
for _, name := range self._order {
|
||||||
if property.enumerable() {
|
if self._property[name].enumerable() {
|
||||||
each(name)
|
each(name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *_objectStash) canPut(name string) bool {
|
func (self *_objectStash) canPut(name string) bool {
|
||||||
property, exists := self.propertyMap[name]
|
property, exists := self._property[name]
|
||||||
if !exists {
|
if !exists {
|
||||||
return self.extensible()
|
return self.extensible()
|
||||||
}
|
}
|
||||||
|
|
@ -95,13 +96,13 @@ func (self *_objectStash) canPut(name string) bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *_objectStash) put(name string, value Value) {
|
func (self *_objectStash) put(name string, value Value) {
|
||||||
property, exists := self.propertyMap[name]
|
property, exists := self._property[name]
|
||||||
if exists {
|
if exists {
|
||||||
switch propertyValue := property.value.(type) {
|
switch propertyValue := property.value.(type) {
|
||||||
case Value:
|
case Value:
|
||||||
if property.writable() {
|
if property.writable() {
|
||||||
property.value = value
|
property.value = value
|
||||||
self.propertyMap[name] = property
|
self._property[name] = property
|
||||||
}
|
}
|
||||||
case _propertyGetSet:
|
case _propertyGetSet:
|
||||||
if propertyValue[1] != nil {
|
if propertyValue[1] != nil {
|
||||||
|
|
@ -109,23 +110,41 @@ func (self *_objectStash) put(name string, value Value) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if self.extensible() {
|
} else if self.extensible() {
|
||||||
self.propertyMap[name] = _property{value, 0111} // Write, Enumerate, Configure
|
self._property[name] = _property{value, 0111} // Write, Enumerate, Configure
|
||||||
|
self._order = append(self._order, name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *_objectStash) set(name string, value Value, mode _propertyMode) {
|
func (self *_objectStash) set(name string, value Value, mode _propertyMode) {
|
||||||
self.propertyMap[name] = _property{value, mode}
|
_, exists := self._property[name]
|
||||||
|
self._property[name] = _property{value, mode}
|
||||||
|
if !exists {
|
||||||
|
self._order = append(self._order, name)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *_objectStash) defineProperty(name string, value interface{}, mode _propertyMode) {
|
func (self *_objectStash) defineProperty(name string, value interface{}, mode _propertyMode) {
|
||||||
if value == nil {
|
if value == nil {
|
||||||
value = UndefinedValue()
|
value = UndefinedValue()
|
||||||
}
|
}
|
||||||
self.propertyMap[name] = _property{value, mode}
|
_, exists := self._property[name]
|
||||||
|
self._property[name] = _property{value, mode}
|
||||||
|
if !exists {
|
||||||
|
self._order = append(self._order, name)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *_objectStash) delete(name string) {
|
func (self *_objectStash) delete(name string) {
|
||||||
delete(self.propertyMap, name)
|
delete(self._property, name)
|
||||||
|
for index, property := range self._order {
|
||||||
|
if name == property {
|
||||||
|
if index == len(self._order)-1 {
|
||||||
|
self._order = self._order[:index]
|
||||||
|
} else {
|
||||||
|
self._order = append(self._order[:index], self._order[index+1:]...)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self _objectStash) extensible() bool {
|
func (self _objectStash) extensible() bool {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user