aboutsummaryrefslogtreecommitdiffstats
path: root/vendor/github.com/robertkrimen/otto/stash.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/robertkrimen/otto/stash.go')
-rw-r--r--vendor/github.com/robertkrimen/otto/stash.go296
1 files changed, 296 insertions, 0 deletions
diff --git a/vendor/github.com/robertkrimen/otto/stash.go b/vendor/github.com/robertkrimen/otto/stash.go
new file mode 100644
index 000000000..0d3ffa511
--- /dev/null
+++ b/vendor/github.com/robertkrimen/otto/stash.go
@@ -0,0 +1,296 @@
+package otto
+
+import (
+ "fmt"
+)
+
+// ======
+// _stash
+// ======
+
+type _stash interface {
+ hasBinding(string) bool //
+ createBinding(string, bool, Value) // CreateMutableBinding
+ setBinding(string, Value, bool) // SetMutableBinding
+ getBinding(string, bool) Value // GetBindingValue
+ deleteBinding(string) bool //
+ setValue(string, Value, bool) // createBinding + setBinding
+
+ outer() _stash
+ runtime() *_runtime
+
+ newReference(string, bool, _at) _reference
+
+ clone(clone *_clone) _stash
+}
+
+// ==========
+// _objectStash
+// ==========
+
+type _objectStash struct {
+ _runtime *_runtime
+ _outer _stash
+ object *_object
+}
+
+func (self *_objectStash) runtime() *_runtime {
+ return self._runtime
+}
+
+func (runtime *_runtime) newObjectStash(object *_object, outer _stash) *_objectStash {
+ if object == nil {
+ object = runtime.newBaseObject()
+ object.class = "environment"
+ }
+ return &_objectStash{
+ _runtime: runtime,
+ _outer: outer,
+ object: object,
+ }
+}
+
+func (in *_objectStash) clone(clone *_clone) _stash {
+ out, exists := clone.objectStash(in)
+ if exists {
+ return out
+ }
+ *out = _objectStash{
+ clone.runtime,
+ clone.stash(in._outer),
+ clone.object(in.object),
+ }
+ return out
+}
+
+func (self *_objectStash) hasBinding(name string) bool {
+ return self.object.hasProperty(name)
+}
+
+func (self *_objectStash) createBinding(name string, deletable bool, value Value) {
+ if self.object.hasProperty(name) {
+ panic(hereBeDragons())
+ }
+ mode := _propertyMode(0111)
+ if !deletable {
+ mode = _propertyMode(0110)
+ }
+ // TODO False?
+ self.object.defineProperty(name, value, mode, false)
+}
+
+func (self *_objectStash) setBinding(name string, value Value, strict bool) {
+ self.object.put(name, value, strict)
+}
+
+func (self *_objectStash) setValue(name string, value Value, throw bool) {
+ if !self.hasBinding(name) {
+ self.createBinding(name, true, value) // Configurable by default
+ } else {
+ self.setBinding(name, value, throw)
+ }
+}
+
+func (self *_objectStash) getBinding(name string, throw bool) Value {
+ if self.object.hasProperty(name) {
+ return self.object.get(name)
+ }
+ if throw { // strict?
+ panic(self._runtime.panicReferenceError("Not Defined", name))
+ }
+ return Value{}
+}
+
+func (self *_objectStash) deleteBinding(name string) bool {
+ return self.object.delete(name, false)
+}
+
+func (self *_objectStash) outer() _stash {
+ return self._outer
+}
+
+func (self *_objectStash) newReference(name string, strict bool, at _at) _reference {
+ return newPropertyReference(self._runtime, self.object, name, strict, at)
+}
+
+// =========
+// _dclStash
+// =========
+
+type _dclStash struct {
+ _runtime *_runtime
+ _outer _stash
+ property map[string]_dclProperty
+}
+
+type _dclProperty struct {
+ value Value
+ mutable bool
+ deletable bool
+ readable bool
+}
+
+func (runtime *_runtime) newDeclarationStash(outer _stash) *_dclStash {
+ return &_dclStash{
+ _runtime: runtime,
+ _outer: outer,
+ property: map[string]_dclProperty{},
+ }
+}
+
+func (in *_dclStash) clone(clone *_clone) _stash {
+ out, exists := clone.dclStash(in)
+ if exists {
+ return out
+ }
+ property := make(map[string]_dclProperty, len(in.property))
+ for index, value := range in.property {
+ property[index] = clone.dclProperty(value)
+ }
+ *out = _dclStash{
+ clone.runtime,
+ clone.stash(in._outer),
+ property,
+ }
+ return out
+}
+
+func (self *_dclStash) hasBinding(name string) bool {
+ _, exists := self.property[name]
+ return exists
+}
+
+func (self *_dclStash) runtime() *_runtime {
+ return self._runtime
+}
+
+func (self *_dclStash) createBinding(name string, deletable bool, value Value) {
+ _, exists := self.property[name]
+ if exists {
+ panic(fmt.Errorf("createBinding: %s: already exists", name))
+ }
+ self.property[name] = _dclProperty{
+ value: value,
+ mutable: true,
+ deletable: deletable,
+ readable: false,
+ }
+}
+
+func (self *_dclStash) setBinding(name string, value Value, strict bool) {
+ property, exists := self.property[name]
+ if !exists {
+ panic(fmt.Errorf("setBinding: %s: missing", name))
+ }
+ if property.mutable {
+ property.value = value
+ self.property[name] = property
+ } else {
+ self._runtime.typeErrorResult(strict)
+ }
+}
+
+func (self *_dclStash) setValue(name string, value Value, throw bool) {
+ if !self.hasBinding(name) {
+ self.createBinding(name, false, value) // NOT deletable by default
+ } else {
+ self.setBinding(name, value, throw)
+ }
+}
+
+// FIXME This is called a __lot__
+func (self *_dclStash) getBinding(name string, throw bool) Value {
+ property, exists := self.property[name]
+ if !exists {
+ panic(fmt.Errorf("getBinding: %s: missing", name))
+ }
+ if !property.mutable && !property.readable {
+ if throw { // strict?
+ panic(self._runtime.panicTypeError())
+ }
+ return Value{}
+ }
+ return property.value
+}
+
+func (self *_dclStash) 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 *_dclStash) outer() _stash {
+ return self._outer
+}
+
+func (self *_dclStash) newReference(name string, strict bool, _ _at) _reference {
+ return &_stashReference{
+ name: name,
+ base: self,
+ }
+}
+
+// ========
+// _fnStash
+// ========
+
+type _fnStash struct {
+ _dclStash
+ arguments *_object
+ indexOfArgumentName map[string]string
+}
+
+func (runtime *_runtime) newFunctionStash(outer _stash) *_fnStash {
+ return &_fnStash{
+ _dclStash: _dclStash{
+ _runtime: runtime,
+ _outer: outer,
+ property: map[string]_dclProperty{},
+ },
+ }
+}
+
+func (in *_fnStash) clone(clone *_clone) _stash {
+ out, exists := clone.fnStash(in)
+ if exists {
+ return out
+ }
+ dclStash := in._dclStash.clone(clone).(*_dclStash)
+ index := make(map[string]string, len(in.indexOfArgumentName))
+ for name, value := range in.indexOfArgumentName {
+ index[name] = value
+ }
+ *out = _fnStash{
+ _dclStash: *dclStash,
+ arguments: clone.object(in.arguments),
+ indexOfArgumentName: index,
+ }
+ return out
+}
+
+func getStashProperties(stash _stash) (keys []string) {
+ switch vars := stash.(type) {
+ case *_dclStash:
+ for k := range vars.property {
+ keys = append(keys, k)
+ }
+ case *_fnStash:
+ for k := range vars.property {
+ keys = append(keys, k)
+ }
+ case *_objectStash:
+ for k := range vars.object.property {
+ keys = append(keys, k)
+ }
+ default:
+ panic("unknown stash type")
+ }
+
+ return
+}