@@ -14,78 +14,54 @@ const ts = require("../../lib/typescript");
1414const del = require ( "del" ) ;
1515const needsUpdate = require ( "./needsUpdate" ) ;
1616const mkdirp = require ( "./mkdirp" ) ;
17- const prettyTime = require ( "pretty-hrtime" ) ;
1817const { reportDiagnostics } = require ( "./diagnostics" ) ;
19- const { CountdownEvent, ManualResetEvent } = require ( "prex" ) ;
18+ const { CountdownEvent, ManualResetEvent, Semaphore } = require ( "prex" ) ;
2019
2120const workStartedEvent = new ManualResetEvent ( ) ;
2221const countdown = new CountdownEvent ( 0 ) ;
2322
24- class CompilationGulp extends gulp . Gulp {
25- /**
26- * @param {boolean } [verbose]
27- */
28- fork ( verbose ) {
29- const child = new ForkedGulp ( this . tasks ) ;
30- child . on ( "task_start" , e => {
31- if ( countdown . remainingCount === 0 ) {
32- countdown . reset ( 1 ) ;
33- workStartedEvent . set ( ) ;
34- workStartedEvent . reset ( ) ;
35- }
36- else {
37- countdown . add ( ) ;
38- }
39- if ( verbose ) {
40- log ( 'Starting' , `'${ chalk . cyan ( e . task ) } ' ${ chalk . gray ( `(${ countdown . remainingCount } remaining)` ) } ...` ) ;
41- }
42- } ) ;
43- child . on ( "task_stop" , e => {
44- countdown . signal ( ) ;
45- if ( verbose ) {
46- log ( 'Finished' , `'${ chalk . cyan ( e . task ) } ' after ${ chalk . magenta ( prettyTime ( /** @type {* }*/ ( e ) . hrDuration ) ) } ${ chalk . gray ( `(${ countdown . remainingCount } remaining)` ) } ` ) ;
47- }
48- } ) ;
49- child . on ( "task_err" , e => {
50- countdown . signal ( ) ;
51- if ( verbose ) {
52- log ( `'${ chalk . cyan ( e . task ) } ' ${ chalk . red ( "errored after" ) } ${ chalk . magenta ( prettyTime ( /** @type {* }*/ ( e ) . hrDuration ) ) } ${ chalk . gray ( `(${ countdown . remainingCount } remaining)` ) } ` ) ;
53- log ( e . err ? e . err . stack : e . message ) ;
54- }
55- } ) ;
56- return child ;
57- }
58-
59- // @ts -ignore
60- start ( ) {
61- throw new Error ( "Not supported, use fork." ) ;
62- }
63- }
64-
65- class ForkedGulp extends gulp . Gulp {
66- /**
67- * @param {gulp.Gulp["tasks"] } tasks
68- */
69- constructor ( tasks ) {
70- super ( ) ;
71- this . tasks = tasks ;
72- }
73-
74- // Do not reset tasks
75- _resetAllTasks ( ) { }
76- _resetSpecificTasks ( ) { }
77- _resetTask ( ) { }
78- }
79-
8023// internal `Gulp` instance for compilation artifacts.
81- const compilationGulp = new CompilationGulp ( ) ;
24+ const compilationGulp = new gulp . Gulp ( ) ;
8225
8326/** @type {Map<ResolvedProjectSpec, ProjectGraph> } */
8427const projectGraphCache = new Map ( ) ;
8528
8629/** @type {Map<string, { typescript: string, alias: string, paths: ResolvedPathOptions }> } */
8730const typescriptAliasMap = new Map ( ) ;
8831
32+ // TODO: allow concurrent outer builds to be run in parallel
33+ const sem = new Semaphore ( 1 ) ;
34+
35+ /**
36+ * @param {string|string[] } taskName
37+ * @param {() => any } [cb]
38+ */
39+ function start ( taskName , cb ) {
40+ return sem . wait ( ) . then ( ( ) => new Promise ( ( resolve , reject ) => {
41+ compilationGulp . start ( taskName , err => {
42+ if ( err ) {
43+ reject ( err ) ;
44+ }
45+ else if ( cb ) {
46+ try {
47+ resolve ( cb ( ) ) ;
48+ }
49+ catch ( e ) {
50+ reject ( err ) ;
51+ }
52+ }
53+ else {
54+ resolve ( ) ;
55+ }
56+ } ) ;
57+ } ) ) . then ( ( ) => {
58+ sem . release ( )
59+ } , e => {
60+ sem . release ( ) ;
61+ throw e ;
62+ } ) ;
63+ }
64+
8965/**
9066 * Defines a gulp orchestration for a TypeScript project, returning a callback that can be used to trigger compilation.
9167 * @param {string } projectSpec The path to a tsconfig.json file or its containing directory.
@@ -98,9 +74,7 @@ function createCompiler(projectSpec, options) {
9874 const projectGraph = getOrCreateProjectGraph ( resolvedProjectSpec , resolvedOptions . paths ) ;
9975 projectGraph . isRoot = true ;
10076 const taskName = compileTaskName ( ensureCompileTask ( projectGraph , resolvedOptions ) , resolvedOptions . typescript ) ;
101- return ( ) => new Promise ( ( resolve , reject ) => compilationGulp
102- . fork ( resolvedOptions . verbose )
103- . start ( taskName , err => err ? reject ( err ) : resolve ( ) ) ) ;
77+ return ( ) => start ( taskName ) ;
10478}
10579exports . createCompiler = createCompiler ;
10680
@@ -139,9 +113,7 @@ function createCleaner(projectSpec, options) {
139113 const projectGraph = getOrCreateProjectGraph ( resolvedProjectSpec , paths ) ;
140114 projectGraph . isRoot = true ;
141115 const taskName = cleanTaskName ( ensureCleanTask ( projectGraph ) ) ;
142- return ( ) => new Promise ( ( resolve , reject ) => compilationGulp
143- . fork ( )
144- . start ( taskName , err => err ? reject ( err ) : resolve ( ) ) ) ;
116+ return ( ) => start ( taskName ) ;
145117}
146118exports . createCleaner = createCleaner ;
147119
@@ -811,7 +783,7 @@ function possiblyTriggerRecompilation(config, task) {
811783function triggerRecompilation ( task , config ) {
812784 compilationGulp . _resetTask ( task ) ;
813785 if ( config . watchers && config . watchers . size ) {
814- compilationGulp . fork ( ) . start ( task . name , ( ) => {
786+ start ( task . name , ( ) => {
815787 /** @type {Set<string> } */
816788 const taskNames = new Set ( ) ;
817789 /** @type {((err?: any) => void)[] } */
@@ -831,7 +803,7 @@ function triggerRecompilation(task, config) {
831803 } ) ;
832804 }
833805 else {
834- compilationGulp . fork ( /*verbose*/ true ) . start ( task . name ) ;
806+ start ( task . name ) ;
835807 }
836808}
837809
0 commit comments