Files
scriptc/tests/corpus/evolving-let-socket-optional-reads.cjs
T
Chris Tate 3ddebf4c31 Read a captured handle let as the checked-dynamic value unless the checker types the read as the handle
Inside a nested function, a read of a captured handle `let` narrowed to
the handle whenever it was a member receiver. A function declared before
the first write reads the binding as `any`, so the narrowed handle reached
member reads typed `any`, and an optional read (`c?.remoteAddress`)
compiled to an unconditional SC1090 throw. js-dyn-server, whose listener
reads `server.listening` inside the callback passed to createServer, hit
the same path.

The read now narrows only when the checker types it as the handle. An
optional member read keeps the tagged value, so undefined short-circuits
and the handle arm narrows; other reads take the checked-dynamic value.
The lowerer's closureDynLets collection is a checked journal table.

Corpus evolving-let-socket-optional-reads.cjs reads and calls members
through `?.` on a captured socket before and after its first write.
2026-10-30 00:07:34 -05:00

21 lines
680 B
JavaScript

'use strict';
// Optional reads and calls on a captured `let` socket, before and after
// its first write: undefined short-circuits, the socket answers.
const net = require('net');
let c;
const server = net.createServer((s) => s.end());
function report(label) {
console.log(label, c?.remoteAddress, c?.address()?.family, c?.remotePort > 0);
}
report('before');
const early = () => console.log('arrow before', c?.remoteAddress ?? 'none');
early();
server.listen(0, '127.0.0.1', () => {
c = net.connect(server.address().port, '127.0.0.1', () => {
report('after');
console.log('inside', c?.remoteAddress, c?.address()?.family);
c.end();
server.close();
});
});