@@ -97,11 +97,11 @@ module.exports = CoreObject.extend({
9797 this . restartPromise = this . stop ( )
9898 . then ( ( ) => this . clearRequireCache ( options . outputPath ) )
9999 . then ( ( ) => this . start ( options ) )
100- . catch ( e => this . ui . writeLine ( e ) )
100+ . catch ( e => this . printError ( e ) )
101101 . finally ( ( ) => {
102102 this . restartPromise = null ;
103103 if ( this . restartAgain ) {
104- debug ( 'restart again' )
104+ debug ( 'restart again' ) ;
105105 this . restartAgain = false ;
106106 this . restart ( options ) ;
107107 }
@@ -120,5 +120,51 @@ module.exports = CoreObject.extend({
120120 delete require . cache [ key ] ;
121121 }
122122 } ) ;
123+ } ,
124+
125+ /*
126+ * Try to show a useful error message if we're not able to start the user's
127+ * app in FastBoot.
128+ */
129+ printError : function ( e ) {
130+ var preamble = [ "There was an error trying to run your application in FastBoot.\n" ,
131+ "This is usually caused by either your application code or an addon trying to access " +
132+ "an API that isn't available in Node.js." ] ;
133+
134+ // If there's a stack trace available, try to extract some information for
135+ // it so we can generate a more helpful error message.
136+ if ( e . stack ) {
137+ // Look at the stack trace line by line
138+ var stack = e . stack . split ( '\n' ) ;
139+
140+ // Verify there's a second line with path information.
141+ // (First line is the error message itself.)
142+ if ( stack [ 1 ] ) {
143+ // Extract path and line number information. An example line looks like:
144+ // at /Users/monegraph/Code/fastboot-test/dist/fastboot/vendor.js:65045:19
145+ var match = stack [ 1 ] . match ( / \s * a t ( [ ^ : ] + ) : ( \d + ) : ( \d + ) $ / ) ;
146+ if ( match ) {
147+ // Print file name and line number from the top of the stack. This is displayed
148+ // anyway, of course, but not everyone knows how to read a stack trace. This makes
149+ // it more obvious.
150+ var badFilePath = path . relative ( process . cwd ( ) , match [ 1 ] ) ;
151+ preamble . push ( "Based on the stack trace, it looks like the exception was generated in " + badFilePath + " on line " + match [ 2 ] + "." ) ;
152+ }
153+
154+ // If the exception is coming from `vendor.js`, that usually means it's from an addon and thus may be
155+ // out of the user's control. Give the user some instructions so they can try to figure out which
156+ // addon is causing the problem.
157+ if ( match && match [ 1 ] . substr ( - 9 ) === 'vendor.js' ) {
158+ preamble . push ( "Because it's coming from vendor.js, an addon is most likely responsible for this error. You should look at this " +
159+ "file and line number to determine which addon is not yet FastBoot compatible." ) ;
160+
161+ }
162+ }
163+
164+ preamble . push ( "\nThe full stack trace is:" ) ;
165+ }
166+
167+ this . ui . writeError ( preamble . join ( '\n' ) + '\n' ) ;
168+ this . ui . writeError ( e ) ;
123169 }
124170} ) ;
0 commit comments