test: deflake user timing WPT assertions

The fixed 20 ms tolerance in mark.any.js can fail when execution pauses
between creating a mark and reading the clock. Adapt the test in memory
to check the mark timestamp against readings before and after mark().
Keep the vendored fixture and subtest names unchanged.

Apply script modifiers to worker entry scripts as well so the check
covers both WPT globals, and remove the suite-wide flaky expectation.

Signed-off-by: Filip Skokan <panva.ip@gmail.com>
Assisted-by: Codex
PR-URL: https://github.com/nodejs/node/pull/66036
Fixes: https://github.com/nodejs/node/issues/40449
Refs: https://github.com/nodejs/node/pull/41203
Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com>
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
This commit is contained in:
Filip Skokan authored and Antoine du Hamel committed 2026-09-18 15:33:46 +02:00
1 parent 13eb4843d5
commit 80c1bf7fb5
5 files changed
+80 -15

No files matched your search

+6 -9
View File
@@ -1039,15 +1039,10 @@ class WPTRunner {
this.scriptsModifier?.(obj);
return obj;
}) ?? [];
if (!isWebWorkerTest) {
// The actual test
const obj = {
code: content,
filename: absolutePath,
};
this.scriptsModifier?.(obj);
scriptsToRun.push(obj);
}
// The actual test, including tests imported by a Web Worker.
const testScript = { code: content, filename: absolutePath };
this.scriptsModifier?.(testScript);
if (!isWebWorkerTest) scriptsToRun.push(testScript);
jobs.push(run(async () => {
this.inProgress.add(spec);
@@ -1066,6 +1061,8 @@ class WPTRunner {
// Set when the test runs inside an actual Web Worker.
webWorker: isWebWorkerTest ? {
path: absolutePath,
modifiedScript: testScript.code !== content || testScript.filename !== absolutePath ?
testScript : undefined,
isAnyTest,
initScript: this.initScript,
title: meta.title,
+14 -4
View File
@@ -123,11 +123,21 @@ globalThis.onmessage = ({ data }) => {
for (const script of data.scripts) {
globalThis.importScripts(pathToFileURL(script).href);
}
globalThis.importScripts(pathToFileURL(data.path).href);
// eslint-disable-next-line no-undef
done();
}
if (data.modifiedScript) {
runInThisContext(data.modifiedScript.code, {
filename: data.modifiedScript.filename,
importModuleDynamically: USE_MAIN_CONTEXT_DEFAULT_LOADER,
});
} else {
// *.worker.js tests import testharness.js and call done() themselves.
// Keep unmodified tests on the native script loading path.
globalThis.importScripts(pathToFileURL(data.path).href);
}
if (data.isAnyTest) {
// *.worker.js tests import testharness.js and call done() themselves.
// eslint-disable-next-line no-undef
done();
}
};
@@ -0,0 +1,38 @@
'use strict';
const common = require('../common');
const assert = require('assert');
const fixtures = require('../common/fixtures');
const { spawnSync } = require('child_process');
if (process.env.NODE_TEST_WPT_MODIFIER_PROBE === '1') {
const { WPTRunner } = require('../common/wpt');
const runner = new WPTRunner('html/webappapis/atob');
runner.setScriptModifier(common.mustCall((script) => {
assert.strictEqual(script.filename,
fixtures.path('wpt', 'html/webappapis/atob', 'base64.any.js'));
script.filename += '.modified';
script.code = `test(() => {
assert_true(new Error().stack.includes(${JSON.stringify(`${script.filename}:`)}));
}, 'modified script retains its filename');`;
}, 2));
runner.runJsTests();
} else {
// eslint-disable-next-line no-unused-vars
const { NODE_TEST_WPT, WPT_REPORT, WPT_INSPECT, ...env } = { ...process.env, NODE_TEST_WPT_MODIFIER_PROBE: '1' };
for (const backend of ['thread', 'process']) {
const result = spawnSync(process.execPath, [__filename, 'base64.any.js'], {
env: { ...env, WPT_BACKEND: backend },
encoding: 'utf8',
timeout: common.platformTimeout(10_000),
});
const { error, status, stdout, stderr } = result;
assert.ifError(error);
assert.strictEqual(status, 0, stdout + stderr);
const results = stdout.split('\n').filter((line) => line.startsWith('[PASS]'));
assert.deepStrictEqual(results.sort(), [
'[PASS] html/webappapis/atob/base64.any.html: modified script retains its filename',
'[PASS] html/webappapis/atob/base64.any.worker.html: modified script retains its filename',
]);
}
}
+22
View File
@@ -1,9 +1,31 @@
'use strict';
const assert = require('assert');
const { basename } = require('path');
const { WPTRunner } = require('../common/wpt');
const runner = new WPTRunner('user-timing');
runner.pretendGlobalThisAs('Window');
runner.setScriptModifier((script) => {
if (basename(script.filename) !== 'mark.any.js') return;
// A scheduling pause between mark() and now() can exceed any fixed
// tolerance. Check that the mark falls between the surrounding clock
// readings instead, leaving the upstream fixture unchanged.
// https://github.com/nodejs/node/issues/40449
function replace(from, to) {
assert(script.code.includes(from), `Unexpected contents of ${script.filename}`);
script.code = script.code.replaceAll(from, to);
}
replace('var expectedTimes = new Array();',
'var beforeTimes = [];\nvar expectedTimes = new Array();');
replace('self.performance.mark("mark");',
'beforeTimes.push(self.performance.now());\n self.performance.mark("mark");');
replace('assert_approx_equals(entries[index].startTime, expectedTimes[index], testThreshold);',
'assert_between_inclusive(entries[index].startTime, beforeTimes[index], expectedTimes[index]);');
});
runner.runJsTests();
-2
View File
@@ -5,8 +5,6 @@ prefix wpt
# sample-test : PASS,FLAKY
[true] # This section applies to all platforms
# https://github.com/nodejs/node/issues/40449
test-user-timing: PASS,FLAKY
[$system==win32]