Pārlūkot izejas kodu

Array.prototype.entries() and fill()

Dmitry Panov 5 gadi atpakaļ
vecāks
revīzija
4b6f505854
3 mainītis faili ar 53 papildinājumiem un 45 dzēšanām
  1. 4 4
      array.go
  2. 44 41
      builtin_array.go
  3. 5 0
      tc39_test.go

+ 4 - 4
array.go

@@ -24,16 +24,16 @@ func (ai *arrayIterObject) next() Value {
 		return ai.val.runtime.createIterResultObject(_undefined, true)
 	}
 	ai.nextIdx++
+	idxVal := intToValue(index)
 	if ai.kind == iterationKindKey {
-		return ai.val.runtime.createIterResultObject(intToValue(index), false)
+		return ai.val.runtime.createIterResultObject(idxVal, false)
 	}
-	elementKey := asciiString(strconv.FormatInt(index, 10))
-	elementValue := ai.obj.self.get(intToValue(index))
+	elementValue := ai.obj.self.get(idxVal)
 	var result Value
 	if ai.kind == iterationKindValue {
 		result = elementValue
 	} else {
-		result = ai.val.runtime.newArrayValues([]Value{elementKey, elementValue})
+		result = ai.val.runtime.newArrayValues([]Value{idxVal, elementValue})
 	}
 	return ai.val.runtime.createIterResultObject(result, false)
 }

+ 44 - 41
builtin_array.go

@@ -35,6 +35,13 @@ func setArrayLength(a *arrayObject, l int64) *arrayObject {
 	return a
 }
 
+func relToIdx(rel, l int64) int64 {
+	if rel >= 0 {
+		return min(rel, l)
+	}
+	return max(l+rel, 0)
+}
+
 func (r *Runtime) newArrayValues(values []Value) *Object {
 	return setArrayValues(r.newArrayObject(), values).val
 }
