Răsfoiți Sursa

Avoid calling iterator's return method again when it throws

Dmitry Panov 4 ani în urmă
părinte
comite
14a1ffa828
2 a modificat fișierele cu 31 adăugiri și 3 ștergeri
  1. 27 0
      runtime_test.go
  2. 4 3
      vm.go

+ 27 - 0
runtime_test.go

@@ -1952,6 +1952,33 @@ func TestAbandonedEnumerate(t *testing.T) {
 	testScript1(SCRIPT, asciiString("baz-foo foo-foo bar-foo "), t)
 	testScript1(SCRIPT, asciiString("baz-foo foo-foo bar-foo "), t)
 }
 }
 
 
+func TestIterCloseThrows(t *testing.T) {
+	const SCRIPT = `
+	var returnCount = 0;
+	var iterable = {};
+	var iterator = {
+	  next: function() {
+		return { value: true };
+	  },
+	  return: function() {
+		returnCount += 1;
+		throw new Error();
+	  }
+	};
+	iterable[Symbol.iterator] = function() {
+	  return iterator;
+	};
+
+	try {
+		for (var i of iterable) {
+				break;
+		}
+	} catch (e) {};
+	returnCount;
+	`
+	testScript1(SCRIPT, valueInt(1), t)
+}
+
 func TestDeclareGlobalFunc(t *testing.T) {
 func TestDeclareGlobalFunc(t *testing.T) {
 	const SCRIPT = `
 	const SCRIPT = `
 	var initial;
 	var initial;

+ 4 - 3
vm.go

@@ -3323,11 +3323,12 @@ var enumPopClose _enumPopClose
 
 
 func (_enumPopClose) exec(vm *vm) {
 func (_enumPopClose) exec(vm *vm) {
 	l := len(vm.iterStack) - 1
 	l := len(vm.iterStack) - 1
-	if iter := vm.iterStack[l].iter; iter != nil {
-		returnIter(iter)
-	}
+	item := vm.iterStack[l]
 	vm.iterStack[l] = iterStackItem{}
 	vm.iterStack[l] = iterStackItem{}
 	vm.iterStack = vm.iterStack[:l]
 	vm.iterStack = vm.iterStack[:l]
+	if iter := item.iter; iter != nil {
+		returnIter(iter)
+	}
 	vm.pc++
 	vm.pc++
 }
 }