Add tests for incorrect multi-value return values.
diff --git a/wasm/jsapi/constructor/multi-value-bad-iterator.any.js b/wasm/jsapi/constructor/multi-value-bad-iterator.any.js
new file mode 100644
index 0000000..6d49639
--- /dev/null
+++ b/wasm/jsapi/constructor/multi-value-bad-iterator.any.js
@@ -0,0 +1,241 @@
+// META: global=jsshell
+// META: script=/wasm/jsapi/wasm-module-builder.js
+// META: script=/wasm/jsapi/assertions.js
+
+async function run_with_result(argument) {
+  const type_if_fi = makeSig([kWasmF64, kWasmI32], [kWasmI32, kWasmF64]);
+
+  const builder = new WasmModuleBuilder();
+
+  const fnIndex = builder.addImport("module", "fn", type_if_fi);
+  builder
+    .addFunction("callfn", kSig_i_v)
+    .addBody([
+        ...wasmF64Const(4.2),
+        ...wasmI32Const(7),
+        kExprCallFunction, fnIndex,
+        kExprDrop,
+        kExprReturn,
+    ])
+    .exportFunc();
+
+  const buffer = builder.toBuffer();
+
+  const imports = {
+    "module": {
+      fn(f32, i32) {
+        return argument;
+      }
+    }
+  };
+  const { instance } = await WebAssembly.instantiate(buffer, imports);
+  return instance.exports.callfn();
+};
+
+promise_test(async t => {
+  return promise_rejects_js(t, TypeError, run_with_result(undefined));
+}, "Return undefined");
+
+promise_test(async t => {
+  return promise_rejects_js(t, TypeError, run_with_result(null));
+}, "Return null");
+
+promise_test(async t => {
+  return promise_rejects_js(t, TypeError, run_with_result({}));
+}, "@@iterator omitted");
+
+promise_test(async t => {
+  return promise_rejects_js(t, TypeError, run_with_result({
+    [Symbol.iterator]: undefined,
+  }));
+}, "@@iterator undefined");
+
+promise_test(async t => {
+  return promise_rejects_js(t, TypeError, run_with_result({
+    [Symbol.iterator]: null,
+  }));
+}, "@@iterator null");
+
+promise_test(async t => {
+  return promise_rejects_js(t, TypeError, run_with_result({
+    [Symbol.iterator]: 7,
+  }));
+}, "@@iterator number");
+
+promise_test(async t => {
+  return promise_rejects_js(t, TypeError, run_with_result({
+    [Symbol.iterator]: "iterator",
+  }));
+}, "@@iterator string");
+
+promise_test(async t => {
+  return promise_rejects_js(t, TypeError, run_with_result({
+    [Symbol.iterator]: {},
+  }));
+}, "@@iterator not callable");
+
+promise_test(async t => {
+  const exception = {};
+  return promise_rejects_exactly(t, exception, run_with_result({
+    get [Symbol.iterator]() {
+      throw exception;
+    }
+  }));
+}, "Throw from @@iterator getter");
+
+promise_test(async t => {
+  const exception = {};
+  return promise_rejects_exactly(t, exception, run_with_result({
+    [Symbol.iterator]() {
+      throw exception;
+    }
+  }));
+}, "Throw from @@iterator");
+
+promise_test(async t => {
+  return promise_rejects_js(t, TypeError, run_with_result({
+    [Symbol.iterator]() {
+      return undefined;
+    }
+  }));
+}, "Return undefined from @@iterator");
+
+promise_test(async t => {
+  return promise_rejects_js(t, TypeError, run_with_result({
+    [Symbol.iterator]() {
+      return null;
+    }
+  }));
+}, "Return null from @@iterator");
+
+promise_test(async t => {
+  return promise_rejects_js(t, TypeError, run_with_result({
+    [Symbol.iterator]() {
+      return 7;
+    }
+  }));
+}, "Return Number from @@iterator");
+
+promise_test(async t => {
+  return promise_rejects_js(t, TypeError, run_with_result({
+    [Symbol.iterator]() {
+      return {
+        next: undefined
+      }
+    }
+  }));
+}, "@@iterator.next undefined");
+
+promise_test(async t => {
+  return promise_rejects_js(t, TypeError, run_with_result({
+    [Symbol.iterator]() {
+      return {
+        next: null
+      }
+    }
+  }));
+}, "@@iterator.next null");
+
+promise_test(async t => {
+  return promise_rejects_js(t, TypeError, run_with_result({
+    [Symbol.iterator]() {
+      return {
+        next: {}
+      }
+    }
+  }));
+}, "@@iterator.next not callable");
+
+promise_test(async t => {
+  const exception = {};
+  return promise_rejects_exactly(t, exception, run_with_result({
+    [Symbol.iterator]() {
+      return {
+        get next() {
+          throw exception;
+        }
+      };
+    }
+  }));
+}, "Throw from @@iterator.next getter");
+
+promise_test(async t => {
+  const exception = {};
+  return promise_rejects_exactly(t, exception, run_with_result({
+    [Symbol.iterator]() {
+      return {
+        next() {
+          throw exception;
+        }
+      };
+    }
+  }));
+}, "Throw from @@iterator.next");
+
+promise_test(async t => {
+  return promise_rejects_js(t, TypeError, run_with_result({
+    [Symbol.iterator]() {
+      return {
+        next() {
+          return undefined;
+        }
+      }
+    }
+  }));
+}, "Return undefined from @@iterator.next");
+
+promise_test(async t => {
+  return promise_rejects_js(t, TypeError, run_with_result({
+    [Symbol.iterator]() {
+      return {
+        next() {
+          return null;
+        }
+      }
+    }
+  }));
+}, "Return null from @@iterator.next");
+
+promise_test(async t => {
+  return promise_rejects_js(t, TypeError, run_with_result({
+    [Symbol.iterator]() {
+      return {
+        next() {
+          return 7;
+        }
+      }
+    }
+  }));
+}, "Return Number from @@iterator.next");
+
+promise_test(async t => {
+  const exception = {};
+  return promise_rejects_exactly(t, exception, run_with_result({
+    [Symbol.iterator]() {
+      return {
+        next() {
+          return {
+            get done() { throw exception },
+            get value() { assert_unreached("Should not call value getter"); }
+          }
+        }
+      }
+    }
+  }));
+}, "Throw from @@iterator.next().done");
+
+promise_test(async t => {
+  const exception = {};
+  return promise_rejects_exactly(t, exception, run_with_result({
+    [Symbol.iterator]() {
+      return {
+        next() {
+          return {
+            done: false,
+            get value() { throw exception },
+          }
+        }
+      }
+    }
+  }));
+}, "Throw from @@iterator.next().value");
diff --git a/wasm/jsapi/constructor/multi-value.any.js b/wasm/jsapi/constructor/multi-value.any.js
index 4b06d1d..063ba88 100644
--- a/wasm/jsapi/constructor/multi-value.any.js
+++ b/wasm/jsapi/constructor/multi-value.any.js
@@ -147,3 +147,65 @@
     "valueOf call 2",
   ]);
 }, "multiple return values from js to wasm");
