Found while validating #1098. This predates the native iterator admission change.
A normal for-of break accepts primitive Symbol and BigInt values returned by the iterator's return method. Node and system JavaScriptCore throw TypeError for both. zig-js returns ["accepted","accepted"] in both tree-walker and required-VM modes, with both the preserved 136178a runner and the current candidate runner.
Reproducer:
(function () {
return JSON.stringify([Symbol("result"), 1n].map(function (result) {
var iterator = {
next: function () { return { done: false, value: 1 }; },
return: function () { return result; }
};
var iterable = { [Symbol.iterator]: function () { return iterator; } };
try {
for (var value of iterable) break;
return "accepted";
} catch (error) {
return error.name;
}
}));
})();Expected: ["TypeError","TypeError"].
ECMA-262 IteratorClose, step 7 requires an Object result after a successful close with a non-throw completion. Step 5 preserves an existing throw completion first.
The shared Interpreter.iteratorClose validation currently checks the object representation tag, which also represents primitive Symbols and BigInts. Correct the semantic Object check without rejecting actual boxed objects.
Evidence:
- Before:
136178a; runner SHA-256 45b2119b7f4bb114dc47889374f0af95b7d5b8c79ec2f70fd2c6bce553d5945b. - Candidate for #1098: runner SHA-256 0d79a3299dcd395338e0d20acdbc2beb92127b5fe47e6d64a40ee1fed15706b9.
- Both runners: tree and required-VM output OK ["accepted","accepted"].
- Node and system JavaScriptCore: ["TypeError","TypeError"].
Acceptance:
- Primitive Symbol and BigInt close results throw TypeError for normal/break/return completion.
- Ordinary and boxed-object results remain accepted; an existing throw completion keeps its original identity.
- Pin oracle-confirmed tree/VM and optimizer-off/on cases, including warmed native closing.
- Measure exact before/after failing-path sets in affected conformance subtrees; run focused normal/TSan checks and callback GC/receiver/single-evaluation controls.