aboutsummaryrefslogblamecommitdiffstats
path: root/Godeps/_workspace/src/github.com/robertkrimen/otto/property.go
blob: 5445eccdeba46ec273d929afc35bc7ebd2877139 (plain) (tree)






















































































                                                                                                    
                                                                                    

                 
                      

























                                                                        
                                                                             

                                           
                                          




                                                                         
                                                                      






                                                                 
                                                                        






                                                             
                                                                    













                                                     
                                                          












                                                    
                                                          










                                                  
                                                  





                                                                  
                                                  













                                                                                                   
                              


                                                       
                              









                                                                                                   
package otto

// property

type _propertyMode int

const (
    modeWriteMask     _propertyMode = 0700
    modeEnumerateMask               = 0070
    modeConfigureMask               = 0007
    modeOnMask                      = 0111
    modeOffMask                     = 0000
    modeSetMask                     = 0222 // If value is 2, then mode is neither "On" nor "Off"
)

type _propertyGetSet [2]*_object

var _nilGetSetObject _object = _object{}

type _property struct {
    value interface{}
    mode  _propertyMode
}

func (self _property) writable() bool {
    return self.mode&modeWriteMask == modeWriteMask&modeOnMask
}

func (self *_property) writeOn() {
    self.mode = (self.mode & ^modeWriteMask) | (modeWriteMask & modeOnMask)
}

func (self *_property) writeOff() {
    self.mode &= ^modeWriteMask
}

func (self *_property) writeClear() {
    self.mode = (self.mode & ^modeWriteMask) | (modeWriteMask & modeSetMask)
}

func (self _property) writeSet() bool {
    return 0 == self.mode&modeWriteMask&modeSetMask
}

func (self _property) enumerable() bool {
    return self.mode&modeEnumerateMask == modeEnumerateMask&modeOnMask
}

func (self *_property) enumerateOn() {
    self.mode = (self.mode & ^modeEnumerateMask) | (modeEnumerateMask & modeOnMask)
}

func (self *_property) enumerateOff() {
    self.mode &= ^modeEnumerateMask
}

func (self _property) enumerateSet() bool {
    return 0 == self.mode&modeEnumerateMask&modeSetMask
}

func (self _property) configurable() bool {
    return self.mode&modeConfigureMask == modeConfigureMask&modeOnMask
}

func (self *_property) configureOn() {
    self.mode = (self.mode & ^modeConfigureMask) | (modeConfigureMask & modeOnMask)
}

func (self *_property) configureOff() {
    self.mode &= ^modeConfigureMask
}

func (self _property) configureSet() bool {
    return 0 == self.mode&modeConfigureMask&modeSetMask
}

func (self _property) copy() *_property {
    property := self
    return &property
}

func (self _property) get(this *_object) Value {
    switch value := self.value.(type) {
    case Value:
        return value
    case _propertyGetSet:
        if value[0] != nil {
            return value[0].call(toValue(this), nil, false, nativeFrame)
        }
    }
    return Value{}
}

func (self _property) isAccessorDescriptor() bool {
    setGet, test := self.value.(_propertyGetSet)
    return test && (setGet[0] != nil || setGet[1] != nil)
}

func (self _property) isDataDescriptor() bool {
    if self.writeSet() { // Either "On" or "Off"
        return true
    }
    value, valid := self.value.(Value)
    return valid && !value.isEmpty()
}

func (self _property) isGenericDescriptor() bool {
    return !(self.isDataDescriptor() || self.isAccessorDescriptor())
}

func (self _property) isEmpty() bool {
    return self.mode == 0222 && self.isGenericDescriptor()
}

// _enumerableValue, _enumerableTrue, _enumerableFalse?
// .enumerableValue() .enumerableExists()

func toPropertyDescriptor(rt *_runtime, value Value) (descriptor _property) {
    objectDescriptor := value._object()
    if objectDescriptor == nil {
        panic(rt.panicTypeError())
    }

    {
        descriptor.mode = modeSetMask // Initially nothing is set
        if objectDescriptor.hasProperty("enumerable") {
            if objectDescriptor.get("enumerable").bool() {
                descriptor.enumerateOn()
            } else {
                descriptor.enumerateOff()
            }
        }

        if objectDescriptor.hasProperty("configurable") {
            if objectDescriptor.get("configurable").bool() {
                descriptor.configureOn()
            } else {
                descriptor.configureOff()
            }
        }

        if objectDescriptor.hasProperty("writable") {
            if objectDescriptor.get("writable").bool() {
                descriptor.writeOn()
            } else {
                descriptor.writeOff()
            }
        }
    }

    var getter, setter *_object
    getterSetter := false

    if objectDescriptor.hasProperty("get") {
        value := objectDescriptor.get("get")
        if value.IsDefined() {
            if !value.isCallable() {
                panic(rt.panicTypeError())
            }
            getter = value._object()
            getterSetter = true
        } else {
            getter = &_nilGetSetObject
            getterSetter = true
        }
    }

    if objectDescriptor.hasProperty("set") {
        value := objectDescriptor.get("set")
        if value.IsDefined() {
            if !value.isCallable() {
                panic(rt.panicTypeError())
            }
            setter = value._object()
            getterSetter = true
        } else {
            setter = &_nilGetSetObject
            getterSetter = true
        }
    }

    if getterSetter {
        if descriptor.writeSet() {
            panic(rt.panicTypeError())
        }
        descriptor.value = _propertyGetSet{getter, setter}
    }

    if objectDescriptor.hasProperty("value") {
        if getterSetter {
            panic(rt.panicTypeError())
        }
        descriptor.value = objectDescriptor.get("value")
    }

    return
}

func (self *_runtime) fromPropertyDescriptor(descriptor _property) *_object {
    object := self.newObject()
    if descriptor.isDataDescriptor() {
        object.defineProperty("value", descriptor.value.(Value), 0111, false)
        object.defineProperty("writable", toValue_bool(descriptor.writable()), 0111, false)
    } else if descriptor.isAccessorDescriptor() {
        getSet := descriptor.value.(_propertyGetSet)
        get := Value{}
        if getSet[0] != nil {
            get = toValue_object(getSet[0])
        }
        set := Value{}
        if getSet[1] != nil {
            set = toValue_object(getSet[1])
        }
        object.defineProperty("get", get, 0111, false)
        object.defineProperty("set", set, 0111, false)
    }
    object.defineProperty("enumerable", toValue_bool(descriptor.enumerable()), 0111, false)
    object.defineProperty("configurable", toValue_bool(descriptor.configurable()), 0111, false)
    return object
}