+
+promise_test(async () => {
+  const builder = new WasmModuleBuilder();
+
+  const fnIndex = builder.addImport("module", "fn", type_if_fi);
+  builder
+    .addFunction("callfn", kSig_i_v)
+    .addBody([
+        ...wasmF64Const(4.2),
+        ...wasmI32Const(7),
+        kExprCallFunction, fnIndex,
+        kExprDrop,
+        kExprReturn,
+    ])
+    .exportFunc();
+
+  const buffer = builder.toBuffer();
+
+  const imports = {
+    "module": {
+      fn(f32, i32) {
+        assert_equals(f32, 4.2);
+        assert_equals(i32, 7);
+        return [2];
+      },
+    }
+  };
+
+  const { instance } = await WebAssembly.instantiate(buffer, imports);
+  assert_throws(new TypeError(), () => instance.exports.callfn());
+}, "Too few results returned from js to wasm");
+
+promise_test(async () => {
+  const builder = new WasmModuleBuilder();
+
+  const fnIndex = builder.addImport("module", "fn", type_if_fi);
+  builder
+    .addFunction("callfn", kSig_i_v)
+    .addBody([
+        ...wasmF64Const(4.2),
+        ...wasmI32Const(7),
+        kExprCallFunction, fnIndex,
+        kExprDrop,
+        kExprReturn,
+    ])
+    .exportFunc();
+
+  const buffer = builder.toBuffer();
+
+  const imports = {
+    "module": {
+      fn(f32, i32) {
+        assert_equals(f32, 4.2);
+        assert_equals(i32, 7);
+        return [2, 4.2, undefined];
+      },
+    }
+  };
+
+  const { instance } = await WebAssembly.instantiate(buffer, imports);
+  assert_throws(new TypeError(), () => instance.exports.callfn());
+}, "Too many results returned from js to wasm");