forked from cerc-io/plugeth
289b30715d
This commit converts the dependency management from Godeps to the vendor folder, also switching the tool from godep to trash. Since the upstream tool lacks a few features proposed via a few PRs, until those PRs are merged in (if), use github.com/karalabe/trash. You can update dependencies via trash --update. All dependencies have been updated to their latest version. Parts of the build system are reworked to drop old notions of Godeps and invocation of the go vet command so that it doesn't run against the vendor folder, as that will just blow up during vetting. The conversion drops OpenCL (and hence GPU mining support) from ethash and our codebase. The short reasoning is that there's noone to maintain and having opencl libs in our deps messes up builds as go install ./... tries to build them, failing with unsatisfied link errors for the C OpenCL deps. golang.org/x/net/context is not vendored in. We expect it to be fetched by the user (i.e. using go get). To keep ci.go builds reproducible the package is "vendored" in build/_vendor.
494 lines
11 KiB
Go
494 lines
11 KiB
Go
package otto
|
|
|
|
import (
|
|
"encoding/json"
|
|
)
|
|
|
|
type _objectClass struct {
|
|
getOwnProperty func(*_object, string) *_property
|
|
getProperty func(*_object, string) *_property
|
|
get func(*_object, string) Value
|
|
canPut func(*_object, string) bool
|
|
put func(*_object, string, Value, bool)
|
|
hasProperty func(*_object, string) bool
|
|
hasOwnProperty func(*_object, string) bool
|
|
defineOwnProperty func(*_object, string, _property, bool) bool
|
|
delete func(*_object, string, bool) bool
|
|
enumerate func(*_object, bool, func(string) bool)
|
|
clone func(*_object, *_object, *_clone) *_object
|
|
marshalJSON func(*_object) json.Marshaler
|
|
}
|
|
|
|
func objectEnumerate(self *_object, all bool, each func(string) bool) {
|
|
for _, name := range self.propertyOrder {
|
|
if all || self.property[name].enumerable() {
|
|
if !each(name) {
|
|
return
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
var (
|
|
_classObject,
|
|
_classArray,
|
|
_classString,
|
|
_classArguments,
|
|
_classGoStruct,
|
|
_classGoMap,
|
|
_classGoArray,
|
|
_classGoSlice,
|
|
_ *_objectClass
|
|
)
|
|
|
|
func init() {
|
|
_classObject = &_objectClass{
|
|
objectGetOwnProperty,
|
|
objectGetProperty,
|
|
objectGet,
|
|
objectCanPut,
|
|
objectPut,
|
|
objectHasProperty,
|
|
objectHasOwnProperty,
|
|
objectDefineOwnProperty,
|
|
objectDelete,
|
|
objectEnumerate,
|
|
objectClone,
|
|
nil,
|
|
}
|
|
|
|
_classArray = &_objectClass{
|
|
objectGetOwnProperty,
|
|
objectGetProperty,
|
|
objectGet,
|
|
objectCanPut,
|
|
objectPut,
|
|
objectHasProperty,
|
|
objectHasOwnProperty,
|
|
arrayDefineOwnProperty,
|
|
objectDelete,
|
|
objectEnumerate,
|
|
objectClone,
|
|
nil,
|
|
}
|
|
|
|
_classString = &_objectClass{
|
|
stringGetOwnProperty,
|
|
objectGetProperty,
|
|
objectGet,
|
|
objectCanPut,
|
|
objectPut,
|
|
objectHasProperty,
|
|
objectHasOwnProperty,
|
|
objectDefineOwnProperty,
|
|
objectDelete,
|
|
stringEnumerate,
|
|
objectClone,
|
|
nil,
|
|
}
|
|
|
|
_classArguments = &_objectClass{
|
|
argumentsGetOwnProperty,
|
|
objectGetProperty,
|
|
argumentsGet,
|
|
objectCanPut,
|
|
objectPut,
|
|
objectHasProperty,
|
|
objectHasOwnProperty,
|
|
argumentsDefineOwnProperty,
|
|
argumentsDelete,
|
|
objectEnumerate,
|
|
objectClone,
|
|
nil,
|
|
}
|
|
|
|
_classGoStruct = &_objectClass{
|
|
goStructGetOwnProperty,
|
|
objectGetProperty,
|
|
objectGet,
|
|
goStructCanPut,
|
|
goStructPut,
|
|
objectHasProperty,
|
|
objectHasOwnProperty,
|
|
objectDefineOwnProperty,
|
|
objectDelete,
|
|
goStructEnumerate,
|
|
objectClone,
|
|
goStructMarshalJSON,
|
|
}
|
|
|
|
_classGoMap = &_objectClass{
|
|
goMapGetOwnProperty,
|
|
objectGetProperty,
|
|
objectGet,
|
|
objectCanPut,
|
|
objectPut,
|
|
objectHasProperty,
|
|
objectHasOwnProperty,
|
|
goMapDefineOwnProperty,
|
|
goMapDelete,
|
|
goMapEnumerate,
|
|
objectClone,
|
|
nil,
|
|
}
|
|
|
|
_classGoArray = &_objectClass{
|
|
goArrayGetOwnProperty,
|
|
objectGetProperty,
|
|
objectGet,
|
|
objectCanPut,
|
|
objectPut,
|
|
objectHasProperty,
|
|
objectHasOwnProperty,
|
|
goArrayDefineOwnProperty,
|
|
goArrayDelete,
|
|
goArrayEnumerate,
|
|
objectClone,
|
|
nil,
|
|
}
|
|
|
|
_classGoSlice = &_objectClass{
|
|
goSliceGetOwnProperty,
|
|
objectGetProperty,
|
|
objectGet,
|
|
objectCanPut,
|
|
objectPut,
|
|
objectHasProperty,
|
|
objectHasOwnProperty,
|
|
goSliceDefineOwnProperty,
|
|
goSliceDelete,
|
|
goSliceEnumerate,
|
|
objectClone,
|
|
nil,
|
|
}
|
|
}
|
|
|
|
// Allons-y
|
|
|
|
// 8.12.1
|
|
func objectGetOwnProperty(self *_object, name string) *_property {
|
|
// Return a _copy_ of the property
|
|
property, exists := self._read(name)
|
|
if !exists {
|
|
return nil
|
|
}
|
|
return &property
|
|
}
|
|
|
|
// 8.12.2
|
|
func objectGetProperty(self *_object, name string) *_property {
|
|
property := self.getOwnProperty(name)
|
|
if property != nil {
|
|
return property
|
|
}
|
|
if self.prototype != nil {
|
|
return self.prototype.getProperty(name)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// 8.12.3
|
|
func objectGet(self *_object, name string) Value {
|
|
property := self.getProperty(name)
|
|
if property != nil {
|
|
return property.get(self)
|
|
}
|
|
return Value{}
|
|
}
|
|
|
|
// 8.12.4
|
|
func objectCanPut(self *_object, name string) bool {
|
|
canPut, _, _ := _objectCanPut(self, name)
|
|
return canPut
|
|
}
|
|
|
|
func _objectCanPut(self *_object, name string) (canPut bool, property *_property, setter *_object) {
|
|
property = self.getOwnProperty(name)
|
|
if property != nil {
|
|
switch propertyValue := property.value.(type) {
|
|
case Value:
|
|
canPut = property.writable()
|
|
return
|
|
case _propertyGetSet:
|
|
setter = propertyValue[1]
|
|
canPut = setter != nil
|
|
return
|
|
default:
|
|
panic(self.runtime.panicTypeError())
|
|
}
|
|
}
|
|
|
|
if self.prototype == nil {
|
|
return self.extensible, nil, nil
|
|
}
|
|
|
|
property = self.prototype.getProperty(name)
|
|
if property == nil {
|
|
return self.extensible, nil, nil
|
|
}
|
|
|
|
switch propertyValue := property.value.(type) {
|
|
case Value:
|
|
if !self.extensible {
|
|
return false, nil, nil
|
|
}
|
|
return property.writable(), nil, nil
|
|
case _propertyGetSet:
|
|
setter = propertyValue[1]
|
|
canPut = setter != nil
|
|
return
|
|
default:
|
|
panic(self.runtime.panicTypeError())
|
|
}
|
|
}
|
|
|
|
// 8.12.5
|
|
func objectPut(self *_object, name string, value Value, throw bool) {
|
|
|
|
if true {
|
|
// Shortcut...
|
|
//
|
|
// So, right now, every class is using objectCanPut and every class
|
|
// is using objectPut.
|
|
//
|
|
// If that were to no longer be the case, we would have to have
|
|
// something to detect that here, so that we do not use an
|
|
// incompatible canPut routine
|
|
canPut, property, setter := _objectCanPut(self, name)
|
|
if !canPut {
|
|
self.runtime.typeErrorResult(throw)
|
|
} else if setter != nil {
|
|
setter.call(toValue(self), []Value{value}, false, nativeFrame)
|
|
} else if property != nil {
|
|
property.value = value
|
|
self.defineOwnProperty(name, *property, throw)
|
|
} else {
|
|
self.defineProperty(name, value, 0111, throw)
|
|
}
|
|
return
|
|
}
|
|
|
|
// The long way...
|
|
//
|
|
// Right now, code should never get here, see above
|
|
if !self.canPut(name) {
|
|
self.runtime.typeErrorResult(throw)
|
|
return
|
|
}
|
|
|
|
property := self.getOwnProperty(name)
|
|
if property == nil {
|
|
property = self.getProperty(name)
|
|
if property != nil {
|
|
if getSet, isAccessor := property.value.(_propertyGetSet); isAccessor {
|
|
getSet[1].call(toValue(self), []Value{value}, false, nativeFrame)
|
|
return
|
|
}
|
|
}
|
|
self.defineProperty(name, value, 0111, throw)
|
|
} else {
|
|
switch propertyValue := property.value.(type) {
|
|
case Value:
|
|
property.value = value
|
|
self.defineOwnProperty(name, *property, throw)
|
|
case _propertyGetSet:
|
|
if propertyValue[1] != nil {
|
|
propertyValue[1].call(toValue(self), []Value{value}, false, nativeFrame)
|
|
return
|
|
}
|
|
if throw {
|
|
panic(self.runtime.panicTypeError())
|
|
}
|
|
default:
|
|
panic(self.runtime.panicTypeError())
|
|
}
|
|
}
|
|
}
|
|
|
|
// 8.12.6
|
|
func objectHasProperty(self *_object, name string) bool {
|
|
return self.getProperty(name) != nil
|
|
}
|
|
|
|
func objectHasOwnProperty(self *_object, name string) bool {
|
|
return self.getOwnProperty(name) != nil
|
|
}
|
|
|
|
// 8.12.9
|
|
func objectDefineOwnProperty(self *_object, name string, descriptor _property, throw bool) bool {
|
|
property, exists := self._read(name)
|
|
{
|
|
if !exists {
|
|
if !self.extensible {
|
|
goto Reject
|
|
}
|
|
if newGetSet, isAccessor := descriptor.value.(_propertyGetSet); isAccessor {
|
|
if newGetSet[0] == &_nilGetSetObject {
|
|
newGetSet[0] = nil
|
|
}
|
|
if newGetSet[1] == &_nilGetSetObject {
|
|
newGetSet[1] = nil
|
|
}
|
|
descriptor.value = newGetSet
|
|
}
|
|
self._write(name, descriptor.value, descriptor.mode)
|
|
return true
|
|
}
|
|
if descriptor.isEmpty() {
|
|
return true
|
|
}
|
|
|
|
// TODO Per 8.12.9.6 - We should shortcut here (returning true) if
|
|
// the current and new (define) properties are the same
|
|
|
|
configurable := property.configurable()
|
|
if !configurable {
|
|
if descriptor.configurable() {
|
|
goto Reject
|
|
}
|
|
// Test that, if enumerable is set on the property descriptor, then it should
|
|
// be the same as the existing property
|
|
if descriptor.enumerateSet() && descriptor.enumerable() != property.enumerable() {
|
|
goto Reject
|
|
}
|
|
}
|
|
value, isDataDescriptor := property.value.(Value)
|
|
getSet, _ := property.value.(_propertyGetSet)
|
|
if descriptor.isGenericDescriptor() {
|
|
// GenericDescriptor
|
|
} else if isDataDescriptor != descriptor.isDataDescriptor() {
|
|
// DataDescriptor <=> AccessorDescriptor
|
|
if !configurable {
|
|
goto Reject
|
|
}
|
|
} else if isDataDescriptor && descriptor.isDataDescriptor() {
|
|
// DataDescriptor <=> DataDescriptor
|
|
if !configurable {
|
|
if !property.writable() && descriptor.writable() {
|
|
goto Reject
|
|
}
|
|
if !property.writable() {
|
|
if descriptor.value != nil && !sameValue(value, descriptor.value.(Value)) {
|
|
goto Reject
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
// AccessorDescriptor <=> AccessorDescriptor
|
|
newGetSet, _ := descriptor.value.(_propertyGetSet)
|
|
presentGet, presentSet := true, true
|
|
if newGetSet[0] == &_nilGetSetObject {
|
|
// Present, but nil
|
|
newGetSet[0] = nil
|
|
} else if newGetSet[0] == nil {
|
|
// Missing, not even nil
|
|
newGetSet[0] = getSet[0]
|
|
presentGet = false
|
|
}
|
|
if newGetSet[1] == &_nilGetSetObject {
|
|
// Present, but nil
|
|
newGetSet[1] = nil
|
|
} else if newGetSet[1] == nil {
|
|
// Missing, not even nil
|
|
newGetSet[1] = getSet[1]
|
|
presentSet = false
|
|
}
|
|
if !configurable {
|
|
if (presentGet && (getSet[0] != newGetSet[0])) || (presentSet && (getSet[1] != newGetSet[1])) {
|
|
goto Reject
|
|
}
|
|
}
|
|
descriptor.value = newGetSet
|
|
}
|
|
{
|
|
// This section will preserve attributes of
|
|
// the original property, if necessary
|
|
value1 := descriptor.value
|
|
if value1 == nil {
|
|
value1 = property.value
|
|
} else if newGetSet, isAccessor := descriptor.value.(_propertyGetSet); isAccessor {
|
|
if newGetSet[0] == &_nilGetSetObject {
|
|
newGetSet[0] = nil
|
|
}
|
|
if newGetSet[1] == &_nilGetSetObject {
|
|
newGetSet[1] = nil
|
|
}
|
|
value1 = newGetSet
|
|
}
|
|
mode1 := descriptor.mode
|
|
if mode1&0222 != 0 {
|
|
// TODO Factor this out into somewhere testable
|
|
// (Maybe put into switch ...)
|
|
mode0 := property.mode
|
|
if mode1&0200 != 0 {
|
|
if descriptor.isDataDescriptor() {
|
|
mode1 &= ^0200 // Turn off "writable" missing
|
|
mode1 |= (mode0 & 0100)
|
|
}
|
|
}
|
|
if mode1&020 != 0 {
|
|
mode1 |= (mode0 & 010)
|
|
}
|
|
if mode1&02 != 0 {
|
|
mode1 |= (mode0 & 01)
|
|
}
|
|
mode1 &= 0311 // 0311 to preserve the non-setting on "writable"
|
|
}
|
|
self._write(name, value1, mode1)
|
|
}
|
|
return true
|
|
}
|
|
Reject:
|
|
if throw {
|
|
panic(self.runtime.panicTypeError())
|
|
}
|
|
return false
|
|
}
|
|
|
|
func objectDelete(self *_object, name string, throw bool) bool {
|
|
property_ := self.getOwnProperty(name)
|
|
if property_ == nil {
|
|
return true
|
|
}
|
|
if property_.configurable() {
|
|
self._delete(name)
|
|
return true
|
|
}
|
|
return self.runtime.typeErrorResult(throw)
|
|
}
|
|
|
|
func objectClone(in *_object, out *_object, clone *_clone) *_object {
|
|
*out = *in
|
|
|
|
out.runtime = clone.runtime
|
|
if out.prototype != nil {
|
|
out.prototype = clone.object(in.prototype)
|
|
}
|
|
out.property = make(map[string]_property, len(in.property))
|
|
out.propertyOrder = make([]string, len(in.propertyOrder))
|
|
copy(out.propertyOrder, in.propertyOrder)
|
|
for index, property := range in.property {
|
|
out.property[index] = clone.property(property)
|
|
}
|
|
|
|
switch value := in.value.(type) {
|
|
case _nativeFunctionObject:
|
|
out.value = value
|
|
case _bindFunctionObject:
|
|
out.value = _bindFunctionObject{
|
|
target: clone.object(value.target),
|
|
this: clone.value(value.this),
|
|
argumentList: clone.valueArray(value.argumentList),
|
|
}
|
|
case _nodeFunctionObject:
|
|
out.value = _nodeFunctionObject{
|
|
node: value.node,
|
|
stash: clone.stash(value.stash),
|
|
}
|
|
case _argumentsObject:
|
|
out.value = value.clone(clone)
|
|
}
|
|
|
|
return out
|
|
}
|