From 61efe8a34b5d5d2bb255f0dd60a35362fc426373 Mon Sep 17 00:00:00 2001 From: Amjad Masad Date: Fri, 22 May 2015 10:17:43 -0700 Subject: [PATCH] [react-packager] Use actual error types Summary: @public Previously, we had to use errors as a property on the result object because there was no way to pass custom props between the child worker and the parent. This has been fixed in node-worker-farm (D2092153) and now we can use regular errors. This also adapts the transformer to babel-specific errors. Generic errors, however, should still work and render readable info. Additionally, I deprecated, but maintained backwards compatiblity for people in OSS that are using custom transformers. Test Plan: 1. `./runJestTests.sh` 2. `./runJestTests.sh PackagerIntegration` 3. open the playground app 4. Add a syntax error. Say `1=x` somewhere in the file 5. Reload and see error message 'SyntaxError description (line:col)' 6. Make sure that the stack trace is clickable and it attempts to open the editor to the location --- .../__tests__/Transformer-test.js | 27 +++++++++----- react-packager/src/JSTransformer/index.js | 37 +++++++++---------- 2 files changed, 35 insertions(+), 29 deletions(-) diff --git a/react-packager/src/JSTransformer/__tests__/Transformer-test.js b/react-packager/src/JSTransformer/__tests__/Transformer-test.js index 5948916a..22ca53e6 100644 --- a/react-packager/src/JSTransformer/__tests__/Transformer-test.js +++ b/react-packager/src/JSTransformer/__tests__/Transformer-test.js @@ -57,25 +57,34 @@ describe('Transformer', function() { }); pit('should add file info to parse errors', function() { + var message = 'message'; + var snippet = 'snippet'; + require('fs').readFile.mockImpl(function(file, callback) { callback(null, 'var x;\nvar answer = 1 = x;'); }); workers.mockImpl(function(data, callback) { - var esprimaError = new Error('Error: Line 2: Invalid left-hand side in assignment'); - esprimaError.description = 'Invalid left-hand side in assignment'; - esprimaError.lineNumber = 2; - esprimaError.column = 15; - callback(null, {error: esprimaError}); + var babelError = new SyntaxError(message); + babelError.type = 'SyntaxError'; + babelError.description = message; + babelError.loc = { + line: 2, + column: 15, + }; + babelError.codeFrame = snippet; + callback(babelError); }); return new Transformer(OPTIONS).loadFileAndTransform('foo-file.js') .catch(function(error) { expect(error.type).toEqual('TransformError'); - expect(error.snippet).toEqual([ - 'var answer = 1 = x;', - ' ^', - ].join('\n')); + expect(error.message).toBe('SyntaxError ' + message); + expect(error.lineNumber).toBe(2); + expect(error.column).toBe(15); + expect(error.filename).toBe('foo-file.js'); + expect(error.description).toBe(message); + expect(error.snippet).toBe(snippet); }); }); }); diff --git a/react-packager/src/JSTransformer/index.js b/react-packager/src/JSTransformer/index.js index 2dc5e20b..513d4394 100644 --- a/react-packager/src/JSTransformer/index.js +++ b/react-packager/src/JSTransformer/index.js @@ -99,7 +99,12 @@ Transformer.prototype.loadFileAndTransform = function(filePath) { }).then( function(res) { if (res.error) { - throw formatError(res.error, filePath, sourceCode); + console.warn( + 'Error property on the result value form the transformer', + 'module is deprecated and will be removed in future versions.', + 'Please pass an error object as the first argument to the callback' + ); + throw formatError(res.error, filePath); } return new ModuleTransport({ @@ -110,6 +115,8 @@ Transformer.prototype.loadFileAndTransform = function(filePath) { }); } ); + }).catch(function(err) { + throw formatError(err, filePath); }); }); }; @@ -118,8 +125,8 @@ function TransformError() {} util.inherits(TransformError, SyntaxError); function formatError(err, filename, source) { - if (err.lineNumber && err.column) { - return formatEsprimaError(err, filename, source); + if (err.loc) { + return formatBabelError(err, filename, source); } else { return formatGenericError(err, filename, source); } @@ -136,26 +143,16 @@ function formatGenericError(err, filename) { return error; } -function formatEsprimaError(err, filename, source) { - var stack = err.stack.split('\n'); - stack.shift(); - - var msg = 'TransformError: ' + err.description + ' ' + filename + ':' + - err.lineNumber + ':' + err.column; - var sourceLine = source.split('\n')[err.lineNumber - 1]; - var snippet = sourceLine + '\n' + new Array(err.column - 1).join(' ') + '^'; - - stack.unshift(msg); - +function formatBabelError(err, filename) { var error = new TransformError(); - error.message = msg; error.type = 'TransformError'; - error.stack = stack.join('\n'); - error.snippet = snippet; + error.message = (err.type || error.type) + ' ' + err.message; + error.stack = err.stack; + error.snippet = err.codeFrame; + error.lineNumber = err.loc.line; + error.column = err.loc.column; error.filename = filename; - error.lineNumber = err.lineNumber; - error.column = err.column; - error.description = err.description; + error.description = err.message; return error; }