Browse Source

Added nil-safety checks for values returned by get*() methods

Dmitry Panov 4 years ago
parent
commit
8253af8f29
8 changed files with 20 additions and 26 deletions
  1. 1 1
      array.go
  2. 7 7
      builtin_array.go
  3. 2 2
      builtin_function.go
  4. 5 11
      builtin_json.go
  5. 2 2
      builtin_object.go
  6. 1 1
      builtin_regexp.go
  7. 1 1
      builtin_string.go
  8. 1 1
      builtin_typedarrays.go

+ 1 - 1
array.go

@@ -31,7 +31,7 @@ func (ai *arrayIterObject) next() Value {
 	if ai.kind == iterationKindKey {
 	if ai.kind == iterationKindKey {
 		return ai.val.runtime.createIterResultObject(idxVal, false)
 		return ai.val.runtime.createIterResultObject(idxVal, false)
 	}
 	}
-	elementValue := ai.obj.self.getIdx(idxVal, nil)
+	elementValue := nilSafe(ai.obj.self.getIdx(idxVal, nil))
 	var result Value
 	var result Value
 	if ai.kind == iterationKindValue {
 	if ai.kind == iterationKindValue {
 		result = elementValue
 		result = elementValue

+ 7 - 7
builtin_array.go

@@ -360,7 +360,7 @@ func (r *Runtime) arrayproto_sort(call FunctionCall) Value {
 		for i := int64(0); i < length; i++ {
 		for i := int64(0); i < length; i++ {
 			idx := valueInt(i)
 			idx := valueInt(i)
 			if o.self.hasPropertyIdx(idx) {
 			if o.self.hasPropertyIdx(idx) {
-				a = append(a, o.self.getIdx(idx, nil))
+				a = append(a, nilSafe(o.self.getIdx(idx, nil)))
 			}
 			}
 		}
 		}
 		ar := r.newArrayValues(a)
 		ar := r.newArrayValues(a)
@@ -436,7 +436,7 @@ func (r *Runtime) arrayproto_splice(call FunctionCall) Value {
 		for k := int64(0); k < actualDeleteCount; k++ {
 		for k := int64(0); k < actualDeleteCount; k++ {
 			from := valueInt(k + actualStart)
 			from := valueInt(k + actualStart)
 			if o.self.hasPropertyIdx(from) {
 			if o.self.hasPropertyIdx(from) {
-				createDataPropertyOrThrow(a, valueInt(k), o.self.getIdx(from, nil))
+				createDataPropertyOrThrow(a, valueInt(k), nilSafe(o.self.getIdx(from, nil)))
 			}
 			}
 		}
 		}
 
 
@@ -445,7 +445,7 @@ func (r *Runtime) arrayproto_splice(call FunctionCall) Value {
 				from := valueInt(k + actualDeleteCount)
 				from := valueInt(k + actualDeleteCount)
 				to := valueInt(k + itemCount)
 				to := valueInt(k + itemCount)
 				if o.self.hasPropertyIdx(from) {
 				if o.self.hasPropertyIdx(from) {
-					o.self.setOwnIdx(to, o.self.getIdx(from, nil), true)
+					o.self.setOwnIdx(to, nilSafe(o.self.getIdx(from, nil)), true)
 				} else {
 				} else {
 					o.self.deleteIdx(to, true)
 					o.self.deleteIdx(to, true)
 				}
 				}
@@ -459,7 +459,7 @@ func (r *Runtime) arrayproto_splice(call FunctionCall) Value {
 				from := valueInt(k + actualDeleteCount - 1)
 				from := valueInt(k + actualDeleteCount - 1)
 				to := valueInt(k + itemCount - 1)
 				to := valueInt(k + itemCount - 1)
 				if o.self.hasPropertyIdx(from) {
 				if o.self.hasPropertyIdx(from) {
-					o.self.setOwnIdx(to, o.self.getIdx(from, nil), true)
+					o.self.setOwnIdx(to, nilSafe(o.self.getIdx(from, nil)), true)
 				} else {
 				} else {
 					o.self.deleteIdx(to, true)
 					o.self.deleteIdx(to, true)
 				}
 				}
@@ -500,7 +500,7 @@ func (r *Runtime) arrayproto_unshift(call FunctionCall) Value {
 			from := valueInt(k)
 			from := valueInt(k)
 			to := valueInt(k + argCount)
 			to := valueInt(k + argCount)
 			if o.self.hasPropertyIdx(from) {
 			if o.self.hasPropertyIdx(from) {
-				o.self.setOwnIdx(to, o.self.getIdx(from, nil), true)
+				o.self.setOwnIdx(to, nilSafe(o.self.getIdx(from, nil)), true)
 			} else {
 			} else {
 				o.self.deleteIdx(to, true)
 				o.self.deleteIdx(to, true)
 			}
 			}
@@ -987,7 +987,7 @@ func (r *Runtime) arrayproto_copyWithin(call FunctionCall) Value {
 	}
 	}
 	for count > 0 {
 	for count > 0 {
 		if o.self.hasPropertyIdx(valueInt(from)) {
 		if o.self.hasPropertyIdx(valueInt(from)) {
-			o.self.setOwnIdx(valueInt(to), o.self.getIdx(valueInt(from), nil), true)
+			o.self.setOwnIdx(valueInt(to), nilSafe(o.self.getIdx(valueInt(from), nil)), true)
 		} else {
 		} else {
 			o.self.deleteIdx(valueInt(to), true)
 			o.self.deleteIdx(valueInt(to), true)
 		}
 		}
@@ -1084,7 +1084,7 @@ func (r *Runtime) flattenIntoArray(target, source *Object, sourceLen, start, dep
 	for sourceIndex < sourceLen {
 	for sourceIndex < sourceLen {
 		p := intToValue(sourceIndex)
 		p := intToValue(sourceIndex)
 		if source.hasProperty(p.toString()) {
 		if source.hasProperty(p.toString()) {
-			element := source.get(p, source)
+			element := nilSafe(source.get(p, source))
 			if mapperFunction != nil {
 			if mapperFunction != nil {
 				element = mapperFunction(FunctionCall{
 				element = mapperFunction(FunctionCall{
 					This:      thisArg,
 					This:      thisArg,

+ 2 - 2
builtin_function.go

@@ -81,7 +81,7 @@ func (r *Runtime) createListFromArrayLike(a Value) []Value {
 	l := toLength(o.self.getStr("length", nil))
 	l := toLength(o.self.getStr("length", nil))
 	res := make([]Value, 0, l)
 	res := make([]Value, 0, l)
 	for k := int64(0); k < l; k++ {
 	for k := int64(0); k < l; k++ {
-		res = append(res, o.self.getIdx(valueInt(k), nil))
+		res = append(res, nilSafe(o.self.getIdx(valueInt(k), nil)))
 	}
 	}
 	return res
 	return res
 }
 }
@@ -153,7 +153,7 @@ func (r *Runtime) functionproto_bind(call FunctionCall) Value {
 	fcall := r.toCallable(call.This)
 	fcall := r.toCallable(call.This)
 	construct := obj.self.assertConstructor()
 	construct := obj.self.assertConstructor()
 
 
-	l := int(toUint32(obj.self.getStr("length", nil)))
+	l := int(toUint32(nilSafe(obj.self.getStr("length", nil))))
 	l -= len(call.Arguments) - 1
 	l -= len(call.Arguments) - 1
 	if l < 0 {
 	if l < 0 {
 		l = 0
 		l = 0

+ 5 - 11
builtin_json.go

@@ -132,14 +132,11 @@ func (r *Runtime) builtinJSON_decodeArray(d *json.Decoder) (*Object, error) {
 }
 }
 
 
 func (r *Runtime) builtinJSON_reviveWalk(reviver func(FunctionCall) Value, holder *Object, name Value) Value {
 func (r *Runtime) builtinJSON_reviveWalk(reviver func(FunctionCall) Value, holder *Object, name Value) Value {
-	value := holder.get(name, nil)
-	if value == nil {
-		value = _undefined
-	}
+	value := nilSafe(holder.get(name, nil))
 
 
 	if object, ok := value.(*Object); ok {
 	if object, ok := value.(*Object); ok {
 		if isArray(object) {
 		if isArray(object) {
-			length := object.self.getStr("length", nil).ToInteger()
+			length := toLength(object.self.getStr("length", nil))
 			for index := int64(0); index < length; index++ {
 			for index := int64(0); index < length; index++ {
 				name := intToValue(index)
 				name := intToValue(index)
 				value := r.builtinJSON_reviveWalk(reviver, object, name)
 				value := r.builtinJSON_reviveWalk(reviver, object, name)
@@ -186,7 +183,7 @@ func (r *Runtime) builtinJSON_stringify(call FunctionCall) Value {
 	replacer, _ := call.Argument(1).(*Object)
 	replacer, _ := call.Argument(1).(*Object)
 	if replacer != nil {
 	if replacer != nil {
 		if isArray(replacer) {
 		if isArray(replacer) {
-			length := replacer.self.getStr("length", nil).ToInteger()
+			length := toLength(replacer.self.getStr("length", nil))
 			seen := map[string]bool{}
 			seen := map[string]bool{}
 			propertyList := make([]Value, length)
 			propertyList := make([]Value, length)
 			length = 0
 			length = 0
@@ -264,10 +261,7 @@ func (ctx *_builtinJSON_stringifyContext) do(v Value) bool {
 }
 }
 
 
 func (ctx *_builtinJSON_stringifyContext) str(key Value, holder *Object) bool {
 func (ctx *_builtinJSON_stringifyContext) str(key Value, holder *Object) bool {
-	value := holder.get(key, nil)
-	if value == nil {
-		value = _undefined
-	}
+	value := nilSafe(holder.get(key, nil))
 
 
 	if object, ok := value.(*Object); ok {
 	if object, ok := value.(*Object); ok {
 		if toJSON, ok := object.self.getStr("toJSON", nil).(*Object); ok {
 		if toJSON, ok := object.self.getStr("toJSON", nil).(*Object); ok {
@@ -368,7 +362,7 @@ func (ctx *_builtinJSON_stringifyContext) ja(array *Object) {
 		stepback = ctx.indent
 		stepback = ctx.indent
 		ctx.indent += ctx.gap
 		ctx.indent += ctx.gap
 	}
 	}
-	length := array.self.getStr("length", nil).ToInteger()
+	length := toLength(array.self.getStr("length", nil))
 	if length == 0 {
 	if length == 0 {
 		ctx.buf.WriteString("[]")
 		ctx.buf.WriteString("[]")
 		return
 		return

+ 2 - 2
builtin_object.go

@@ -377,7 +377,7 @@ func (r *Runtime) object_entries(call FunctionCall) Value {
 	}
 	}
 
 
 	for item, next := iter.next(); next != nil; item, next = next() {
 	for item, next := iter.next(); next != nil; item, next = next() {
-		v := obj.self.getStr(item.name, nil)
+		v := nilSafe(obj.self.getStr(item.name, nil))
 		values = append(values, r.newArrayValues([]Value{stringValueFromRaw(item.name), v}))
 		values = append(values, r.newArrayValues([]Value{stringValueFromRaw(item.name), v}))
 	}
 	}
 
 
@@ -393,7 +393,7 @@ func (r *Runtime) object_values(call FunctionCall) Value {
 	}
 	}
 
 
 	for item, next := iter.next(); next != nil; item, next = next() {
 	for item, next := iter.next(); next != nil; item, next = next() {
-		values = append(values, obj.self.getStr(item.name, nil))
+		values = append(values, nilSafe(obj.self.getStr(item.name, nil)))
 	}
 	}
 
 
 	return r.newArrayValues(values)
 	return r.newArrayValues(values)

+ 1 - 1
builtin_regexp.go

@@ -900,7 +900,7 @@ func (r *Runtime) regexpproto_stdSplitterGeneric(splitter *Object, s valueString
 				}
 				}
 				numberOfCaptures := max(toLength(z.self.getStr("length", nil))-1, 0)
 				numberOfCaptures := max(toLength(z.self.getStr("length", nil))-1, 0)
 				for i := int64(1); i <= numberOfCaptures; i++ {
 				for i := int64(1); i <= numberOfCaptures; i++ {
-					a = append(a, z.self.getIdx(valueInt(i), nil))
+					a = append(a, nilSafe(z.self.getIdx(valueInt(i), nil)))
 					if int64(len(a)) == lim {
 					if int64(len(a)) == lim {
 						return r.newArrayValues(a)
 						return r.newArrayValues(a)
 					}
 					}

+ 1 - 1
builtin_string.go

@@ -377,7 +377,7 @@ func (r *Runtime) stringproto_matchAll(call FunctionCall) Value {
 	if regexp != _undefined && regexp != _null {
 	if regexp != _undefined && regexp != _null {
 		if isRegexp(regexp) {
 		if isRegexp(regexp) {
 			if o, ok := regexp.(*Object); ok {
 			if o, ok := regexp.(*Object); ok {
-				flags := o.self.getStr("flags", nil)
+				flags := nilSafe(o.self.getStr("flags", nil))
 				r.checkObjectCoercible(flags)
 				r.checkObjectCoercible(flags)
 				if !strings.Contains(flags.toString().String(), "g") {
 				if !strings.Contains(flags.toString().String(), "g") {
 					panic(r.NewTypeError("RegExp doesn't have global flag set"))
 					panic(r.NewTypeError("RegExp doesn't have global flag set"))

+ 1 - 1
builtin_typedarrays.go

@@ -1028,7 +1028,7 @@ func (r *Runtime) typedArrayProto_values(call FunctionCall) Value {
 func (r *Runtime) typedArrayProto_toStringTag(call FunctionCall) Value {
 func (r *Runtime) typedArrayProto_toStringTag(call FunctionCall) Value {
 	if obj, ok := call.This.(*Object); ok {
 	if obj, ok := call.This.(*Object); ok {
 		if ta, ok := obj.self.(*typedArrayObject); ok {
 		if ta, ok := obj.self.(*typedArrayObject); ok {
-			return ta.defaultCtor.self.getStr("name", nil)
+			return nilSafe(ta.defaultCtor.self.getStr("name", nil))
 		}
 		}
 	}
 	}