@@ -6,8 +6,8 @@ const fixtures = require('../common/fixtures');
6
6
const fs = require ( 'fs' ) ;
7
7
const fsPromises = fs . promises ;
8
8
const path = require ( 'path' ) ;
9
- const vm = require ( 'vm' ) ;
10
9
const { inspect } = require ( 'util' ) ;
10
+ const { Worker } = require ( 'worker_threads' ) ;
11
11
12
12
// https://github.com/w3c/testharness.js/blob/master/testharness.js
13
13
// TODO: get rid of this half-baked harness in favor of the one
@@ -222,7 +222,6 @@ class IntlRequirement {
222
222
223
223
const intlRequirements = new IntlRequirement ( ) ;
224
224
225
-
226
225
class StatusLoader {
227
226
/**
228
227
* @param {string } path relative path of the WPT subset
@@ -287,10 +286,9 @@ class WPTRunner {
287
286
constructor ( path ) {
288
287
this . path = path ;
289
288
this . resource = new ResourceLoader ( path ) ;
290
- this . sandbox = null ;
291
- this . context = null ;
292
289
293
- this . globals = new Map ( ) ;
290
+ this . flags = [ ] ;
291
+ this . initScript = null ;
294
292
295
293
this . status = new StatusLoader ( path ) ;
296
294
this . status . load ( ) ;
@@ -304,28 +302,19 @@ class WPTRunner {
304
302
}
305
303
306
304
/**
307
- * Specify that certain global descriptors from the object
308
- * should be defined in the vm
309
- * @param {object } obj
310
- * @param {string[] } names
305
+ * Sets the Node.js flags passed to the worker.
306
+ * @param {Array<string> } flags
311
307
*/
312
- copyGlobalsFromObject ( obj , names ) {
313
- for ( const name of names ) {
314
- const desc = Object . getOwnPropertyDescriptor ( obj , name ) ;
315
- if ( ! desc ) {
316
- assert . fail ( `${ name } does not exist on the object` ) ;
317
- }
318
- this . globals . set ( name , desc ) ;
319
- }
308
+ setFlags ( flags ) {
309
+ this . flags = flags ;
320
310
}
321
311
322
312
/**
323
- * Specify that certain global descriptors should be defined in the vm
324
- * @param {string } name
325
- * @param {object } descriptor
313
+ * Sets a script to be run in the worker before executing the tests.
314
+ * @param {string } script
326
315
*/
327
- defineGlobal ( name , descriptor ) {
328
- this . globals . set ( name , descriptor ) ;
316
+ setInitScript ( script ) {
317
+ this . initScript = script ;
329
318
}
330
319
331
320
// TODO(joyeecheung): work with the upstream to port more tests in .html
@@ -353,8 +342,8 @@ class WPTRunner {
353
342
const meta = spec . title = this . getMeta ( content ) ;
354
343
355
344
const absolutePath = spec . getAbsolutePath ( ) ;
356
- const context = this . generateContext ( spec ) ;
357
345
const relativePath = spec . getRelativePath ( ) ;
346
+ const harnessPath = fixtures . path ( 'wpt' , 'resources' , 'testharness.js' ) ;
358
347
const scriptsToRun = [ ] ;
359
348
// Scripts specified with the `// META: script=` header
360
349
if ( meta . script ) {
@@ -371,24 +360,46 @@ class WPTRunner {
371
360
filename : absolutePath
372
361
} ) ;
373
362
374
- for ( const { code, filename } of scriptsToRun ) {
375
- try {
376
- vm . runInContext ( code , context , { filename } ) ;
377
- } catch ( err ) {
378
- this . fail (
379
- testFileName ,
380
- {
381
- status : NODE_UNCAUGHT ,
382
- name : 'evaluation in WPTRunner.runJsTests()' ,
383
- message : err . message ,
384
- stack : inspect ( err )
385
- } ,
386
- kUncaught
387
- ) ;
388
- this . inProgress . delete ( filename ) ;
389
- break ;
363
+ const workerPath = path . join ( __dirname , 'wpt/worker.js' ) ;
364
+ const worker = new Worker ( workerPath , {
365
+ execArgv : this . flags ,
366
+ workerData : {
367
+ filename : testFileName ,
368
+ wptRunner : __filename ,
369
+ wptPath : this . path ,
370
+ initScript : this . initScript ,
371
+ harness : {
372
+ code : fs . readFileSync ( harnessPath , 'utf8' ) ,
373
+ filename : harnessPath ,
374
+ } ,
375
+ scriptsToRun,
376
+ } ,
377
+ } ) ;
378
+
379
+ worker . on ( 'message' , ( message ) => {
380
+ switch ( message . type ) {
381
+ case 'result' :
382
+ return this . resultCallback ( testFileName , message . result ) ;
383
+ case 'completion' :
384
+ return this . completionCallback ( testFileName , message . status ) ;
385
+ default :
386
+ throw new Error ( `Unexpected message from worker: ${ message . type } ` ) ;
390
387
}
391
- }
388
+ } ) ;
389
+
390
+ worker . on ( 'error' , ( err ) => {
391
+ this . fail (
392
+ testFileName ,
393
+ {
394
+ status : NODE_UNCAUGHT ,
395
+ name : 'evaluation in WPTRunner.runJsTests()' ,
396
+ message : err . message ,
397
+ stack : inspect ( err )
398
+ } ,
399
+ kUncaught
400
+ ) ;
401
+ this . inProgress . delete ( testFileName ) ;
402
+ } ) ;
392
403
}
393
404
394
405
process . on ( 'exit' , ( ) => {
@@ -430,56 +441,6 @@ class WPTRunner {
430
441
} ) ;
431
442
}
432
443
433
- mock ( testfile ) {
434
- const resource = this . resource ;
435
- const result = {
436
- // This is a mock, because at the moment fetch is not implemented
437
- // in Node.js, but some tests and harness depend on this to pull
438
- // resources.
439
- fetch ( file ) {
440
- return resource . read ( testfile , file , true ) ;
441
- } ,
442
- GLOBAL : {
443
- isWindow ( ) { return false ; }
444
- } ,
445
- Object
446
- } ;
447
-
448
- return result ;
449
- }
450
-
451
- // Note: this is how our global space for the WPT test should look like
452
- getSandbox ( filename ) {
453
- const result = this . mock ( filename ) ;
454
- for ( const [ name , desc ] of this . globals ) {
455
- Object . defineProperty ( result , name , desc ) ;
456
- }
457
- return result ;
458
- }
459
-
460
- generateContext ( test ) {
461
- const filename = test . filename ;
462
- const sandbox = this . sandbox = this . getSandbox ( test . getRelativePath ( ) ) ;
463
- const context = this . context = vm . createContext ( sandbox ) ;
464
-
465
- const harnessPath = fixtures . path ( 'wpt' , 'resources' , 'testharness.js' ) ;
466
- const harness = fs . readFileSync ( harnessPath , 'utf8' ) ;
467
- vm . runInContext ( harness , context , {
468
- filename : harnessPath
469
- } ) ;
470
-
471
- sandbox . add_result_callback (
472
- this . resultCallback . bind ( this , filename )
473
- ) ;
474
- sandbox . add_completion_callback (
475
- this . completionCallback . bind ( this , filename )
476
- ) ;
477
- sandbox . self = sandbox ;
478
- // TODO(joyeecheung): we are not a window - work with the upstream to
479
- // add a new scope for us.
480
- return context ;
481
- }
482
-
483
444
getTestTitle ( filename ) {
484
445
const spec = this . specMap . get ( filename ) ;
485
446
const title = spec . meta && spec . meta . title ;
@@ -524,9 +485,9 @@ class WPTRunner {
524
485
* Report the status of each WPT test (one per file)
525
486
*
526
487
* @param {string } filename
527
- * @param {Test[] } test The Test objects returned by WPT harness
488
+ * @param {object } harnessStatus - The status object returned by WPT harness.
528
489
*/
529
- completionCallback ( filename , tests , harnessStatus ) {
490
+ completionCallback ( filename , harnessStatus ) {
530
491
// Treat it like a test case failure
531
492
if ( harnessStatus . status === 2 ) {
532
493
const title = this . getTestTitle ( filename ) ;
@@ -644,5 +605,6 @@ class WPTRunner {
644
605
645
606
module . exports = {
646
607
harness : harnessMock ,
608
+ ResourceLoader,
647
609
WPTRunner
648
610
} ;
0 commit comments