Skip to content

Commit 9650b45

Browse files
authored
Merge pull request: wait for module-import telemetry
Wait for module-import telemetry instead of hoping one tick was enough
2 parents f112496 + 4495586 commit 9650b45

3 files changed

Lines changed: 50 additions & 3 deletions

File tree

‎test/fixtures/remote-loopback/no-egress-child.mjs‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,7 @@ async function productRun() {
143143
policy_version: "synthetic-policy-v1",
144144
},
145145
)).status);
146-
await new Promise(resolve => setImmediate(resolve));
146+
await globalThis.__PDF_LOOPBACK_EGRESS_FLUSH();
147147
emit({
148148
mode: "product",
149149
statuses,
@@ -190,7 +190,7 @@ async function calibrationRun() {
190190
});
191191
}
192192
}
193-
await new Promise(resolve => setImmediate(resolve));
193+
await globalThis.__PDF_LOOPBACK_EGRESS_FLUSH();
194194
emit({
195195
mode: "calibration",
196196
denials,
@@ -289,7 +289,7 @@ async function dynamicLoaderCalibrationRun() {
289289
});
290290
}
291291
}
292-
await new Promise(resolve => setImmediate(resolve));
292+
await globalThis.__PDF_LOOPBACK_EGRESS_FLUSH();
293293
emit({
294294
mode: "dynamic_loader_calibration",
295295
denials,

‎test/fixtures/remote-loopback/no-egress-preload.mjs‎

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,15 +48,51 @@ Object.defineProperty(globalThis, "__PDF_LOOPBACK_EGRESS_RECEIPT", {
4848
});
4949

5050
const { port1, port2 } = new MessageChannel();
51+
const flushWaiters = new Map();
52+
let nextFlushId = 0;
5153
port1.on("message", message => {
5254
if (message?.type === "unreviewed_module_import_attempt") {
5355
telemetry.unreviewed_module_import_attempts += 1;
5456
if (message.bare_package === true) {
5557
telemetry.bare_package_import_attempts += 1;
5658
}
59+
return;
60+
}
61+
if (message?.type === "telemetry_flush_ack") {
62+
const resolve = flushWaiters.get(message.id);
63+
flushWaiters.delete(message.id);
64+
resolve?.();
5765
}
5866
});
5967
port1.unref();
68+
69+
// Every other counter here is incremented synchronously, in this thread, by the
70+
// guard that denied the attempt. The two module-import counters are not: the
71+
// resolve hook runs on the loader thread and reports across this port, so the
72+
// import can have already rejected while its telemetry is still in flight.
73+
// Reading the receipt after a setImmediate assumed that a single turn of this
74+
// loop was enough for a cross-thread delivery. Usually it is. On a loaded
75+
// two-core runner it was not, and the calibration reported zero attempts for
76+
// exactly those two probes - a security calibration failing to prove its own
77+
// guards were live. Wait for a round trip instead of for a tick.
78+
Object.defineProperty(globalThis, "__PDF_LOOPBACK_EGRESS_FLUSH", {
79+
value() {
80+
const id = nextFlushId;
81+
nextFlushId += 1;
82+
return new Promise(resolve => {
83+
flushWaiters.set(id, resolve);
84+
// The port is unreffed so it cannot hold the process open on its own;
85+
// hold it only for as long as this round trip is outstanding.
86+
port1.ref();
87+
port1.postMessage({ type: "telemetry_flush", id });
88+
}).finally(() => {
89+
if (flushWaiters.size === 0) port1.unref();
90+
});
91+
},
92+
configurable: false,
93+
enumerable: false,
94+
writable: false,
95+
});
6096
register("./no-package-loader.mjs", import.meta.url, {
6197
data: { port: port2 },
6298
transferList: [port2],

‎test/fixtures/remote-loopback/no-package-loader.mjs‎

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,17 @@ let telemetryPort;
22

33
export function initialize({ port }) {
44
telemetryPort = port;
5+
// Answer the preload's flush probe. Module-resolution telemetry is posted
6+
// from this loader thread, so the main thread cannot know a denial has been
7+
// counted just because the import already rejected. A MessagePort delivers
8+
// in order, so an ack posted when this handler runs necessarily follows
9+
// every attempt message posted before it.
10+
port.on("message", message => {
11+
if (message?.type === "telemetry_flush") {
12+
port.postMessage({ type: "telemetry_flush_ack", id: message.id });
13+
}
14+
});
15+
port.unref?.();
516
}
617

718
const FIXTURE_DIRECTORY = new URL("./", import.meta.url);

0 commit comments

Comments
 (0)