@@ -9,6 +9,7 @@ import { ParsedConfigurationFiles } from '@codesandbox/common/lib/templates/temp
99import DependencyNotFoundError from 'sandbox-hooks/errors/dependency-not-found-error' ;
1010import ModuleNotFoundError from 'sandbox-hooks/errors/module-not-found-error' ;
1111
12+ import { generateBenchmarkInterface } from '../utils/benchmark' ;
1213import { Module } from './types/module' ;
1314import TranspiledModule , {
1415 ChildModule ,
@@ -28,6 +29,7 @@ import { packageFilter } from './utils/resolve-utils';
2829import { ignoreNextCache , deleteAPICache , clearIndexedDBCache } from './cache' ;
2930import { shouldTranspile } from './transpilers/babel/check' ;
3031import { splitQueryFromPath } from './utils/query-path' ;
32+ import { measure , endMeasure } from '../utils/metrics' ;
3133
3234declare const BrowserFS : any ;
3335
@@ -122,7 +124,10 @@ export default class Manager {
122124 fileResolver : IFileResolver | undefined ;
123125
124126 // List of modules that are being transpiled, to prevent duplicate jobs.
125- transpileJobs : { [ transpiledModuleId : string ] : true } ;
127+ transpileJobs : {
128+ [ transpiledModuleId : string ] : true | Promise < TranspiledModule > ;
129+ } ;
130+
126131 transpiledModulesByHash : { [ hash : string ] : TranspiledModule } ;
127132
128133 // All paths are resolved at least twice: during transpilation and evaluation.
@@ -161,6 +166,9 @@ export default class Manager {
161166 if ( process . env . NODE_ENV === 'development' ) {
162167 // eslint-disable-next-line no-console
163168 console . log ( this ) ;
169+
170+ // Initialize benchmark logic
171+ getGlobal ( ) . Benchmark = generateBenchmarkInterface ( this ) ;
164172 }
165173
166174 BrowserFS . configure (
@@ -266,7 +274,7 @@ export default class Manager {
266274 return this . fileResolver . readFile ( p ) . then ( code => {
267275 this . addModule ( { code, path : p } ) ;
268276
269- callback ( code ) ;
277+ callback ( null , code ) ;
270278 } ) ;
271279 }
272280
@@ -499,6 +507,10 @@ export default class Manager {
499507 this . getTranspiledModules ( ) . map ( tModule => tModule . resetCompilation ( ) ) ;
500508 }
501509
510+ clearTranspilationCache ( ) {
511+ this . getTranspiledModules ( ) . map ( tModule => tModule . resetTranspilation ( ) ) ;
512+ }
513+
502514 getModules ( ) : Array < Module | ChildModule > {
503515 return values ( this . transpiledModules ) . map ( t => t . module ) ;
504516 }
@@ -587,102 +599,111 @@ export default class Manager {
587599 currentPath : string ,
588600 defaultExtensions = [ 'js' , 'jsx' , 'json' ]
589601 ) : Promise < Module > {
590- return new Promise ( promiseResolve => {
591- const dirredPath = pathUtils . dirname ( currentPath ) ;
592- if ( this . cachedPaths [ dirredPath ] === undefined ) {
593- this . cachedPaths [ dirredPath ] = { } ;
594- }
602+ const dirredPath = pathUtils . dirname ( currentPath ) ;
603+ if ( this . cachedPaths [ dirredPath ] === undefined ) {
604+ this . cachedPaths [ dirredPath ] = { } ;
605+ }
595606
596- const cachedPath = this . cachedPaths [ dirredPath ] [ path ] ;
607+ const cachedPath = this . cachedPaths [ dirredPath ] [ path ] ;
597608
598- let resolvedPath ;
609+ if ( cachedPath ) {
610+ return Promise . resolve ( this . transpiledModules [ cachedPath ] . module ) ;
611+ }
599612
600- if ( cachedPath ) {
601- resolvedPath = cachedPath ;
602- } else {
603- const presetAliasedPath = this . getPresetAliasedPath ( path ) ;
613+ const measureKey = `resolve-async: ${ path } : ${ currentPath } ` ;
614+ return new Promise ( ( promiseResolve , promiseReject ) => {
615+ measure ( measureKey ) ;
616+ const presetAliasedPath = this . getPresetAliasedPath ( path ) ;
604617
605- const aliasedPath = this . getAliasedDependencyPath (
606- presetAliasedPath ,
607- currentPath
608- ) ;
609- const shimmedPath = coreLibraries [ aliasedPath ] || aliasedPath ;
618+ const aliasedPath = this . getAliasedDependencyPath (
619+ presetAliasedPath ,
620+ currentPath
621+ ) ;
622+ const shimmedPath = coreLibraries [ aliasedPath ] || aliasedPath ;
610623
611- if ( NODE_LIBS . indexOf ( shimmedPath ) > - 1 ) {
612- this . cachedPaths [ dirredPath ] [ path ] = shimmedPath ;
613- promiseResolve ( getShimmedModuleFromPath ( currentPath , path ) ) ;
614- return ;
615- }
624+ if ( NODE_LIBS . indexOf ( shimmedPath ) > - 1 ) {
625+ this . cachedPaths [ dirredPath ] [ path ] = shimmedPath ;
626+ promiseResolve ( getShimmedModuleFromPath ( currentPath , path ) ) ;
627+ return ;
628+ }
616629
617- try {
618- resolve (
619- shimmedPath ,
620- {
621- filename : currentPath ,
622- extensions : defaultExtensions . map ( ext => '.' + ext ) ,
623- isFile : this . isFile ,
624- readFileSync : this . readFileSync ,
625- packageFilter,
626- moduleDirectory : this . getModuleDirectories ( ) ,
627- } ,
628- ( err , foundPath ) => {
629- if ( err ) {
630- throw err ;
631- }
630+ resolve (
631+ shimmedPath ,
632+ {
633+ filename : currentPath ,
634+ extensions : defaultExtensions . map ( ext => '.' + ext ) ,
635+ isFile : this . isFile ,
636+ readFileSync : this . readFileSync ,
637+ packageFilter,
638+ moduleDirectory : this . getModuleDirectories ( ) ,
639+ } ,
640+ ( err , foundPath ) => {
641+ endMeasure ( measureKey , { silent : true } ) ;
642+ if ( err ) {
643+ if (
644+ this . cachedPaths [ dirredPath ] &&
645+ this . cachedPaths [ dirredPath ] [ path ]
646+ ) {
647+ delete this . cachedPaths [ dirredPath ] [ path ] ;
648+ }
632649
633- this . cachedPaths [ dirredPath ] [ path ] = foundPath ;
650+ let connectedPath = shimmedPath ;
651+ if ( connectedPath . indexOf ( '/node_modules' ) !== 0 ) {
652+ connectedPath = / ^ ( \w | @ \w ) / . test ( shimmedPath )
653+ ? pathUtils . join ( '/node_modules' , shimmedPath )
654+ : pathUtils . join ( pathUtils . dirname ( currentPath ) , shimmedPath ) ;
655+ }
634656
635- if ( foundPath === '//empty.js' ) {
636- promiseResolve ( getShimmedModuleFromPath ( currentPath , path ) ) ;
637- return ;
638- }
657+ const isDependency = connectedPath . includes ( '/node_modules/' ) ;
639658
640- if ( ! this . transpiledModules [ foundPath ] ) {
641- this . readFileSync ( foundPath , code => {
642- this . addModule ( { path : foundPath , code } ) ;
643- promiseResolve ( this . transpiledModules [ foundPath ] . module ) ;
644- } ) ;
645- } else {
646- promiseResolve ( this . transpiledModules [ foundPath ] . module ) ;
647- }
659+ connectedPath = connectedPath . replace ( '/node_modules/' , '' ) ;
660+
661+ if ( ! isDependency ) {
662+ promiseReject (
663+ new ModuleNotFoundError ( shimmedPath , false , currentPath )
664+ ) ;
648665 }
649- ) ;
650- } catch ( e ) {
651- if (
652- this . cachedPaths [ dirredPath ] &&
653- this . cachedPaths [ dirredPath ] [ path ]
654- ) {
655- delete this . cachedPaths [ dirredPath ] [ path ] ;
656- }
657666
658- let connectedPath = shimmedPath ;
659- if ( connectedPath . indexOf ( '/node_modules' ) !== 0 ) {
660- connectedPath = / ^ ( \w | @ \w ) / . test ( shimmedPath )
661- ? pathUtils . join ( '/node_modules' , shimmedPath )
662- : pathUtils . join ( pathUtils . dirname ( currentPath ) , shimmedPath ) ;
663- }
667+ const dependencyName = getDependencyName ( connectedPath ) ;
668+
669+ if (
670+ this . manifest . dependencies . find ( d => d . name === dependencyName ) ||
671+ this . manifest . dependencyDependencies [ dependencyName ]
672+ ) {
673+ promiseReject (
674+ new ModuleNotFoundError ( connectedPath , true , currentPath )
675+ ) ;
676+ } else {
677+ promiseReject (
678+ new DependencyNotFoundError ( connectedPath , currentPath )
679+ ) ;
680+ }
664681
665- const isDependency = connectedPath . includes ( '/node_modules/' ) ;
682+ return ;
683+ }
666684
667- connectedPath = connectedPath . replace ( '/node_modules/' , '' ) ;
685+ this . cachedPaths [ dirredPath ] [ path ] = foundPath ;
668686
669- if ( ! isDependency ) {
670- throw new ModuleNotFoundError ( shimmedPath , false , currentPath ) ;
687+ if ( foundPath === '//empty.js' ) {
688+ promiseResolve ( getShimmedModuleFromPath ( currentPath , path ) ) ;
689+ return ;
671690 }
672691
673- const dependencyName = getDependencyName ( connectedPath ) ;
692+ if ( ! this . transpiledModules [ foundPath ] ) {
693+ this . readFileSync ( foundPath , ( error , code ) => {
694+ if ( error ) {
695+ promiseReject ( error ) ;
696+ return ;
697+ }
674698
675- if (
676- this . manifest . dependencies . find ( d => d . name === dependencyName ) ||
677- this . manifest . dependencyDependencies [ dependencyName ]
678- ) {
679- throw new ModuleNotFoundError ( connectedPath , true , currentPath ) ;
699+ this . addModule ( { path : foundPath , code } ) ;
700+ promiseResolve ( this . transpiledModules [ foundPath ] . module ) ;
701+ } ) ;
680702 } else {
681- throw new DependencyNotFoundError ( connectedPath , currentPath ) ;
703+ promiseResolve ( this . transpiledModules [ foundPath ] . module ) ;
682704 }
683705 }
684- }
685- promiseResolve ( this . transpiledModules [ resolvedPath ] . module ) ;
706+ ) ;
686707 } ) ;
687708 }
688709
@@ -704,6 +725,8 @@ export default class Manager {
704725 if ( cachedPath && this . transpiledModules [ cachedPath ] ) {
705726 resolvedPath = cachedPath ;
706727 } else {
728+ const measureKey = `resolve-sync:${ path } :${ currentPath } ` ;
729+ measure ( measureKey ) ;
707730 const presetAliasedPath = this . getPresetAliasedPath ( path ) ;
708731
709732 const aliasedPath = this . getAliasedDependencyPath (
@@ -726,6 +749,7 @@ export default class Manager {
726749 packageFilter,
727750 moduleDirectory : this . getModuleDirectories ( ) ,
728751 } ) ;
752+ endMeasure ( measureKey , { silent : true } ) ;
729753
730754 this . cachedPaths [ dirredPath ] [ path ] = resolvedPath ;
731755
@@ -812,12 +836,10 @@ export default class Manager {
812836 const tModule =
813837 currentTModule || this . getTranspiledModule ( this . modules [ '/package.json' ] ) ; // Get arbitrary file from root
814838 try {
815- return Promise . resolve (
816- this . resolveTranspiledModule (
817- path ,
818- tModule . module . path ,
819- ignoredExtensions
820- )
839+ return this . resolveTranspiledModule (
840+ path ,
841+ tModule . module . path ,
842+ ignoredExtensions
821843 ) ;
822844 } catch ( e ) {
823845 if ( e . type === 'module-not-found' && e . isDependency ) {
0 commit comments