1
0
mirror of https://github.com/robertkrimen/otto synced 2025-10-12 20:27:30 +08:00
otto/environment.go
Robert Krimen ad8a97c028 New parser
* Faster, more straightforward, etc.
* More advanced object literals (get ..., set ...)
* More tests using JavaScript from the wild (http://cdnjs.com/)
2014-04-10 20:42:25 -07:00

297 lines
7.2 KiB
Go

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()
}
//func (self *_functionEnvironment) newReference(name string, strict bool) _reference {
// index, exists := self.indexOfArgumentName[name]
// if !exists {
// return self._declarativeEnvironment.newReference(name, strict)
// }
// return newArgumentReference(self.arguments, index, strict)
//}
//func (self *_functionEnvironment) HasBinding(name string) bool {
// _, exists := self.indexOfArgumentName[name]
// if exists {
// return true
// }
// return self._declarativeEnvironment.HasBinding(name)
//}
// _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, nil)
}
// _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)
}