mirror of
https://github.com/robertkrimen/otto
synced 2025-10-26 20:28:49 +08:00
Cleanup of stash, property, and object
Use octal to designate write/enumerate/configure (experimental) Move extensibility responsibility into the stash Rename propertyStash => objectStash (be congruent with arrayStash, etc.) Get rid of a bunch of useless methods Privatize everything ([A-Z] => [a-z_]) gofmt
This commit is contained in:
parent
c1a21812fe
commit
3c93384f5c
|
|
@ -8,6 +8,8 @@ WITH_otto := --command "$(otto)"
|
||||||
test:
|
test:
|
||||||
$(TEST) $(WITH_otto)
|
$(TEST) $(WITH_otto)
|
||||||
|
|
||||||
|
release: otto gauntlet
|
||||||
|
|
||||||
test-otto: test
|
test-otto: test
|
||||||
|
|
||||||
otto: build
|
otto: build
|
||||||
|
|
|
||||||
194
builtin.go
194
builtin.go
|
|
@ -81,13 +81,13 @@ func _builtinGlobal_encodeURI(call FunctionCall, characterRegexp *regexp.Regexp)
|
||||||
return toValue(string(value))
|
return toValue(string(value))
|
||||||
}
|
}
|
||||||
|
|
||||||
var encodeURI_Regexp *regexp.Regexp = regexp.MustCompile(`([^~!@#$&*()=:/,;?+'])`)
|
var encodeURI_Regexp = regexp.MustCompile(`([^~!@#$&*()=:/,;?+'])`)
|
||||||
|
|
||||||
func builtinGlobal_encodeURI(call FunctionCall) Value {
|
func builtinGlobal_encodeURI(call FunctionCall) Value {
|
||||||
return _builtinGlobal_encodeURI(call, encodeURI_Regexp)
|
return _builtinGlobal_encodeURI(call, encodeURI_Regexp)
|
||||||
}
|
}
|
||||||
|
|
||||||
var encodeURIComponent_Regexp *regexp.Regexp = regexp.MustCompile(`([^~!*()'])`)
|
var encodeURIComponent_Regexp = regexp.MustCompile(`([^~!*()'])`)
|
||||||
|
|
||||||
func builtinGlobal_encodeURIComponent(call FunctionCall) Value {
|
func builtinGlobal_encodeURIComponent(call FunctionCall) Value {
|
||||||
return _builtinGlobal_encodeURI(call, encodeURIComponent_Regexp)
|
return _builtinGlobal_encodeURI(call, encodeURIComponent_Regexp)
|
||||||
|
|
@ -124,7 +124,7 @@ func builtinObject_toString(call FunctionCall) Value {
|
||||||
} else if call.This.IsNull() {
|
} else if call.This.IsNull() {
|
||||||
result = "[object Null]"
|
result = "[object Null]"
|
||||||
} else {
|
} else {
|
||||||
result = fmt.Sprintf("[object %s]", call.thisObject().Class)
|
result = fmt.Sprintf("[object %s]", call.thisObject().class)
|
||||||
}
|
}
|
||||||
return toValue(result)
|
return toValue(result)
|
||||||
}
|
}
|
||||||
|
|
@ -177,10 +177,10 @@ func builtinFunction_apply(call FunctionCall) Value {
|
||||||
|
|
||||||
arrayObject := argumentList._object()
|
arrayObject := argumentList._object()
|
||||||
thisObject := call.thisObject()
|
thisObject := call.thisObject()
|
||||||
length := uint(toUI32(arrayObject.Get("length")))
|
length := uint(toUI32(arrayObject.get("length")))
|
||||||
valueArray := make([]Value, length)
|
valueArray := make([]Value, length)
|
||||||
for index := uint(0); index < length; index++ {
|
for index := uint(0); index < length; index++ {
|
||||||
valueArray[index] = arrayObject.Get(arrayIndexToString(index))
|
valueArray[index] = arrayObject.get(arrayIndexToString(index))
|
||||||
}
|
}
|
||||||
return thisObject.Call(this, valueArray)
|
return thisObject.Call(this, valueArray)
|
||||||
}
|
}
|
||||||
|
|
@ -317,10 +317,10 @@ func builtinString_match(call FunctionCall) Value {
|
||||||
target := toString(call.This)
|
target := toString(call.This)
|
||||||
matcherValue := call.Argument(0)
|
matcherValue := call.Argument(0)
|
||||||
matcher := matcherValue._object()
|
matcher := matcherValue._object()
|
||||||
if !matcherValue.IsObject() || matcher.Class != "RegExp" {
|
if !matcherValue.IsObject() || matcher.class != "RegExp" {
|
||||||
matcher = call.runtime.newRegExp(matcherValue, UndefinedValue())
|
matcher = call.runtime.newRegExp(matcherValue, UndefinedValue())
|
||||||
}
|
}
|
||||||
global := toBoolean(matcher.Get("global"))
|
global := toBoolean(matcher.get("global"))
|
||||||
if !global {
|
if !global {
|
||||||
match, result := execRegExp(matcher, target)
|
match, result := execRegExp(matcher, target)
|
||||||
if !match {
|
if !match {
|
||||||
|
|
@ -330,10 +330,10 @@ func builtinString_match(call FunctionCall) Value {
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
result := matcher.RegExp.RegularExpression.FindAllStringIndex(target, -1)
|
result := matcher._RegExp.RegularExpression.FindAllStringIndex(target, -1)
|
||||||
matchCount := len(result)
|
matchCount := len(result)
|
||||||
if result == nil {
|
if result == nil {
|
||||||
matcher.WriteValue("lastIndex", toValue(0), true)
|
matcher.set("lastIndex", toValue(0), true)
|
||||||
return UndefinedValue() // !match
|
return UndefinedValue() // !match
|
||||||
}
|
}
|
||||||
matchCount = len(result)
|
matchCount = len(result)
|
||||||
|
|
@ -341,12 +341,12 @@ func builtinString_match(call FunctionCall) Value {
|
||||||
for index := 0; index < matchCount; index++ {
|
for index := 0; index < matchCount; index++ {
|
||||||
valueArray[index] = toValue(target[result[index][0]:result[index][1]])
|
valueArray[index] = toValue(target[result[index][0]:result[index][1]])
|
||||||
}
|
}
|
||||||
matcher.WriteValue("lastIndex", toValue(result[matchCount-1][1]), true)
|
matcher.set("lastIndex", toValue(result[matchCount-1][1]), true)
|
||||||
return toValue(call.runtime.newArray(valueArray))
|
return toValue(call.runtime.newArray(valueArray))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var builtinString_replace_Regexp *regexp.Regexp = regexp.MustCompile("\\$(?:[\\$\\&\\'\\`1-9]|0[1-9]|[1-9][0-9])")
|
var builtinString_replace_Regexp = regexp.MustCompile("\\$(?:[\\$\\&\\'\\`1-9]|0[1-9]|[1-9][0-9])")
|
||||||
|
|
||||||
func builtinString_findAndReplaceString(input []byte, lastIndex int, match []int, target []byte, replaceValue []byte) (output []byte) {
|
func builtinString_findAndReplaceString(input []byte, lastIndex int, match []int, target []byte, replaceValue []byte) (output []byte) {
|
||||||
matchCount := len(match) / 2
|
matchCount := len(match) / 2
|
||||||
|
|
@ -391,9 +391,9 @@ func builtinString_replace(call FunctionCall) Value {
|
||||||
var search *regexp.Regexp
|
var search *regexp.Regexp
|
||||||
global := false
|
global := false
|
||||||
find := 1
|
find := 1
|
||||||
if searchValue.IsObject() && searchObject.Class == "RegExp" {
|
if searchValue.IsObject() && searchObject.class == "RegExp" {
|
||||||
search = searchObject.RegExp.RegularExpression
|
search = searchObject._RegExp.RegularExpression
|
||||||
global = toBoolean(searchObject.Get("global"))
|
global = toBoolean(searchObject.get("global"))
|
||||||
if global {
|
if global {
|
||||||
find = -1
|
find = -1
|
||||||
}
|
}
|
||||||
|
|
@ -448,7 +448,7 @@ func builtinString_replace(call FunctionCall) Value {
|
||||||
}
|
}
|
||||||
|
|
||||||
if global && searchObject != nil {
|
if global && searchObject != nil {
|
||||||
searchObject.Put("lastIndex", toValue(lastIndex), true)
|
searchObject.put("lastIndex", toValue(lastIndex), true)
|
||||||
}
|
}
|
||||||
|
|
||||||
return toValue(string(result))
|
return toValue(string(result))
|
||||||
|
|
@ -462,10 +462,10 @@ func builtinString_search(call FunctionCall) Value {
|
||||||
target := toString(call.This)
|
target := toString(call.This)
|
||||||
searchValue := call.Argument(0)
|
searchValue := call.Argument(0)
|
||||||
search := searchValue._object()
|
search := searchValue._object()
|
||||||
if !searchValue.IsObject() || search.Class != "RegExp" {
|
if !searchValue.IsObject() || search.class != "RegExp" {
|
||||||
search = call.runtime.newRegExp(searchValue, UndefinedValue())
|
search = call.runtime.newRegExp(searchValue, UndefinedValue())
|
||||||
}
|
}
|
||||||
result := search.RegExp.RegularExpression.FindStringIndex(target)
|
result := search._RegExp.RegularExpression.FindStringIndex(target)
|
||||||
if result == nil {
|
if result == nil {
|
||||||
return toValue(-1)
|
return toValue(-1)
|
||||||
}
|
}
|
||||||
|
|
@ -504,7 +504,7 @@ func builtinString_split(call FunctionCall) Value {
|
||||||
|
|
||||||
if separatorValue.isRegExp() {
|
if separatorValue.isRegExp() {
|
||||||
targetLength := len(target)
|
targetLength := len(target)
|
||||||
search := separatorValue._object().RegExp.RegularExpression
|
search := separatorValue._object()._RegExp.RegularExpression
|
||||||
valueArray := []Value{}
|
valueArray := []Value{}
|
||||||
result := search.FindAllStringSubmatchIndex(target, -1)
|
result := search.FindAllStringSubmatchIndex(target, -1)
|
||||||
lastIndex := 0
|
lastIndex := 0
|
||||||
|
|
@ -697,8 +697,8 @@ func builtinArray_concat(call FunctionCall) Value {
|
||||||
switch item._valueType {
|
switch item._valueType {
|
||||||
case valueObject:
|
case valueObject:
|
||||||
value := item._object()
|
value := item._object()
|
||||||
if value.Class == "Array" {
|
if value.class == "Array" {
|
||||||
itemValueArray := value._propertyStash.(*_arrayStash).valueArray
|
itemValueArray := value.stash.(*_arrayStash).valueArray
|
||||||
for _, item := range itemValueArray {
|
for _, item := range itemValueArray {
|
||||||
if item._valueType == valueEmpty {
|
if item._valueType == valueEmpty {
|
||||||
continue
|
continue
|
||||||
|
|
@ -717,50 +717,50 @@ func builtinArray_concat(call FunctionCall) Value {
|
||||||
|
|
||||||
func builtinArray_shift(call FunctionCall) Value {
|
func builtinArray_shift(call FunctionCall) Value {
|
||||||
thisObject := call.thisObject()
|
thisObject := call.thisObject()
|
||||||
length := uint(toUI32(thisObject.Get("length")))
|
length := uint(toUI32(thisObject.get("length")))
|
||||||
if 0 == length {
|
if 0 == length {
|
||||||
thisObject.Put("length", toValue(length), true)
|
thisObject.put("length", toValue(length), true)
|
||||||
return UndefinedValue()
|
return UndefinedValue()
|
||||||
}
|
}
|
||||||
first := thisObject.Get("0")
|
first := thisObject.get("0")
|
||||||
for index := uint(1); index < length; index++ {
|
for index := uint(1); index < length; index++ {
|
||||||
from := arrayIndexToString(index)
|
from := arrayIndexToString(index)
|
||||||
to := arrayIndexToString(index - 1)
|
to := arrayIndexToString(index - 1)
|
||||||
if thisObject.HasProperty(from) {
|
if thisObject.hasProperty(from) {
|
||||||
thisObject.Put(to, thisObject.Get(from), true)
|
thisObject.put(to, thisObject.get(from), true)
|
||||||
} else {
|
} else {
|
||||||
thisObject.Delete(to, true)
|
thisObject.delete(to, true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
thisObject.Delete(arrayIndexToString(length - 1), true)
|
thisObject.delete(arrayIndexToString(length - 1), true)
|
||||||
thisObject.Put("length", toValue(length - 1), true)
|
thisObject.put("length", toValue(length - 1), true)
|
||||||
return first
|
return first
|
||||||
}
|
}
|
||||||
|
|
||||||
func builtinArray_push(call FunctionCall) Value {
|
func builtinArray_push(call FunctionCall) Value {
|
||||||
thisObject := call.thisObject()
|
thisObject := call.thisObject()
|
||||||
itemList := call.ArgumentList
|
itemList := call.ArgumentList
|
||||||
index := uint(toUI32(thisObject.Get("length")))
|
index := uint(toUI32(thisObject.get("length")))
|
||||||
for len(itemList) > 0 {
|
for len(itemList) > 0 {
|
||||||
thisObject.Put(arrayIndexToString(index), itemList[0], true)
|
thisObject.put(arrayIndexToString(index), itemList[0], true)
|
||||||
itemList = itemList[1:]
|
itemList = itemList[1:]
|
||||||
index += 1
|
index += 1
|
||||||
}
|
}
|
||||||
length := toValue(index)
|
length := toValue(index)
|
||||||
thisObject.Put("length", length, true)
|
thisObject.put("length", length, true)
|
||||||
return length
|
return length
|
||||||
}
|
}
|
||||||
|
|
||||||
func builtinArray_pop(call FunctionCall) Value {
|
func builtinArray_pop(call FunctionCall) Value {
|
||||||
thisObject := call.thisObject()
|
thisObject := call.thisObject()
|
||||||
length := uint(toUI32(thisObject.Get("length")))
|
length := uint(toUI32(thisObject.get("length")))
|
||||||
if 0 == length {
|
if 0 == length {
|
||||||
thisObject.Put("length", toValue(length), true)
|
thisObject.put("length", toValue(length), true)
|
||||||
return UndefinedValue()
|
return UndefinedValue()
|
||||||
}
|
}
|
||||||
last := thisObject.Get(arrayIndexToString(length - 1))
|
last := thisObject.get(arrayIndexToString(length - 1))
|
||||||
thisObject.Delete(arrayIndexToString(length - 1), true)
|
thisObject.delete(arrayIndexToString(length - 1), true)
|
||||||
thisObject.Put("length", toValue(length - 1), true)
|
thisObject.put("length", toValue(length - 1), true)
|
||||||
return last
|
return last
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -773,17 +773,17 @@ func builtinArray_join(call FunctionCall) Value {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
thisObject := call.thisObject()
|
thisObject := call.thisObject()
|
||||||
if stash, isArray := thisObject._propertyStash.(*_arrayStash); isArray {
|
if stash, isArray := thisObject.stash.(*_arrayStash); isArray {
|
||||||
return toValue(builtinArray_joinNative(stash.valueArray, separator))
|
return toValue(builtinArray_joinNative(stash.valueArray, separator))
|
||||||
}
|
}
|
||||||
// Generic .join
|
// Generic .join
|
||||||
length := uint(toUI32(thisObject.Get("length")))
|
length := uint(toUI32(thisObject.get("length")))
|
||||||
if length == 0 {
|
if length == 0 {
|
||||||
return toValue("")
|
return toValue("")
|
||||||
}
|
}
|
||||||
stringList := make([]string, 0, length)
|
stringList := make([]string, 0, length)
|
||||||
for index := uint(0); index < length; index += 1 {
|
for index := uint(0); index < length; index += 1 {
|
||||||
value := thisObject.Get(arrayIndexToString(index))
|
value := thisObject.get(arrayIndexToString(index))
|
||||||
stringValue := ""
|
stringValue := ""
|
||||||
switch value._valueType {
|
switch value._valueType {
|
||||||
case valueEmpty, valueUndefined, valueNull:
|
case valueEmpty, valueUndefined, valueNull:
|
||||||
|
|
@ -852,7 +852,7 @@ func rangeStartLength(source []Value, size uint) (start, length int64) {
|
||||||
|
|
||||||
func builtinArray_splice(call FunctionCall) Value {
|
func builtinArray_splice(call FunctionCall) Value {
|
||||||
thisObject := call.thisObject()
|
thisObject := call.thisObject()
|
||||||
length := uint(toUI32(thisObject.Get("length")))
|
length := uint(toUI32(thisObject.get("length")))
|
||||||
|
|
||||||
start := valueToArrayIndex(call.Argument(0), length, true)
|
start := valueToArrayIndex(call.Argument(0), length, true)
|
||||||
deleteCount := valueToArrayIndex(call.Argument(1), length - start, false)
|
deleteCount := valueToArrayIndex(call.Argument(1), length - start, false)
|
||||||
|
|
@ -860,8 +860,8 @@ func builtinArray_splice(call FunctionCall) Value {
|
||||||
|
|
||||||
for index := uint(0); index < deleteCount; index++ {
|
for index := uint(0); index < deleteCount; index++ {
|
||||||
indexString := arrayIndexToString(start + index)
|
indexString := arrayIndexToString(start + index)
|
||||||
if thisObject.HasProperty(indexString) {
|
if thisObject.hasProperty(indexString) {
|
||||||
valueArray[index] = thisObject.Get(indexString)
|
valueArray[index] = thisObject.get(indexString)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -887,17 +887,17 @@ func builtinArray_splice(call FunctionCall) Value {
|
||||||
for index := start; index < stop; index++ {
|
for index := start; index < stop; index++ {
|
||||||
from := arrayIndexToString(index + deleteCount) // Position just after deletion
|
from := arrayIndexToString(index + deleteCount) // Position just after deletion
|
||||||
to := arrayIndexToString(index + itemCount) // Position just after splice (insertion)
|
to := arrayIndexToString(index + itemCount) // Position just after splice (insertion)
|
||||||
if thisObject.HasProperty(from) {
|
if thisObject.hasProperty(from) {
|
||||||
thisObject.Put(to, thisObject.Get(from), true)
|
thisObject.put(to, thisObject.get(from), true)
|
||||||
} else {
|
} else {
|
||||||
thisObject.Delete(to, true)
|
thisObject.delete(to, true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Delete off the end
|
// Delete off the end
|
||||||
// We don't bother to delete below <stop + itemCount> (if any) since those
|
// We don't bother to delete below <stop + itemCount> (if any) since those
|
||||||
// will be overwritten anyway
|
// will be overwritten anyway
|
||||||
for index := length; index > (stop + itemCount); index-- {
|
for index := length; index > (stop + itemCount); index-- {
|
||||||
thisObject.Delete(arrayIndexToString(index - 1), true)
|
thisObject.delete(arrayIndexToString(index - 1), true)
|
||||||
}
|
}
|
||||||
} else if itemCount > deleteCount {
|
} else if itemCount > deleteCount {
|
||||||
// The Object/Array is growing
|
// The Object/Array is growing
|
||||||
|
|
@ -910,18 +910,18 @@ func builtinArray_splice(call FunctionCall) Value {
|
||||||
for index := length - deleteCount; index > start; index-- {
|
for index := length - deleteCount; index > start; index-- {
|
||||||
from := arrayIndexToString(index + deleteCount - 1)
|
from := arrayIndexToString(index + deleteCount - 1)
|
||||||
to := arrayIndexToString(index + itemCount - 1)
|
to := arrayIndexToString(index + itemCount - 1)
|
||||||
if thisObject.HasProperty(from) {
|
if thisObject.hasProperty(from) {
|
||||||
thisObject.Put(to, thisObject.Get(from), true)
|
thisObject.put(to, thisObject.get(from), true)
|
||||||
} else {
|
} else {
|
||||||
thisObject.Delete(to, true)
|
thisObject.delete(to, true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for index := uint(0); index < itemCount; index++ {
|
for index := uint(0); index < itemCount; index++ {
|
||||||
thisObject.Put(arrayIndexToString(index + start), itemList[index], true)
|
thisObject.put(arrayIndexToString(index + start), itemList[index], true)
|
||||||
}
|
}
|
||||||
thisObject.Put("length", toValue(length + itemCount - deleteCount), true)
|
thisObject.put("length", toValue(length + itemCount - deleteCount), true)
|
||||||
|
|
||||||
return toValue(call.runtime.newArray(valueArray))
|
return toValue(call.runtime.newArray(valueArray))
|
||||||
}
|
}
|
||||||
|
|
@ -929,7 +929,7 @@ func builtinArray_splice(call FunctionCall) Value {
|
||||||
func builtinArray_slice(call FunctionCall) Value {
|
func builtinArray_slice(call FunctionCall) Value {
|
||||||
thisObject := call.thisObject()
|
thisObject := call.thisObject()
|
||||||
|
|
||||||
length := uint(toUI32(thisObject.Get("length")))
|
length := uint(toUI32(thisObject.get("length")))
|
||||||
start, end := rangeStartEnd(call.ArgumentList, length)
|
start, end := rangeStartEnd(call.ArgumentList, length)
|
||||||
|
|
||||||
if start >= end {
|
if start >= end {
|
||||||
|
|
@ -940,13 +940,13 @@ func builtinArray_slice(call FunctionCall) Value {
|
||||||
sliceValueArray := make([]Value, sliceLength)
|
sliceValueArray := make([]Value, sliceLength)
|
||||||
|
|
||||||
// Native slicing if a "real" array
|
// Native slicing if a "real" array
|
||||||
if _arrayStash, ok := thisObject._propertyStash.(*_arrayStash); ok {
|
if _arrayStash, ok := thisObject.stash.(*_arrayStash); ok {
|
||||||
copy(sliceValueArray, _arrayStash.valueArray[start:start+sliceLength])
|
copy(sliceValueArray, _arrayStash.valueArray[start:start+sliceLength])
|
||||||
} else {
|
} else {
|
||||||
for index := uint(0); index < sliceLength; index++ {
|
for index := uint(0); index < sliceLength; index++ {
|
||||||
from := arrayIndexToString(index + start)
|
from := arrayIndexToString(index + start)
|
||||||
if thisObject.HasProperty(from) {
|
if thisObject.hasProperty(from) {
|
||||||
sliceValueArray[index] = thisObject.Get(from)
|
sliceValueArray[index] = thisObject.get(from)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -956,32 +956,32 @@ func builtinArray_slice(call FunctionCall) Value {
|
||||||
|
|
||||||
func builtinArray_unshift(call FunctionCall) Value {
|
func builtinArray_unshift(call FunctionCall) Value {
|
||||||
thisObject := call.thisObject()
|
thisObject := call.thisObject()
|
||||||
length := uint(toUI32(thisObject.Get("length")))
|
length := uint(toUI32(thisObject.get("length")))
|
||||||
itemList := call.ArgumentList
|
itemList := call.ArgumentList
|
||||||
itemCount := uint(len(itemList))
|
itemCount := uint(len(itemList))
|
||||||
|
|
||||||
for index := length; index > 0; index-- {
|
for index := length; index > 0; index-- {
|
||||||
from := arrayIndexToString(index - 1)
|
from := arrayIndexToString(index - 1)
|
||||||
to := arrayIndexToString(index + itemCount - 1)
|
to := arrayIndexToString(index + itemCount - 1)
|
||||||
if thisObject.HasProperty(from) {
|
if thisObject.hasProperty(from) {
|
||||||
thisObject.Put(to, thisObject.Get(from), true)
|
thisObject.put(to, thisObject.get(from), true)
|
||||||
} else {
|
} else {
|
||||||
thisObject.Delete(to, true)
|
thisObject.delete(to, true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for index := uint(0); index < itemCount; index++ {
|
for index := uint(0); index < itemCount; index++ {
|
||||||
thisObject.Put(arrayIndexToString(index), itemList[index], true)
|
thisObject.put(arrayIndexToString(index), itemList[index], true)
|
||||||
}
|
}
|
||||||
|
|
||||||
newLength := toValue(length + itemCount)
|
newLength := toValue(length + itemCount)
|
||||||
thisObject.Put("length", newLength, true)
|
thisObject.put("length", newLength, true)
|
||||||
return newLength
|
return newLength
|
||||||
}
|
}
|
||||||
|
|
||||||
func builtinArray_reverse(call FunctionCall) Value {
|
func builtinArray_reverse(call FunctionCall) Value {
|
||||||
thisObject := call.thisObject()
|
thisObject := call.thisObject()
|
||||||
length := uint(toUI32(thisObject.Get("length")))
|
length := uint(toUI32(thisObject.get("length")))
|
||||||
|
|
||||||
lower := struct {
|
lower := struct {
|
||||||
name string
|
name string
|
||||||
|
|
@ -998,22 +998,22 @@ func builtinArray_reverse(call FunctionCall) Value {
|
||||||
upper.index = length - lower.index - 1
|
upper.index = length - lower.index - 1
|
||||||
upper.name = arrayIndexToString(upper.index)
|
upper.name = arrayIndexToString(upper.index)
|
||||||
|
|
||||||
lower.exists = thisObject.HasProperty(lower.name)
|
lower.exists = thisObject.hasProperty(lower.name)
|
||||||
upper.exists = thisObject.HasProperty(upper.name)
|
upper.exists = thisObject.hasProperty(upper.name)
|
||||||
|
|
||||||
if lower.exists && upper.exists {
|
if lower.exists && upper.exists {
|
||||||
lowerValue := thisObject.Get(lower.name)
|
lowerValue := thisObject.get(lower.name)
|
||||||
upperValue := thisObject.Get(upper.name)
|
upperValue := thisObject.get(upper.name)
|
||||||
thisObject.Put(lower.name, upperValue, true)
|
thisObject.put(lower.name, upperValue, true)
|
||||||
thisObject.Put(upper.name, lowerValue, true)
|
thisObject.put(upper.name, lowerValue, true)
|
||||||
} else if !lower.exists && upper.exists {
|
} else if !lower.exists && upper.exists {
|
||||||
value := thisObject.Get(upper.name)
|
value := thisObject.get(upper.name)
|
||||||
thisObject.Delete(upper.name, true)
|
thisObject.delete(upper.name, true)
|
||||||
thisObject.Put(lower.name, value, true)
|
thisObject.put(lower.name, value, true)
|
||||||
} else if lower.exists && !upper.exists {
|
} else if lower.exists && !upper.exists {
|
||||||
value := thisObject.Get(lower.name)
|
value := thisObject.get(lower.name)
|
||||||
thisObject.Delete(lower.name, true)
|
thisObject.delete(lower.name, true)
|
||||||
thisObject.Put(upper.name, value, true)
|
thisObject.put(upper.name, value, true)
|
||||||
} else {
|
} else {
|
||||||
// Nothing happens.
|
// Nothing happens.
|
||||||
}
|
}
|
||||||
|
|
@ -1033,9 +1033,9 @@ func sortCompare(thisObject *_object, index0, index1 uint, compare *_object) int
|
||||||
}{}
|
}{}
|
||||||
k := j
|
k := j
|
||||||
j.name = arrayIndexToString(index0)
|
j.name = arrayIndexToString(index0)
|
||||||
j.exists = thisObject.HasProperty(j.name)
|
j.exists = thisObject.hasProperty(j.name)
|
||||||
k.name = arrayIndexToString(index1)
|
k.name = arrayIndexToString(index1)
|
||||||
k.exists = thisObject.HasProperty(k.name)
|
k.exists = thisObject.hasProperty(k.name)
|
||||||
|
|
||||||
if !j.exists && !k.exists {
|
if !j.exists && !k.exists {
|
||||||
return 0
|
return 0
|
||||||
|
|
@ -1045,8 +1045,8 @@ func sortCompare(thisObject *_object, index0, index1 uint, compare *_object) int
|
||||||
return -1
|
return -1
|
||||||
}
|
}
|
||||||
|
|
||||||
x := thisObject.Get(j.name)
|
x := thisObject.get(j.name)
|
||||||
y := thisObject.Get(k.name)
|
y := thisObject.get(k.name)
|
||||||
j.defined = x.IsDefined()
|
j.defined = x.IsDefined()
|
||||||
k.defined = y.IsDefined()
|
k.defined = y.IsDefined()
|
||||||
|
|
||||||
|
|
@ -1083,23 +1083,23 @@ func arraySortSwap(thisObject *_object, index0, index1 uint) {
|
||||||
k := j
|
k := j
|
||||||
|
|
||||||
j.name = arrayIndexToString(index0)
|
j.name = arrayIndexToString(index0)
|
||||||
j.exists = thisObject.HasProperty(j.name)
|
j.exists = thisObject.hasProperty(j.name)
|
||||||
k.name = arrayIndexToString(index1)
|
k.name = arrayIndexToString(index1)
|
||||||
k.exists = thisObject.HasProperty(k.name)
|
k.exists = thisObject.hasProperty(k.name)
|
||||||
|
|
||||||
if j.exists && k.exists {
|
if j.exists && k.exists {
|
||||||
jValue := thisObject.Get(j.name)
|
jValue := thisObject.get(j.name)
|
||||||
kValue := thisObject.Get(k.name)
|
kValue := thisObject.get(k.name)
|
||||||
thisObject.Put(j.name, kValue, true)
|
thisObject.put(j.name, kValue, true)
|
||||||
thisObject.Put(k.name, jValue, true)
|
thisObject.put(k.name, jValue, true)
|
||||||
} else if !j.exists && k.exists {
|
} else if !j.exists && k.exists {
|
||||||
value := thisObject.Get(k.name)
|
value := thisObject.get(k.name)
|
||||||
thisObject.Delete(k.name, true)
|
thisObject.delete(k.name, true)
|
||||||
thisObject.Put(j.name, value, true)
|
thisObject.put(j.name, value, true)
|
||||||
} else if j.exists && !k.exists {
|
} else if j.exists && !k.exists {
|
||||||
value := thisObject.Get(j.name)
|
value := thisObject.get(j.name)
|
||||||
thisObject.Delete(j.name, true)
|
thisObject.delete(j.name, true)
|
||||||
thisObject.Put(k.name, value, true)
|
thisObject.put(k.name, value, true)
|
||||||
} else {
|
} else {
|
||||||
// Nothing happens.
|
// Nothing happens.
|
||||||
}
|
}
|
||||||
|
|
@ -1131,7 +1131,7 @@ func arraySortQuickSort(thisObject *_object, left, right uint, compare *_object)
|
||||||
|
|
||||||
func builtinArray_sort(call FunctionCall) Value {
|
func builtinArray_sort(call FunctionCall) Value {
|
||||||
thisObject := call.thisObject()
|
thisObject := call.thisObject()
|
||||||
length := uint(toUI32(thisObject.Get("length")))
|
length := uint(toUI32(thisObject.get("length")))
|
||||||
compareValue := call.Argument(0)
|
compareValue := call.Argument(0)
|
||||||
compare := compareValue._object()
|
compare := compareValue._object()
|
||||||
if compareValue.IsUndefined() {
|
if compareValue.IsUndefined() {
|
||||||
|
|
@ -1156,15 +1156,15 @@ func builtinNewRegExp(self *_object, _ Value, argumentList []Value) Value {
|
||||||
|
|
||||||
func builtinRegExp_toString(call FunctionCall) Value {
|
func builtinRegExp_toString(call FunctionCall) Value {
|
||||||
thisObject := call.thisObject()
|
thisObject := call.thisObject()
|
||||||
source := toString(thisObject.Get("source"))
|
source := toString(thisObject.get("source"))
|
||||||
flags := []byte{}
|
flags := []byte{}
|
||||||
if toBoolean(thisObject.Get("global")) {
|
if toBoolean(thisObject.get("global")) {
|
||||||
flags = append(flags, 'g')
|
flags = append(flags, 'g')
|
||||||
}
|
}
|
||||||
if toBoolean(thisObject.Get("ignoreCase")) {
|
if toBoolean(thisObject.get("ignoreCase")) {
|
||||||
flags = append(flags, 'i')
|
flags = append(flags, 'i')
|
||||||
}
|
}
|
||||||
if toBoolean(thisObject.Get("multiline")) {
|
if toBoolean(thisObject.get("multiline")) {
|
||||||
flags = append(flags, 'm')
|
flags = append(flags, 'm')
|
||||||
}
|
}
|
||||||
return toValue(fmt.Sprintf("/%s/%s", source, flags))
|
return toValue(fmt.Sprintf("/%s/%s", source, flags))
|
||||||
|
|
@ -1339,13 +1339,13 @@ func builtinError_toString(call FunctionCall) Value {
|
||||||
}
|
}
|
||||||
|
|
||||||
name := "Error"
|
name := "Error"
|
||||||
nameValue := thisObject.Get("name")
|
nameValue := thisObject.get("name")
|
||||||
if nameValue.IsDefined() {
|
if nameValue.IsDefined() {
|
||||||
name = toString(nameValue)
|
name = toString(nameValue)
|
||||||
}
|
}
|
||||||
|
|
||||||
message := ""
|
message := ""
|
||||||
messageValue := thisObject.Get("message")
|
messageValue := thisObject.get("message")
|
||||||
if messageValue.IsDefined() {
|
if messageValue.IsDefined() {
|
||||||
message = toString(messageValue)
|
message = toString(messageValue)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -32,7 +32,7 @@ func builtinConsole_placeholder(call FunctionCall) Value {
|
||||||
func (runtime *_runtime) newConsole() *_object {
|
func (runtime *_runtime) newConsole() *_object {
|
||||||
|
|
||||||
self := runtime.newObject()
|
self := runtime.newObject()
|
||||||
self.Define(
|
self.write(
|
||||||
"log", builtinConsole_log,
|
"log", builtinConsole_log,
|
||||||
"debug", builtinConsole_log,
|
"debug", builtinConsole_log,
|
||||||
"info", builtinConsole_log,
|
"info", builtinConsole_log,
|
||||||
|
|
|
||||||
|
|
@ -58,7 +58,7 @@ func (self *_functionEnvironment) HasBinding(name string) bool {
|
||||||
if exists {
|
if exists {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
return self.Object.HasProperty(name)
|
return self.Object.hasProperty(name)
|
||||||
}
|
}
|
||||||
|
|
||||||
type _objectEnvironment struct {
|
type _objectEnvironment struct {
|
||||||
|
|
@ -77,23 +77,23 @@ func (runtime *_runtime) newObjectEnvironment() *_objectEnvironment {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *_objectEnvironment) HasBinding(name string) bool {
|
func (self *_objectEnvironment) HasBinding(name string) bool {
|
||||||
return self.Object.HasProperty(name)
|
return self.Object.hasProperty(name)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *_objectEnvironment) CreateMutableBinding(name string, configure bool) {
|
func (self *_objectEnvironment) CreateMutableBinding(name string, configure bool) {
|
||||||
if self.Object.HasProperty(name) {
|
if self.Object.hasProperty(name) {
|
||||||
panic(hereBeDragons())
|
panic(hereBeDragons())
|
||||||
}
|
}
|
||||||
self.Object._propertyStash.Write(name, UndefinedValue())
|
self.Object.stash.put(name, UndefinedValue())
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *_objectEnvironment) SetMutableBinding(name string, value Value, strict bool) {
|
func (self *_objectEnvironment) SetMutableBinding(name string, value Value, strict bool) {
|
||||||
self.Object.WriteValue(name, value, strict)
|
self.Object.set(name, value, strict)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *_objectEnvironment) GetBindingValue(name string, strict bool) Value {
|
func (self *_objectEnvironment) GetBindingValue(name string, strict bool) Value {
|
||||||
if self.Object.HasProperty(name) {
|
if self.Object.hasProperty(name) {
|
||||||
return self.Object.Get(name)
|
return self.Object.get(name)
|
||||||
}
|
}
|
||||||
if strict {
|
if strict {
|
||||||
panic(newReferenceError("Not Defined", name))
|
panic(newReferenceError("Not Defined", name))
|
||||||
|
|
@ -102,7 +102,7 @@ func (self *_objectEnvironment) GetBindingValue(name string, strict bool) Value
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *_objectEnvironment) DeleteBinding(name string) bool {
|
func (self *_objectEnvironment) DeleteBinding(name string) bool {
|
||||||
return self.Object.Delete(name, false)
|
return self.Object.delete(name, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *_objectEnvironment) ImplicitThisValue() *_object {
|
func (self *_objectEnvironment) ImplicitThisValue() *_object {
|
||||||
|
|
|
||||||
|
|
@ -46,7 +46,7 @@ func (self *_runtime) evaluateObject(node *_objectNode) Value {
|
||||||
result := self.newObject()
|
result := self.newObject()
|
||||||
|
|
||||||
for _, property := range node.propertyList {
|
for _, property := range node.propertyList {
|
||||||
result.WriteValue(property.Key, self.GetValue(self.evaluate(property.Value)), false)
|
result.set(property.Key, self.GetValue(self.evaluate(property.Value)), false)
|
||||||
}
|
}
|
||||||
|
|
||||||
return toValue(result)
|
return toValue(result)
|
||||||
|
|
@ -118,7 +118,7 @@ func (self *_runtime) evaluateUnaryOperation(node *_unaryOperationNode) Value {
|
||||||
case valueString:
|
case valueString:
|
||||||
return toValue("string")
|
return toValue("string")
|
||||||
case valueObject:
|
case valueObject:
|
||||||
if targetValue._object().Function != nil {
|
if targetValue._object()._Function != nil {
|
||||||
return toValue("function")
|
return toValue("function")
|
||||||
}
|
}
|
||||||
return toValue("object")
|
return toValue("object")
|
||||||
|
|
@ -256,7 +256,7 @@ func (self *_runtime) calculateBinaryOperation(operator string, left Value, righ
|
||||||
if !rightValue.IsObject() {
|
if !rightValue.IsObject() {
|
||||||
panic(newTypeError())
|
panic(newTypeError())
|
||||||
}
|
}
|
||||||
return toValue(rightValue._object().HasProperty(toString(leftValue)))
|
return toValue(rightValue._object().hasProperty(toString(leftValue)))
|
||||||
}
|
}
|
||||||
|
|
||||||
panic(hereBeDragons(operator))
|
panic(hereBeDragons(operator))
|
||||||
|
|
|
||||||
|
|
@ -190,7 +190,7 @@ func (self *_runtime) evaluateForIn(node *_forInNode) Value {
|
||||||
result := emptyValue()
|
result := emptyValue()
|
||||||
object := sourceObject
|
object := sourceObject
|
||||||
for object != nil {
|
for object != nil {
|
||||||
object.Enumerate(func(name string){
|
object.enumerate(func(name string){
|
||||||
into := self.evaluate(into)
|
into := self.evaluate(into)
|
||||||
// In the case of: for (var abc in def) ...
|
// In the case of: for (var abc in def) ...
|
||||||
if into.reference() == nil {
|
if into.reference() == nil {
|
||||||
|
|
@ -204,7 +204,7 @@ func (self *_runtime) evaluateForIn(node *_forInNode) Value {
|
||||||
result = value
|
result = value
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
object = object.Prototype
|
object = object.prototype
|
||||||
}
|
}
|
||||||
return result
|
return result
|
||||||
})
|
})
|
||||||
|
|
|
||||||
159
global.go
159
global.go
|
|
@ -10,45 +10,43 @@ type _globalConstructFunction _constructFunction
|
||||||
|
|
||||||
func (self *_runtime) newGlobalFunction(
|
func (self *_runtime) newGlobalFunction(
|
||||||
length int,
|
length int,
|
||||||
callFunction _globalCallFunction,
|
name string, callFunction _globalCallFunction,
|
||||||
constructFunction _globalConstructFunction,
|
constructFunction _globalConstructFunction,
|
||||||
prototype *_object,
|
prototype *_object,
|
||||||
nameAndValue... interface{}) *_object {
|
definition... interface{}) *_object {
|
||||||
//
|
|
||||||
// TODO We're overwriting the prototype of newNativeFunction with this one,
|
// TODO We're overwriting the prototype of newNativeFunction with this one,
|
||||||
// what is going on?
|
// what is going on?
|
||||||
target := self.newNativeFunction(_nativeFunction(callFunction), length)
|
functionObject := self.newNativeFunction(_nativeFunction(callFunction), length, "native" + name)
|
||||||
target.Function.Construct = _constructFunction(constructFunction)
|
functionObject._Function.Construct = _constructFunction(constructFunction)
|
||||||
target.define(_propertyMode(0), "prototype", toValue(prototype))
|
functionObject.stash.set("prototype", toValue(prototype), _propertyMode(0))
|
||||||
nameAndValue = append(
|
|
||||||
[]interface{}{
|
prototype.write(append([]interface{}{
|
||||||
_functionSignature("builtin"),
|
_functionSignature("builtin"),
|
||||||
_propertyMode(propertyModeWrite | propertyModeConfigure),
|
_propertyMode(0101), // Write | Configure
|
||||||
"constructor", toValue(target),
|
"constructor", toValue(functionObject),
|
||||||
},
|
},
|
||||||
nameAndValue...,
|
definition...,
|
||||||
)
|
)...)
|
||||||
// This actually may be slower than Define
|
|
||||||
// Benchmark?
|
return functionObject
|
||||||
prototype.define(nameAndValue...)
|
|
||||||
return target
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *_runtime) newGlobalObject(
|
func (self *_runtime) newGlobalObject(
|
||||||
class string,
|
class string,
|
||||||
nameAndValue... interface{}) *_object {
|
nameAndValue... interface{}) *_object {
|
||||||
//
|
|
||||||
target := self.newClassObject(class)
|
target := self.newClassObject(class)
|
||||||
nameAndValue = append(
|
nameAndValue = append(
|
||||||
[]interface{}{
|
[]interface{}{
|
||||||
_functionSignature("builtin"),
|
_functionSignature("builtin"),
|
||||||
_propertyMode(propertyModeWrite | propertyModeConfigure),
|
_propertyMode(0101), // Write | Configure
|
||||||
},
|
},
|
||||||
nameAndValue...,
|
nameAndValue...,
|
||||||
)
|
)
|
||||||
// This actually may be slower than Define
|
// This actually may be slower than Define
|
||||||
// Benchmark?
|
// Benchmark?
|
||||||
target.define(nameAndValue...)
|
target.write(nameAndValue...)
|
||||||
return target
|
return target
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -56,11 +54,11 @@ func builtinDefine(target *_object, nameAndValue... interface{}) {
|
||||||
nameAndValue = append(
|
nameAndValue = append(
|
||||||
[]interface{}{
|
[]interface{}{
|
||||||
_functionSignature("builtin"),
|
_functionSignature("builtin"),
|
||||||
_propertyMode(propertyModeWrite | propertyModeConfigure),
|
_propertyMode(0101), // Write | Configure
|
||||||
},
|
},
|
||||||
nameAndValue...,
|
nameAndValue...,
|
||||||
)
|
)
|
||||||
target.define(nameAndValue)
|
target.write(nameAndValue)
|
||||||
}
|
}
|
||||||
|
|
||||||
func newContext() *_runtime {
|
func newContext() *_runtime {
|
||||||
|
|
@ -76,63 +74,63 @@ func newContext() *_runtime {
|
||||||
|
|
||||||
{
|
{
|
||||||
ObjectPrototype := self.newObject()
|
ObjectPrototype := self.newObject()
|
||||||
ObjectPrototype.Prototype = nil
|
ObjectPrototype.prototype = nil
|
||||||
self.Global.ObjectPrototype = ObjectPrototype
|
self.Global.ObjectPrototype = ObjectPrototype
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
FunctionPrototype := self.newNativeFunctionObject(func(FunctionCall) Value {
|
FunctionPrototype := self.newNativeFunctionObject(func(FunctionCall) Value {
|
||||||
return UndefinedValue()
|
return UndefinedValue()
|
||||||
}, 0)
|
}, 0, "nativeFunction_")
|
||||||
FunctionPrototype.Prototype = self.Global.ObjectPrototype
|
FunctionPrototype.prototype = self.Global.ObjectPrototype
|
||||||
self.Global.FunctionPrototype = FunctionPrototype
|
self.Global.FunctionPrototype = FunctionPrototype
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
ArrayPrototype := self.newArray([]Value{})
|
ArrayPrototype := self.newArray([]Value{})
|
||||||
ArrayPrototype.Prototype = self.Global.ObjectPrototype
|
ArrayPrototype.prototype = self.Global.ObjectPrototype
|
||||||
self.Global.ArrayPrototype = ArrayPrototype
|
self.Global.ArrayPrototype = ArrayPrototype
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
StringPrototype := self.newString(toValue(""))
|
StringPrototype := self.newString(toValue(""))
|
||||||
StringPrototype.Prototype = self.Global.ObjectPrototype
|
StringPrototype.prototype = self.Global.ObjectPrototype
|
||||||
self.Global.StringPrototype = StringPrototype
|
self.Global.StringPrototype = StringPrototype
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
BooleanPrototype := self.newBoolean(FalseValue())
|
BooleanPrototype := self.newBoolean(FalseValue())
|
||||||
BooleanPrototype.Prototype = self.Global.ObjectPrototype
|
BooleanPrototype.prototype = self.Global.ObjectPrototype
|
||||||
self.Global.BooleanPrototype = BooleanPrototype
|
self.Global.BooleanPrototype = BooleanPrototype
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
NumberPrototype := self.newNumber(toValue(0))
|
NumberPrototype := self.newNumber(toValue(0))
|
||||||
NumberPrototype.Prototype = self.Global.ObjectPrototype
|
NumberPrototype.prototype = self.Global.ObjectPrototype
|
||||||
self.Global.NumberPrototype = NumberPrototype
|
self.Global.NumberPrototype = NumberPrototype
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
DatePrototype := self.newDate(0)
|
DatePrototype := self.newDate(0)
|
||||||
DatePrototype.Prototype = self.Global.ObjectPrototype
|
DatePrototype.prototype = self.Global.ObjectPrototype
|
||||||
self.Global.DatePrototype = DatePrototype
|
self.Global.DatePrototype = DatePrototype
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
RegExpPrototype := self.newRegExp(UndefinedValue(), UndefinedValue())
|
RegExpPrototype := self.newRegExp(UndefinedValue(), UndefinedValue())
|
||||||
RegExpPrototype.Prototype = self.Global.ObjectPrototype
|
RegExpPrototype.prototype = self.Global.ObjectPrototype
|
||||||
self.Global.RegExpPrototype = RegExpPrototype
|
self.Global.RegExpPrototype = RegExpPrototype
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
ErrorPrototype := self.newErrorObject(UndefinedValue())
|
ErrorPrototype := self.newErrorObject(UndefinedValue())
|
||||||
ErrorPrototype.Prototype = self.Global.ObjectPrototype
|
ErrorPrototype.prototype = self.Global.ObjectPrototype
|
||||||
self.Global.ErrorPrototype = ErrorPrototype
|
self.Global.ErrorPrototype = ErrorPrototype
|
||||||
}
|
}
|
||||||
|
|
||||||
self.Global.Object = self.newGlobalFunction(
|
self.Global.Object = self.newGlobalFunction(
|
||||||
1,
|
1,
|
||||||
builtinObject,
|
"Object", builtinObject,
|
||||||
builtinNewObject,
|
builtinNewObject,
|
||||||
self.Global.ObjectPrototype,
|
self.Global.ObjectPrototype,
|
||||||
"valueOf", func(call FunctionCall) Value {
|
"valueOf", func(call FunctionCall) Value {
|
||||||
|
|
@ -142,27 +140,27 @@ func newContext() *_runtime {
|
||||||
"hasOwnProperty", func(call FunctionCall) Value {
|
"hasOwnProperty", func(call FunctionCall) Value {
|
||||||
propertyName := toString(call.Argument(0))
|
propertyName := toString(call.Argument(0))
|
||||||
thisObject := call.thisObject()
|
thisObject := call.thisObject()
|
||||||
return toValue(thisObject.HasOwnProperty(propertyName))
|
return toValue(thisObject.hasOwnProperty(propertyName))
|
||||||
},
|
},
|
||||||
"isPrototypeOf", func(call FunctionCall) Value {
|
"isPrototypeOf", func(call FunctionCall) Value {
|
||||||
value := call.Argument(0)
|
value := call.Argument(0)
|
||||||
if !value.IsObject() {
|
if !value.IsObject() {
|
||||||
return FalseValue()
|
return FalseValue()
|
||||||
}
|
}
|
||||||
prototype := call.toObject(value).Prototype
|
prototype := call.toObject(value).prototype
|
||||||
thisObject := call.thisObject()
|
thisObject := call.thisObject()
|
||||||
for prototype != nil {
|
for prototype != nil {
|
||||||
if thisObject == prototype {
|
if thisObject == prototype {
|
||||||
return TrueValue()
|
return TrueValue()
|
||||||
}
|
}
|
||||||
prototype = prototype.Prototype
|
prototype = prototype.prototype
|
||||||
}
|
}
|
||||||
return FalseValue()
|
return FalseValue()
|
||||||
},
|
},
|
||||||
"propertyIsEnumerable", func(call FunctionCall) Value {
|
"propertyIsEnumerable", func(call FunctionCall) Value {
|
||||||
propertyName := toString(call.Argument(0))
|
propertyName := toString(call.Argument(0))
|
||||||
thisObject := call.thisObject()
|
thisObject := call.thisObject()
|
||||||
property := thisObject.GetOwnProperty(propertyName)
|
property := thisObject.getOwnProperty(propertyName)
|
||||||
if property != nil && property.CanEnumerate() {
|
if property != nil && property.CanEnumerate() {
|
||||||
return TrueValue()
|
return TrueValue()
|
||||||
}
|
}
|
||||||
|
|
@ -172,7 +170,7 @@ func newContext() *_runtime {
|
||||||
|
|
||||||
self.Global.Function = self.newGlobalFunction(
|
self.Global.Function = self.newGlobalFunction(
|
||||||
1,
|
1,
|
||||||
builtinFunction,
|
"Function", builtinFunction,
|
||||||
builtinNewFunction,
|
builtinNewFunction,
|
||||||
self.Global.FunctionPrototype,
|
self.Global.FunctionPrototype,
|
||||||
"toString", func(FunctionCall) Value {
|
"toString", func(FunctionCall) Value {
|
||||||
|
|
@ -184,16 +182,16 @@ func newContext() *_runtime {
|
||||||
|
|
||||||
self.Global.Array = self.newGlobalFunction(
|
self.Global.Array = self.newGlobalFunction(
|
||||||
1,
|
1,
|
||||||
builtinArray,
|
"Array", builtinArray,
|
||||||
builtinNewArray,
|
builtinNewArray,
|
||||||
self.Global.ArrayPrototype,
|
self.Global.ArrayPrototype,
|
||||||
"toString", func(call FunctionCall) Value {
|
"toString", func(call FunctionCall) Value {
|
||||||
thisObject := call.thisObject()
|
thisObject := call.thisObject()
|
||||||
join := thisObject.Get("join")
|
join := thisObject.get("join")
|
||||||
if join.isCallable() {
|
if join.isCallable() {
|
||||||
join := join._object()
|
join := join._object()
|
||||||
if join.Function.Call.Signature() == "builtin" {
|
if join._Function.Call.name() == "nativeArray_join" {
|
||||||
if stash, isArray := thisObject._propertyStash.(*_arrayStash); isArray {
|
if stash, isArray := thisObject.stash.(*_arrayStash); isArray {
|
||||||
return toValue(builtinArray_joinNative(stash.valueArray, ","))
|
return toValue(builtinArray_joinNative(stash.valueArray, ","))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -215,14 +213,14 @@ func newContext() *_runtime {
|
||||||
|
|
||||||
self.Global.String = self.newGlobalFunction(
|
self.Global.String = self.newGlobalFunction(
|
||||||
1,
|
1,
|
||||||
builtinString,
|
"String", builtinString,
|
||||||
builtinNewString,
|
builtinNewString,
|
||||||
self.Global.StringPrototype,
|
self.Global.StringPrototype,
|
||||||
"toString", func(call FunctionCall) Value {
|
"toString", func(call FunctionCall) Value {
|
||||||
return *call.thisClassObject("String").Primitive
|
return *call.thisClassObject("String").primitive
|
||||||
},
|
},
|
||||||
"valueOf", func(call FunctionCall) Value {
|
"valueOf", func(call FunctionCall) Value {
|
||||||
return *call.thisClassObject("String").Primitive
|
return *call.thisClassObject("String").primitive
|
||||||
},
|
},
|
||||||
"charAt", 1, builtinString_charAt,
|
"charAt", 1, builtinString_charAt,
|
||||||
"charCodeAt", 1, builtinString_charCodeAt,
|
"charCodeAt", 1, builtinString_charCodeAt,
|
||||||
|
|
@ -240,27 +238,27 @@ func newContext() *_runtime {
|
||||||
"substr", 2, builtinString_substr,
|
"substr", 2, builtinString_substr,
|
||||||
)
|
)
|
||||||
// TODO Maybe streamline this redundancy?
|
// TODO Maybe streamline this redundancy?
|
||||||
self.Global.String.Define(
|
self.Global.String.write(
|
||||||
"fromCharCode", 1, builtinString_fromCharCode,
|
"fromCharCode", 1, builtinString_fromCharCode,
|
||||||
)
|
)
|
||||||
|
|
||||||
self.Global.Boolean = self.newGlobalFunction(
|
self.Global.Boolean = self.newGlobalFunction(
|
||||||
1,
|
1,
|
||||||
builtinBoolean,
|
"Boolean", builtinBoolean,
|
||||||
builtinNewBoolean,
|
builtinNewBoolean,
|
||||||
self.Global.BooleanPrototype,
|
self.Global.BooleanPrototype,
|
||||||
"toString", func(call FunctionCall) Value {
|
"toString", func(call FunctionCall) Value {
|
||||||
value := call.This
|
value := call.This
|
||||||
if !value.IsBoolean() {
|
if !value.IsBoolean() {
|
||||||
// Will throw a TypeError if ThisObject is not a Boolean
|
// Will throw a TypeError if ThisObject is not a Boolean
|
||||||
value = call.thisClassObject("Boolean").PrimitiveValue()
|
value = call.thisClassObject("Boolean").primitiveValue()
|
||||||
}
|
}
|
||||||
return toValue(toString(value))
|
return toValue(toString(value))
|
||||||
},
|
},
|
||||||
"valueOf", func(call FunctionCall) Value {
|
"valueOf", func(call FunctionCall) Value {
|
||||||
value := call.This
|
value := call.This
|
||||||
if !value.IsBoolean() {
|
if !value.IsBoolean() {
|
||||||
value = call.thisClassObject("Boolean").PrimitiveValue()
|
value = call.thisClassObject("Boolean").primitiveValue()
|
||||||
}
|
}
|
||||||
return value
|
return value
|
||||||
},
|
},
|
||||||
|
|
@ -268,18 +266,18 @@ func newContext() *_runtime {
|
||||||
|
|
||||||
self.Global.Number = self.newGlobalFunction(
|
self.Global.Number = self.newGlobalFunction(
|
||||||
1,
|
1,
|
||||||
builtinNumber,
|
"Number", builtinNumber,
|
||||||
builtinNewNumber,
|
builtinNewNumber,
|
||||||
self.Global.NumberPrototype,
|
self.Global.NumberPrototype,
|
||||||
"valueOf", func(call FunctionCall) Value {
|
"valueOf", func(call FunctionCall) Value {
|
||||||
return *call.thisClassObject("Number").Primitive
|
return *call.thisClassObject("Number").primitive
|
||||||
},
|
},
|
||||||
// TODO toFixed
|
// TODO toFixed
|
||||||
// TODO toExponential
|
// TODO toExponential
|
||||||
// TODO toPrecision
|
// TODO toPrecision
|
||||||
)
|
)
|
||||||
|
|
||||||
self.Global.Number.Define(
|
self.Global.Number.write(
|
||||||
_propertyMode(0),
|
_propertyMode(0),
|
||||||
"MAX_VALUE", toValue(math.MaxFloat64),
|
"MAX_VALUE", toValue(math.MaxFloat64),
|
||||||
"MIN_VALUE", toValue(math.SmallestNonzeroFloat64),
|
"MIN_VALUE", toValue(math.SmallestNonzeroFloat64),
|
||||||
|
|
@ -300,7 +298,7 @@ func newContext() *_runtime {
|
||||||
|
|
||||||
self.Global.Date = self.newGlobalFunction(
|
self.Global.Date = self.newGlobalFunction(
|
||||||
7,
|
7,
|
||||||
builtinDate,
|
"Date", builtinDate,
|
||||||
builtinNewDate,
|
builtinNewDate,
|
||||||
self.Global.DatePrototype,
|
self.Global.DatePrototype,
|
||||||
"toString", 0, builtinDate_toString,
|
"toString", 0, builtinDate_toString,
|
||||||
|
|
@ -584,7 +582,7 @@ func newContext() *_runtime {
|
||||||
|
|
||||||
self.Global.RegExp = self.newGlobalFunction(
|
self.Global.RegExp = self.newGlobalFunction(
|
||||||
2,
|
2,
|
||||||
builtinRegExp,
|
"RegExp", builtinRegExp,
|
||||||
builtinNewRegExp,
|
builtinNewRegExp,
|
||||||
self.Global.RegExpPrototype,
|
self.Global.RegExpPrototype,
|
||||||
"toString", 0, builtinRegExp_toString,
|
"toString", 0, builtinRegExp_toString,
|
||||||
|
|
@ -594,14 +592,14 @@ func newContext() *_runtime {
|
||||||
|
|
||||||
self.Global.Error = self.newGlobalFunction(
|
self.Global.Error = self.newGlobalFunction(
|
||||||
1,
|
1,
|
||||||
builtinError,
|
"Error", builtinError,
|
||||||
builtinNewError,
|
builtinNewError,
|
||||||
self.Global.ErrorPrototype,
|
self.Global.ErrorPrototype,
|
||||||
"name", toValue("Error"),
|
"name", toValue("Error"),
|
||||||
"toString", 0, builtinError_toString,
|
"toString", 0, builtinError_toString,
|
||||||
)
|
)
|
||||||
|
|
||||||
self.GlobalObject.Define(
|
self.GlobalObject.write(
|
||||||
"Object", toValue(self.Global.Object),
|
"Object", toValue(self.Global.Object),
|
||||||
"Function", toValue(self.Global.Function),
|
"Function", toValue(self.Global.Function),
|
||||||
"Array", toValue(self.Global.Array),
|
"Array", toValue(self.Global.Array),
|
||||||
|
|
@ -651,37 +649,37 @@ func (runtime *_runtime) newClassObject(class string) *_object {
|
||||||
|
|
||||||
func (runtime *_runtime) newPrimitiveObject(class string, value Value) *_object {
|
func (runtime *_runtime) newPrimitiveObject(class string, value Value) *_object {
|
||||||
self := runtime.newClassObject(class)
|
self := runtime.newClassObject(class)
|
||||||
self.Primitive = &value
|
self.primitive = &value
|
||||||
return self
|
return self
|
||||||
}
|
}
|
||||||
|
|
||||||
func (runtime *_runtime) newObject() *_object {
|
func (runtime *_runtime) newObject() *_object {
|
||||||
self := runtime.newClassObject("Object")
|
self := runtime.newClassObject("Object")
|
||||||
self.Prototype = runtime.Global.ObjectPrototype
|
self.prototype = runtime.Global.ObjectPrototype
|
||||||
return self
|
return self
|
||||||
}
|
}
|
||||||
|
|
||||||
func (runtime *_runtime) newArray(valueArray []Value) *_object {
|
func (runtime *_runtime) newArray(valueArray []Value) *_object {
|
||||||
self := runtime.newArrayObject(valueArray)
|
self := runtime.newArrayObject(valueArray)
|
||||||
self.Prototype = runtime.Global.ArrayPrototype
|
self.prototype = runtime.Global.ArrayPrototype
|
||||||
return self
|
return self
|
||||||
}
|
}
|
||||||
|
|
||||||
func (runtime *_runtime) newString(value Value) *_object {
|
func (runtime *_runtime) newString(value Value) *_object {
|
||||||
self := runtime.newStringObject(value)
|
self := runtime.newStringObject(value)
|
||||||
self.Prototype = runtime.Global.StringPrototype
|
self.prototype = runtime.Global.StringPrototype
|
||||||
return self
|
return self
|
||||||
}
|
}
|
||||||
|
|
||||||
func (runtime *_runtime) newBoolean(value Value) *_object {
|
func (runtime *_runtime) newBoolean(value Value) *_object {
|
||||||
self := runtime.newBooleanObject(value)
|
self := runtime.newBooleanObject(value)
|
||||||
self.Prototype = runtime.Global.BooleanPrototype
|
self.prototype = runtime.Global.BooleanPrototype
|
||||||
return self
|
return self
|
||||||
}
|
}
|
||||||
|
|
||||||
func (runtime *_runtime) newNumber(value Value) *_object {
|
func (runtime *_runtime) newNumber(value Value) *_object {
|
||||||
self := runtime.newNumberObject(value)
|
self := runtime.newNumberObject(value)
|
||||||
self.Prototype = runtime.Global.NumberPrototype
|
self.prototype = runtime.Global.NumberPrototype
|
||||||
return self
|
return self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -699,14 +697,14 @@ func (runtime *_runtime) newRegExp(patternValue Value, flagsValue Value) *_objec
|
||||||
|
|
||||||
func (runtime *_runtime) _newRegExp(pattern string, flags string) *_object {
|
func (runtime *_runtime) _newRegExp(pattern string, flags string) *_object {
|
||||||
self := runtime.newRegExpObject(pattern, flags)
|
self := runtime.newRegExpObject(pattern, flags)
|
||||||
self.Prototype = runtime.Global.RegExpPrototype
|
self.prototype = runtime.Global.RegExpPrototype
|
||||||
return self
|
return self
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO Should (probably) be one argument, right? This is redundant
|
// TODO Should (probably) be one argument, right? This is redundant
|
||||||
func (runtime *_runtime) newDate(epoch float64) *_object {
|
func (runtime *_runtime) newDate(epoch float64) *_object {
|
||||||
self := runtime.newDateObject(epoch)
|
self := runtime.newDateObject(epoch)
|
||||||
self.Prototype = runtime.Global.DatePrototype
|
self.prototype = runtime.Global.DatePrototype
|
||||||
return self
|
return self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -717,43 +715,37 @@ func (runtime *_runtime) newError(name string, message Value) *_object {
|
||||||
self = _newError(message)
|
self = _newError(message)
|
||||||
} else {
|
} else {
|
||||||
self = runtime.newErrorObject(message)
|
self = runtime.newErrorObject(message)
|
||||||
self.Prototype = runtime.Global.ErrorPrototype
|
self.prototype = runtime.Global.ErrorPrototype
|
||||||
if name != "" {
|
if name != "" {
|
||||||
self.WriteValue("name", toValue(name), false)
|
self.set("name", toValue(name), false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return self
|
return self
|
||||||
}
|
}
|
||||||
|
|
||||||
func (runtime *_runtime) newNativeFunction(_nativeFunction _nativeFunction, length int) *_object {
|
func (runtime *_runtime) newNativeFunction(_nativeFunction _nativeFunction, length int, name string) *_object {
|
||||||
self := runtime.newNativeFunctionObject(_nativeFunction, length)
|
self := runtime.newNativeFunctionObject(_nativeFunction, length, name)
|
||||||
self.Prototype = runtime.Global.FunctionPrototype
|
self.prototype = runtime.Global.FunctionPrototype
|
||||||
prototype := runtime.newObject()
|
prototype := runtime.newObject()
|
||||||
self.define(_propertyMode(0), "prototype", toValue(prototype))
|
self.stash.set("prototype", toValue(prototype), _propertyMode(0100))
|
||||||
prototype.define(
|
prototype.stash.set("constructor", toValue(self), _propertyMode(0101))
|
||||||
_propertyMode(propertyModeWrite | propertyModeConfigure),
|
|
||||||
"constructor", toValue(self),
|
|
||||||
)
|
|
||||||
return self
|
return self
|
||||||
}
|
}
|
||||||
|
|
||||||
func (runtime *_runtime) newNodeFunction(node *_functionNode, scopeEnvironment _environment) *_object {
|
func (runtime *_runtime) newNodeFunction(node *_functionNode, scopeEnvironment _environment) *_object {
|
||||||
// TODO Implement 13.2 fully
|
// TODO Implement 13.2 fully
|
||||||
self := runtime.newNodeFunctionObject(node, scopeEnvironment)
|
self := runtime.newNodeFunctionObject(node, scopeEnvironment)
|
||||||
self.Prototype = runtime.Global.FunctionPrototype
|
self.prototype = runtime.Global.FunctionPrototype
|
||||||
prototype := runtime.newObject()
|
prototype := runtime.newObject()
|
||||||
self.define(_propertyMode(propertyModeWrite), "prototype", toValue(prototype))
|
self.stash.set("prototype", toValue(prototype), _propertyMode(0100))
|
||||||
prototype.define(
|
prototype.stash.set("constructor", toValue(self), _propertyMode(0101))
|
||||||
_propertyMode(propertyModeWrite | propertyModeConfigure),
|
|
||||||
"constructor", toValue(self),
|
|
||||||
)
|
|
||||||
return self
|
return self
|
||||||
}
|
}
|
||||||
|
|
||||||
func (runtime *_runtime) newErrorPrototype(name string) *_object {
|
func (runtime *_runtime) newErrorPrototype(name string) *_object {
|
||||||
prototype := runtime.newClassObject("Error")
|
prototype := runtime.newClassObject("Error")
|
||||||
prototype.WriteValue("name", toValue(name), false)
|
prototype.set("name", toValue(name), false)
|
||||||
prototype.Prototype = runtime.Global.ErrorPrototype
|
prototype.prototype = runtime.Global.ErrorPrototype
|
||||||
return prototype
|
return prototype
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -762,13 +754,14 @@ func (runtime *_runtime) defineError(name string) func(Value) *_object {
|
||||||
|
|
||||||
errorFunction := func(message Value) *_object {
|
errorFunction := func(message Value) *_object {
|
||||||
error := runtime.newErrorObject(message)
|
error := runtime.newErrorObject(message)
|
||||||
error.Prototype = prototype
|
error.prototype = prototype
|
||||||
return error
|
return error
|
||||||
}
|
}
|
||||||
|
|
||||||
runtime.GlobalObject.WriteValue(name, toValue(runtime.newGlobalFunction(
|
runtime.GlobalObject.set(name, toValue(runtime.newGlobalFunction(
|
||||||
1,
|
1,
|
||||||
// e.g. TypeError( ... )
|
// e.g. TypeError( ... )
|
||||||
|
name,
|
||||||
func (call FunctionCall) Value { // TypeError( ... )
|
func (call FunctionCall) Value { // TypeError( ... )
|
||||||
return toValue(errorFunction(call.Argument(0)))
|
return toValue(errorFunction(call.Argument(0)))
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -17,21 +17,21 @@ func TestGlobal(t *testing.T) {
|
||||||
result := runtime.localGet("Object")._object().Call(UndefinedValue(), []Value{toValue(runtime.newObject())})
|
result := runtime.localGet("Object")._object().Call(UndefinedValue(), []Value{toValue(runtime.newObject())})
|
||||||
Is(result.IsObject(), true)
|
Is(result.IsObject(), true)
|
||||||
Is(result, "[object Object]")
|
Is(result, "[object Object]")
|
||||||
Is(result._object().Prototype == runtime.Global.ObjectPrototype, true)
|
Is(result._object().prototype == runtime.Global.ObjectPrototype, true)
|
||||||
Is(result._object().Prototype == runtime.Global.Object.Get("prototype")._object(), true)
|
Is(result._object().prototype == runtime.Global.Object.get("prototype")._object(), true)
|
||||||
Is(runtime.newObject().Prototype == runtime.Global.Object.Get("prototype")._object(), true)
|
Is(runtime.newObject().prototype == runtime.Global.Object.get("prototype")._object(), true)
|
||||||
Is(result._object().Get("toString"), "[function]")
|
Is(result._object().get("toString"), "[function]")
|
||||||
//Is(result.Object().CallMethod("hasOwnProperty", "hasOwnProperty"), falseValue)
|
//Is(result.Object().CallMethod("hasOwnProperty", "hasOwnProperty"), falseValue)
|
||||||
//Is(result.Object().Get("toString").Object().Prototype.CallMethod("toString"), "[function]")
|
//Is(result.Object().get("toString").Object().prototype.CallMethod("toString"), "[function]")
|
||||||
//Is(result.Object().Get("toString").Object().Get("toString").Object(), "[function]")
|
//Is(result.Object().get("toString").Object().get("toString").Object(), "[function]")
|
||||||
//Is(result.Object().Get("toString").Object().Get("toString"), "[function]")
|
//Is(result.Object().get("toString").Object().get("toString"), "[function]")
|
||||||
//Is(runtime.localGet("Object").Object().CallMethod("isPrototypeOf", result), falseValue)
|
//Is(runtime.localGet("Object").Object().CallMethod("isPrototypeOf", result), falseValue)
|
||||||
//Is(runtime.localGet("Object").Object().Get("prototype").Object().CallMethod("isPrototypeOf", result), trueValue)
|
//Is(runtime.localGet("Object").Object().get("prototype").Object().CallMethod("isPrototypeOf", result), trueValue)
|
||||||
//Is(runtime.localGet("Function").Object().CallMethod("isPrototypeOf", result), falseValue)
|
//Is(runtime.localGet("Function").Object().CallMethod("isPrototypeOf", result), falseValue)
|
||||||
//Is(result.Object().CallMethod("propertyIsEnumerable", "isPrototypeOf"), falseValue)
|
//Is(result.Object().CallMethod("propertyIsEnumerable", "isPrototypeOf"), falseValue)
|
||||||
//result.Object().WriteValue("xyzzy", toValue("Nothing happens."), false)
|
//result.Object().WriteValue("xyzzy", toValue("Nothing happens."), false)
|
||||||
//Is(result.Object().CallMethod("propertyIsEnumerable", "xyzzy"), trueValue)
|
//Is(result.Object().CallMethod("propertyIsEnumerable", "xyzzy"), trueValue)
|
||||||
//Is(result.Object().Get("xyzzy"), "Nothing happens.")
|
//Is(result.Object().get("xyzzy"), "Nothing happens.")
|
||||||
|
|
||||||
abc := runtime.newBoolean(TrueValue())
|
abc := runtime.newBoolean(TrueValue())
|
||||||
Is(abc, "true")
|
Is(abc, "true")
|
||||||
|
|
|
||||||
296
object.go
296
object.go
|
|
@ -3,70 +3,55 @@ package otto
|
||||||
type _object struct {
|
type _object struct {
|
||||||
runtime *_runtime
|
runtime *_runtime
|
||||||
|
|
||||||
Class string
|
class string
|
||||||
Extensible bool
|
prototype *_object
|
||||||
Prototype *_object
|
|
||||||
|
|
||||||
_propertyStash _stash
|
stash _stash
|
||||||
|
|
||||||
Primitive *Value
|
primitive *Value
|
||||||
Function *_functionObject
|
_Function *_functionObject
|
||||||
RegExp *_regExpObject
|
_RegExp *_regExpObject
|
||||||
Date *_dateObject
|
_Date *_dateObject
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self _object) PrimitiveValue() Value {
|
func (self _object) extensible() bool {
|
||||||
return *self.Primitive
|
return self.stash.extensible()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (self _object) primitiveValue() Value {
|
||||||
|
return *self.primitive
|
||||||
}
|
}
|
||||||
|
|
||||||
func newObject(runtime *_runtime, class string) *_object {
|
func newObject(runtime *_runtime, class string) *_object {
|
||||||
return &_object{
|
return &_object{
|
||||||
runtime: runtime,
|
runtime: runtime,
|
||||||
|
|
||||||
Class: class,
|
class: class,
|
||||||
Extensible: true,
|
|
||||||
|
|
||||||
_propertyStash: newPropertyStash(true),
|
stash: newObjectStash(true),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Write
|
|
||||||
|
|
||||||
func (self *_object) WriteValue(name string, value Value, throw bool) {
|
|
||||||
canWrite := self._propertyStash.CanWrite(name)
|
|
||||||
if !canWrite {
|
|
||||||
typeErrorResult(throw)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
self._propertyStash.Write(name, value)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Delete
|
// Delete
|
||||||
|
|
||||||
func (self *_object) Delete(name string, throw bool) bool {
|
func (self *_object) delete(name string, throw bool) bool {
|
||||||
property_ := self.GetOwnProperty(name)
|
property_ := self.getOwnProperty(name)
|
||||||
if property_ == nil {
|
if property_ == nil {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
if property_.CanConfigure() {
|
if property_.CanConfigure() {
|
||||||
self._propertyStash.Delete(name)
|
self.stash.delete(name)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
return typeErrorResult(throw)
|
return typeErrorResult(throw)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get
|
|
||||||
|
|
||||||
func (self *_object) GetValue(name string) Value {
|
|
||||||
return self.Get(name)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 8.12
|
// 8.12
|
||||||
|
|
||||||
// 8.12.1
|
// 8.12.1
|
||||||
func (self *_object) GetOwnProperty(name string) *_property {
|
func (self *_object) getOwnProperty(name string) *_property {
|
||||||
// Return a _copy_ of the property
|
// Return a _copy_ of the property
|
||||||
property := self._propertyStash.property(name)
|
property := self.stash.property(name)
|
||||||
if property == nil {
|
if property == nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
@ -76,10 +61,11 @@ func (self *_object) GetOwnProperty(name string) *_property {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 8.12.2
|
||||||
func (self *_object) getProperty(name string) *_property {
|
func (self *_object) getProperty(name string) *_property {
|
||||||
|
for object := self; object != nil; object = object.prototype {
|
||||||
for object := self; object != nil; object = object.Prototype {
|
// Despite being a pointer, this property is always a copy
|
||||||
property := object._propertyStash.property(name)
|
property := object.stash.property(name)
|
||||||
if property != nil {
|
if property != nil {
|
||||||
return property
|
return property
|
||||||
}
|
}
|
||||||
|
|
@ -88,31 +74,22 @@ func (self *_object) getProperty(name string) *_property {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// 8.12.2
|
|
||||||
func (self *_object) GetProperty(name string) *_property {
|
|
||||||
property := self.getProperty(name)
|
|
||||||
if property != nil {
|
|
||||||
property = property.Copy()
|
|
||||||
}
|
|
||||||
return property
|
|
||||||
}
|
|
||||||
|
|
||||||
// 8.12.3
|
// 8.12.3
|
||||||
func (self *_object) Get(name string) Value {
|
func (self *_object) get(name string) Value {
|
||||||
object := self
|
object := self
|
||||||
for object != nil {
|
for object != nil {
|
||||||
if object._propertyStash.CanRead(name) {
|
if object.stash.test(name) {
|
||||||
return object._propertyStash.Read(name)
|
return object.stash.get(name)
|
||||||
}
|
}
|
||||||
object = object.Prototype
|
object = object.prototype
|
||||||
}
|
}
|
||||||
return UndefinedValue()
|
return UndefinedValue()
|
||||||
}
|
}
|
||||||
|
|
||||||
// 8.12.4
|
// 8.12.4
|
||||||
func (self *_object) CanPut(name string) bool {
|
func (self *_object) canPut(name string) bool {
|
||||||
|
|
||||||
property := self._propertyStash.property(name)
|
property := self.stash.property(name)
|
||||||
if property != nil {
|
if property != nil {
|
||||||
switch value := property.Value.(type) {
|
switch value := property.Value.(type) {
|
||||||
case Value:
|
case Value:
|
||||||
|
|
@ -124,16 +101,16 @@ func (self *_object) CanPut(name string) bool {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if self.Prototype != nil {
|
if self.prototype != nil {
|
||||||
property = self.Prototype.getProperty(name)
|
property = self.prototype.getProperty(name)
|
||||||
}
|
}
|
||||||
if property == nil {
|
if property == nil {
|
||||||
return self.Extensible
|
return self.extensible()
|
||||||
}
|
}
|
||||||
|
|
||||||
switch value := property.Value.(type) {
|
switch value := property.Value.(type) {
|
||||||
case Value:
|
case Value:
|
||||||
if !self.Extensible {
|
if !self.extensible() {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
return property.CanWrite()
|
return property.CanWrite()
|
||||||
|
|
@ -145,18 +122,27 @@ func (self *_object) CanPut(name string) bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
// 8.12.5
|
// 8.12.5
|
||||||
func (self *_object) Put(name string, value Value, throw bool) {
|
func (self *_object) put(name string, value Value, throw bool) {
|
||||||
if !self.CanPut(name) {
|
if !self.canPut(name) {
|
||||||
typeErrorResult(throw)
|
typeErrorResult(throw)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
self._propertyStash.Write(name, value)
|
self.stash.put(name, value)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Like put, but bypass checking of prototype property presence
|
||||||
|
func (self *_object) set(name string, value Value, throw bool) {
|
||||||
|
if !self.stash.canPut(name) {
|
||||||
|
typeErrorResult(throw)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
self.stash.put(name, value)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 8.12.6
|
// 8.12.6
|
||||||
func (self *_object) HasProperty(name string) bool {
|
func (self *_object) hasProperty(name string) bool {
|
||||||
for object := self; object != nil; object = object.Prototype {
|
for object := self; object != nil; object = object.prototype {
|
||||||
if object._propertyStash.CanRead(name) {
|
if object.stash.test(name) {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -167,29 +153,29 @@ func (self *_object) HasProperty(name string) bool {
|
||||||
type _defaultValueHint int
|
type _defaultValueHint int
|
||||||
|
|
||||||
const (
|
const (
|
||||||
defaultValueNoHint _defaultValueHint = iota
|
defaultValueNoHint _defaultValueHint = iota
|
||||||
defaultValueHintString
|
defaultValueHintString
|
||||||
defaultValueHintNumber
|
defaultValueHintNumber
|
||||||
)
|
)
|
||||||
|
|
||||||
// 8.12.8
|
// 8.12.8
|
||||||
func (self *_object) DefaultValue(hint _defaultValueHint) Value {
|
func (self *_object) DefaultValue(hint _defaultValueHint) Value {
|
||||||
if hint == defaultValueNoHint {
|
if hint == defaultValueNoHint {
|
||||||
hint = defaultValueHintNumber
|
hint = defaultValueHintNumber
|
||||||
}
|
}
|
||||||
methodSequence := []string{"valueOf", "toString"}
|
methodSequence := []string{"valueOf", "toString"}
|
||||||
if (hint == defaultValueHintString) {
|
if hint == defaultValueHintString {
|
||||||
methodSequence = []string{"toString", "valueOf"}
|
methodSequence = []string{"toString", "valueOf"}
|
||||||
}
|
}
|
||||||
for _, methodName := range methodSequence {
|
for _, methodName := range methodSequence {
|
||||||
method := self.Get(methodName)
|
method := self.get(methodName)
|
||||||
if method.isCallable() {
|
if method.isCallable() {
|
||||||
result := method._object().Call(toValue(self))
|
result := method._object().Call(toValue(self))
|
||||||
if result.IsPrimitive() {
|
if result.IsPrimitive() {
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
panic(newTypeError())
|
panic(newTypeError())
|
||||||
return UndefinedValue()
|
return UndefinedValue()
|
||||||
|
|
@ -200,105 +186,93 @@ func (self *_object) String() string {
|
||||||
}
|
}
|
||||||
|
|
||||||
// 8.12.9
|
// 8.12.9
|
||||||
func (self *_object) DefineOwnProperty(name string, _defineProperty _defineProperty, throw bool) bool {
|
func (self *_object) defineOwnProperty(name string, _defineProperty _defineProperty, throw bool) bool {
|
||||||
return self._propertyStash.Define(name, _defineProperty)
|
return self.stash.define(name, _defineProperty)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *_object) DefineOwnValueProperty(name string, value Value, mode _propertyMode, throw bool) bool {
|
func (self *_object) hasOwnProperty(name string) bool {
|
||||||
return self._propertyStash.Define(name, _property{Value: value, Mode: mode}.toDefineProperty())
|
return self.stash.test(name)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *_object) HasOwnProperty(name string) bool {
|
//func (self *_object) Define(definition... interface{}) {
|
||||||
return self._propertyStash.CanRead(name)
|
// property_ := _property{ Mode: 0111 }.toDefineProperty()
|
||||||
}
|
// length := 0
|
||||||
|
// nativeClass_ := "native" + self.Class + "_"
|
||||||
|
|
||||||
func (self *_object) Define(nameAndValue... interface{}) {
|
// for index := 0; index < len(definition); index++ {
|
||||||
property_ := _property{Mode: propertyModeWriteEnumerateConfigure}.toDefineProperty()
|
// value := definition[index]
|
||||||
|
// switch value := value.(type) {
|
||||||
|
// case _propertyMode:
|
||||||
|
// property_ = _property{Mode: value}.toDefineProperty()
|
||||||
|
// case string:
|
||||||
|
// name := value
|
||||||
|
// length = 0
|
||||||
|
// index += 1
|
||||||
|
//REPEAT: {
|
||||||
|
// value := definition[index]
|
||||||
|
// switch value := value.(type) {
|
||||||
|
// case func(FunctionCall) Value: {
|
||||||
|
// value := self.runtime.newNativeFunction(value, length, nativeClass_ + name)
|
||||||
|
// property_.Value = toValue(value)
|
||||||
|
// self.DefineOwnProperty(name, property_, false)
|
||||||
|
// }
|
||||||
|
// case *_object:
|
||||||
|
// property_.Value = toValue(value)
|
||||||
|
// self.DefineOwnProperty(name, property_, false)
|
||||||
|
// case Value:
|
||||||
|
// property_.Value = value
|
||||||
|
// self.DefineOwnProperty(name, property_, false)
|
||||||
|
// case int:
|
||||||
|
// length = value
|
||||||
|
// index += 1
|
||||||
|
// goto REPEAT
|
||||||
|
// default:
|
||||||
|
// panic(hereBeDragons())
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//}
|
||||||
|
|
||||||
|
func (self *_object) write(definition ...interface{}) {
|
||||||
|
mode := _propertyMode(0111)
|
||||||
length := 0
|
length := 0
|
||||||
signature := _functionSignature("")
|
nativeClass_ := "native" + self.class + "_"
|
||||||
|
|
||||||
for index := 0; index < len(nameAndValue); index++ {
|
for index := 0; index < len(definition); index++ {
|
||||||
value := nameAndValue[index]
|
value := definition[index]
|
||||||
switch value := value.(type) {
|
switch value := value.(type) {
|
||||||
case _functionSignature:
|
|
||||||
signature = value
|
|
||||||
case _propertyMode:
|
|
||||||
property_ = _property{Mode: value}.toDefineProperty()
|
|
||||||
case string:
|
|
||||||
name := value
|
|
||||||
length = 0
|
|
||||||
index += 1
|
|
||||||
REPEAT: {
|
|
||||||
value := nameAndValue[index]
|
|
||||||
switch value := value.(type) {
|
|
||||||
case func(FunctionCall) Value: {
|
|
||||||
value := self.runtime.newNativeFunction(value, length)
|
|
||||||
value.Function.Call.Sign(signature)
|
|
||||||
property_.Value = toValue(value)
|
|
||||||
self.DefineOwnProperty(name, property_, false)
|
|
||||||
}
|
|
||||||
case *_object:
|
|
||||||
property_.Value = toValue(value)
|
|
||||||
self.DefineOwnProperty(name, property_, false)
|
|
||||||
case Value:
|
|
||||||
property_.Value = value
|
|
||||||
self.DefineOwnProperty(name, property_, false)
|
|
||||||
case int:
|
|
||||||
length = value
|
|
||||||
index += 1
|
|
||||||
goto REPEAT
|
|
||||||
default:
|
|
||||||
panic(hereBeDragons())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (self *_object) define(nameAndValue... interface{}) {
|
|
||||||
mode := propertyModeWriteEnumerateConfigure
|
|
||||||
length := 0
|
|
||||||
signature := _functionSignature("")
|
|
||||||
|
|
||||||
stash := map[string]_valueProperty{}
|
|
||||||
|
|
||||||
for index := 0; index < len(nameAndValue); index++ {
|
|
||||||
value := nameAndValue[index]
|
|
||||||
switch value := value.(type) {
|
|
||||||
case _functionSignature:
|
|
||||||
signature = value
|
|
||||||
case _propertyMode:
|
case _propertyMode:
|
||||||
mode = value
|
mode = value
|
||||||
case string:
|
case string:
|
||||||
name := value
|
name := value
|
||||||
length = 0
|
length = 0
|
||||||
index += 1
|
index += 1
|
||||||
REPEAT: {
|
REPEAT:
|
||||||
value := nameAndValue[index]
|
{
|
||||||
|
value := definition[index]
|
||||||
switch value := value.(type) {
|
switch value := value.(type) {
|
||||||
case func(FunctionCall) Value: {
|
case func(FunctionCall) Value:
|
||||||
value := self.runtime.newNativeFunction(value, length)
|
{
|
||||||
value.Function.Call.Sign(signature)
|
value := self.runtime.newNativeFunction(value, length, nativeClass_+name)
|
||||||
stash[name] = _valueProperty{ toValue(value), mode }
|
self.stash.set(name, toValue(value), mode)
|
||||||
}
|
}
|
||||||
case *_object:
|
case *_object:
|
||||||
stash[name] = _valueProperty{ toValue(value), mode }
|
self.stash.set(name, toValue(value), mode)
|
||||||
case Value:
|
case Value:
|
||||||
stash[name] = _valueProperty{ value, mode }
|
self.stash.set(name, value, mode)
|
||||||
case int:
|
case int:
|
||||||
length = value
|
length = value
|
||||||
index += 1
|
index += 1
|
||||||
goto REPEAT
|
goto REPEAT
|
||||||
default:
|
default:
|
||||||
panic(hereBeDragons())
|
panic(hereBeDragons())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
self._propertyStash.writeValuePropertyMap(stash)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *_object) Enumerate(each func(string)) {
|
func (self *_object) enumerate(each func(string)) {
|
||||||
self._propertyStash.Enumerate(each)
|
self.stash.enumerate(each)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -11,15 +11,15 @@ func TestObject_(t *testing.T) {
|
||||||
object := newObject(nil, "")
|
object := newObject(nil, "")
|
||||||
IsTrue(object != nil)
|
IsTrue(object != nil)
|
||||||
|
|
||||||
object.Put("xyzzy", toValue("Nothing happens."), true)
|
object.put("xyzzy", toValue("Nothing happens."), true)
|
||||||
Is(object.Get("xyzzy"), "Nothing happens.")
|
Is(object.get("xyzzy"), "Nothing happens.")
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestStringObject(t *testing.T) {
|
func TestStringObject(t *testing.T) {
|
||||||
Terst(t)
|
Terst(t)
|
||||||
|
|
||||||
object := New().runtime.newStringObject(toValue("xyzzy"))
|
object := New().runtime.newStringObject(toValue("xyzzy"))
|
||||||
Is(object.Get("1"), "y")
|
Is(object.get("1"), "y")
|
||||||
Is(object.Get("10"), "undefined")
|
Is(object.get("10"), "undefined")
|
||||||
Is(object.Get("2"), "z")
|
Is(object.get("2"), "z")
|
||||||
}
|
}
|
||||||
|
|
|
||||||
6
otto.go
6
otto.go
|
|
@ -289,7 +289,7 @@ func (self Object) Value() Value {
|
||||||
func (self Object) Get(name string) (Value, error) {
|
func (self Object) Get(name string) (Value, error) {
|
||||||
result := UndefinedValue()
|
result := UndefinedValue()
|
||||||
err := catchPanic(func(){
|
err := catchPanic(func(){
|
||||||
result = self.object.Get(name)
|
result = self.object.get(name)
|
||||||
})
|
})
|
||||||
return result, err
|
return result, err
|
||||||
}
|
}
|
||||||
|
|
@ -300,7 +300,7 @@ func (self Object) Get(name string) (Value, error) {
|
||||||
// or there is an error during conversion of the given value.
|
// or there is an error during conversion of the given value.
|
||||||
func (self Object) Set(name string, value interface{}) (error) {
|
func (self Object) Set(name string, value interface{}) (error) {
|
||||||
err := catchPanic(func(){
|
err := catchPanic(func(){
|
||||||
self.object.Put(name, self.object.runtime.toValue(value), true)
|
self.object.put(name, self.object.runtime.toValue(value), true)
|
||||||
})
|
})
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
@ -319,5 +319,5 @@ func (self Object) Set(name string, value interface{}) (error) {
|
||||||
// RegExp
|
// RegExp
|
||||||
//
|
//
|
||||||
func (self Object) Class() string {
|
func (self Object) Class() string {
|
||||||
return self.object.Class
|
return self.object.class
|
||||||
}
|
}
|
||||||
|
|
|
||||||
18
otto_test.go
18
otto_test.go
|
|
@ -948,7 +948,7 @@ func TestObjectLiteral(t *testing.T) {
|
||||||
Otto.Run(`
|
Otto.Run(`
|
||||||
result = { xyzzy: "Nothing happens.", 0: 1 }
|
result = { xyzzy: "Nothing happens.", 0: 1 }
|
||||||
`)
|
`)
|
||||||
Is(Otto.getValue("result")._object().GetValue("xyzzy"), "Nothing happens.")
|
Is(Otto.getValue("result")._object().get("xyzzy"), "Nothing happens.")
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestArrayLiteral(t *testing.T) {
|
func TestArrayLiteral(t *testing.T) {
|
||||||
|
|
@ -963,7 +963,7 @@ func TestArrayLiteral(t *testing.T) {
|
||||||
test(`
|
test(`
|
||||||
result = [ "Nothing happens.", 0, 1 ]
|
result = [ "Nothing happens.", 0, 1 ]
|
||||||
`)
|
`)
|
||||||
Is(test("result")._object().GetValue("0"), "Nothing happens.")
|
Is(test("result")._object().get("0"), "Nothing happens.")
|
||||||
|
|
||||||
test(`
|
test(`
|
||||||
xyzzy = [ "Nothing happens.", 0, 1 ]
|
xyzzy = [ "Nothing happens.", 0, 1 ]
|
||||||
|
|
@ -1554,15 +1554,15 @@ func TestRegExp(t *testing.T) {
|
||||||
test(`""+/abc/gi`, "/abc/gi")
|
test(`""+/abc/gi`, "/abc/gi")
|
||||||
|
|
||||||
result := test(`/(a)?/.exec('b')`, ",")
|
result := test(`/(a)?/.exec('b')`, ",")
|
||||||
Is(result._object().Get("0"), "")
|
Is(result._object().get("0"), "")
|
||||||
Is(result._object().Get("1"), "undefined")
|
Is(result._object().get("1"), "undefined")
|
||||||
Is(result._object().Get("length"), "2")
|
Is(result._object().get("length"), "2")
|
||||||
|
|
||||||
result = test(`/(a)?(b)?/.exec('b')`, "b,,b")
|
result = test(`/(a)?(b)?/.exec('b')`, "b,,b")
|
||||||
Is(result._object().Get("0"), "b")
|
Is(result._object().get("0"), "b")
|
||||||
Is(result._object().Get("1"), "undefined")
|
Is(result._object().get("1"), "undefined")
|
||||||
Is(result._object().Get("2"), "b")
|
Is(result._object().get("2"), "b")
|
||||||
Is(result._object().Get("length"), "3")
|
Is(result._object().get("length"), "3")
|
||||||
|
|
||||||
test(`/\u0041/.source`, "\\u0041")
|
test(`/\u0041/.source`, "\\u0041")
|
||||||
test(`/\a/.source`, "\\a")
|
test(`/\a/.source`, "\\a")
|
||||||
|
|
|
||||||
76
property.go
76
property.go
|
|
@ -5,63 +5,62 @@ package otto
|
||||||
type _propertyMode int
|
type _propertyMode int
|
||||||
|
|
||||||
const (
|
const (
|
||||||
propertyModeEmpty _propertyMode = 1
|
propertyModeWrite _propertyMode = 0100
|
||||||
propertyModeWrite = 2
|
propertyModeEnumerate = 0010
|
||||||
propertyModeEnumerate = 4
|
propertyModeConfigure = 0001
|
||||||
propertyModeConfigure = 8
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
propertyModeWriteEnumerateConfigure _propertyMode = propertyModeWrite | propertyModeEnumerate | propertyModeConfigure
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type _propertyGetSet [2]*_object
|
type _propertyGetSet [2]*_object
|
||||||
|
|
||||||
type _property struct {
|
type _property struct {
|
||||||
Value interface{}
|
Value interface{}
|
||||||
Mode _propertyMode
|
Mode _propertyMode
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self _property) CanWrite() bool {
|
func (self _property) CanWrite() bool {
|
||||||
return self.Mode & propertyModeWrite != 0
|
return self.Mode&propertyModeWrite != 0
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self _property) CanEnumerate() bool {
|
func (self _property) CanEnumerate() bool {
|
||||||
return self.Mode & propertyModeEnumerate != 0
|
return self.Mode&propertyModeEnumerate != 0
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self _property) CanConfigure() bool {
|
func (self _property) CanConfigure() bool {
|
||||||
return self.Mode & propertyModeConfigure != 0
|
return self.Mode&propertyModeConfigure != 0
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self _property) toDefineProperty() _defineProperty {
|
func (self _property) toDefineProperty() _defineProperty {
|
||||||
property := _defineProperty{
|
property := _defineProperty{
|
||||||
Value: self.Value,
|
Value: self.Value,
|
||||||
}
|
}
|
||||||
mode := self.Mode
|
|
||||||
if mode & propertyModeEmpty != 0 {
|
{
|
||||||
return property
|
mode := self.Mode
|
||||||
}
|
|
||||||
if mode & propertyModeWrite != 0 {
|
if mode&propertyModeWrite != 0 {
|
||||||
property.Write = propertyAttributeTrue
|
property.Write = propertyAttributeTrue
|
||||||
} else {
|
} else {
|
||||||
property.Write = propertyAttributeFalse
|
property.Write = propertyAttributeFalse
|
||||||
}
|
}
|
||||||
if mode & propertyModeEnumerate != 0 {
|
|
||||||
property.Enumerate = propertyAttributeTrue
|
if mode&propertyModeEnumerate != 0 {
|
||||||
} else {
|
property.Enumerate = propertyAttributeTrue
|
||||||
property.Enumerate = propertyAttributeFalse
|
} else {
|
||||||
}
|
property.Enumerate = propertyAttributeFalse
|
||||||
if mode & propertyModeConfigure != 0 {
|
}
|
||||||
property.Configure = propertyAttributeTrue
|
|
||||||
} else {
|
if mode&propertyModeConfigure != 0 {
|
||||||
property.Configure = propertyAttributeFalse
|
property.Configure = propertyAttributeTrue
|
||||||
|
} else {
|
||||||
|
property.Configure = propertyAttributeFalse
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return property
|
return property
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *_property) Copy() *_property {
|
func (self _property) Copy() *_property {
|
||||||
property := *self
|
property := self
|
||||||
return &property
|
return &property
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -69,7 +68,7 @@ func (self *_property) Copy() *_property {
|
||||||
|
|
||||||
type _valueProperty struct {
|
type _valueProperty struct {
|
||||||
Value Value
|
Value Value
|
||||||
Mode _propertyMode
|
Mode _propertyMode
|
||||||
}
|
}
|
||||||
|
|
||||||
// _defineProperty
|
// _defineProperty
|
||||||
|
|
@ -83,8 +82,8 @@ const (
|
||||||
)
|
)
|
||||||
|
|
||||||
type _defineProperty struct {
|
type _defineProperty struct {
|
||||||
Value interface{}
|
Value interface{}
|
||||||
Write _propertyAttributeBoolean
|
Write _propertyAttributeBoolean
|
||||||
Enumerate _propertyAttributeBoolean
|
Enumerate _propertyAttributeBoolean
|
||||||
Configure _propertyAttributeBoolean
|
Configure _propertyAttributeBoolean
|
||||||
}
|
}
|
||||||
|
|
@ -130,9 +129,9 @@ func (self _defineProperty) IsGenericDescriptor() bool {
|
||||||
|
|
||||||
func (self _defineProperty) isEmpty() bool {
|
func (self _defineProperty) isEmpty() bool {
|
||||||
return self.IsGenericDescriptor() &&
|
return self.IsGenericDescriptor() &&
|
||||||
self.Write == propertyAttributeNotSet &&
|
self.Write == propertyAttributeNotSet &&
|
||||||
self.Enumerate == propertyAttributeNotSet &&
|
self.Enumerate == propertyAttributeNotSet &&
|
||||||
self.Configure == propertyAttributeNotSet
|
self.Configure == propertyAttributeNotSet
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self _defineProperty) CopyInto(other *_property) {
|
func (self _defineProperty) CopyInto(other *_property) {
|
||||||
|
|
@ -161,4 +160,3 @@ func (self _defineProperty) CopyInto(other *_property) {
|
||||||
other.Value = self.Value
|
other.Value = self.Value
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
10
runtime.go
10
runtime.go
|
|
@ -61,7 +61,7 @@ func (self *_runtime) _executionContext(depth int) *_executionContext {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *_runtime) EnterFunctionExecutionContext(function *_object, this Value) *_functionEnvironment {
|
func (self *_runtime) EnterFunctionExecutionContext(function *_object, this Value) *_functionEnvironment {
|
||||||
scopeEnvironment := function.Function.Call.ScopeEnvironment()
|
scopeEnvironment := function._Function.Call.ScopeEnvironment()
|
||||||
if scopeEnvironment == nil {
|
if scopeEnvironment == nil {
|
||||||
scopeEnvironment = self.GlobalEnvironment
|
scopeEnvironment = self.GlobalEnvironment
|
||||||
}
|
}
|
||||||
|
|
@ -112,7 +112,7 @@ func (self *_runtime) PutValue(reference _reference, value Value) {
|
||||||
if !reference.PutValue(value) {
|
if !reference.PutValue(value) {
|
||||||
// Why? -- If reference.Base == nil
|
// Why? -- If reference.Base == nil
|
||||||
strict := false
|
strict := false
|
||||||
self.GlobalObject.WriteValue(reference.Name(), value, strict)
|
self.GlobalObject.set(reference.Name(), value, strict)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -173,7 +173,7 @@ func (self *_runtime) Call(function *_object, this Value, argumentList []Value)
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
returnValue = function.Function.Call.Dispatch(_functionEnvironment, self, this, argumentList)
|
returnValue = function._Function.Call.Dispatch(_functionEnvironment, self, this, argumentList)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -307,9 +307,9 @@ func testObjectCoercible(value Value) (isObject bool, mustCoerce bool) {
|
||||||
func (self *_runtime) toValue(value interface{}) Value {
|
func (self *_runtime) toValue(value interface{}) Value {
|
||||||
switch value := value.(type) {
|
switch value := value.(type) {
|
||||||
case func(FunctionCall) Value:
|
case func(FunctionCall) Value:
|
||||||
return toValue(self.newNativeFunction(value, 0))
|
return toValue(self.newNativeFunction(value, 0, "nativeFunction"))
|
||||||
case _nativeFunction:
|
case _nativeFunction:
|
||||||
return toValue(self.newNativeFunction(value, 0))
|
return toValue(self.newNativeFunction(value, 0, "nativeFunction"))
|
||||||
}
|
}
|
||||||
return toValue(value)
|
return toValue(value)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
162
stash.go
162
stash.go
|
|
@ -1,38 +1,44 @@
|
||||||
package otto
|
package otto
|
||||||
|
|
||||||
type _stash interface {
|
type _stash interface {
|
||||||
CanRead(string) bool
|
test(string) bool
|
||||||
Read(string) Value
|
get(string) Value
|
||||||
CanWrite(string) bool
|
|
||||||
Write(string, Value)
|
|
||||||
property(string) *_property
|
property(string) *_property
|
||||||
Delete(string)
|
enumerate(func(string))
|
||||||
Define(string, _defineProperty) bool
|
|
||||||
Enumerate(func(string))
|
canPut(string) bool
|
||||||
writeValuePropertyMap(map[string]_valueProperty)
|
put(string, Value)
|
||||||
|
set(string, Value, _propertyMode)
|
||||||
|
define(string, _defineProperty) bool
|
||||||
|
|
||||||
|
delete(string)
|
||||||
|
|
||||||
|
extensible() bool
|
||||||
|
lock()
|
||||||
|
unlock()
|
||||||
}
|
}
|
||||||
|
|
||||||
type _propertyStash struct {
|
type _objectStash struct {
|
||||||
canCreate bool
|
_extensible bool
|
||||||
propertyMap map[string]*_property
|
propertyMap map[string]_property
|
||||||
}
|
}
|
||||||
|
|
||||||
func newPropertyStash(canCreate bool) *_propertyStash {
|
func newObjectStash(extensible bool) *_objectStash {
|
||||||
return &_propertyStash{
|
return &_objectStash{
|
||||||
canCreate: canCreate,
|
_extensible: extensible,
|
||||||
propertyMap: make(map[string]*_property),
|
propertyMap: make(map[string]_property),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *_propertyStash) CanRead(name string) bool {
|
func (self *_objectStash) test(name string) bool {
|
||||||
_, exists := self.propertyMap[name]
|
_, exists := self.propertyMap[name]
|
||||||
return exists
|
return exists
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *_propertyStash) Read(name string) Value {
|
func (self *_objectStash) get(name string) Value {
|
||||||
property := self.propertyMap[name]
|
property, exists := self.propertyMap[name]
|
||||||
|
|
||||||
if property == nil {
|
if !exists {
|
||||||
return UndefinedValue()
|
return UndefinedValue()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -49,10 +55,34 @@ func (self *_propertyStash) Read(name string) Value {
|
||||||
panic(hereBeDragons())
|
panic(hereBeDragons())
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *_propertyStash) CanWrite(name string) bool {
|
func (self *_objectStash) property(name string) *_property {
|
||||||
property, _ := self.propertyMap[name]
|
property, exists := self.propertyMap[name]
|
||||||
|
if !exists {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return &property
|
||||||
|
}
|
||||||
|
|
||||||
|
func (self _objectStash) index(name string) (_property, bool) {
|
||||||
|
property := self.property(name)
|
||||||
if property == nil {
|
if property == nil {
|
||||||
return self.canCreate
|
return _property{}, false
|
||||||
|
}
|
||||||
|
return *property, true
|
||||||
|
}
|
||||||
|
|
||||||
|
func (self *_objectStash) enumerate(each func(string)) {
|
||||||
|
for name, property := range self.propertyMap {
|
||||||
|
if property.CanEnumerate() {
|
||||||
|
each(name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (self *_objectStash) canPut(name string) bool {
|
||||||
|
property, exists := self.propertyMap[name]
|
||||||
|
if !exists {
|
||||||
|
return self.extensible()
|
||||||
}
|
}
|
||||||
switch propertyValue := property.Value.(type) {
|
switch propertyValue := property.Value.(type) {
|
||||||
case Value:
|
case Value:
|
||||||
|
|
@ -63,45 +93,40 @@ func (self *_propertyStash) CanWrite(name string) bool {
|
||||||
panic(hereBeDragons())
|
panic(hereBeDragons())
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *_propertyStash) Write(name string, value Value) {
|
func (self *_objectStash) put(name string, value Value) {
|
||||||
property_, _ := self.propertyMap[name]
|
property, exists := self.propertyMap[name]
|
||||||
if property_ != nil {
|
if exists {
|
||||||
switch propertyValue := property_.Value.(type) {
|
switch propertyValue := property.Value.(type) {
|
||||||
case Value:
|
case Value:
|
||||||
if property_.CanWrite() {
|
if property.CanWrite() {
|
||||||
property_.Value = value
|
property.Value = value
|
||||||
|
self.propertyMap[name] = property
|
||||||
}
|
}
|
||||||
case _propertyGetSet:
|
case _propertyGetSet:
|
||||||
if propertyValue[1] != nil {
|
if propertyValue[1] != nil {
|
||||||
propertyValue[1].CallSet(name, value)
|
propertyValue[1].CallSet(name, value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if self.canCreate {
|
} else if self.extensible() {
|
||||||
self.propertyMap[name] = &_property{ value, propertyModeWriteEnumerateConfigure }
|
self.propertyMap[name] = _property{value, 0111} // Write, Enumerate, Configure
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *_propertyStash) property(name string) *_property {
|
func (self *_objectStash) set(name string, value Value, mode _propertyMode) {
|
||||||
property, _ := self.propertyMap[name]
|
self.propertyMap[name] = _property{value, mode}
|
||||||
return property
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *_propertyStash) Delete(name string) {
|
// FIME This is wrong, and doesn't work like you think
|
||||||
delete(self.propertyMap, name)
|
func (self *_objectStash) define(name string, define _defineProperty) bool {
|
||||||
}
|
property, exists := self.index(name)
|
||||||
|
if !exists {
|
||||||
func (self *_propertyStash) Define(name string, define _defineProperty) bool {
|
if !self.extensible() {
|
||||||
canCreate := self.canCreate
|
|
||||||
property_, _ := self.propertyMap[name]
|
|
||||||
if property_ == nil {
|
|
||||||
if !canCreate {
|
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
property_ = &_property{
|
self.propertyMap[name] = _property{
|
||||||
Value: define.Value,
|
Value: define.Value,
|
||||||
Mode: define.Mode(),
|
Mode: define.Mode(),
|
||||||
}
|
}
|
||||||
self.propertyMap[name] = property_
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
if define.isEmpty() {
|
if define.isEmpty() {
|
||||||
|
|
@ -111,31 +136,33 @@ func (self *_propertyStash) Define(name string, define _defineProperty) bool {
|
||||||
// TODO Per 8.12.9.6 - We should shortcut here (returning true) if
|
// TODO Per 8.12.9.6 - We should shortcut here (returning true) if
|
||||||
// the current and new (define) properties are the same
|
// the current and new (define) properties are the same
|
||||||
|
|
||||||
canConfigure := property_.CanConfigure()
|
// TODO Use the other stash methods so we write to special properties properly?
|
||||||
|
|
||||||
|
canConfigure := property.CanConfigure()
|
||||||
if !canConfigure {
|
if !canConfigure {
|
||||||
if define.CanConfigure() {
|
if define.CanConfigure() {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
if define.Enumerate != propertyAttributeNotSet && define.CanEnumerate() != property_.CanEnumerate() {
|
if define.Enumerate != propertyAttributeNotSet && define.CanEnumerate() != property.CanEnumerate() {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
value, isDataDescriptor := property_.Value.(Value)
|
value, isDataDescriptor := property.Value.(Value)
|
||||||
getSet, _ := property_.Value.(_propertyGetSet)
|
getSet, _ := property.Value.(_propertyGetSet)
|
||||||
if define.IsGenericDescriptor() {
|
if define.IsGenericDescriptor() {
|
||||||
; // GenericDescriptor
|
// GenericDescriptor
|
||||||
} else if isDataDescriptor != define.IsDataDescriptor() {
|
} else if isDataDescriptor != define.IsDataDescriptor() {
|
||||||
var interface_ interface{}
|
var interface_ interface{}
|
||||||
if isDataDescriptor {
|
if isDataDescriptor {
|
||||||
property_.Mode = property_.Mode & ^propertyModeWrite
|
property.Mode = property.Mode & ^propertyModeWrite
|
||||||
property_.Value = interface_
|
property.Value = interface_
|
||||||
} else {
|
} else {
|
||||||
property_.Mode |= propertyModeWrite
|
property.Mode |= propertyModeWrite
|
||||||
property_.Value = interface_
|
property.Value = interface_
|
||||||
}
|
}
|
||||||
} else if isDataDescriptor && define.IsDataDescriptor() {
|
} else if isDataDescriptor && define.IsDataDescriptor() {
|
||||||
if !canConfigure {
|
if !canConfigure {
|
||||||
if property_.CanWrite() != define.CanWrite() {
|
if property.CanWrite() != define.CanWrite() {
|
||||||
return false
|
return false
|
||||||
} else if !sameValue(value, define.Value.(Value)) {
|
} else if !sameValue(value, define.Value.(Value)) {
|
||||||
return false
|
return false
|
||||||
|
|
@ -149,20 +176,23 @@ func (self *_propertyStash) Define(name string, define _defineProperty) bool {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
define.CopyInto(property_)
|
define.CopyInto(&property)
|
||||||
|
self.propertyMap[name] = property
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *_propertyStash) Enumerate(each func(string)) {
|
func (self *_objectStash) delete(name string) {
|
||||||
for name, property_ := range self.propertyMap {
|
delete(self.propertyMap, name)
|
||||||
if property_.CanEnumerate() {
|
|
||||||
each(name)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *_propertyStash) writeValuePropertyMap(valuePropertyMap map[string]_valueProperty) {
|
func (self _objectStash) extensible() bool {
|
||||||
for name, _valueProperty := range valuePropertyMap {
|
return self._extensible
|
||||||
self.propertyMap[name] = &_property{ Value: _valueProperty.Value, Mode: _valueProperty.Mode }
|
}
|
||||||
}
|
|
||||||
|
func (self *_objectStash) lock() {
|
||||||
|
self._extensible = false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (self *_objectStash) unlock() {
|
||||||
|
self._extensible = true
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -8,19 +8,19 @@ import (
|
||||||
func TestStash(t *testing.T) {
|
func TestStash(t *testing.T) {
|
||||||
Terst(t)
|
Terst(t)
|
||||||
|
|
||||||
stash := newPropertyStash(true)
|
stash := newObjectStash(true)
|
||||||
IsTrue(stash.CanWrite("xyzzy"))
|
IsTrue(stash.canPut("xyzzy"))
|
||||||
|
|
||||||
stash.Define("xyzzy", _defineProperty{
|
stash.define("xyzzy", _defineProperty{
|
||||||
Value: toValue("Nothing happens."),
|
Value: toValue("Nothing happens."),
|
||||||
})
|
})
|
||||||
IsTrue(stash.CanRead("xyzzy"))
|
IsTrue(stash.test("xyzzy"))
|
||||||
IsTrue(stash.CanWrite("xyzzy"))
|
IsTrue(stash.canPut("xyzzy"))
|
||||||
|
|
||||||
stash.Define("xyzzy", _defineProperty{
|
stash.define("xyzzy", _defineProperty{
|
||||||
Value: toValue("Something else happens."),
|
Value: toValue("Something else happens."),
|
||||||
Write: propertyAttributeFalse,
|
Write: propertyAttributeFalse,
|
||||||
})
|
})
|
||||||
IsTrue(stash.CanRead("xyzzy"))
|
IsTrue(stash.test("xyzzy"))
|
||||||
IsFalse(stash.CanWrite("xyzzy"))
|
IsFalse(stash.canPut("xyzzy"))
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,14 +2,14 @@ package otto
|
||||||
|
|
||||||
func (runtime *_runtime) newArgumentsObject(argumentList []Value) *_object {
|
func (runtime *_runtime) newArgumentsObject(argumentList []Value) *_object {
|
||||||
self := runtime.newClassObject("Arguments")
|
self := runtime.newClassObject("Arguments")
|
||||||
self.Prototype = runtime.Global.ObjectPrototype
|
self.prototype = runtime.Global.ObjectPrototype
|
||||||
|
|
||||||
for index, value := range argumentList {
|
for index, value := range argumentList {
|
||||||
// TODO Write test for runtime.GetValue(value)
|
// TODO Write test for runtime.GetValue(value)
|
||||||
// The problem here is possible reference nesting, is this the right place to GetValue?
|
// The problem here is possible reference nesting, is this the right place to GetValue?
|
||||||
self.WriteValue(arrayIndexToString(uint(index)), runtime.GetValue(value), false)
|
self.set(arrayIndexToString(uint(index)), runtime.GetValue(value), false)
|
||||||
}
|
}
|
||||||
self.DefineOwnProperty("length", _property{Value: toValue(len(argumentList)), Mode: propertyModeWrite | propertyModeConfigure}.toDefineProperty(), false)
|
self.stash.set("length", toValue(len(argumentList)), 0101)
|
||||||
|
|
||||||
return self
|
return self
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,8 +6,8 @@ import (
|
||||||
|
|
||||||
func (runtime *_runtime) newArrayObject(valueArray []Value) *_object {
|
func (runtime *_runtime) newArrayObject(valueArray []Value) *_object {
|
||||||
self := runtime.newObject()
|
self := runtime.newObject()
|
||||||
self.Class = "Array"
|
self.class = "Array"
|
||||||
self._propertyStash = newArrayStash(valueArray, self._propertyStash)
|
self.stash = newArrayStash(valueArray, self.stash)
|
||||||
return self
|
return self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -26,7 +26,7 @@ func newArrayStash(valueArray []Value, stash _stash) *_arrayStash {
|
||||||
return self
|
return self
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *_arrayStash) CanWrite(name string) bool {
|
func (self *_arrayStash) canPut(name string) bool {
|
||||||
// length
|
// length
|
||||||
if name == "length" {
|
if name == "length" {
|
||||||
return true
|
return true
|
||||||
|
|
@ -38,10 +38,10 @@ func (self *_arrayStash) CanWrite(name string) bool {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
return self._stash.CanWrite(name)
|
return self._stash.canPut(name)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *_arrayStash) CanRead(name string) bool {
|
func (self *_arrayStash) test(name string) bool {
|
||||||
// length
|
// length
|
||||||
if name == "length" {
|
if name == "length" {
|
||||||
return true
|
return true
|
||||||
|
|
@ -53,10 +53,10 @@ func (self *_arrayStash) CanRead(name string) bool {
|
||||||
return index < int64(len(self.valueArray)) && self.valueArray[index]._valueType != valueEmpty
|
return index < int64(len(self.valueArray)) && self.valueArray[index]._valueType != valueEmpty
|
||||||
}
|
}
|
||||||
|
|
||||||
return self._stash.CanRead(name)
|
return self._stash.test(name)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *_arrayStash) Read(name string) Value {
|
func (self *_arrayStash) get(name string) Value {
|
||||||
// length
|
// length
|
||||||
if name == "length" {
|
if name == "length" {
|
||||||
return toValue(len(self.valueArray))
|
return toValue(len(self.valueArray))
|
||||||
|
|
@ -74,10 +74,10 @@ func (self *_arrayStash) Read(name string) Value {
|
||||||
return UndefinedValue()
|
return UndefinedValue()
|
||||||
}
|
}
|
||||||
|
|
||||||
return self._stash.Read(name)
|
return self._stash.get(name)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *_arrayStash) Write(name string, value Value) {
|
func (self *_arrayStash) put(name string, value Value) {
|
||||||
// length
|
// length
|
||||||
if name == "length" {
|
if name == "length" {
|
||||||
value := uint(toUI32(value))
|
value := uint(toUI32(value))
|
||||||
|
|
@ -109,7 +109,7 @@ func (self *_arrayStash) Write(name string, value Value) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
self._stash.Write(name, value)
|
self._stash.put(name, value)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *_arrayStash) property(name string) *_property {
|
func (self *_arrayStash) property(name string) *_property {
|
||||||
|
|
@ -130,14 +130,14 @@ func (self *_arrayStash) property(name string) *_property {
|
||||||
}
|
}
|
||||||
return &_property{
|
return &_property{
|
||||||
Value: value,
|
Value: value,
|
||||||
Mode: propertyModeWriteEnumerateConfigure, // +Write +Enumerate +Configure
|
Mode: 0111, // +Write +Enumerate +Configure
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return self._stash.property(name)
|
return self._stash.property(name)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *_arrayStash) Enumerate(each func(string)) {
|
func (self *_arrayStash) enumerate(each func(string)) {
|
||||||
// .0, .1, .2, ...
|
// .0, .1, .2, ...
|
||||||
for index, _ := range self.valueArray {
|
for index, _ := range self.valueArray {
|
||||||
if self.valueArray[index]._valueType == valueEmpty {
|
if self.valueArray[index]._valueType == valueEmpty {
|
||||||
|
|
@ -146,5 +146,5 @@ func (self *_arrayStash) Enumerate(each func(string)) {
|
||||||
name := strconv.FormatInt(int64(index), 10)
|
name := strconv.FormatInt(int64(index), 10)
|
||||||
each(name)
|
each(name)
|
||||||
}
|
}
|
||||||
self._stash.Enumerate(each)
|
self._stash.enumerate(each)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
10
type_date.go
10
type_date.go
|
|
@ -110,19 +110,19 @@ func timeToEpoch(time tme.Time) float64 {
|
||||||
|
|
||||||
func (runtime *_runtime) newDateObject(epoch float64) *_object {
|
func (runtime *_runtime) newDateObject(epoch float64) *_object {
|
||||||
self := runtime.newObject()
|
self := runtime.newObject()
|
||||||
self.Class = "Date"
|
self.class = "Date"
|
||||||
|
|
||||||
// TODO Fix this, redundant arguments, etc.
|
// TODO Fix this, redundant arguments, etc.
|
||||||
self.Date = &_dateObject{}
|
self._Date = &_dateObject{}
|
||||||
self.Date.Set(epoch)
|
self._Date.Set(epoch)
|
||||||
return self
|
return self
|
||||||
}
|
}
|
||||||
|
|
||||||
func dateObjectOf(_dateObject *_object) *_dateObject {
|
func dateObjectOf(_dateObject *_object) *_dateObject {
|
||||||
if _dateObject == nil || _dateObject.Class != "Date" {
|
if _dateObject == nil || _dateObject.class != "Date" {
|
||||||
panic(newTypeError())
|
panic(newTypeError())
|
||||||
}
|
}
|
||||||
return _dateObject.Date
|
return _dateObject._Date
|
||||||
}
|
}
|
||||||
|
|
||||||
// JavaScript is 0-based, Go is 1-based (15.9.1.4)
|
// JavaScript is 0-based, Go is 1-based (15.9.1.4)
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ package otto
|
||||||
func (runtime *_runtime) newErrorObject(message Value) *_object {
|
func (runtime *_runtime) newErrorObject(message Value) *_object {
|
||||||
self := runtime.newClassObject("Error")
|
self := runtime.newClassObject("Error")
|
||||||
if message.IsDefined() {
|
if message.IsDefined() {
|
||||||
self.WriteValue("message", toValue(toString(message)), false)
|
self.set("message", toValue(toString(message)), false)
|
||||||
}
|
}
|
||||||
return self
|
return self
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -8,28 +8,28 @@ type _functionObject struct {
|
||||||
Construct _constructFunction
|
Construct _constructFunction
|
||||||
}
|
}
|
||||||
|
|
||||||
func (runtime *_runtime) newNativeFunctionObject(native _nativeFunction, length int) *_object {
|
func (runtime *_runtime) newNativeFunctionObject(native _nativeFunction, length int, name string) *_object {
|
||||||
self := runtime.newClassObject("Function")
|
self := runtime.newClassObject("Function")
|
||||||
self.Function = &_functionObject{
|
self._Function = &_functionObject{
|
||||||
Call: newNativeCallFunction(native),
|
Call: newNativeCallFunction(native, name),
|
||||||
Construct: defaultConstructFunction,
|
Construct: defaultConstructFunction,
|
||||||
}
|
}
|
||||||
self.DefineOwnProperty("length", _property{Mode: 0, Value: toValue(length)}.toDefineProperty(), false)
|
self.stash.set("length", toValue(length), _propertyMode(0))
|
||||||
return self
|
return self
|
||||||
}
|
}
|
||||||
|
|
||||||
func (runtime *_runtime) newNodeFunctionObject(node *_functionNode, scopeEnvironment _environment) *_object {
|
func (runtime *_runtime) newNodeFunctionObject(node *_functionNode, scopeEnvironment _environment) *_object {
|
||||||
self := runtime.newClassObject("Function")
|
self := runtime.newClassObject("Function")
|
||||||
self.Function = &_functionObject{
|
self._Function = &_functionObject{
|
||||||
Call: newNodeCallFunction(node, scopeEnvironment),
|
Call: newNodeCallFunction(node, scopeEnvironment),
|
||||||
Construct: defaultConstructFunction,
|
Construct: defaultConstructFunction,
|
||||||
}
|
}
|
||||||
self.DefineOwnValueProperty("length", toValue(len(node.ParameterList)), 0 /* -Write -Configure -Enumerate */, false)
|
self.stash.set("length", toValue(len(node.ParameterList)), _propertyMode(0))
|
||||||
return self
|
return self
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *_object) Call(this Value, argumentList... interface{}) Value {
|
func (self *_object) Call(this Value, argumentList... interface{}) Value {
|
||||||
if self.Function == nil {
|
if self._Function == nil {
|
||||||
panic(newTypeError("%v is not a function", toValue(self)))
|
panic(newTypeError("%v is not a function", toValue(self)))
|
||||||
}
|
}
|
||||||
return self.runtime.Call(self, this, toValueArray(argumentList...))
|
return self.runtime.Call(self, this, toValueArray(argumentList...))
|
||||||
|
|
@ -37,21 +37,20 @@ func (self *_object) Call(this Value, argumentList... interface{}) Value {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *_object) Construct(this Value, argumentList... interface{}) Value {
|
func (self *_object) Construct(this Value, argumentList... interface{}) Value {
|
||||||
if self.Function == nil {
|
if self._Function == nil {
|
||||||
panic(newTypeError("%v is not a function", toValue(self)))
|
panic(newTypeError("%v is not a function", toValue(self)))
|
||||||
}
|
}
|
||||||
return self.Function.Construct(self, this, toValueArray(argumentList...))
|
return self._Function.Construct(self, this, toValueArray(argumentList...))
|
||||||
}
|
}
|
||||||
|
|
||||||
func defaultConstructFunction(self *_object, this Value, argumentList []Value) Value {
|
func defaultConstructFunction(self *_object, this Value, argumentList []Value) Value {
|
||||||
newObject := self.runtime.newObject()
|
newObject := self.runtime.newObject()
|
||||||
newObject.Class = "Object"
|
newObject.class = "Object"
|
||||||
newObject.Extensible = true
|
prototypeValue := self.get("prototype")
|
||||||
prototypeValue := self.Get("prototype")
|
|
||||||
if !prototypeValue.IsObject() {
|
if !prototypeValue.IsObject() {
|
||||||
prototypeValue = toValue(self.runtime.Global.ObjectPrototype)
|
prototypeValue = toValue(self.runtime.Global.ObjectPrototype)
|
||||||
}
|
}
|
||||||
newObject.Prototype = prototypeValue._object()
|
newObject.prototype = prototypeValue._object()
|
||||||
newObjectValue := toValue(newObject)
|
newObjectValue := toValue(newObject)
|
||||||
result := self.Call(newObjectValue, argumentList)
|
result := self.Call(newObjectValue, argumentList)
|
||||||
if result.IsObject() {
|
if result.IsObject() {
|
||||||
|
|
@ -73,11 +72,11 @@ func (self *_object) HasInstance(of Value) bool {
|
||||||
if !of.IsObject() {
|
if !of.IsObject() {
|
||||||
panic(newTypeError())
|
panic(newTypeError())
|
||||||
}
|
}
|
||||||
prototype := self.Get("prototype")
|
prototype := self.get("prototype")
|
||||||
if !prototype.IsObject() {
|
if !prototype.IsObject() {
|
||||||
panic(newTypeError())
|
panic(newTypeError())
|
||||||
}
|
}
|
||||||
ofPrototype := of._object().Prototype
|
ofPrototype := of._object().prototype
|
||||||
if ofPrototype == nil {
|
if ofPrototype == nil {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
@ -96,37 +95,34 @@ type _callFunction interface {
|
||||||
Dispatch(*_functionEnvironment, *_runtime, Value, []Value) Value
|
Dispatch(*_functionEnvironment, *_runtime, Value, []Value) Value
|
||||||
Source() string
|
Source() string
|
||||||
ScopeEnvironment() _environment
|
ScopeEnvironment() _environment
|
||||||
Sign(_functionSignature)
|
name() string
|
||||||
Signature() _functionSignature
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type _callFunctionBase struct {
|
type _callFunction_ struct {
|
||||||
scopeEnvironment _environment // Can be either Lexical or Variable
|
scopeEnvironment _environment // Can be either Lexical or Variable
|
||||||
signature _functionSignature
|
_name string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self _callFunctionBase) ScopeEnvironment() _environment {
|
func (self _callFunction_) ScopeEnvironment() _environment {
|
||||||
return self.scopeEnvironment
|
return self.scopeEnvironment
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *_callFunctionBase) Sign(signature _functionSignature) {
|
func (self _callFunction_) name() string {
|
||||||
self.signature = signature
|
return self._name
|
||||||
}
|
|
||||||
|
|
||||||
func (self _callFunctionBase) Signature() _functionSignature {
|
|
||||||
return self.signature
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// _nativeCallFunction
|
// _nativeCallFunction
|
||||||
type _nativeCallFunction struct {
|
type _nativeCallFunction struct {
|
||||||
_callFunctionBase
|
_callFunction_
|
||||||
Native _nativeFunction
|
Native _nativeFunction
|
||||||
}
|
}
|
||||||
|
|
||||||
func newNativeCallFunction(native _nativeFunction) *_nativeCallFunction {
|
func newNativeCallFunction(native _nativeFunction, name string) *_nativeCallFunction {
|
||||||
return &_nativeCallFunction{
|
self := &_nativeCallFunction{
|
||||||
Native: native,
|
Native: native,
|
||||||
}
|
}
|
||||||
|
self._callFunction_._name = name
|
||||||
|
return self
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self _nativeCallFunction) Dispatch(_ *_functionEnvironment, runtime *_runtime, this Value, argumentList []Value) Value {
|
func (self _nativeCallFunction) Dispatch(_ *_functionEnvironment, runtime *_runtime, this Value, argumentList []Value) Value {
|
||||||
|
|
@ -143,7 +139,7 @@ func (self _nativeCallFunction) Source() string {
|
||||||
|
|
||||||
// _nodeCallFunction
|
// _nodeCallFunction
|
||||||
type _nodeCallFunction struct {
|
type _nodeCallFunction struct {
|
||||||
_callFunctionBase
|
_callFunction_
|
||||||
node *_functionNode
|
node *_functionNode
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -190,7 +186,7 @@ func (self *FunctionCall) thisObject() *_object {
|
||||||
|
|
||||||
func (self *FunctionCall) thisClassObject(class string) *_object {
|
func (self *FunctionCall) thisClassObject(class string) *_object {
|
||||||
thisObject := self.thisObject()
|
thisObject := self.thisObject()
|
||||||
if thisObject.Class != class {
|
if thisObject.class != class {
|
||||||
panic(newTypeError())
|
panic(newTypeError())
|
||||||
}
|
}
|
||||||
return self._thisObject
|
return self._thisObject
|
||||||
|
|
|
||||||
|
|
@ -53,11 +53,11 @@ func (self *_argumentReference) GetBase() *_object {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *_argumentReference) GetValue() Value {
|
func (self *_argumentReference) GetValue() Value {
|
||||||
return self.Base.GetValue(self.name)
|
return self.Base.get(self.name)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *_argumentReference) PutValue(value Value) bool {
|
func (self *_argumentReference) PutValue(value Value) bool {
|
||||||
self.Base.WriteValue(self.name, value, self._referenceBase.strict)
|
self.Base.set(self.name, value, self._referenceBase.strict)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -86,14 +86,14 @@ func (self *_objectReference) GetValue() Value {
|
||||||
if self.Base == nil {
|
if self.Base == nil {
|
||||||
panic(newReferenceError("notDefined", self.name, self.node))
|
panic(newReferenceError("notDefined", self.name, self.node))
|
||||||
}
|
}
|
||||||
return self.Base.GetValue(self.name)
|
return self.Base.get(self.name)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *_objectReference) PutValue(value Value) bool {
|
func (self *_objectReference) PutValue(value Value) bool {
|
||||||
if self.Base == nil {
|
if self.Base == nil {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
self.Base.WriteValue(self.name, value, self.Strict())
|
self.Base.set(self.name, value, self.Strict())
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -101,7 +101,7 @@ func (self *_objectReference) Delete() {
|
||||||
if self.Base == nil {
|
if self.Base == nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
self.Base.Delete(self.name, self.Strict())
|
self.Base.delete(self.name, self.Strict())
|
||||||
}
|
}
|
||||||
|
|
||||||
type _primitiveReference struct {
|
type _primitiveReference struct {
|
||||||
|
|
@ -130,11 +130,11 @@ func (self *_primitiveReference) baseAsObject() *_object {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *_primitiveReference) GetValue() Value {
|
func (self *_primitiveReference) GetValue() Value {
|
||||||
return self.baseAsObject().GetValue(self.name)
|
return self.baseAsObject().get(self.name)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *_primitiveReference) PutValue(value Value) bool {
|
func (self *_primitiveReference) PutValue(value Value) bool {
|
||||||
self.baseAsObject().WriteValue(self.name, value, self.Strict())
|
self.baseAsObject().set(self.name, value, self.Strict())
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,7 @@ type _regExpObject struct {
|
||||||
|
|
||||||
func (runtime *_runtime) newRegExpObject(pattern string, flags string) *_object {
|
func (runtime *_runtime) newRegExpObject(pattern string, flags string) *_object {
|
||||||
self := runtime.newObject()
|
self := runtime.newObject()
|
||||||
self.Class = "RegExp"
|
self.class = "RegExp"
|
||||||
|
|
||||||
global := false
|
global := false
|
||||||
ignoreCase := false
|
ignoreCase := false
|
||||||
|
|
@ -50,7 +50,7 @@ func (runtime *_runtime) newRegExpObject(pattern string, flags string) *_object
|
||||||
re2pattern = fmt.Sprintf("(?%s:%s)", re2flags, re2pattern)
|
re2pattern = fmt.Sprintf("(?%s:%s)", re2flags, re2pattern)
|
||||||
}
|
}
|
||||||
|
|
||||||
self.RegExp = &_regExpObject{
|
self._RegExp = &_regExpObject{
|
||||||
RegularExpression: regexp.MustCompile(re2pattern),
|
RegularExpression: regexp.MustCompile(re2pattern),
|
||||||
Global: global,
|
Global: global,
|
||||||
IgnoreCase: ignoreCase,
|
IgnoreCase: ignoreCase,
|
||||||
|
|
@ -58,29 +58,29 @@ func (runtime *_runtime) newRegExpObject(pattern string, flags string) *_object
|
||||||
Source: pattern,
|
Source: pattern,
|
||||||
LastIndex: toValue(0),
|
LastIndex: toValue(0),
|
||||||
}
|
}
|
||||||
self._propertyStash = newRegExpStash(self.RegExp, self._propertyStash)
|
self.stash = newRegExpStash(self._RegExp, self.stash)
|
||||||
return self
|
return self
|
||||||
}
|
}
|
||||||
|
|
||||||
func execRegExp(this *_object, target string) (match bool, result []int) {
|
func execRegExp(this *_object, target string) (match bool, result []int) {
|
||||||
lastIndex := toInteger(this.Get("lastIndex"))
|
lastIndex := toInteger(this.get("lastIndex"))
|
||||||
index := lastIndex
|
index := lastIndex
|
||||||
global := toBoolean(this.Get("global"))
|
global := toBoolean(this.get("global"))
|
||||||
if !global {
|
if !global {
|
||||||
index = 0
|
index = 0
|
||||||
}
|
}
|
||||||
if 0 > index || index > int64(len(target)) {
|
if 0 > index || index > int64(len(target)) {
|
||||||
} else {
|
} else {
|
||||||
result = this.RegExp.RegularExpression.FindStringSubmatchIndex(target[index:])
|
result = this._RegExp.RegularExpression.FindStringSubmatchIndex(target[index:])
|
||||||
}
|
}
|
||||||
if result == nil {
|
if result == nil {
|
||||||
this.WriteValue("lastIndex", toValue(0), true)
|
this.set("lastIndex", toValue(0), true)
|
||||||
return // !match
|
return // !match
|
||||||
}
|
}
|
||||||
match = true
|
match = true
|
||||||
endIndex := result[len(result)-1]
|
endIndex := result[len(result)-1]
|
||||||
if global {
|
if global {
|
||||||
this.WriteValue("lastIndex", toValue(endIndex), true)
|
this.set("lastIndex", toValue(endIndex), true)
|
||||||
}
|
}
|
||||||
return // match
|
return // match
|
||||||
}
|
}
|
||||||
|
|
@ -230,15 +230,15 @@ func newRegExpStash(_regExpObject *_regExpObject, stash _stash) *_regExpStash {
|
||||||
return self
|
return self
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *_regExpStash) CanRead(name string) bool {
|
func (self *_regExpStash) test(name string) bool {
|
||||||
switch name {
|
switch name {
|
||||||
case "global", "ignoreCase", "multiline", "lastIndex", "source":
|
case "global", "ignoreCase", "multiline", "lastIndex", "source":
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
return self._stash.CanRead(name)
|
return self._stash.test(name)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *_regExpStash) Read(name string) Value {
|
func (self *_regExpStash) get(name string) Value {
|
||||||
switch name {
|
switch name {
|
||||||
case "global":
|
case "global":
|
||||||
return toValue(self._regExpObject.Global)
|
return toValue(self._regExpObject.Global)
|
||||||
|
|
@ -251,10 +251,10 @@ func (self *_regExpStash) Read(name string) Value {
|
||||||
case "source":
|
case "source":
|
||||||
return toValue(self._regExpObject.Source)
|
return toValue(self._regExpObject.Source)
|
||||||
}
|
}
|
||||||
return self._stash.Read(name)
|
return self._stash.get(name)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *_regExpStash) Write(name string, value Value) {
|
func (self *_regExpStash) put(name string, value Value) {
|
||||||
switch name {
|
switch name {
|
||||||
case "global", "ignoreCase", "multiline", "source":
|
case "global", "ignoreCase", "multiline", "source":
|
||||||
// TODO Is this good enough? Check DefineOwnProperty
|
// TODO Is this good enough? Check DefineOwnProperty
|
||||||
|
|
@ -263,7 +263,7 @@ func (self *_regExpStash) Write(name string, value Value) {
|
||||||
self._regExpObject.LastIndex = value
|
self._regExpObject.LastIndex = value
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
self._stash.Write(name, value)
|
self._stash.put(name, value)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *_regExpStash) property(name string) *_property {
|
func (self *_regExpStash) property(name string) *_property {
|
||||||
|
|
@ -282,7 +282,7 @@ func (self *_regExpStash) property(name string) *_property {
|
||||||
return self._stash.property(name)
|
return self._stash.property(name)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *_regExpStash) Enumerate(each func(string)) {
|
func (self *_regExpStash) enumerate(each func(string)) {
|
||||||
// Skip global, ignoreCase, multiline, source, & lastIndex
|
// Skip global, ignoreCase, multiline, source, & lastIndex
|
||||||
self._stash.Enumerate(each)
|
self._stash.enumerate(each)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@ import (
|
||||||
|
|
||||||
func (runtime *_runtime) newStringObject(value Value) *_object {
|
func (runtime *_runtime) newStringObject(value Value) *_object {
|
||||||
self := runtime.newPrimitiveObject("String", toValue(toString(value)))
|
self := runtime.newPrimitiveObject("String", toValue(toString(value)))
|
||||||
self._propertyStash = newStringStash(toString(value), self._propertyStash)
|
self.stash = newStringStash(toString(value), self.stash)
|
||||||
return self
|
return self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -23,7 +23,7 @@ func newStringStash(value string, stash _stash) *_stringStash {
|
||||||
return self
|
return self
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *_stringStash) CanRead(name string) bool {
|
func (self *_stringStash) test(name string) bool {
|
||||||
// .length
|
// .length
|
||||||
if name == "length" {
|
if name == "length" {
|
||||||
return true
|
return true
|
||||||
|
|
@ -35,10 +35,10 @@ func (self *_stringStash) CanRead(name string) bool {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
return self._stash.CanRead(name)
|
return self._stash.test(name)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *_stringStash) Read(name string) Value {
|
func (self *_stringStash) get(name string) Value {
|
||||||
// .length
|
// .length
|
||||||
if name == "length" {
|
if name == "length" {
|
||||||
return toValue(len(string(self.value)))
|
return toValue(len(string(self.value)))
|
||||||
|
|
@ -50,7 +50,7 @@ func (self *_stringStash) Read(name string) Value {
|
||||||
return toValue(string(self.value[index]))
|
return toValue(string(self.value[index]))
|
||||||
}
|
}
|
||||||
|
|
||||||
return self._stash.Read(name)
|
return self._stash.get(name)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *_stringStash) property(name string) *_property {
|
func (self *_stringStash) property(name string) *_property {
|
||||||
|
|
@ -74,11 +74,11 @@ func (self *_stringStash) property(name string) *_property {
|
||||||
return self._stash.property(name)
|
return self._stash.property(name)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *_stringStash) Enumerate(each func(string)) {
|
func (self *_stringStash) enumerate(each func(string)) {
|
||||||
// .0, .1, .2, ...
|
// .0, .1, .2, ...
|
||||||
for index, _ := range self.value {
|
for index, _ := range self.value {
|
||||||
name := strconv.FormatInt(int64(index), 10)
|
name := strconv.FormatInt(int64(index), 10)
|
||||||
each(name)
|
each(name)
|
||||||
}
|
}
|
||||||
self._stash.Enumerate(each)
|
self._stash.enumerate(each)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
20
value.go
20
value.go
|
|
@ -75,7 +75,7 @@ func (value Value) IsNull() bool {
|
||||||
func (value Value) isCallable() bool {
|
func (value Value) isCallable() bool {
|
||||||
switch value := value.value.(type) {
|
switch value := value.value.(type) {
|
||||||
case *_object:
|
case *_object:
|
||||||
return value.Function != nil
|
return value._Function != nil
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
@ -157,7 +157,7 @@ func (value Value) IsFunction() bool {
|
||||||
if value._valueType != valueObject {
|
if value._valueType != valueObject {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
return value.value.(*_object).Class == "Function"
|
return value.value.(*_object).class == "Function"
|
||||||
}
|
}
|
||||||
|
|
||||||
// Class will return the class string of the value or the empty string if value is not an object.
|
// Class will return the class string of the value or the empty string if value is not an object.
|
||||||
|
|
@ -177,56 +177,56 @@ func (value Value) Class() string {
|
||||||
if value._valueType != valueObject {
|
if value._valueType != valueObject {
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
return value.value.(*_object).Class
|
return value.value.(*_object).class
|
||||||
}
|
}
|
||||||
|
|
||||||
func (value Value) isArray() bool {
|
func (value Value) isArray() bool {
|
||||||
if value._valueType != valueObject {
|
if value._valueType != valueObject {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
return value.value.(*_object).Class == "Array"
|
return value.value.(*_object).class == "Array"
|
||||||
}
|
}
|
||||||
|
|
||||||
func (value Value) isStringObject() bool {
|
func (value Value) isStringObject() bool {
|
||||||
if value._valueType != valueObject {
|
if value._valueType != valueObject {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
return value.value.(*_object).Class == "String"
|
return value.value.(*_object).class == "String"
|
||||||
}
|
}
|
||||||
|
|
||||||
func (value Value) isBooleanObject() bool {
|
func (value Value) isBooleanObject() bool {
|
||||||
if value._valueType != valueObject {
|
if value._valueType != valueObject {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
return value.value.(*_object).Class == "Boolean"
|
return value.value.(*_object).class == "Boolean"
|
||||||
}
|
}
|
||||||
|
|
||||||
func (value Value) isNumberObject() bool {
|
func (value Value) isNumberObject() bool {
|
||||||
if value._valueType != valueObject {
|
if value._valueType != valueObject {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
return value.value.(*_object).Class == "Number"
|
return value.value.(*_object).class == "Number"
|
||||||
}
|
}
|
||||||
|
|
||||||
func (value Value) isDate() bool {
|
func (value Value) isDate() bool {
|
||||||
if value._valueType != valueObject {
|
if value._valueType != valueObject {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
return value.value.(*_object).Class == "Date"
|
return value.value.(*_object).class == "Date"
|
||||||
}
|
}
|
||||||
|
|
||||||
func (value Value) isRegExp() bool {
|
func (value Value) isRegExp() bool {
|
||||||
if value._valueType != valueObject {
|
if value._valueType != valueObject {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
return value.value.(*_object).Class == "RegExp"
|
return value.value.(*_object).class == "RegExp"
|
||||||
}
|
}
|
||||||
|
|
||||||
func (value Value) isError() bool {
|
func (value Value) isError() bool {
|
||||||
if value._valueType != valueObject {
|
if value._valueType != valueObject {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
return value.value.(*_object).Class == "Error"
|
return value.value.(*_object).class == "Error"
|
||||||
}
|
}
|
||||||
|
|
||||||
// ---
|
// ---
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user