Allow zlib callbacks to assign to their result

The error-path copy of a zlib callback reads its result from a hidden
local that was immutable, so a body that assigned a fallback Buffer to
the result (if (!out) out = Buffer.from("fallback")) failed to compile
with an internal compiler error. The local is now mutable, and an
assigned value is read back as a checked-dynamic value, as in Node.
This commit is contained in:
Chris Tate
2026-10-21 18:11:33 -05:00
parent eca349d244
commit 982ef6dbef
2 changed files with 17 additions and 1 deletions
@@ -2,6 +2,7 @@ import { declareTypedArguments } from "./typed-arguments.js";
import { dynUndefinedExpr, varRef } from "../../ir/build.js";
import { everyStmtList, transformStmtList } from "../../ir/traverse.js";
import { bindingNeverReassigned } from "./binding-analysis.js";
import { declareContextLocal } from "./function-context.js";
import { isErrorFirstErrorType } from "./builtins/arguments.js";
import { InternalCompilerError } from "../../errors.js";
import * as ts from "../ts7/adapter.js";
@@ -786,7 +787,8 @@ function lowerUndefinedResultBody(
lowerer.suppressStats = stats;
}
};
const slot = lowerer.declareHiddenLocal("%result", DYN);
// Mutable: the body may assign to its result (`if (!out) out = ...`).
const slot = declareContextLocal(lowerer.ctx, "%result", DYN, true, undefined, undefined);
const undefinedResult: IrStmt = {
kind: "varDecl",
localId: slot.id,
@@ -176,6 +176,19 @@ function namedRetry(): void {
});
}
function fallbackResult(): void {
// The body assigns a fallback Buffer to its result.
zlib.inflate(bad, (err, out) => {
if (!out) out = Buffer.from("fallback");
console.log("fallback", err?.code, typeof out, out.toString());
zlib.inflate(good, (err2, out2) => {
if (err2) out2 = Buffer.alloc(0);
console.log("fallback nested", err2, out2.length);
step();
});
});
}
function functionValues(next: () => void): void {
steps.push(
() => zlib.inflate(good, named),
@@ -203,6 +216,7 @@ function functionValues(next: () => void): void {
() => zlib.inflate(good, captures),
nestedForward,
namedRetry,
fallbackResult,
() => {
named(new Error("direct"), Buffer.from("both"));
},