aboutsummaryrefslogblamecommitdiffstats
path: root/Godeps/_workspace/src/github.com/obscuren/otto/environment.go
blob: 891a3c9af5a118710a7b687ef599568ee2675284 (plain) (tree)























































































































































































































































































                                                                                                        
package otto

import (
    "fmt"
)

// _environment

type _environment interface {
    HasBinding(string) bool

    CreateMutableBinding(string, bool)
    SetMutableBinding(string, Value, bool)
    // SetMutableBinding with Lazy CreateMutableBinding(..., true)
    SetValue(string, Value, bool)

    GetBindingValue(string, bool) Value
    GetValue(string, bool) Value // GetBindingValue
    DeleteBinding(string) bool
    ImplicitThisValue() *_object

    Outer() _environment

    newReference(string, bool) _reference
    clone(clone *_clone) _environment
    runtimeOf() *_runtime
}

// _functionEnvironment

type _functionEnvironment struct {
    _declarativeEnvironment
    arguments           *_object
    indexOfArgumentName map[string]string
}

func (runtime *_runtime) newFunctionEnvironment(outer _environment) *_functionEnvironment {
    return &_functionEnvironment{
        _declarativeEnvironment: _declarativeEnvironment{
            runtime:  runtime,
            outer:    outer,
            property: map[string]_declarativeProperty{},
        },
    }
}

func (self0 _functionEnvironment) clone(clone *_clone) _environment {
    return &_functionEnvironment{
        *(self0._declarativeEnvironment.clone(clone).(*_declarativeEnvironment)),
        clone.object(self0.arguments),
        self0.indexOfArgumentName,
    }
}

func (self _functionEnvironment) runtimeOf() *_runtime {
    return self._declarativeEnvironment.runtimeOf()
}

// _objectEnvironment

type _objectEnvironment struct {
    runtime     *_runtime
    outer       _environment
    Object      *_object
    ProvideThis bool
}

func (self *_objectEnvironment) runtimeOf() *_runtime {
    return self.runtime
}

func (runtime *_runtime) newObjectEnvironment(object *_object, outer _environment) *_objectEnvironment {
    if object == nil {
        object = runtime.newBaseObject()
        object.class = "environment"
    }
    return &_objectEnvironment{
        runtime: runtime,
        outer:   outer,
        Object:  object,
    }
}

func (self0 *_objectEnvironment) clone(clone *_clone) _environment {
    self1, exists := clone.objectEnvironment(self0)
    if exists {
        return self1
    }
    *self1 = _objectEnvironment{
        clone.runtime,
        clone.environment(self0.outer),
        clone.object(self0.Object),
        self0.ProvideThis,
    }
    return self1
}

func (self *_objectEnvironment) HasBinding(name string) bool {
    return self.Object.hasProperty(name)
}

func (self *_objectEnvironment) CreateMutableBinding(name string, deletable bool) {
    if self.Object.hasProperty(name) {
        panic(hereBeDragons())
    }
    mode := _propertyMode(0111)
    if !deletable {
        mode = _propertyMode(0110)
    }
    // TODO False?
    self.Object.defineProperty(name, UndefinedValue(), mode, false)
}

func (self *_objectEnvironment) SetMutableBinding(name string, value Value, strict bool) {
    self.Object.put(name, value, strict)
}

func (self *_objectEnvironment) SetValue(name string, value Value, throw bool) {
    if !self.HasBinding(name) {
        self.CreateMutableBinding(name, true) // Configurable by default
    }
    self.SetMutableBinding(name, value, throw)
}

func (self *_objectEnvironment) GetBindingValue(name string, strict bool) Value {
    if self.Object.hasProperty(name) {
        return self.Object.get(name)
    }
    if strict {
        panic(newReferenceError("Not Defined", name))
    }
    return UndefinedValue()
}

func (self *_objectEnvironment) GetValue(name string, throw bool) Value {
    return self.GetBindingValue(name, throw)
}

func (self *_objectEnvironment) DeleteBinding(name string) bool {
    return self.Object.delete(name, false)
}

func (self *_objectEnvironment) ImplicitThisValue() *_object {
    if self.ProvideThis {
        return self.Object
    }
    return nil
}

func (self *_objectEnvironment) Outer() _environment {
    return self.outer
}

func (self *_objectEnvironment) newReference(name string, strict bool) _reference {
    return newPropertyReference(self.Object, name, strict)
}

// _declarativeEnvironment

func (runtime *_runtime) newDeclarativeEnvironment(outer _environment) *_declarativeEnvironment {
    return &_declarativeEnvironment{
        runtime:  runtime,
        outer:    outer,
        property: map[string]_declarativeProperty{},
    }
}

func (self0 *_declarativeEnvironment) clone(clone *_clone) _environment {
    self1, exists := clone.declarativeEnvironment(self0)
    if exists {
        return self1
    }
    property := make(map[string]_declarativeProperty, len(self0.property))
    for index, value := range self0.property {
        property[index] = clone.declarativeProperty(value)
    }
    *self1 = _declarativeEnvironment{
        clone.runtime,
        clone.environment(self0.outer),
        property,
    }
    return self1
}

type _declarativeProperty struct {
    value     Value
    mutable   bool
    deletable bool
    readable  bool
}

type _declarativeEnvironment struct {
    runtime  *_runtime
    outer    _environment
    property map[string]_declarativeProperty
}

func (self *_declarativeEnvironment) HasBinding(name string) bool {
    _, exists := self.property[name]
    return exists
}

func (self *_declarativeEnvironment) runtimeOf() *_runtime {
    return self.runtime
}

func (self *_declarativeEnvironment) CreateMutableBinding(name string, deletable bool) {
    _, exists := self.property[name]
    if exists {
        panic(fmt.Errorf("CreateMutableBinding: %s: already exists", name))
    }
    self.property[name] = _declarativeProperty{
        value:     UndefinedValue(),
        mutable:   true,
        deletable: deletable,
        readable:  false,
    }
}

func (self *_declarativeEnvironment) SetMutableBinding(name string, value Value, strict bool) {
    property, exists := self.property[name]
    if !exists {
        panic(fmt.Errorf("SetMutableBinding: %s: missing", name))
    }
    if property.mutable {
        property.value = value
        self.property[name] = property
    } else {
        typeErrorResult(strict)
    }
}

func (self *_declarativeEnvironment) SetValue(name string, value Value, throw bool) {
    if !self.HasBinding(name) {
        self.CreateMutableBinding(name, false) // NOT deletable by default
    }
    self.SetMutableBinding(name, value, throw)
}

func (self *_declarativeEnvironment) GetBindingValue(name string, strict bool) Value {
    property, exists := self.property[name]
    if !exists {
        panic(fmt.Errorf("GetBindingValue: %s: missing", name))
    }
    if !property.mutable && !property.readable {
        if strict {
            panic(newTypeError())
        }
        return UndefinedValue()
    }
    return property.value
}

func (self *_declarativeEnvironment) GetValue(name string, throw bool) Value {
    return self.GetBindingValue(name, throw)
}

func (self *_declarativeEnvironment) DeleteBinding(name string) bool {
    property, exists := self.property[name]
    if !exists {
        return true
    }
    if !property.deletable {
        return false
    }
    delete(self.property, name)
    return true
}

func (self *_declarativeEnvironment) ImplicitThisValue() *_object {
    return nil
}

func (self *_declarativeEnvironment) Outer() _environment {
    return self.outer
}

func (self *_declarativeEnvironment) newReference(name string, strict bool) _reference {
    return newEnvironmentReference(self, name, strict, nil)
}