@@ -8,11 +8,11 @@ const path = require('path');
88const events = require ( 'events' ) ;
99const os = require ( 'os' ) ;
1010const { inspect } = require ( 'util' ) ;
11+ const { pathToFileURL } = require ( 'url' ) ;
1112const { Worker } = require ( 'worker_threads' ) ;
1213const { fork } = require ( 'child_process' ) ;
1314
1415const workerPath = path . join ( __dirname , 'wpt/worker.js' ) ;
15- const kRunWorkerGlobals = false ;
1616
1717function getBrowserProperties ( ) {
1818 const { node : version } = process . versions ; // e.g. 18.13.0, 20.0.0-nightly202302078e6e215481
@@ -190,6 +190,24 @@ class ResourceLoader {
190190 fixtures . path ( 'wpt' , base , url ) ;
191191 }
192192
193+ /**
194+ * Map a URL that a test would have fetched from the WPT server (an
195+ * absolute path, or a path relative to the test file) to a file: URL
196+ * into the fixtures directory. URLs that already have a scheme (data:,
197+ * blob:, http:, ...) are returned unchanged.
198+ * @param {string } from the path of the file loading this resource,
199+ * relative to the WPT folder.
200+ * @param {string|URL } url the url of the resource being loaded.
201+ * @returns {string }
202+ */
203+ mapServerURL ( from , url ) {
204+ url = `${ url } ` ;
205+ if ( / ^ [ a - z A - Z ] [ a - z A - Z 0 - 9 + . - ] * : | ^ \/ \/ / . test ( url ) ) {
206+ return url ;
207+ }
208+ return pathToFileURL ( this . toRealFilePath ( from , url ) ) . href ;
209+ }
210+
193211 /**
194212 * Load a resource in test/fixtures/wpt specified with a URL
195213 * @param {string } from the path of the file loading this resource,
@@ -805,7 +823,11 @@ class WPTRunner {
805823 this . resource = new ResourceLoader ( path ) ;
806824 this . concurrency = concurrency ;
807825
808- this . flags = [ ] ;
826+ // Since we need to prepare the Web Worker APIs
827+ // in the harness that runs on all WPT workers,
828+ // we enable the API globally. This has no practical
829+ // effect on the non-web-worker tests, however.
830+ this . flags = [ '--experimental-web-worker' ] ;
809831 this . globalThisInitScripts = [ ] ;
810832 this . initScript = null ;
811833
@@ -832,7 +854,7 @@ class WPTRunner {
832854 * @param {string[] } flags
833855 */
834856 setFlags ( flags ) {
835- this . flags = flags ;
857+ this . flags = this . flags . concat ( flags ) ;
836858 }
837859
838860 /**
@@ -919,22 +941,33 @@ class WPTRunner {
919941 const absolutePath = spec . getAbsolutePath ( ) ;
920942 const relativePath = spec . getRelativePath ( ) ;
921943 const harnessPath = fixtures . path ( 'wpt' , 'resources' , 'testharness.js' ) ;
922- // Scripts specified with the `// META: script=` header
923- const scriptsToRun = meta . script ?. map ( ( script ) => {
944+ // *.worker.js tests are dedicated worker tests by definition. Each
945+ // dedicated worker variant generated from a multi-global (*.any.js)
946+ // test also runs inside an actual Web Worker. Refs:
947+ // https://web-platform-tests.org/writing-tests/testharness.html#multi-global-tests
948+ const isAnyTest = spec . isAnyTest ( ) ;
949+ const isWebWorkerTest = spec . isWebWorkerTest ( ) ;
950+
951+ // Scripts specified with the `// META: script=` header. For tests
952+ // that run inside a Web Worker they are imported by the worker
953+ // instead.
954+ const scriptsToRun = isWebWorkerTest ? [ ] : meta . script ?. map ( ( script ) => {
924955 const obj = {
925956 filename : this . resource . toRealFilePath ( relativePath , script ) ,
926957 code : this . resource . read ( relativePath , script ) ,
927958 } ;
928959 this . scriptsModifier ?. ( obj ) ;
929960 return obj ;
930961 } ) ?? [ ] ;
931- // The actual test
932- const obj = {
933- code : content ,
934- filename : absolutePath ,
935- } ;
936- this . scriptsModifier ?. ( obj ) ;
937- scriptsToRun . push ( obj ) ;
962+ if ( ! isWebWorkerTest ) {
963+ // The actual test
964+ const obj = {
965+ code : content ,
966+ filename : absolutePath ,
967+ } ;
968+ this . scriptsModifier ?. ( obj ) ;
969+ scriptsToRun . push ( obj ) ;
970+ }
938971
939972 run ( async ( ) => {
940973 this . inProgress . add ( spec ) ;
@@ -950,6 +983,17 @@ class WPTRunner {
950983 filename : harnessPath ,
951984 } ,
952985 scriptsToRun,
986+ // Set when the test runs inside an actual Web Worker.
987+ webWorker : isWebWorkerTest ? {
988+ path : absolutePath ,
989+ isAnyTest,
990+ initScript : this . initScript ,
991+ variant : spec . variant ,
992+ scripts : meta . script ?. map (
993+ ( script ) => this . resource . toRealFilePath ( relativePath , script ) ,
994+ ) ?? [ ] ,
995+ skippedTests : spec . skippedTests ,
996+ } : undefined ,
953997 needsGc : ! ! meta . script ?. find ( ( script ) => script === '/common/gc.js' ) ,
954998 skippedTests : spec . skippedTests ,
955999 } , {
@@ -1222,10 +1266,6 @@ class WPTRunner {
12221266 this . skippedSpecCount = 0 ;
12231267 const arg = process . argv [ 2 ] ;
12241268 for ( const spec of this . specs ) {
1225- if ( ! kRunWorkerGlobals && spec . isWebWorkerTest ( ) ) {
1226- continue ;
1227- }
1228-
12291269 if ( arg ) {
12301270 if ( spec . isSelectedBy ( arg ) ) {
12311271 queue . push ( spec ) ;
@@ -1248,13 +1288,11 @@ class WPTRunner {
12481288 }
12491289
12501290 // If the tests are run as `node test/wpt/test-something.js subset.any.js`,
1251- // only `subset.any.js` (all enabled variants and globals) will be run by
1252- // the runner.
1291+ // only `subset.any.js` (all variants and globals) will be run by the runner.
12531292 // If the tests are run as `node test/wpt/test-something.js 'subset.any.js?1-10'`,
12541293 // only the `?1-10` variant of `subset.any.js` will be run by the runner.
12551294 // A test path as printed with the results, e.g.
1256- // `'dir/subset.any.worker.html?1-10'`, runs exactly that one when its
1257- // global is enabled.
1295+ // `'dir/subset.any.worker.html?1-10'`, runs exactly that one.
12581296 if ( arg && queue . length === 0 ) {
12591297 throw new Error ( `${ arg } not found!` ) ;
12601298 }
0 commit comments