mirror of
https://github.com/robertkrimen/otto
synced 2025-10-12 20:27:30 +08:00

* Streamline what we get from "otto/parser" * Get rid of some "otto/parser" cruft * FunctionExpression => FunctionLiteral * The debugger statement (debugger) should do nothing (not panic) * Fix aspects of function expression call evaluation
281 lines
6.7 KiB
Go
281 lines
6.7 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()
|
|
}
|
|
|
|
// _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)
|
|
}
|