1
0
mirror of https://github.com/robertkrimen/otto synced 2025-10-19 19:55:30 +08:00
otto/type_reference.go
Robert Krimen 7e2b4f2063 Rewrite of property handling to be more robust and compliant
* No more _stash
* Now using a "virtual table" system via _objectClass
* Make Array.concat GoArray compatible (via .isArray())

Fix #16
2013-05-12 14:14:51 -07:00

156 lines
3.5 KiB
Go

package otto
type _reference interface {
GetBase() interface{} // GetBase
GetName() string // GetReferencedName
IsStrict() bool // IsStrictReference
IsUnresolvable() bool // IsUnresolvableReference
IsPropertyReference() bool // IsPropertyReference
GetValue() Value // GetValue
PutValue(Value) bool // PutValue
Delete() bool
}
// Reference
type _referenceDefault struct {
name string
strict bool
}
func (self _referenceDefault) GetName() string {
return self.name
}
func (self _referenceDefault) IsStrict() bool {
return self.strict
}
// PropertyReference
type _propertyReference struct {
_referenceDefault
Base *_object
node _node
}
func newPropertyReference(base *_object, name string, strict bool, node _node) *_propertyReference {
return &_propertyReference{
Base: base,
_referenceDefault: _referenceDefault{
name: name,
strict: strict,
},
node: node,
}
}
func (self *_propertyReference) GetBase() interface{} {
return self.Base
}
func (self *_propertyReference) IsUnresolvable() bool {
return self.Base == nil
}
func (self *_propertyReference) IsPropertyReference() bool {
return true
}
func (self *_propertyReference) GetValue() Value {
if self.Base == nil {
panic(newReferenceError("notDefined", self.name, self.node))
}
return self.Base.get(self.name)
}
func (self *_propertyReference) PutValue(value Value) bool {
if self.Base == nil {
return false
}
self.Base.put(self.name, value, self.IsStrict())
return true
}
func (self *_propertyReference) Delete() bool {
if self.Base == nil {
// TODO Throw an error if strict
return true
}
return self.Base.delete(self.name, self.IsStrict())
}
// ArgumentReference
func newArgumentReference(base *_object, name string, strict bool) *_propertyReference {
if base == nil {
panic(hereBeDragons())
}
return newPropertyReference(base, name, strict, nil)
}
type _environmentReference struct {
_referenceDefault
Base _environment
node _node
}
func newEnvironmentReference(base _environment, name string, strict bool, node _node) *_environmentReference {
return &_environmentReference{
Base: base,
_referenceDefault: _referenceDefault{
name: name,
strict: strict,
},
node: node,
}
}
func (self *_environmentReference) GetBase() interface{} {
return self.Base
}
func (self *_environmentReference) IsUnresolvable() bool {
return self.Base == nil // The base (an environment) will never be nil
}
func (self *_environmentReference) IsPropertyReference() bool {
return false
}
func (self *_environmentReference) GetValue() Value {
if self.Base == nil {
// This should never be reached, but just in case
}
return self.Base.GetValue(self.name, self.IsStrict())
}
func (self *_environmentReference) PutValue(value Value) bool {
if self.Base == nil {
// This should never be reached, but just in case
return false
}
self.Base.SetValue(self.name, value, self.IsStrict())
return true
}
func (self *_environmentReference) Delete() bool {
if self.Base == nil {
// This should never be reached, but just in case
return false
}
return self.Base.DeleteBinding(self.name)
}
// getIdentifierReference
func getIdentifierReference(environment _environment, name string, strict bool, node _node) _reference {
if environment == nil {
return newPropertyReference(nil, name, strict, node)
}
if environment.HasBinding(name) {
return environment.newReference(name, strict)
}
return getIdentifierReference(environment.Outer(), name, strict, node)
}