ソースを参照

Set objCount when switching from sparse to normal array (fixes #38)

Dmitry Panov 8 年 前
コミット
0aeff7545e
2 ファイル変更67 行追加5 行削除
  1. 4 2
      array.go
  2. 63 3
      array_sparse_test.go

+ 4 - 2
array.go

@@ -332,8 +332,9 @@ func (a *arrayObject) expand(idx int64) bool {
 			if idx > 4096 && (a.objCount == 0 || idx/a.objCount > 10) {
 				//log.Println("Switching standard->sparse")
 				sa := &sparseArrayObject{
-					baseObject: a.baseObject,
-					length:     a.length,
+					baseObject:     a.baseObject,
+					length:         a.length,
+					propValueCount: a.propValueCount,
 				}
 				sa.setValues(a.values)
 				sa.val.self = sa
@@ -496,4 +497,5 @@ func (a *arrayObject) setValuesFromSparse(items []sparseArrayItem) {
 	for _, item := range items {
 		a.values[item.idx] = item.value
 	}
+	a.objCount = int64(len(items))
 }

+ 63 - 3
array_sparse_test.go

@@ -24,19 +24,79 @@ func TestSparseArraySwitch(t *testing.T) {
 	const SCRIPT = `
 	var a = [];
 	a[20470] = 5; // switch to sparse
-	for (var i = a.length - 1; i >= 0; i--) {
-		a[i] = i; // switch to normal at some point
+	var cutoffIdx = Math.round(20470 - 20470/8);
+	for (var i = a.length - 1; i >= cutoffIdx; i--) {
+		a[i] = i;
 	}
 
+	// At this point it will have switched to a normal array
 	if (a.length != 20471) {
 		throw new Error("Invalid length: " + a.length);
 	}
 
-	for (var i = 0; i < a.length; i++) {
+	for (var i = 0; i < cutoffIdx; i++) {
+		if (a[i] !== undefined) {
+			throw new Error("Invalid value at " + i + ": " + a[i]);
+		}
+	}
+
+	for (var i = cutoffIdx; i < a.length; i++) {
+		if (a[i] !== i) {
+			throw new Error("Invalid value at " + i + ": " + a[i]);
+		}
+	}
+
+	// Now try to expand. Should stay a normal array
+	a[20471] = 20471;
+	if (a.length != 20472) {
+		throw new Error("Invalid length: " + a.length);
+	}
+
+	for (var i = 0; i < cutoffIdx; i++) {
+		if (a[i] !== undefined) {
+			throw new Error("Invalid value at " + i + ": " + a[i]);
+		}
+	}
+
+	for (var i = cutoffIdx; i < a.length; i++) {
+		if (a[i] !== i) {
+			throw new Error("Invalid value at " + i + ": " + a[i]);
+		}
+	}
+
+	// Delete enough elements for it to become sparse again.
+	var cutoffIdx1 = Math.round(20472 - 20472/10);
+	for (var i = cutoffIdx; i < cutoffIdx1; i++) {
+		delete a[i];
+	}
+
+	// This should switch it back to sparse.
+	a[25590] = 25590;
+	if (a.length != 25591) {
+		throw new Error("Invalid length: " + a.length);
+	}
+
+	for (var i = 0; i < cutoffIdx1; i++) {
+		if (a[i] !== undefined) {
+			throw new Error("Invalid value at " + i + ": " + a[i]);
+		}
+	}
+
+	for (var i = cutoffIdx1; i < 20472; i++) {
 		if (a[i] !== i) {
 			throw new Error("Invalid value at " + i + ": " + a[i]);
 		}
 	}
+
+	for (var i = 20472; i < 25590; i++) {
+		if (a[i] !== undefined) {
+			throw new Error("Invalid value at " + i + ": " + a[i]);
+		}
+	}
+
+	if (a[25590] !== 25590) {
+		throw new Error("Invalid value at 25590: " + a[25590]);
+	}
 	`
 
 	testScript1(SCRIPT, _undefined, t)