@@ -6,8 +6,8 @@ const fixtures = require('../common/fixtures');
66const fs = require ( 'fs' ) ;
77const fsPromises = fs . promises ;
88const path = require ( 'path' ) ;
9- const vm = require ( 'vm' ) ;
109const { inspect } = require ( 'util' ) ;
10+ const { Worker } = require ( 'worker_threads' ) ;
1111
1212// https://github.com/w3c/testharness.js/blob/master/testharness.js
1313// TODO: get rid of this half-baked harness in favor of the one
@@ -222,7 +222,6 @@ class IntlRequirement {
222222
223223const intlRequirements = new IntlRequirement ( ) ;
224224
225-
226225class StatusLoader {
227226 /**
228227 * @param {string } path relative path of the WPT subset
@@ -287,10 +286,9 @@ class WPTRunner {
287286 constructor ( path ) {
288287 this . path = path ;
289288 this . resource = new ResourceLoader ( path ) ;
290- this . sandbox = null ;
291- this . context = null ;
292289
293- this . globals = new Map ( ) ;
290+ this . flags = [ ] ;
291+ this . initScript = null ;
294292
295293 this . status = new StatusLoader ( path ) ;
296294 this . status . load ( ) ;
@@ -304,28 +302,19 @@ class WPTRunner {
304302 }
305303
306304 /**
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
311307 */
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 ;
320310 }
321311
322312 /**
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
326315 */
327- defineGlobal ( name , descriptor ) {
328- this . globals . set ( name , descriptor ) ;
316+ setInitScript ( script ) {
317+ this . initScript = script ;
329318 }
330319
331320 // TODO(joyeecheung): work with the upstream to port more tests in .html
@@ -353,8 +342,8 @@ class WPTRunner {
353342 const meta = spec . title = this . getMeta ( content ) ;
354343
355344 const absolutePath = spec . getAbsolutePath ( ) ;
356- const context = this . generateContext ( spec ) ;
357345 const relativePath = spec . getRelativePath ( ) ;
346+ const harnessPath = fixtures . path ( 'wpt' , 'resources' , 'testharness.js' ) ;
358347 const scriptsToRun = [ ] ;
359348 // Scripts specified with the `// META: script=` header
360349 if ( meta . script ) {
@@ -371,24 +360,46 @@ class WPTRunner {
371360 filename : absolutePath
372361 } ) ;
373362
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 } ` ) ;
390387 }
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+ } ) ;
392403 }
393404
394405 process . on ( 'exit' , ( ) => {
@@ -430,56 +441,6 @@ class WPTRunner {
430441 } ) ;
431442 }
432443
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-
483444 getTestTitle ( filename ) {
484445 const spec = this . specMap . get ( filename ) ;
485446 const title = spec . meta && spec . meta . title ;
@@ -524,9 +485,9 @@ class WPTRunner {
524485 * Report the status of each WPT test (one per file)
525486 *
526487 * @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.
528489 */
529- completionCallback ( filename , tests , harnessStatus ) {
490+ completionCallback ( filename , harnessStatus ) {
530491 // Treat it like a test case failure
531492 if ( harnessStatus . status === 2 ) {
532493 const title = this . getTestTitle ( filename ) ;
@@ -644,5 +605,6 @@ class WPTRunner {
644605
645606module . exports = {
646607 harness : harnessMock ,
608+ ResourceLoader,
647609 WPTRunner
648610} ;
0 commit comments