diff --git a/.test262/Makefile b/.test262/Makefile index 0c47354..5c51eb9 100644 --- a/.test262/Makefile +++ b/.test262/Makefile @@ -8,6 +8,8 @@ WITH_otto := --command "$(otto)" test: $(TEST) $(WITH_otto) +release: otto gauntlet + test-otto: test otto: build diff --git a/builtin.go b/builtin.go index 134dc83..9774901 100644 --- a/builtin.go +++ b/builtin.go @@ -81,13 +81,13 @@ func _builtinGlobal_encodeURI(call FunctionCall, characterRegexp *regexp.Regexp) return toValue(string(value)) } -var encodeURI_Regexp *regexp.Regexp = regexp.MustCompile(`([^~!@#$&*()=:/,;?+'])`) +var encodeURI_Regexp = regexp.MustCompile(`([^~!@#$&*()=:/,;?+'])`) func builtinGlobal_encodeURI(call FunctionCall) Value { return _builtinGlobal_encodeURI(call, encodeURI_Regexp) } -var encodeURIComponent_Regexp *regexp.Regexp = regexp.MustCompile(`([^~!*()'])`) +var encodeURIComponent_Regexp = regexp.MustCompile(`([^~!*()'])`) func builtinGlobal_encodeURIComponent(call FunctionCall) Value { return _builtinGlobal_encodeURI(call, encodeURIComponent_Regexp) @@ -124,7 +124,7 @@ func builtinObject_toString(call FunctionCall) Value { } else if call.This.IsNull() { result = "[object Null]" } else { - result = fmt.Sprintf("[object %s]", call.thisObject().Class) + result = fmt.Sprintf("[object %s]", call.thisObject().class) } return toValue(result) } @@ -177,10 +177,10 @@ func builtinFunction_apply(call FunctionCall) Value { arrayObject := argumentList._object() thisObject := call.thisObject() - length := uint(toUI32(arrayObject.Get("length"))) + length := uint(toUI32(arrayObject.get("length"))) valueArray := make([]Value, length) for index := uint(0); index < length; index++ { - valueArray[index] = arrayObject.Get(arrayIndexToString(index)) + valueArray[index] = arrayObject.get(arrayIndexToString(index)) } return thisObject.Call(this, valueArray) } @@ -317,10 +317,10 @@ func builtinString_match(call FunctionCall) Value { target := toString(call.This) matcherValue := call.Argument(0) matcher := matcherValue._object() - if !matcherValue.IsObject() || matcher.Class != "RegExp" { + if !matcherValue.IsObject() || matcher.class != "RegExp" { matcher = call.runtime.newRegExp(matcherValue, UndefinedValue()) } - global := toBoolean(matcher.Get("global")) + global := toBoolean(matcher.get("global")) if !global { match, result := execRegExp(matcher, target) 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) if result == nil { - matcher.WriteValue("lastIndex", toValue(0), true) + matcher.set("lastIndex", toValue(0), true) return UndefinedValue() // !match } matchCount = len(result) @@ -341,12 +341,12 @@ func builtinString_match(call FunctionCall) Value { for index := 0; index < matchCount; index++ { 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)) } } -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) { matchCount := len(match) / 2 @@ -391,9 +391,9 @@ func builtinString_replace(call FunctionCall) Value { var search *regexp.Regexp global := false find := 1 - if searchValue.IsObject() && searchObject.Class == "RegExp" { - search = searchObject.RegExp.RegularExpression - global = toBoolean(searchObject.Get("global")) + if searchValue.IsObject() && searchObject.class == "RegExp" { + search = searchObject._RegExp.RegularExpression + global = toBoolean(searchObject.get("global")) if global { find = -1 } @@ -448,7 +448,7 @@ func builtinString_replace(call FunctionCall) Value { } if global && searchObject != nil { - searchObject.Put("lastIndex", toValue(lastIndex), true) + searchObject.put("lastIndex", toValue(lastIndex), true) } return toValue(string(result)) @@ -462,10 +462,10 @@ func builtinString_search(call FunctionCall) Value { target := toString(call.This) searchValue := call.Argument(0) search := searchValue._object() - if !searchValue.IsObject() || search.Class != "RegExp" { + if !searchValue.IsObject() || search.class != "RegExp" { search = call.runtime.newRegExp(searchValue, UndefinedValue()) } - result := search.RegExp.RegularExpression.FindStringIndex(target) + result := search._RegExp.RegularExpression.FindStringIndex(target) if result == nil { return toValue(-1) } @@ -504,7 +504,7 @@ func builtinString_split(call FunctionCall) Value { if separatorValue.isRegExp() { targetLength := len(target) - search := separatorValue._object().RegExp.RegularExpression + search := separatorValue._object()._RegExp.RegularExpression valueArray := []Value{} result := search.FindAllStringSubmatchIndex(target, -1) lastIndex := 0 @@ -697,8 +697,8 @@ func builtinArray_concat(call FunctionCall) Value { switch item._valueType { case valueObject: value := item._object() - if value.Class == "Array" { - itemValueArray := value._propertyStash.(*_arrayStash).valueArray + if value.class == "Array" { + itemValueArray := value.stash.(*_arrayStash).valueArray for _, item := range itemValueArray { if item._valueType == valueEmpty { continue @@ -717,50 +717,50 @@ func builtinArray_concat(call FunctionCall) Value { func builtinArray_shift(call FunctionCall) Value { thisObject := call.thisObject() - length := uint(toUI32(thisObject.Get("length"))) + length := uint(toUI32(thisObject.get("length"))) if 0 == length { - thisObject.Put("length", toValue(length), true) + thisObject.put("length", toValue(length), true) return UndefinedValue() } - first := thisObject.Get("0") + first := thisObject.get("0") for index := uint(1); index < length; index++ { from := arrayIndexToString(index) to := arrayIndexToString(index - 1) - if thisObject.HasProperty(from) { - thisObject.Put(to, thisObject.Get(from), true) + if thisObject.hasProperty(from) { + thisObject.put(to, thisObject.get(from), true) } else { - thisObject.Delete(to, true) + thisObject.delete(to, true) } } - thisObject.Delete(arrayIndexToString(length - 1), true) - thisObject.Put("length", toValue(length - 1), true) + thisObject.delete(arrayIndexToString(length - 1), true) + thisObject.put("length", toValue(length - 1), true) return first } func builtinArray_push(call FunctionCall) Value { thisObject := call.thisObject() itemList := call.ArgumentList - index := uint(toUI32(thisObject.Get("length"))) + index := uint(toUI32(thisObject.get("length"))) for len(itemList) > 0 { - thisObject.Put(arrayIndexToString(index), itemList[0], true) + thisObject.put(arrayIndexToString(index), itemList[0], true) itemList = itemList[1:] index += 1 } length := toValue(index) - thisObject.Put("length", length, true) + thisObject.put("length", length, true) return length } func builtinArray_pop(call FunctionCall) Value { thisObject := call.thisObject() - length := uint(toUI32(thisObject.Get("length"))) + length := uint(toUI32(thisObject.get("length"))) if 0 == length { - thisObject.Put("length", toValue(length), true) + thisObject.put("length", toValue(length), true) return UndefinedValue() } - last := thisObject.Get(arrayIndexToString(length - 1)) - thisObject.Delete(arrayIndexToString(length - 1), true) - thisObject.Put("length", toValue(length - 1), true) + last := thisObject.get(arrayIndexToString(length - 1)) + thisObject.delete(arrayIndexToString(length - 1), true) + thisObject.put("length", toValue(length - 1), true) return last } @@ -773,17 +773,17 @@ func builtinArray_join(call FunctionCall) Value { } } thisObject := call.thisObject() - if stash, isArray := thisObject._propertyStash.(*_arrayStash); isArray { + if stash, isArray := thisObject.stash.(*_arrayStash); isArray { return toValue(builtinArray_joinNative(stash.valueArray, separator)) } // Generic .join - length := uint(toUI32(thisObject.Get("length"))) + length := uint(toUI32(thisObject.get("length"))) if length == 0 { return toValue("") } stringList := make([]string, 0, length) for index := uint(0); index < length; index += 1 { - value := thisObject.Get(arrayIndexToString(index)) + value := thisObject.get(arrayIndexToString(index)) stringValue := "" switch value._valueType { case valueEmpty, valueUndefined, valueNull: @@ -852,7 +852,7 @@ func rangeStartLength(source []Value, size uint) (start, length int64) { func builtinArray_splice(call FunctionCall) Value { thisObject := call.thisObject() - length := uint(toUI32(thisObject.Get("length"))) + length := uint(toUI32(thisObject.get("length"))) start := valueToArrayIndex(call.Argument(0), length, true) 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++ { indexString := arrayIndexToString(start + index) - if thisObject.HasProperty(indexString) { - valueArray[index] = thisObject.Get(indexString) + if thisObject.hasProperty(indexString) { + valueArray[index] = thisObject.get(indexString) } } @@ -887,17 +887,17 @@ func builtinArray_splice(call FunctionCall) Value { for index := start; index < stop; index++ { from := arrayIndexToString(index + deleteCount) // Position just after deletion to := arrayIndexToString(index + itemCount) // Position just after splice (insertion) - if thisObject.HasProperty(from) { - thisObject.Put(to, thisObject.Get(from), true) + if thisObject.hasProperty(from) { + thisObject.put(to, thisObject.get(from), true) } else { - thisObject.Delete(to, true) + thisObject.delete(to, true) } } // Delete off the end // We don't bother to delete below (if any) since those // will be overwritten anyway for index := length; index > (stop + itemCount); index-- { - thisObject.Delete(arrayIndexToString(index - 1), true) + thisObject.delete(arrayIndexToString(index - 1), true) } } else if itemCount > deleteCount { // The Object/Array is growing @@ -910,18 +910,18 @@ func builtinArray_splice(call FunctionCall) Value { for index := length - deleteCount; index > start; index-- { from := arrayIndexToString(index + deleteCount - 1) to := arrayIndexToString(index + itemCount - 1) - if thisObject.HasProperty(from) { - thisObject.Put(to, thisObject.Get(from), true) + if thisObject.hasProperty(from) { + thisObject.put(to, thisObject.get(from), true) } else { - thisObject.Delete(to, true) + thisObject.delete(to, true) } } } 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)) } @@ -929,7 +929,7 @@ func builtinArray_splice(call FunctionCall) Value { func builtinArray_slice(call FunctionCall) Value { thisObject := call.thisObject() - length := uint(toUI32(thisObject.Get("length"))) + length := uint(toUI32(thisObject.get("length"))) start, end := rangeStartEnd(call.ArgumentList, length) if start >= end { @@ -940,13 +940,13 @@ func builtinArray_slice(call FunctionCall) Value { sliceValueArray := make([]Value, sliceLength) // 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]) } else { for index := uint(0); index < sliceLength; index++ { from := arrayIndexToString(index + start) - if thisObject.HasProperty(from) { - sliceValueArray[index] = thisObject.Get(from) + if thisObject.hasProperty(from) { + sliceValueArray[index] = thisObject.get(from) } } } @@ -956,32 +956,32 @@ func builtinArray_slice(call FunctionCall) Value { func builtinArray_unshift(call FunctionCall) Value { thisObject := call.thisObject() - length := uint(toUI32(thisObject.Get("length"))) + length := uint(toUI32(thisObject.get("length"))) itemList := call.ArgumentList itemCount := uint(len(itemList)) for index := length; index > 0; index-- { from := arrayIndexToString(index - 1) to := arrayIndexToString(index + itemCount - 1) - if thisObject.HasProperty(from) { - thisObject.Put(to, thisObject.Get(from), true) + if thisObject.hasProperty(from) { + thisObject.put(to, thisObject.get(from), true) } else { - thisObject.Delete(to, true) + thisObject.delete(to, true) } } 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) - thisObject.Put("length", newLength, true) + thisObject.put("length", newLength, true) return newLength } func builtinArray_reverse(call FunctionCall) Value { thisObject := call.thisObject() - length := uint(toUI32(thisObject.Get("length"))) + length := uint(toUI32(thisObject.get("length"))) lower := struct { name string @@ -998,22 +998,22 @@ func builtinArray_reverse(call FunctionCall) Value { upper.index = length - lower.index - 1 upper.name = arrayIndexToString(upper.index) - lower.exists = thisObject.HasProperty(lower.name) - upper.exists = thisObject.HasProperty(upper.name) + lower.exists = thisObject.hasProperty(lower.name) + upper.exists = thisObject.hasProperty(upper.name) if lower.exists && upper.exists { - lowerValue := thisObject.Get(lower.name) - upperValue := thisObject.Get(upper.name) - thisObject.Put(lower.name, upperValue, true) - thisObject.Put(upper.name, lowerValue, true) + lowerValue := thisObject.get(lower.name) + upperValue := thisObject.get(upper.name) + thisObject.put(lower.name, upperValue, true) + thisObject.put(upper.name, lowerValue, true) } else if !lower.exists && upper.exists { - value := thisObject.Get(upper.name) - thisObject.Delete(upper.name, true) - thisObject.Put(lower.name, value, true) + value := thisObject.get(upper.name) + thisObject.delete(upper.name, true) + thisObject.put(lower.name, value, true) } else if lower.exists && !upper.exists { - value := thisObject.Get(lower.name) - thisObject.Delete(lower.name, true) - thisObject.Put(upper.name, value, true) + value := thisObject.get(lower.name) + thisObject.delete(lower.name, true) + thisObject.put(upper.name, value, true) } else { // Nothing happens. } @@ -1033,9 +1033,9 @@ func sortCompare(thisObject *_object, index0, index1 uint, compare *_object) int }{} k := j j.name = arrayIndexToString(index0) - j.exists = thisObject.HasProperty(j.name) + j.exists = thisObject.hasProperty(j.name) k.name = arrayIndexToString(index1) - k.exists = thisObject.HasProperty(k.name) + k.exists = thisObject.hasProperty(k.name) if !j.exists && !k.exists { return 0 @@ -1045,8 +1045,8 @@ func sortCompare(thisObject *_object, index0, index1 uint, compare *_object) int return -1 } - x := thisObject.Get(j.name) - y := thisObject.Get(k.name) + x := thisObject.get(j.name) + y := thisObject.get(k.name) j.defined = x.IsDefined() k.defined = y.IsDefined() @@ -1083,23 +1083,23 @@ func arraySortSwap(thisObject *_object, index0, index1 uint) { k := j j.name = arrayIndexToString(index0) - j.exists = thisObject.HasProperty(j.name) + j.exists = thisObject.hasProperty(j.name) k.name = arrayIndexToString(index1) - k.exists = thisObject.HasProperty(k.name) + k.exists = thisObject.hasProperty(k.name) if j.exists && k.exists { - jValue := thisObject.Get(j.name) - kValue := thisObject.Get(k.name) - thisObject.Put(j.name, kValue, true) - thisObject.Put(k.name, jValue, true) + jValue := thisObject.get(j.name) + kValue := thisObject.get(k.name) + thisObject.put(j.name, kValue, true) + thisObject.put(k.name, jValue, true) } else if !j.exists && k.exists { - value := thisObject.Get(k.name) - thisObject.Delete(k.name, true) - thisObject.Put(j.name, value, true) + value := thisObject.get(k.name) + thisObject.delete(k.name, true) + thisObject.put(j.name, value, true) } else if j.exists && !k.exists { - value := thisObject.Get(j.name) - thisObject.Delete(j.name, true) - thisObject.Put(k.name, value, true) + value := thisObject.get(j.name) + thisObject.delete(j.name, true) + thisObject.put(k.name, value, true) } else { // Nothing happens. } @@ -1131,7 +1131,7 @@ func arraySortQuickSort(thisObject *_object, left, right uint, compare *_object) func builtinArray_sort(call FunctionCall) Value { thisObject := call.thisObject() - length := uint(toUI32(thisObject.Get("length"))) + length := uint(toUI32(thisObject.get("length"))) compareValue := call.Argument(0) compare := compareValue._object() if compareValue.IsUndefined() { @@ -1156,15 +1156,15 @@ func builtinNewRegExp(self *_object, _ Value, argumentList []Value) Value { func builtinRegExp_toString(call FunctionCall) Value { thisObject := call.thisObject() - source := toString(thisObject.Get("source")) + source := toString(thisObject.get("source")) flags := []byte{} - if toBoolean(thisObject.Get("global")) { + if toBoolean(thisObject.get("global")) { flags = append(flags, 'g') } - if toBoolean(thisObject.Get("ignoreCase")) { + if toBoolean(thisObject.get("ignoreCase")) { flags = append(flags, 'i') } - if toBoolean(thisObject.Get("multiline")) { + if toBoolean(thisObject.get("multiline")) { flags = append(flags, 'm') } return toValue(fmt.Sprintf("/%s/%s", source, flags)) @@ -1339,13 +1339,13 @@ func builtinError_toString(call FunctionCall) Value { } name := "Error" - nameValue := thisObject.Get("name") + nameValue := thisObject.get("name") if nameValue.IsDefined() { name = toString(nameValue) } message := "" - messageValue := thisObject.Get("message") + messageValue := thisObject.get("message") if messageValue.IsDefined() { message = toString(messageValue) } diff --git a/console.go b/console.go index 35f000d..6310790 100644 --- a/console.go +++ b/console.go @@ -32,7 +32,7 @@ func builtinConsole_placeholder(call FunctionCall) Value { func (runtime *_runtime) newConsole() *_object { self := runtime.newObject() - self.Define( + self.write( "log", builtinConsole_log, "debug", builtinConsole_log, "info", builtinConsole_log, diff --git a/environment.go b/environment.go index 45a2b5f..c4b6ba4 100644 --- a/environment.go +++ b/environment.go @@ -58,7 +58,7 @@ func (self *_functionEnvironment) HasBinding(name string) bool { if exists { return true } - return self.Object.HasProperty(name) + return self.Object.hasProperty(name) } type _objectEnvironment struct { @@ -77,23 +77,23 @@ func (runtime *_runtime) newObjectEnvironment() *_objectEnvironment { } 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) { - if self.Object.HasProperty(name) { + if self.Object.hasProperty(name) { panic(hereBeDragons()) } - self.Object._propertyStash.Write(name, UndefinedValue()) + self.Object.stash.put(name, UndefinedValue()) } 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 { - if self.Object.HasProperty(name) { - return self.Object.Get(name) + if self.Object.hasProperty(name) { + return self.Object.get(name) } if strict { 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 { - return self.Object.Delete(name, false) + return self.Object.delete(name, false) } func (self *_objectEnvironment) ImplicitThisValue() *_object { diff --git a/evaluate_expression.go b/evaluate_expression.go index 2d5fae4..a9b7b15 100644 --- a/evaluate_expression.go +++ b/evaluate_expression.go @@ -46,7 +46,7 @@ func (self *_runtime) evaluateObject(node *_objectNode) Value { result := self.newObject() 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) @@ -118,7 +118,7 @@ func (self *_runtime) evaluateUnaryOperation(node *_unaryOperationNode) Value { case valueString: return toValue("string") case valueObject: - if targetValue._object().Function != nil { + if targetValue._object()._Function != nil { return toValue("function") } return toValue("object") @@ -256,7 +256,7 @@ func (self *_runtime) calculateBinaryOperation(operator string, left Value, righ if !rightValue.IsObject() { panic(newTypeError()) } - return toValue(rightValue._object().HasProperty(toString(leftValue))) + return toValue(rightValue._object().hasProperty(toString(leftValue))) } panic(hereBeDragons(operator)) diff --git a/evaluate_statement.go b/evaluate_statement.go index edc7a1e..8bb81b1 100644 --- a/evaluate_statement.go +++ b/evaluate_statement.go @@ -190,7 +190,7 @@ func (self *_runtime) evaluateForIn(node *_forInNode) Value { result := emptyValue() object := sourceObject for object != nil { - object.Enumerate(func(name string){ + object.enumerate(func(name string){ into := self.evaluate(into) // In the case of: for (var abc in def) ... if into.reference() == nil { @@ -204,7 +204,7 @@ func (self *_runtime) evaluateForIn(node *_forInNode) Value { result = value } }) - object = object.Prototype + object = object.prototype } return result }) diff --git a/global.go b/global.go index 5962ac1..7fc93a1 100644 --- a/global.go +++ b/global.go @@ -10,45 +10,43 @@ type _globalConstructFunction _constructFunction func (self *_runtime) newGlobalFunction( length int, - callFunction _globalCallFunction, + name string, callFunction _globalCallFunction, constructFunction _globalConstructFunction, prototype *_object, - nameAndValue... interface{}) *_object { -// + definition... interface{}) *_object { + // TODO We're overwriting the prototype of newNativeFunction with this one, // what is going on? - target := self.newNativeFunction(_nativeFunction(callFunction), length) - target.Function.Construct = _constructFunction(constructFunction) - target.define(_propertyMode(0), "prototype", toValue(prototype)) - nameAndValue = append( - []interface{}{ + functionObject := self.newNativeFunction(_nativeFunction(callFunction), length, "native" + name) + functionObject._Function.Construct = _constructFunction(constructFunction) + functionObject.stash.set("prototype", toValue(prototype), _propertyMode(0)) + + prototype.write(append([]interface{}{ _functionSignature("builtin"), - _propertyMode(propertyModeWrite | propertyModeConfigure), - "constructor", toValue(target), + _propertyMode(0101), // Write | Configure + "constructor", toValue(functionObject), }, - nameAndValue..., - ) - // This actually may be slower than Define - // Benchmark? - prototype.define(nameAndValue...) - return target + definition..., + )...) + + return functionObject } func (self *_runtime) newGlobalObject( class string, nameAndValue... interface{}) *_object { -// + target := self.newClassObject(class) nameAndValue = append( []interface{}{ _functionSignature("builtin"), - _propertyMode(propertyModeWrite | propertyModeConfigure), + _propertyMode(0101), // Write | Configure }, nameAndValue..., ) // This actually may be slower than Define // Benchmark? - target.define(nameAndValue...) + target.write(nameAndValue...) return target } @@ -56,11 +54,11 @@ func builtinDefine(target *_object, nameAndValue... interface{}) { nameAndValue = append( []interface{}{ _functionSignature("builtin"), - _propertyMode(propertyModeWrite | propertyModeConfigure), + _propertyMode(0101), // Write | Configure }, nameAndValue..., ) - target.define(nameAndValue) + target.write(nameAndValue) } func newContext() *_runtime { @@ -76,63 +74,63 @@ func newContext() *_runtime { { ObjectPrototype := self.newObject() - ObjectPrototype.Prototype = nil + ObjectPrototype.prototype = nil self.Global.ObjectPrototype = ObjectPrototype } { FunctionPrototype := self.newNativeFunctionObject(func(FunctionCall) Value { return UndefinedValue() - }, 0) - FunctionPrototype.Prototype = self.Global.ObjectPrototype + }, 0, "nativeFunction_") + FunctionPrototype.prototype = self.Global.ObjectPrototype self.Global.FunctionPrototype = FunctionPrototype } { ArrayPrototype := self.newArray([]Value{}) - ArrayPrototype.Prototype = self.Global.ObjectPrototype + ArrayPrototype.prototype = self.Global.ObjectPrototype self.Global.ArrayPrototype = ArrayPrototype } { StringPrototype := self.newString(toValue("")) - StringPrototype.Prototype = self.Global.ObjectPrototype + StringPrototype.prototype = self.Global.ObjectPrototype self.Global.StringPrototype = StringPrototype } { BooleanPrototype := self.newBoolean(FalseValue()) - BooleanPrototype.Prototype = self.Global.ObjectPrototype + BooleanPrototype.prototype = self.Global.ObjectPrototype self.Global.BooleanPrototype = BooleanPrototype } { NumberPrototype := self.newNumber(toValue(0)) - NumberPrototype.Prototype = self.Global.ObjectPrototype + NumberPrototype.prototype = self.Global.ObjectPrototype self.Global.NumberPrototype = NumberPrototype } { DatePrototype := self.newDate(0) - DatePrototype.Prototype = self.Global.ObjectPrototype + DatePrototype.prototype = self.Global.ObjectPrototype self.Global.DatePrototype = DatePrototype } { RegExpPrototype := self.newRegExp(UndefinedValue(), UndefinedValue()) - RegExpPrototype.Prototype = self.Global.ObjectPrototype + RegExpPrototype.prototype = self.Global.ObjectPrototype self.Global.RegExpPrototype = RegExpPrototype } { ErrorPrototype := self.newErrorObject(UndefinedValue()) - ErrorPrototype.Prototype = self.Global.ObjectPrototype + ErrorPrototype.prototype = self.Global.ObjectPrototype self.Global.ErrorPrototype = ErrorPrototype } self.Global.Object = self.newGlobalFunction( 1, - builtinObject, + "Object", builtinObject, builtinNewObject, self.Global.ObjectPrototype, "valueOf", func(call FunctionCall) Value { @@ -142,27 +140,27 @@ func newContext() *_runtime { "hasOwnProperty", func(call FunctionCall) Value { propertyName := toString(call.Argument(0)) thisObject := call.thisObject() - return toValue(thisObject.HasOwnProperty(propertyName)) + return toValue(thisObject.hasOwnProperty(propertyName)) }, "isPrototypeOf", func(call FunctionCall) Value { value := call.Argument(0) if !value.IsObject() { return FalseValue() } - prototype := call.toObject(value).Prototype + prototype := call.toObject(value).prototype thisObject := call.thisObject() for prototype != nil { if thisObject == prototype { return TrueValue() } - prototype = prototype.Prototype + prototype = prototype.prototype } return FalseValue() }, "propertyIsEnumerable", func(call FunctionCall) Value { propertyName := toString(call.Argument(0)) thisObject := call.thisObject() - property := thisObject.GetOwnProperty(propertyName) + property := thisObject.getOwnProperty(propertyName) if property != nil && property.CanEnumerate() { return TrueValue() } @@ -172,7 +170,7 @@ func newContext() *_runtime { self.Global.Function = self.newGlobalFunction( 1, - builtinFunction, + "Function", builtinFunction, builtinNewFunction, self.Global.FunctionPrototype, "toString", func(FunctionCall) Value { @@ -184,16 +182,16 @@ func newContext() *_runtime { self.Global.Array = self.newGlobalFunction( 1, - builtinArray, + "Array", builtinArray, builtinNewArray, self.Global.ArrayPrototype, "toString", func(call FunctionCall) Value { thisObject := call.thisObject() - join := thisObject.Get("join") + join := thisObject.get("join") if join.isCallable() { join := join._object() - if join.Function.Call.Signature() == "builtin" { - if stash, isArray := thisObject._propertyStash.(*_arrayStash); isArray { + if join._Function.Call.name() == "nativeArray_join" { + if stash, isArray := thisObject.stash.(*_arrayStash); isArray { return toValue(builtinArray_joinNative(stash.valueArray, ",")) } } @@ -215,14 +213,14 @@ func newContext() *_runtime { self.Global.String = self.newGlobalFunction( 1, - builtinString, + "String", builtinString, builtinNewString, self.Global.StringPrototype, "toString", func(call FunctionCall) Value { - return *call.thisClassObject("String").Primitive + return *call.thisClassObject("String").primitive }, "valueOf", func(call FunctionCall) Value { - return *call.thisClassObject("String").Primitive + return *call.thisClassObject("String").primitive }, "charAt", 1, builtinString_charAt, "charCodeAt", 1, builtinString_charCodeAt, @@ -240,27 +238,27 @@ func newContext() *_runtime { "substr", 2, builtinString_substr, ) // TODO Maybe streamline this redundancy? - self.Global.String.Define( + self.Global.String.write( "fromCharCode", 1, builtinString_fromCharCode, ) self.Global.Boolean = self.newGlobalFunction( 1, - builtinBoolean, + "Boolean", builtinBoolean, builtinNewBoolean, self.Global.BooleanPrototype, "toString", func(call FunctionCall) Value { value := call.This if !value.IsBoolean() { // Will throw a TypeError if ThisObject is not a Boolean - value = call.thisClassObject("Boolean").PrimitiveValue() + value = call.thisClassObject("Boolean").primitiveValue() } return toValue(toString(value)) }, "valueOf", func(call FunctionCall) Value { value := call.This if !value.IsBoolean() { - value = call.thisClassObject("Boolean").PrimitiveValue() + value = call.thisClassObject("Boolean").primitiveValue() } return value }, @@ -268,18 +266,18 @@ func newContext() *_runtime { self.Global.Number = self.newGlobalFunction( 1, - builtinNumber, + "Number", builtinNumber, builtinNewNumber, self.Global.NumberPrototype, "valueOf", func(call FunctionCall) Value { - return *call.thisClassObject("Number").Primitive + return *call.thisClassObject("Number").primitive }, // TODO toFixed // TODO toExponential // TODO toPrecision ) - self.Global.Number.Define( + self.Global.Number.write( _propertyMode(0), "MAX_VALUE", toValue(math.MaxFloat64), "MIN_VALUE", toValue(math.SmallestNonzeroFloat64), @@ -300,7 +298,7 @@ func newContext() *_runtime { self.Global.Date = self.newGlobalFunction( 7, - builtinDate, + "Date", builtinDate, builtinNewDate, self.Global.DatePrototype, "toString", 0, builtinDate_toString, @@ -584,7 +582,7 @@ func newContext() *_runtime { self.Global.RegExp = self.newGlobalFunction( 2, - builtinRegExp, + "RegExp", builtinRegExp, builtinNewRegExp, self.Global.RegExpPrototype, "toString", 0, builtinRegExp_toString, @@ -594,14 +592,14 @@ func newContext() *_runtime { self.Global.Error = self.newGlobalFunction( 1, - builtinError, + "Error", builtinError, builtinNewError, self.Global.ErrorPrototype, "name", toValue("Error"), "toString", 0, builtinError_toString, ) - self.GlobalObject.Define( + self.GlobalObject.write( "Object", toValue(self.Global.Object), "Function", toValue(self.Global.Function), "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 { self := runtime.newClassObject(class) - self.Primitive = &value + self.primitive = &value return self } func (runtime *_runtime) newObject() *_object { self := runtime.newClassObject("Object") - self.Prototype = runtime.Global.ObjectPrototype + self.prototype = runtime.Global.ObjectPrototype return self } func (runtime *_runtime) newArray(valueArray []Value) *_object { self := runtime.newArrayObject(valueArray) - self.Prototype = runtime.Global.ArrayPrototype + self.prototype = runtime.Global.ArrayPrototype return self } func (runtime *_runtime) newString(value Value) *_object { self := runtime.newStringObject(value) - self.Prototype = runtime.Global.StringPrototype + self.prototype = runtime.Global.StringPrototype return self } func (runtime *_runtime) newBoolean(value Value) *_object { self := runtime.newBooleanObject(value) - self.Prototype = runtime.Global.BooleanPrototype + self.prototype = runtime.Global.BooleanPrototype return self } func (runtime *_runtime) newNumber(value Value) *_object { self := runtime.newNumberObject(value) - self.Prototype = runtime.Global.NumberPrototype + self.prototype = runtime.Global.NumberPrototype return self } @@ -699,14 +697,14 @@ func (runtime *_runtime) newRegExp(patternValue Value, flagsValue Value) *_objec func (runtime *_runtime) _newRegExp(pattern string, flags string) *_object { self := runtime.newRegExpObject(pattern, flags) - self.Prototype = runtime.Global.RegExpPrototype + self.prototype = runtime.Global.RegExpPrototype return self } // TODO Should (probably) be one argument, right? This is redundant func (runtime *_runtime) newDate(epoch float64) *_object { self := runtime.newDateObject(epoch) - self.Prototype = runtime.Global.DatePrototype + self.prototype = runtime.Global.DatePrototype return self } @@ -717,43 +715,37 @@ func (runtime *_runtime) newError(name string, message Value) *_object { self = _newError(message) } else { self = runtime.newErrorObject(message) - self.Prototype = runtime.Global.ErrorPrototype + self.prototype = runtime.Global.ErrorPrototype if name != "" { - self.WriteValue("name", toValue(name), false) + self.set("name", toValue(name), false) } } return self } -func (runtime *_runtime) newNativeFunction(_nativeFunction _nativeFunction, length int) *_object { - self := runtime.newNativeFunctionObject(_nativeFunction, length) - self.Prototype = runtime.Global.FunctionPrototype +func (runtime *_runtime) newNativeFunction(_nativeFunction _nativeFunction, length int, name string) *_object { + self := runtime.newNativeFunctionObject(_nativeFunction, length, name) + self.prototype = runtime.Global.FunctionPrototype prototype := runtime.newObject() - self.define(_propertyMode(0), "prototype", toValue(prototype)) - prototype.define( - _propertyMode(propertyModeWrite | propertyModeConfigure), - "constructor", toValue(self), - ) + self.stash.set("prototype", toValue(prototype), _propertyMode(0100)) + prototype.stash.set("constructor", toValue(self), _propertyMode(0101)) return self } func (runtime *_runtime) newNodeFunction(node *_functionNode, scopeEnvironment _environment) *_object { // TODO Implement 13.2 fully self := runtime.newNodeFunctionObject(node, scopeEnvironment) - self.Prototype = runtime.Global.FunctionPrototype + self.prototype = runtime.Global.FunctionPrototype prototype := runtime.newObject() - self.define(_propertyMode(propertyModeWrite), "prototype", toValue(prototype)) - prototype.define( - _propertyMode(propertyModeWrite | propertyModeConfigure), - "constructor", toValue(self), - ) + self.stash.set("prototype", toValue(prototype), _propertyMode(0100)) + prototype.stash.set("constructor", toValue(self), _propertyMode(0101)) return self } func (runtime *_runtime) newErrorPrototype(name string) *_object { prototype := runtime.newClassObject("Error") - prototype.WriteValue("name", toValue(name), false) - prototype.Prototype = runtime.Global.ErrorPrototype + prototype.set("name", toValue(name), false) + prototype.prototype = runtime.Global.ErrorPrototype return prototype } @@ -762,13 +754,14 @@ func (runtime *_runtime) defineError(name string) func(Value) *_object { errorFunction := func(message Value) *_object { error := runtime.newErrorObject(message) - error.Prototype = prototype + error.prototype = prototype return error } - runtime.GlobalObject.WriteValue(name, toValue(runtime.newGlobalFunction( + runtime.GlobalObject.set(name, toValue(runtime.newGlobalFunction( 1, // e.g. TypeError( ... ) + name, func (call FunctionCall) Value { // TypeError( ... ) return toValue(errorFunction(call.Argument(0))) }, diff --git a/global_test.go b/global_test.go index 3fe6308..3fdddae 100644 --- a/global_test.go +++ b/global_test.go @@ -17,21 +17,21 @@ func TestGlobal(t *testing.T) { result := runtime.localGet("Object")._object().Call(UndefinedValue(), []Value{toValue(runtime.newObject())}) Is(result.IsObject(), true) Is(result, "[object Object]") - Is(result._object().Prototype == runtime.Global.ObjectPrototype, true) - Is(result._object().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().prototype == runtime.Global.ObjectPrototype, true) + Is(result._object().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().CallMethod("hasOwnProperty", "hasOwnProperty"), falseValue) - //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"), "[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"), "[function]") //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(result.Object().CallMethod("propertyIsEnumerable", "isPrototypeOf"), falseValue) //result.Object().WriteValue("xyzzy", toValue("Nothing happens."), false) //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()) Is(abc, "true") diff --git a/object.go b/object.go index 4c765bd..fa4a786 100644 --- a/object.go +++ b/object.go @@ -3,70 +3,55 @@ package otto type _object struct { runtime *_runtime - Class string - Extensible bool - Prototype *_object + class string + prototype *_object - _propertyStash _stash + stash _stash - Primitive *Value - Function *_functionObject - RegExp *_regExpObject - Date *_dateObject + primitive *Value + _Function *_functionObject + _RegExp *_regExpObject + _Date *_dateObject } -func (self _object) PrimitiveValue() Value { - return *self.Primitive +func (self _object) extensible() bool { + return self.stash.extensible() +} + +func (self _object) primitiveValue() Value { + return *self.primitive } func newObject(runtime *_runtime, class string) *_object { return &_object{ runtime: runtime, - Class: class, - Extensible: true, + class: class, - _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 -func (self *_object) Delete(name string, throw bool) bool { - property_ := self.GetOwnProperty(name) +func (self *_object) delete(name string, throw bool) bool { + property_ := self.getOwnProperty(name) if property_ == nil { return true } if property_.CanConfigure() { - self._propertyStash.Delete(name) + self.stash.delete(name) return true } return typeErrorResult(throw) } -// Get - -func (self *_object) GetValue(name string) Value { - return self.Get(name) -} - // 8.12 // 8.12.1 -func (self *_object) GetOwnProperty(name string) *_property { +func (self *_object) getOwnProperty(name string) *_property { // Return a _copy_ of the property - property := self._propertyStash.property(name) + property := self.stash.property(name) if property == nil { return nil } @@ -76,10 +61,11 @@ func (self *_object) GetOwnProperty(name string) *_property { } } +// 8.12.2 func (self *_object) getProperty(name string) *_property { - - for object := self; object != nil; object = object.Prototype { - property := object._propertyStash.property(name) + for object := self; object != nil; object = object.prototype { + // Despite being a pointer, this property is always a copy + property := object.stash.property(name) if property != nil { return property } @@ -88,31 +74,22 @@ func (self *_object) getProperty(name string) *_property { 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 -func (self *_object) Get(name string) Value { +func (self *_object) get(name string) Value { object := self for object != nil { - if object._propertyStash.CanRead(name) { - return object._propertyStash.Read(name) + if object.stash.test(name) { + return object.stash.get(name) } - object = object.Prototype + object = object.prototype } return UndefinedValue() } // 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 { switch value := property.Value.(type) { case Value: @@ -124,16 +101,16 @@ func (self *_object) CanPut(name string) bool { } } - if self.Prototype != nil { - property = self.Prototype.getProperty(name) + if self.prototype != nil { + property = self.prototype.getProperty(name) } if property == nil { - return self.Extensible + return self.extensible() } switch value := property.Value.(type) { case Value: - if !self.Extensible { + if !self.extensible() { return false } return property.CanWrite() @@ -145,18 +122,27 @@ func (self *_object) CanPut(name string) bool { } // 8.12.5 -func (self *_object) Put(name string, value Value, throw bool) { - if !self.CanPut(name) { +func (self *_object) put(name string, value Value, throw bool) { + if !self.canPut(name) { typeErrorResult(throw) 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 -func (self *_object) HasProperty(name string) bool { - for object := self; object != nil; object = object.Prototype { - if object._propertyStash.CanRead(name) { +func (self *_object) hasProperty(name string) bool { + for object := self; object != nil; object = object.prototype { + if object.stash.test(name) { return true } } @@ -167,29 +153,29 @@ func (self *_object) HasProperty(name string) bool { type _defaultValueHint int const ( - defaultValueNoHint _defaultValueHint = iota - defaultValueHintString - defaultValueHintNumber + defaultValueNoHint _defaultValueHint = iota + defaultValueHintString + defaultValueHintNumber ) // 8.12.8 func (self *_object) DefaultValue(hint _defaultValueHint) Value { - if hint == defaultValueNoHint { - hint = defaultValueHintNumber - } - methodSequence := []string{"valueOf", "toString"} - if (hint == defaultValueHintString) { - methodSequence = []string{"toString", "valueOf"} - } - for _, methodName := range methodSequence { - method := self.Get(methodName) - if method.isCallable() { - result := method._object().Call(toValue(self)) - if result.IsPrimitive() { - return result - } - } - } + if hint == defaultValueNoHint { + hint = defaultValueHintNumber + } + methodSequence := []string{"valueOf", "toString"} + if hint == defaultValueHintString { + methodSequence = []string{"toString", "valueOf"} + } + for _, methodName := range methodSequence { + method := self.get(methodName) + if method.isCallable() { + result := method._object().Call(toValue(self)) + if result.IsPrimitive() { + return result + } + } + } panic(newTypeError()) return UndefinedValue() @@ -200,105 +186,93 @@ func (self *_object) String() string { } // 8.12.9 -func (self *_object) DefineOwnProperty(name string, _defineProperty _defineProperty, throw bool) bool { - return self._propertyStash.Define(name, _defineProperty) +func (self *_object) defineOwnProperty(name string, _defineProperty _defineProperty, throw bool) bool { + return self.stash.define(name, _defineProperty) } -func (self *_object) DefineOwnValueProperty(name string, value Value, mode _propertyMode, throw bool) bool { - return self._propertyStash.Define(name, _property{Value: value, Mode: mode}.toDefineProperty()) +func (self *_object) hasOwnProperty(name string) bool { + return self.stash.test(name) } -func (self *_object) HasOwnProperty(name string) bool { - return self._propertyStash.CanRead(name) -} +//func (self *_object) Define(definition... interface{}) { +// property_ := _property{ Mode: 0111 }.toDefineProperty() +// length := 0 +// nativeClass_ := "native" + self.Class + "_" -func (self *_object) Define(nameAndValue... interface{}) { - property_ := _property{Mode: propertyModeWriteEnumerateConfigure}.toDefineProperty() +// for index := 0; index < len(definition); index++ { +// 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 - signature := _functionSignature("") + nativeClass_ := "native" + self.class + "_" - for index := 0; index < len(nameAndValue); index++ { - value := nameAndValue[index] + for index := 0; index < len(definition); index++ { + value := definition[index] 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: mode = value case string: name := value length = 0 index += 1 -REPEAT: { - value := nameAndValue[index] + REPEAT: + { + value := definition[index] switch value := value.(type) { - case func(FunctionCall) Value: { - value := self.runtime.newNativeFunction(value, length) - value.Function.Call.Sign(signature) - stash[name] = _valueProperty{ toValue(value), mode } + case func(FunctionCall) Value: + { + value := self.runtime.newNativeFunction(value, length, nativeClass_+name) + self.stash.set(name, toValue(value), mode) } - case *_object: - stash[name] = _valueProperty{ toValue(value), mode } - case Value: - stash[name] = _valueProperty{ value, mode } - case int: - length = value - index += 1 - goto REPEAT - default: - panic(hereBeDragons()) + case *_object: + self.stash.set(name, toValue(value), mode) + case Value: + self.stash.set(name, value, mode) + case int: + length = value + index += 1 + goto REPEAT + default: + panic(hereBeDragons()) } } } } - - self._propertyStash.writeValuePropertyMap(stash) } -func (self *_object) Enumerate(each func(string)) { - self._propertyStash.Enumerate(each) +func (self *_object) enumerate(each func(string)) { + self.stash.enumerate(each) } diff --git a/object_test.go b/object_test.go index c65a552..e87a54d 100644 --- a/object_test.go +++ b/object_test.go @@ -11,15 +11,15 @@ func TestObject_(t *testing.T) { object := newObject(nil, "") IsTrue(object != nil) - object.Put("xyzzy", toValue("Nothing happens."), true) - Is(object.Get("xyzzy"), "Nothing happens.") + object.put("xyzzy", toValue("Nothing happens."), true) + Is(object.get("xyzzy"), "Nothing happens.") } func TestStringObject(t *testing.T) { Terst(t) object := New().runtime.newStringObject(toValue("xyzzy")) - Is(object.Get("1"), "y") - Is(object.Get("10"), "undefined") - Is(object.Get("2"), "z") + Is(object.get("1"), "y") + Is(object.get("10"), "undefined") + Is(object.get("2"), "z") } diff --git a/otto.go b/otto.go index 0bfc154..c640a4f 100644 --- a/otto.go +++ b/otto.go @@ -289,7 +289,7 @@ func (self Object) Value() Value { func (self Object) Get(name string) (Value, error) { result := UndefinedValue() err := catchPanic(func(){ - result = self.object.Get(name) + result = self.object.get(name) }) 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. func (self Object) Set(name string, value interface{}) (error) { 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 } @@ -319,5 +319,5 @@ func (self Object) Set(name string, value interface{}) (error) { // RegExp // func (self Object) Class() string { - return self.object.Class + return self.object.class } diff --git a/otto_test.go b/otto_test.go index fa150c8..5dfd2b5 100644 --- a/otto_test.go +++ b/otto_test.go @@ -948,7 +948,7 @@ func TestObjectLiteral(t *testing.T) { Otto.Run(` 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) { @@ -963,7 +963,7 @@ func TestArrayLiteral(t *testing.T) { test(` result = [ "Nothing happens.", 0, 1 ] `) - Is(test("result")._object().GetValue("0"), "Nothing happens.") + Is(test("result")._object().get("0"), "Nothing happens.") test(` xyzzy = [ "Nothing happens.", 0, 1 ] @@ -1554,15 +1554,15 @@ func TestRegExp(t *testing.T) { test(`""+/abc/gi`, "/abc/gi") result := test(`/(a)?/.exec('b')`, ",") - Is(result._object().Get("0"), "") - Is(result._object().Get("1"), "undefined") - Is(result._object().Get("length"), "2") + Is(result._object().get("0"), "") + Is(result._object().get("1"), "undefined") + Is(result._object().get("length"), "2") result = test(`/(a)?(b)?/.exec('b')`, "b,,b") - Is(result._object().Get("0"), "b") - Is(result._object().Get("1"), "undefined") - Is(result._object().Get("2"), "b") - Is(result._object().Get("length"), "3") + Is(result._object().get("0"), "b") + Is(result._object().get("1"), "undefined") + Is(result._object().get("2"), "b") + Is(result._object().get("length"), "3") test(`/\u0041/.source`, "\\u0041") test(`/\a/.source`, "\\a") diff --git a/property.go b/property.go index 71e55a5..36465dc 100644 --- a/property.go +++ b/property.go @@ -5,63 +5,62 @@ package otto type _propertyMode int const ( - propertyModeEmpty _propertyMode = 1 - propertyModeWrite = 2 - propertyModeEnumerate = 4 - propertyModeConfigure = 8 -) - -const ( - propertyModeWriteEnumerateConfigure _propertyMode = propertyModeWrite | propertyModeEnumerate | propertyModeConfigure + propertyModeWrite _propertyMode = 0100 + propertyModeEnumerate = 0010 + propertyModeConfigure = 0001 ) type _propertyGetSet [2]*_object type _property struct { Value interface{} - Mode _propertyMode + Mode _propertyMode } func (self _property) CanWrite() bool { - return self.Mode & propertyModeWrite != 0 + return self.Mode&propertyModeWrite != 0 } func (self _property) CanEnumerate() bool { - return self.Mode & propertyModeEnumerate != 0 + return self.Mode&propertyModeEnumerate != 0 } func (self _property) CanConfigure() bool { - return self.Mode & propertyModeConfigure != 0 + return self.Mode&propertyModeConfigure != 0 } func (self _property) toDefineProperty() _defineProperty { property := _defineProperty{ Value: self.Value, } - mode := self.Mode - if mode & propertyModeEmpty != 0 { - return property - } - if mode & propertyModeWrite != 0 { - property.Write = propertyAttributeTrue - } else { - property.Write = propertyAttributeFalse - } - if mode & propertyModeEnumerate != 0 { - property.Enumerate = propertyAttributeTrue - } else { - property.Enumerate = propertyAttributeFalse - } - if mode & propertyModeConfigure != 0 { - property.Configure = propertyAttributeTrue - } else { - property.Configure = propertyAttributeFalse + + { + mode := self.Mode + + if mode&propertyModeWrite != 0 { + property.Write = propertyAttributeTrue + } else { + property.Write = propertyAttributeFalse + } + + if mode&propertyModeEnumerate != 0 { + property.Enumerate = propertyAttributeTrue + } else { + property.Enumerate = propertyAttributeFalse + } + + if mode&propertyModeConfigure != 0 { + property.Configure = propertyAttributeTrue + } else { + property.Configure = propertyAttributeFalse + } } + return property } -func (self *_property) Copy() *_property { - property := *self +func (self _property) Copy() *_property { + property := self return &property } @@ -69,7 +68,7 @@ func (self *_property) Copy() *_property { type _valueProperty struct { Value Value - Mode _propertyMode + Mode _propertyMode } // _defineProperty @@ -83,8 +82,8 @@ const ( ) type _defineProperty struct { - Value interface{} - Write _propertyAttributeBoolean + Value interface{} + Write _propertyAttributeBoolean Enumerate _propertyAttributeBoolean Configure _propertyAttributeBoolean } @@ -130,9 +129,9 @@ func (self _defineProperty) IsGenericDescriptor() bool { func (self _defineProperty) isEmpty() bool { return self.IsGenericDescriptor() && - self.Write == propertyAttributeNotSet && - self.Enumerate == propertyAttributeNotSet && - self.Configure == propertyAttributeNotSet + self.Write == propertyAttributeNotSet && + self.Enumerate == propertyAttributeNotSet && + self.Configure == propertyAttributeNotSet } func (self _defineProperty) CopyInto(other *_property) { @@ -161,4 +160,3 @@ func (self _defineProperty) CopyInto(other *_property) { other.Value = self.Value } } - diff --git a/runtime.go b/runtime.go index a015588..c36661a 100644 --- a/runtime.go +++ b/runtime.go @@ -61,7 +61,7 @@ func (self *_runtime) _executionContext(depth int) *_executionContext { } func (self *_runtime) EnterFunctionExecutionContext(function *_object, this Value) *_functionEnvironment { - scopeEnvironment := function.Function.Call.ScopeEnvironment() + scopeEnvironment := function._Function.Call.ScopeEnvironment() if scopeEnvironment == nil { scopeEnvironment = self.GlobalEnvironment } @@ -112,7 +112,7 @@ func (self *_runtime) PutValue(reference _reference, value Value) { if !reference.PutValue(value) { // Why? -- If reference.Base == nil 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 } @@ -307,9 +307,9 @@ func testObjectCoercible(value Value) (isObject bool, mustCoerce bool) { func (self *_runtime) toValue(value interface{}) Value { switch value := value.(type) { case func(FunctionCall) Value: - return toValue(self.newNativeFunction(value, 0)) + return toValue(self.newNativeFunction(value, 0, "nativeFunction")) case _nativeFunction: - return toValue(self.newNativeFunction(value, 0)) + return toValue(self.newNativeFunction(value, 0, "nativeFunction")) } return toValue(value) } diff --git a/stash.go b/stash.go index b279f60..59b9402 100644 --- a/stash.go +++ b/stash.go @@ -1,38 +1,44 @@ package otto type _stash interface { - CanRead(string) bool - Read(string) Value - CanWrite(string) bool - Write(string, Value) + test(string) bool + get(string) Value property(string) *_property - Delete(string) - Define(string, _defineProperty) bool - Enumerate(func(string)) - writeValuePropertyMap(map[string]_valueProperty) + enumerate(func(string)) + + canPut(string) bool + put(string, Value) + set(string, Value, _propertyMode) + define(string, _defineProperty) bool + + delete(string) + + extensible() bool + lock() + unlock() } -type _propertyStash struct { - canCreate bool - propertyMap map[string]*_property +type _objectStash struct { + _extensible bool + propertyMap map[string]_property } -func newPropertyStash(canCreate bool) *_propertyStash { - return &_propertyStash{ - canCreate: canCreate, - propertyMap: make(map[string]*_property), +func newObjectStash(extensible bool) *_objectStash { + return &_objectStash{ + _extensible: extensible, + propertyMap: make(map[string]_property), } } -func (self *_propertyStash) CanRead(name string) bool { +func (self *_objectStash) test(name string) bool { _, exists := self.propertyMap[name] return exists } -func (self *_propertyStash) Read(name string) Value { - property := self.propertyMap[name] +func (self *_objectStash) get(name string) Value { + property, exists := self.propertyMap[name] - if property == nil { + if !exists { return UndefinedValue() } @@ -49,10 +55,34 @@ func (self *_propertyStash) Read(name string) Value { panic(hereBeDragons()) } -func (self *_propertyStash) CanWrite(name string) bool { - property, _ := self.propertyMap[name] +func (self *_objectStash) property(name string) *_property { + 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 { - 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) { case Value: @@ -63,45 +93,40 @@ func (self *_propertyStash) CanWrite(name string) bool { panic(hereBeDragons()) } -func (self *_propertyStash) Write(name string, value Value) { - property_, _ := self.propertyMap[name] - if property_ != nil { - switch propertyValue := property_.Value.(type) { +func (self *_objectStash) put(name string, value Value) { + property, exists := self.propertyMap[name] + if exists { + switch propertyValue := property.Value.(type) { case Value: - if property_.CanWrite() { - property_.Value = value + if property.CanWrite() { + property.Value = value + self.propertyMap[name] = property } case _propertyGetSet: if propertyValue[1] != nil { propertyValue[1].CallSet(name, value) } } - } else if self.canCreate { - self.propertyMap[name] = &_property{ value, propertyModeWriteEnumerateConfigure } + } else if self.extensible() { + self.propertyMap[name] = _property{value, 0111} // Write, Enumerate, Configure } } -func (self *_propertyStash) property(name string) *_property { - property, _ := self.propertyMap[name] - return property +func (self *_objectStash) set(name string, value Value, mode _propertyMode) { + self.propertyMap[name] = _property{value, mode} } -func (self *_propertyStash) Delete(name string) { - delete(self.propertyMap, name) -} - -func (self *_propertyStash) Define(name string, define _defineProperty) bool { - canCreate := self.canCreate - property_, _ := self.propertyMap[name] - if property_ == nil { - if !canCreate { +// FIME This is wrong, and doesn't work like you think +func (self *_objectStash) define(name string, define _defineProperty) bool { + property, exists := self.index(name) + if !exists { + if !self.extensible() { return false } - property_ = &_property{ + self.propertyMap[name] = _property{ Value: define.Value, - Mode: define.Mode(), + Mode: define.Mode(), } - self.propertyMap[name] = property_ return true } 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 // 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 define.CanConfigure() { return false } - if define.Enumerate != propertyAttributeNotSet && define.CanEnumerate() != property_.CanEnumerate() { + if define.Enumerate != propertyAttributeNotSet && define.CanEnumerate() != property.CanEnumerate() { return false } } - value, isDataDescriptor := property_.Value.(Value) - getSet, _ := property_.Value.(_propertyGetSet) + value, isDataDescriptor := property.Value.(Value) + getSet, _ := property.Value.(_propertyGetSet) if define.IsGenericDescriptor() { - ; // GenericDescriptor + // GenericDescriptor } else if isDataDescriptor != define.IsDataDescriptor() { var interface_ interface{} if isDataDescriptor { - property_.Mode = property_.Mode & ^propertyModeWrite - property_.Value = interface_ + property.Mode = property.Mode & ^propertyModeWrite + property.Value = interface_ } else { - property_.Mode |= propertyModeWrite - property_.Value = interface_ + property.Mode |= propertyModeWrite + property.Value = interface_ } } else if isDataDescriptor && define.IsDataDescriptor() { if !canConfigure { - if property_.CanWrite() != define.CanWrite() { + if property.CanWrite() != define.CanWrite() { return false } else if !sameValue(value, define.Value.(Value)) { 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 } -func (self *_propertyStash) Enumerate(each func(string)) { - for name, property_ := range self.propertyMap { - if property_.CanEnumerate() { - each(name) - } - } +func (self *_objectStash) delete(name string) { + delete(self.propertyMap, name) } -func (self *_propertyStash) writeValuePropertyMap(valuePropertyMap map[string]_valueProperty) { - for name, _valueProperty := range valuePropertyMap { - self.propertyMap[name] = &_property{ Value: _valueProperty.Value, Mode: _valueProperty.Mode } - } +func (self _objectStash) extensible() bool { + return self._extensible +} + +func (self *_objectStash) lock() { + self._extensible = false +} + +func (self *_objectStash) unlock() { + self._extensible = true } diff --git a/stash_test.go b/stash_test.go index 17c68da..8514d60 100644 --- a/stash_test.go +++ b/stash_test.go @@ -8,19 +8,19 @@ import ( func TestStash(t *testing.T) { Terst(t) - stash := newPropertyStash(true) - IsTrue(stash.CanWrite("xyzzy")) + stash := newObjectStash(true) + IsTrue(stash.canPut("xyzzy")) - stash.Define("xyzzy", _defineProperty{ + stash.define("xyzzy", _defineProperty{ Value: toValue("Nothing happens."), }) - IsTrue(stash.CanRead("xyzzy")) - IsTrue(stash.CanWrite("xyzzy")) + IsTrue(stash.test("xyzzy")) + IsTrue(stash.canPut("xyzzy")) - stash.Define("xyzzy", _defineProperty{ + stash.define("xyzzy", _defineProperty{ Value: toValue("Something else happens."), Write: propertyAttributeFalse, }) - IsTrue(stash.CanRead("xyzzy")) - IsFalse(stash.CanWrite("xyzzy")) + IsTrue(stash.test("xyzzy")) + IsFalse(stash.canPut("xyzzy")) } diff --git a/type_arguments.go b/type_arguments.go index 9ab328e..65a5102 100644 --- a/type_arguments.go +++ b/type_arguments.go @@ -2,14 +2,14 @@ package otto func (runtime *_runtime) newArgumentsObject(argumentList []Value) *_object { self := runtime.newClassObject("Arguments") - self.Prototype = runtime.Global.ObjectPrototype + self.prototype = runtime.Global.ObjectPrototype for index, value := range argumentList { // TODO Write test for runtime.GetValue(value) // 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 } diff --git a/type_array.go b/type_array.go index 626c2b6..6a0324d 100644 --- a/type_array.go +++ b/type_array.go @@ -6,8 +6,8 @@ import ( func (runtime *_runtime) newArrayObject(valueArray []Value) *_object { self := runtime.newObject() - self.Class = "Array" - self._propertyStash = newArrayStash(valueArray, self._propertyStash) + self.class = "Array" + self.stash = newArrayStash(valueArray, self.stash) return self } @@ -26,7 +26,7 @@ func newArrayStash(valueArray []Value, stash _stash) *_arrayStash { return self } -func (self *_arrayStash) CanWrite(name string) bool { +func (self *_arrayStash) canPut(name string) bool { // length if name == "length" { return true @@ -38,10 +38,10 @@ func (self *_arrayStash) CanWrite(name string) bool { 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 if name == "length" { 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 self._stash.CanRead(name) + return self._stash.test(name) } -func (self *_arrayStash) Read(name string) Value { +func (self *_arrayStash) get(name string) Value { // length if name == "length" { return toValue(len(self.valueArray)) @@ -74,10 +74,10 @@ func (self *_arrayStash) Read(name string) Value { 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 if name == "length" { value := uint(toUI32(value)) @@ -109,7 +109,7 @@ func (self *_arrayStash) Write(name string, value Value) { return } - self._stash.Write(name, value) + self._stash.put(name, value) } func (self *_arrayStash) property(name string) *_property { @@ -130,14 +130,14 @@ func (self *_arrayStash) property(name string) *_property { } return &_property{ Value: value, - Mode: propertyModeWriteEnumerateConfigure, // +Write +Enumerate +Configure + Mode: 0111, // +Write +Enumerate +Configure } } return self._stash.property(name) } -func (self *_arrayStash) Enumerate(each func(string)) { +func (self *_arrayStash) enumerate(each func(string)) { // .0, .1, .2, ... for index, _ := range self.valueArray { if self.valueArray[index]._valueType == valueEmpty { @@ -146,5 +146,5 @@ func (self *_arrayStash) Enumerate(each func(string)) { name := strconv.FormatInt(int64(index), 10) each(name) } - self._stash.Enumerate(each) + self._stash.enumerate(each) } diff --git a/type_date.go b/type_date.go index 0c997ae..583fcf1 100644 --- a/type_date.go +++ b/type_date.go @@ -110,19 +110,19 @@ func timeToEpoch(time tme.Time) float64 { func (runtime *_runtime) newDateObject(epoch float64) *_object { self := runtime.newObject() - self.Class = "Date" + self.class = "Date" // TODO Fix this, redundant arguments, etc. - self.Date = &_dateObject{} - self.Date.Set(epoch) + self._Date = &_dateObject{} + self._Date.Set(epoch) return self } func dateObjectOf(_dateObject *_object) *_dateObject { - if _dateObject == nil || _dateObject.Class != "Date" { + if _dateObject == nil || _dateObject.class != "Date" { panic(newTypeError()) } - return _dateObject.Date + return _dateObject._Date } // JavaScript is 0-based, Go is 1-based (15.9.1.4) diff --git a/type_error.go b/type_error.go index f983aca..941923e 100644 --- a/type_error.go +++ b/type_error.go @@ -3,7 +3,7 @@ package otto func (runtime *_runtime) newErrorObject(message Value) *_object { self := runtime.newClassObject("Error") if message.IsDefined() { - self.WriteValue("message", toValue(toString(message)), false) + self.set("message", toValue(toString(message)), false) } return self } diff --git a/type_function.go b/type_function.go index b6ab445..aff1265 100644 --- a/type_function.go +++ b/type_function.go @@ -8,28 +8,28 @@ type _functionObject struct { 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.Function = &_functionObject{ - Call: newNativeCallFunction(native), + self._Function = &_functionObject{ + Call: newNativeCallFunction(native, name), Construct: defaultConstructFunction, } - self.DefineOwnProperty("length", _property{Mode: 0, Value: toValue(length)}.toDefineProperty(), false) + self.stash.set("length", toValue(length), _propertyMode(0)) return self } func (runtime *_runtime) newNodeFunctionObject(node *_functionNode, scopeEnvironment _environment) *_object { self := runtime.newClassObject("Function") - self.Function = &_functionObject{ + self._Function = &_functionObject{ Call: newNodeCallFunction(node, scopeEnvironment), 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 } 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))) } 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 { - if self.Function == nil { + if self._Function == nil { 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 { newObject := self.runtime.newObject() - newObject.Class = "Object" - newObject.Extensible = true - prototypeValue := self.Get("prototype") + newObject.class = "Object" + prototypeValue := self.get("prototype") if !prototypeValue.IsObject() { prototypeValue = toValue(self.runtime.Global.ObjectPrototype) } - newObject.Prototype = prototypeValue._object() + newObject.prototype = prototypeValue._object() newObjectValue := toValue(newObject) result := self.Call(newObjectValue, argumentList) if result.IsObject() { @@ -73,11 +72,11 @@ func (self *_object) HasInstance(of Value) bool { if !of.IsObject() { panic(newTypeError()) } - prototype := self.Get("prototype") + prototype := self.get("prototype") if !prototype.IsObject() { panic(newTypeError()) } - ofPrototype := of._object().Prototype + ofPrototype := of._object().prototype if ofPrototype == nil { return false } @@ -96,37 +95,34 @@ type _callFunction interface { Dispatch(*_functionEnvironment, *_runtime, Value, []Value) Value Source() string ScopeEnvironment() _environment - Sign(_functionSignature) - Signature() _functionSignature + name() string } -type _callFunctionBase struct { +type _callFunction_ struct { 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 } -func (self *_callFunctionBase) Sign(signature _functionSignature) { - self.signature = signature -} - -func (self _callFunctionBase) Signature() _functionSignature { - return self.signature +func (self _callFunction_) name() string { + return self._name } // _nativeCallFunction type _nativeCallFunction struct { - _callFunctionBase + _callFunction_ Native _nativeFunction } -func newNativeCallFunction(native _nativeFunction) *_nativeCallFunction { - return &_nativeCallFunction{ +func newNativeCallFunction(native _nativeFunction, name string) *_nativeCallFunction { + self := &_nativeCallFunction{ Native: native, } + self._callFunction_._name = name + return self } func (self _nativeCallFunction) Dispatch(_ *_functionEnvironment, runtime *_runtime, this Value, argumentList []Value) Value { @@ -143,7 +139,7 @@ func (self _nativeCallFunction) Source() string { // _nodeCallFunction type _nodeCallFunction struct { - _callFunctionBase + _callFunction_ node *_functionNode } @@ -190,7 +186,7 @@ func (self *FunctionCall) thisObject() *_object { func (self *FunctionCall) thisClassObject(class string) *_object { thisObject := self.thisObject() - if thisObject.Class != class { + if thisObject.class != class { panic(newTypeError()) } return self._thisObject diff --git a/type_reference.go b/type_reference.go index e5755fc..a651b0a 100644 --- a/type_reference.go +++ b/type_reference.go @@ -53,11 +53,11 @@ func (self *_argumentReference) GetBase() *_object { } func (self *_argumentReference) GetValue() Value { - return self.Base.GetValue(self.name) + return self.Base.get(self.name) } 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 } @@ -86,14 +86,14 @@ func (self *_objectReference) GetValue() Value { if self.Base == nil { 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 { if self.Base == nil { return false } - self.Base.WriteValue(self.name, value, self.Strict()) + self.Base.set(self.name, value, self.Strict()) return true } @@ -101,7 +101,7 @@ func (self *_objectReference) Delete() { if self.Base == nil { return } - self.Base.Delete(self.name, self.Strict()) + self.Base.delete(self.name, self.Strict()) } type _primitiveReference struct { @@ -130,11 +130,11 @@ func (self *_primitiveReference) baseAsObject() *_object { } func (self *_primitiveReference) GetValue() Value { - return self.baseAsObject().GetValue(self.name) + return self.baseAsObject().get(self.name) } 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 } diff --git a/type_regexp.go b/type_regexp.go index 163c60b..6ce2fab 100644 --- a/type_regexp.go +++ b/type_regexp.go @@ -17,7 +17,7 @@ type _regExpObject struct { func (runtime *_runtime) newRegExpObject(pattern string, flags string) *_object { self := runtime.newObject() - self.Class = "RegExp" + self.class = "RegExp" global := false ignoreCase := false @@ -50,7 +50,7 @@ func (runtime *_runtime) newRegExpObject(pattern string, flags string) *_object re2pattern = fmt.Sprintf("(?%s:%s)", re2flags, re2pattern) } - self.RegExp = &_regExpObject{ + self._RegExp = &_regExpObject{ RegularExpression: regexp.MustCompile(re2pattern), Global: global, IgnoreCase: ignoreCase, @@ -58,29 +58,29 @@ func (runtime *_runtime) newRegExpObject(pattern string, flags string) *_object Source: pattern, LastIndex: toValue(0), } - self._propertyStash = newRegExpStash(self.RegExp, self._propertyStash) + self.stash = newRegExpStash(self._RegExp, self.stash) return self } func execRegExp(this *_object, target string) (match bool, result []int) { - lastIndex := toInteger(this.Get("lastIndex")) + lastIndex := toInteger(this.get("lastIndex")) index := lastIndex - global := toBoolean(this.Get("global")) + global := toBoolean(this.get("global")) if !global { index = 0 } if 0 > index || index > int64(len(target)) { } else { - result = this.RegExp.RegularExpression.FindStringSubmatchIndex(target[index:]) + result = this._RegExp.RegularExpression.FindStringSubmatchIndex(target[index:]) } if result == nil { - this.WriteValue("lastIndex", toValue(0), true) + this.set("lastIndex", toValue(0), true) return // !match } match = true endIndex := result[len(result)-1] if global { - this.WriteValue("lastIndex", toValue(endIndex), true) + this.set("lastIndex", toValue(endIndex), true) } return // match } @@ -230,15 +230,15 @@ func newRegExpStash(_regExpObject *_regExpObject, stash _stash) *_regExpStash { return self } -func (self *_regExpStash) CanRead(name string) bool { +func (self *_regExpStash) test(name string) bool { switch name { case "global", "ignoreCase", "multiline", "lastIndex", "source": 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 { case "global": return toValue(self._regExpObject.Global) @@ -251,10 +251,10 @@ func (self *_regExpStash) Read(name string) Value { case "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 { case "global", "ignoreCase", "multiline", "source": // TODO Is this good enough? Check DefineOwnProperty @@ -263,7 +263,7 @@ func (self *_regExpStash) Write(name string, value Value) { self._regExpObject.LastIndex = value return } - self._stash.Write(name, value) + self._stash.put(name, value) } func (self *_regExpStash) property(name string) *_property { @@ -282,7 +282,7 @@ func (self *_regExpStash) property(name string) *_property { 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 - self._stash.Enumerate(each) + self._stash.enumerate(each) } diff --git a/type_string.go b/type_string.go index 0cf816c..889fb74 100644 --- a/type_string.go +++ b/type_string.go @@ -6,7 +6,7 @@ import ( func (runtime *_runtime) newStringObject(value Value) *_object { self := runtime.newPrimitiveObject("String", toValue(toString(value))) - self._propertyStash = newStringStash(toString(value), self._propertyStash) + self.stash = newStringStash(toString(value), self.stash) return self } @@ -23,7 +23,7 @@ func newStringStash(value string, stash _stash) *_stringStash { return self } -func (self *_stringStash) CanRead(name string) bool { +func (self *_stringStash) test(name string) bool { // .length if name == "length" { return true @@ -35,10 +35,10 @@ func (self *_stringStash) CanRead(name string) bool { 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 if name == "length" { return toValue(len(string(self.value))) @@ -50,7 +50,7 @@ func (self *_stringStash) Read(name string) Value { return toValue(string(self.value[index])) } - return self._stash.Read(name) + return self._stash.get(name) } func (self *_stringStash) property(name string) *_property { @@ -74,11 +74,11 @@ func (self *_stringStash) property(name string) *_property { return self._stash.property(name) } -func (self *_stringStash) Enumerate(each func(string)) { +func (self *_stringStash) enumerate(each func(string)) { // .0, .1, .2, ... for index, _ := range self.value { name := strconv.FormatInt(int64(index), 10) each(name) } - self._stash.Enumerate(each) + self._stash.enumerate(each) } diff --git a/value.go b/value.go index 573aeba..25beb15 100644 --- a/value.go +++ b/value.go @@ -75,7 +75,7 @@ func (value Value) IsNull() bool { func (value Value) isCallable() bool { switch value := value.value.(type) { case *_object: - return value.Function != nil + return value._Function != nil } return false } @@ -157,7 +157,7 @@ func (value Value) IsFunction() bool { if value._valueType != valueObject { 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. @@ -177,56 +177,56 @@ func (value Value) Class() string { if value._valueType != valueObject { return "" } - return value.value.(*_object).Class + return value.value.(*_object).class } func (value Value) isArray() bool { if value._valueType != valueObject { return false } - return value.value.(*_object).Class == "Array" + return value.value.(*_object).class == "Array" } func (value Value) isStringObject() bool { if value._valueType != valueObject { return false } - return value.value.(*_object).Class == "String" + return value.value.(*_object).class == "String" } func (value Value) isBooleanObject() bool { if value._valueType != valueObject { return false } - return value.value.(*_object).Class == "Boolean" + return value.value.(*_object).class == "Boolean" } func (value Value) isNumberObject() bool { if value._valueType != valueObject { return false } - return value.value.(*_object).Class == "Number" + return value.value.(*_object).class == "Number" } func (value Value) isDate() bool { if value._valueType != valueObject { return false } - return value.value.(*_object).Class == "Date" + return value.value.(*_object).class == "Date" } func (value Value) isRegExp() bool { if value._valueType != valueObject { return false } - return value.value.(*_object).Class == "RegExp" + return value.value.(*_object).class == "RegExp" } func (value Value) isError() bool { if value._valueType != valueObject { return false } - return value.value.(*_object).Class == "Error" + return value.value.(*_object).class == "Error" } // ---