1
0
mirror of https://github.com/robertkrimen/otto synced 2025-09-28 18:45:22 +08:00
otto/object.go
2012-10-05 18:47:53 -07:00

305 lines
6.6 KiB
Go

package otto
type _object struct {
runtime *_runtime
Class string
Extensible bool
Prototype *_object
_propertyStash _stash
Primitive *Value
Function *_functionObject
RegExp *_regExpObject
Date *_dateObject
}
func (self _object) PrimitiveValue() Value {
return *self.Primitive
}
func newObject(runtime *_runtime, class string) *_object {
return &_object{
runtime: runtime,
Class: class,
Extensible: true,
_propertyStash: newPropertyStash(true),
}
}
// Write
func (self *_object) WriteValue(name string, value Value, throw bool) {
canWrite := self._propertyStash.CanWrite(name)
if !canWrite {
typeErrorResult(throw)
return
}
self._propertyStash.Write(name, value)
}
// Delete
func (self *_object) Delete(name string, throw bool) bool {
property_ := self.GetOwnProperty(name)
if property_ == nil {
return true
}
if property_.CanConfigure() {
self._propertyStash.Delete(name)
return true
}
return typeErrorResult(throw)
}
// Get
func (self *_object) GetValue(name string) Value {
return self.Get(name)
}
// 8.12
// 8.12.1
func (self *_object) GetOwnProperty(name string) *_property {
// Return a _copy_ of the property
property := self._propertyStash.property(name)
if property == nil {
return nil
}
{
property := *property
return &property
}
}
func (self *_object) getProperty(name string) *_property {
for object := self; object != nil; object = object.Prototype {
property := object._propertyStash.property(name)
if property != nil {
return property
}
}
return nil
}
// 8.12.2
func (self *_object) GetProperty(name string) *_property {
property := self.getProperty(name)
if property != nil {
property = property.Copy()
}
return property
}
// 8.12.3
func (self *_object) Get(name string) Value {
object := self
for object != nil {
if object._propertyStash.CanRead(name) {
return object._propertyStash.Read(name)
}
object = object.Prototype
}
return UndefinedValue()
}
// 8.12.4
func (self *_object) CanPut(name string) bool {
property := self._propertyStash.property(name)
if property != nil {
switch value := property.Value.(type) {
case Value:
return property.CanWrite()
case _propertyGetSet:
return value[1] != nil
default:
panic(hereBeDragons())
}
}
if self.Prototype != nil {
property = self.Prototype.getProperty(name)
}
if property == nil {
return self.Extensible
}
switch value := property.Value.(type) {
case Value:
if !self.Extensible {
return false
}
return property.CanWrite()
case _propertyGetSet:
return value[1] != nil
}
panic(hereBeDragons())
}
// 8.12.5
func (self *_object) Put(name string, value Value, throw bool) {
if !self.CanPut(name) {
typeErrorResult(throw)
return
}
self._propertyStash.Write(name, value)
}
// 8.12.6
func (self *_object) HasProperty(name string) bool {
for object := self; object != nil; object = object.Prototype {
if object._propertyStash.CanRead(name) {
return true
}
}
return false
}
type _defaultValueHint int
const (
defaultValueNoHint _defaultValueHint = iota
defaultValueHintString
defaultValueHintNumber
)
// 8.12.8
func (self *_object) DefaultValue(hint _defaultValueHint) Value {
if hint == defaultValueNoHint {
hint = defaultValueHintNumber
}
methodSequence := []string{"valueOf", "toString"}
if (hint == defaultValueHintString) {
methodSequence = []string{"toString", "valueOf"}
}
for _, methodName := range methodSequence {
method := self.Get(methodName)
if method.isCallable() {
result := method._object().Call(toValue(self))
if result.IsPrimitive() {
return result
}
}
}
panic(newTypeError())
return UndefinedValue()
}
func (self *_object) String() string {
return toString(self.DefaultValue(defaultValueHintString))
}
// 8.12.9
func (self *_object) DefineOwnProperty(name string, _defineProperty _defineProperty, throw bool) bool {
return self._propertyStash.Define(name, _defineProperty)
}
func (self *_object) DefineOwnValueProperty(name string, value Value, mode _propertyMode, throw bool) bool {
return self._propertyStash.Define(name, _property{Value: value, Mode: mode}.toDefineProperty())
}
func (self *_object) HasOwnProperty(name string) bool {
return self._propertyStash.CanRead(name)
}
func (self *_object) Define(nameAndValue... interface{}) {
property_ := _property{Mode: propertyModeWriteEnumerateConfigure}.toDefineProperty()
length := 0
signature := _functionSignature("")
for index := 0; index < len(nameAndValue); index++ {
value := nameAndValue[index]
switch value := value.(type) {
case _functionSignature:
signature = value
case _propertyMode:
property_ = _property{Mode: value}.toDefineProperty()
case string:
name := value
length = 0
index += 1
REPEAT: {
value := nameAndValue[index]
switch value := value.(type) {
case func(FunctionCall) Value: {
value := self.runtime.newNativeFunction(value, length)
value.Function.Call.Sign(signature)
property_.Value = toValue(value)
self.DefineOwnProperty(name, property_, false)
}
case *_object:
property_.Value = toValue(value)
self.DefineOwnProperty(name, property_, false)
case Value:
property_.Value = value
self.DefineOwnProperty(name, property_, false)
case int:
length = value
index += 1
goto REPEAT
default:
panic(hereBeDragons())
}
}
}
}
}
func (self *_object) define(nameAndValue... interface{}) {
mode := propertyModeWriteEnumerateConfigure
length := 0
signature := _functionSignature("")
stash := map[string]_valueProperty{}
for index := 0; index < len(nameAndValue); index++ {
value := nameAndValue[index]
switch value := value.(type) {
case _functionSignature:
signature = value
case _propertyMode:
mode = value
case string:
name := value
length = 0
index += 1
REPEAT: {
value := nameAndValue[index]
switch value := value.(type) {
case func(FunctionCall) Value: {
value := self.runtime.newNativeFunction(value, length)
value.Function.Call.Sign(signature)
stash[name] = _valueProperty{ toValue(value), mode }
}
case *_object:
stash[name] = _valueProperty{ toValue(value), mode }
case Value:
stash[name] = _valueProperty{ value, mode }
case int:
length = value
index += 1
goto REPEAT
default:
panic(hereBeDragons())
}
}
}
}
self._propertyStash.writeValuePropertyMap(stash)
}
func (self *_object) Enumerate(each func(string)) {
self._propertyStash.Enumerate(each)
}