@@ -9,12 +9,14 @@ const path = require("path");
99const fs = require ( "graceful-fs" ) ;
1010const vm = require ( "vm" ) ;
1111const rimraf = require ( "rimraf" ) ;
12+ const { pathToFileURL, fileURLToPath } = require ( "url" ) ;
1213const checkArrayExpectation = require ( "./checkArrayExpectation" ) ;
1314const createLazyTestEnv = require ( "./helpers/createLazyTestEnv" ) ;
1415const { remove } = require ( "./helpers/remove" ) ;
1516const prepareOptions = require ( "./helpers/prepareOptions" ) ;
1617const deprecationTracking = require ( "./helpers/deprecationTracking" ) ;
1718const FakeDocument = require ( "./helpers/FakeDocument" ) ;
19+ const asModule = require ( "./helpers/asModule" ) ;
1820
1921/**
2022 * @param {string } src src
@@ -200,7 +202,7 @@ const describeCases = config => {
200202 {
201203 aggregateTimeout : 1000
202204 } ,
203- ( err , stats ) => {
205+ async ( err , stats ) => {
204206 if ( err ) return compilationFinished ( err ) ;
205207 if ( ! stats ) {
206208 return compilationFinished (
@@ -273,29 +275,122 @@ const describeCases = config => {
273275 document : new FakeDocument ( )
274276 } ;
275277
278+ const baseModuleScope = {
279+ console,
280+ it : run . it ,
281+ beforeEach : _beforeEach ,
282+ afterEach : _afterEach ,
283+ expect,
284+ jest,
285+ STATS_JSON : jsonStats ,
286+ nsObj : m => {
287+ Object . defineProperty ( m , Symbol . toStringTag , {
288+ value : "Module"
289+ } ) ;
290+ return m ;
291+ } ,
292+ window : globalContext ,
293+ self : globalContext ,
294+ WATCH_STEP : run . name ,
295+ STATE : state
296+ } ;
297+
298+ const esmCache = new Map ( ) ;
299+ const esmIdentifier = `${ category . name } -${ testName } ` ;
300+ const esmContext = vm . createContext ( baseModuleScope , {
301+ name : "context for esm"
302+ } ) ;
303+ // ESM
304+ const isModule =
305+ options . experiments && options . experiments . outputModule ;
306+
276307 /**
277- * @param {string } currentDirectory the current directory
278- * @param {TODO } module a module
308+ * @param {string } currentDirectory The directory to resolve relative paths from
309+ * @param {string } module The module to require
310+ * @param {("unlinked"|"evaluated") } esmMode The mode for ESM module handling
279311 * @returns {EXPECTED_ANY } required module
280312 * @private
281313 */
282- function _require ( currentDirectory , module ) {
283- if ( Array . isArray ( module ) || / ^ \. \. ? \/ / . test ( module ) ) {
314+ function _require ( currentDirectory , module , esmMode ) {
315+ if ( / ^ \. \. ? \/ / . test ( module ) || path . isAbsolute ( module ) ) {
284316 let fn ;
285- let content ;
286- let p ;
287- if ( Array . isArray ( module ) ) {
288- p = path . join ( currentDirectory , module [ 0 ] ) ;
289- content = module
290- . map ( arg => {
291- p = path . join ( currentDirectory , arg ) ;
292- return fs . readFileSync ( p , "utf-8" ) ;
293- } )
294- . join ( "\n" ) ;
295- } else {
296- p = path . join ( currentDirectory , module ) ;
297- content = fs . readFileSync ( p , "utf-8" ) ;
317+ const p = path . isAbsolute ( module )
318+ ? module
319+ : path . join ( currentDirectory , module ) ;
320+ const content = fs . readFileSync ( p , "utf-8" ) ;
321+
322+ if ( isModule ) {
323+ if ( ! vm . SourceTextModule )
324+ throw new Error (
325+ "Running this test requires '--experimental-vm-modules'.\nRun with 'node --experimental-vm-modules node_modules/jest-cli/bin/jest'."
326+ ) ;
327+ let esm = esmCache . get ( p ) ;
328+ if ( ! esm ) {
329+ esm = new vm . SourceTextModule ( content , {
330+ identifier : `${ esmIdentifier } -${ p } ` ,
331+ url : `${ pathToFileURL ( p ) . href } ?${ esmIdentifier } ` ,
332+ context : esmContext ,
333+ initializeImportMeta : ( meta , module ) => {
334+ meta . url = pathToFileURL ( p ) . href ;
335+ } ,
336+ importModuleDynamically : async (
337+ specifier ,
338+ module
339+ ) => {
340+ const normalizedSpecifier =
341+ specifier . startsWith ( "file:" )
342+ ? `./${ path . relative (
343+ path . dirname ( p ) ,
344+ fileURLToPath ( specifier )
345+ ) } `
346+ : specifier . replace (
347+ / h t t p s : \/ \/ t e s t .c a s e s \/ p a t h \/ / ,
348+ "./"
349+ ) ;
350+ const result = await _require (
351+ currentDirectory ,
352+ normalizedSpecifier ,
353+ "evaluated"
354+ ) ;
355+ return await asModule ( result , module . context ) ;
356+ }
357+ } ) ;
358+ esmCache . set ( p , esm ) ;
359+ }
360+ if ( esmMode === "unlinked" ) return esm ;
361+ return ( async ( ) => {
362+ if ( esmMode === "unlinked" ) return esm ;
363+ if ( esm . status !== "evaluated" ) {
364+ await esm . link (
365+ async ( specifier , referencingModule ) =>
366+ await asModule (
367+ await _require (
368+ path . dirname (
369+ referencingModule . identifier
370+ ? referencingModule . identifier . slice (
371+ esmIdentifier . length + 1
372+ )
373+ : fileURLToPath ( referencingModule . url )
374+ ) ,
375+ specifier ,
376+ "unlinked"
377+ ) ,
378+ referencingModule . context ,
379+ true
380+ )
381+ ) ;
382+ // node.js 10 needs instantiate
383+ if ( esm . instantiate ) esm . instantiate ( ) ;
384+ await esm . evaluate ( ) ;
385+ }
386+ if ( esmMode === "evaluated" ) return esm ;
387+ const ns = esm . namespace ;
388+ return ns . default && ns . default instanceof Promise
389+ ? ns . default
390+ : ns ;
391+ } ) ( ) ;
298392 }
393+
299394 if (
300395 options . target === "web" ||
301396 options . target === "webworker"
@@ -358,10 +453,33 @@ const describeCases = config => {
358453
359454 if ( testConfig . noTests )
360455 return process . nextTick ( compilationFinished ) ;
361- _require (
456+
457+ const getBundle = ( outputDirectory , module ) => {
458+ if ( Array . isArray ( module ) ) {
459+ return module . map ( arg =>
460+ path . join ( outputDirectory , arg )
461+ ) ;
462+ } else if ( module instanceof RegExp ) {
463+ return fs
464+ . readdirSync ( outputDirectory )
465+ . filter ( f => module . test ( f ) )
466+ . map ( f => path . join ( outputDirectory , f ) ) ;
467+ }
468+ return [ path . join ( outputDirectory , module ) ] ;
469+ } ;
470+
471+ const promises = [ ] ;
472+ for ( const p of getBundle (
362473 outputDirectory ,
363474 testConfig . bundlePath || "./bundle.js"
364- ) ;
475+ ) ) {
476+ promises . push (
477+ Promise . resolve ( ) . then ( ( ) =>
478+ _require ( outputDirectory , p )
479+ )
480+ ) ;
481+ }
482+ await Promise . all ( promises ) ;
365483
366484 if ( run . getNumberOfTests ( ) < 1 )
367485 return compilationFinished (
@@ -431,6 +549,12 @@ const describeCases = config => {
431549 afterAll ( ( ) => {
432550 remove ( tempDirectory ) ;
433551 } ) ;
552+
553+ const {
554+ it : _it ,
555+ beforeEach : _beforeEach ,
556+ afterEach : _afterEach
557+ } = createLazyTestEnv ( 10000 ) ;
434558 } ) ;
435559 }
436560 } ) ;
0 commit comments