@@ -301,23 +308,14 @@ func min(a, b int64) int64 {
 func (r *Runtime) arrayproto_slice(call FunctionCall) Value {
 	o := call.This.ToObject(r)
 	length := toLength(o.self.getStr("length"))
-	start := call.Argument(0).ToInteger()
-	if start < 0 {
-		start = max(length+start, 0)
-	} else {
-		start = min(start, length)
-	}
+	start := relToIdx(call.Argument(0).ToInteger(), length)
 	var end int64
 	if endArg := call.Argument(1); endArg != _undefined {
 		end = endArg.ToInteger()
 	} else {
 		end = length
 	}
-	if end < 0 {
-		end = max(length+end, 0)
-	} else {
-		end = min(end, length)
-	}
+	end = relToIdx(end, length)
 
 	count := end - start
 	if count < 0 {
@@ -365,13 +363,7 @@ func (r *Runtime) arrayproto_splice(call FunctionCall) Value {
 	o := call.This.ToObject(r)
 	a := r.newArrayValues(nil)
 	length := toLength(o.self.getStr("length"))
-	relativeStart := call.Argument(0).ToInteger()
-	var actualStart int64
-	if relativeStart < 0 {
-		actualStart = max(length+relativeStart, 0)
-	} else {
-		actualStart = min(relativeStart, length)
-	}
+	actualStart := relToIdx(call.Argument(0).ToInteger(), length)
 
 	actualDeleteCount := min(max(call.Argument(1).ToInteger(), 0), length-actualStart)
 
@@ -839,29 +831,15 @@ func (r *Runtime) arrayproto_values(call FunctionCall) Value {
 func (r *Runtime) arrayproto_copyWithin(call FunctionCall) Value {
 	o := call.This.ToObject(r)
 	l := toLength(o.self.getStr("length"))
-	relTarget := call.Argument(0).ToInteger()
-	var from, to, relEnd, final, dir int64
-	if relTarget < 0 {
-		to = max(l+relTarget, 0)
-	} else {
-		to = min(relTarget, l)
-	}
-	relStart := call.Argument(1).ToInteger()
-	if relStart < 0 {
-		from = max(l+relStart, 0)
-	} else {
-		from = min(relStart, l)
-	}
+	var relEnd, dir int64
+	to := relToIdx(call.Argument(0).ToInteger(), l)
+	from := relToIdx(call.Argument(1).ToInteger(), l)
 	if end := call.Argument(2); end != _undefined {
 		relEnd = end.ToInteger()
 	} else {
 		relEnd = l
 	}
-	if relEnd < 0 {
-		final = max(l+relEnd, 0)
-	} else {
-		final = min(relEnd, l)
-	}
+	final := relToIdx(relEnd, l)
 	count := min(final-from, l-to)
 	if arr := r.checkStdArrayObj(o); arr != nil {
 		if count > 0 {
@@ -890,6 +868,34 @@ func (r *Runtime) arrayproto_copyWithin(call FunctionCall) Value {
 	return o
 }
 
+func (r *Runtime) arrayproto_entries(call FunctionCall) Value {
+	return r.createArrayIterator(call.This.ToObject(r), iterationKindKeyValue)
+}
+
+func (r *Runtime) arrayproto_fill(call FunctionCall) Value {
+	o := call.This.ToObject(r)
+	l := toLength(o.self.getStr("length"))
+	k := relToIdx(call.Argument(1).ToInteger(), l)
+	var relEnd int64
+	if endArg := call.Argument(2); endArg != _undefined {
+		relEnd = endArg.ToInteger()
+	} else {
+		relEnd = l
+	}
+	final := relToIdx(relEnd, l)
+	value := call.Argument(0)
+	if arr := r.checkStdArrayObj(o); arr != nil {
+		for ; k < final; k++ {
+			arr.values[k] = value
+		}
+	} else {
+		for ; k < final; k++ {
+			o.self.put(intToValue(k), value, true)
+		}
+	}
+	return o
+}
+
 func (r *Runtime) checkStdArrayObj(obj *Object) *arrayObject {
 	if arr, ok := obj.self.(*arrayObject); ok &&
 		arr.propValueCount == 0 &&
@@ -938,11 +944,6 @@ func (r *Runtime) array_from(call FunctionCall) Value {
 		if arr := r.checkStdArrayIter(items); arr != nil {
 			items := make([]Value, len(arr.values))
 			copy(items, arr.values)
-			for i, item := range items {
-				if item == nil {
-					items[i] = _undefined
-				}
-			}
 			return r.newArrayValues(items)
 		}
 	}
@@ -1069,6 +1070,8 @@ func (r *Runtime) createArrayProto(val *Object) objectImpl {
 
 	o._putProp("constructor", r.global.Array, true, false, true)
 	o._putProp("copyWithin", r.newNativeFunc(r.arrayproto_copyWithin, nil, "copyWithin", nil, 2), true, false, true)
+	o._putProp("entries", r.newNativeFunc(r.arrayproto_entries, nil, "entries", nil, 0), true, false, true)
+	o._putProp("fill", r.newNativeFunc(r.arrayproto_fill, nil, "fill", nil, 1), true, false, true)
 	o._putProp("pop", r.newNativeFunc(r.arrayproto_pop, nil, "pop", nil, 0), true, false, true)
 	o._putProp("push", r.newNativeFunc(r.arrayproto_push, nil, "push", nil, 1), true, false, true)
 	o._putProp("join", r.newNativeFunc(r.arrayproto_join, nil, "join", nil, 1), true, false, true)

+ 5 - 0
tc39_test.go

@@ -80,6 +80,9 @@ var (
 
 		// Typed arrays
 		"test/built-ins/Array/from/items-is-arraybuffer.js": true,
+
+		// for-of
+		"test/language/statements/for-of/Array.prototype.entries.js": true,
 	}
 
 	featuresBlackList = []string{
@@ -103,6 +106,8 @@ var (
 		"22.1.2.5",
 		//"22.1.3.1",
 		"22.1.3.3",
+		"22.1.3.4",
+		"22.1.3.6",
 		"22.1.3.29",
 		"23.1",
 		"23.2",