diff --git a/vendor/browser-transforms.js b/vendor/browser-transforms.js index f6a6980c691b..701693c34a7c 100644 --- a/vendor/browser-transforms.js +++ b/vendor/browser-transforms.js @@ -37,11 +37,65 @@ exports.exec = function(code) { var inlineScriptCount = 0; +// This method returns a nicely formated line of code pointing the +// exactly location of the error `e`. +// The line is limited in size so big lines of code are also shown +// in a readable way. +// Example: +// +// ... x', overflow:'scroll'}} id={} onScroll={this.scroll} class=" ... +// ^ +var createSourceCodeErrorMessage = function(code, e) { + var sourceLines = code.split('\n'); + var erroneousLine = sourceLines[e.lineNumber - 1]; + + // Removes any leading indenting spaces and gets the number of + // chars indenting the `erroneousLine` + var indentation = 0; + erroneousLine = erroneousLine.replace(/^\s+/, function(leadingSpaces) { + indentation = leadingSpaces.length; + return ''; + }); + + // Defines the number of characters that are going to show + // before and after the erroneous code + var LIMIT = 30; + var errorColumn = e.column - indentation; + + if (errorColumn > LIMIT) { + erroneousLine = '... ' + erroneousLine.slice(errorColumn - LIMIT); + errorColumn = 4 + LIMIT; + } + if (erroneousLine.length - errorColumn > LIMIT) { + erroneousLine = erroneousLine.slice(0, errorColumn + LIMIT) + ' ...'; + } + var message = '\n\n' + erroneousLine + '\n'; + message += new Array(errorColumn - 1).join(' ') + '^'; + return message; +}; + var transformCode = function(code, source) { var jsx = docblock.parseAsObject(docblock.extract(code)).jsx; if (jsx) { - var transformed = transformReact(code); + try { + var transformed = transformReact(code); + } catch(e) { + e.message += '\n at '; + if (source) { + if ('fileName' in e) { + // We set `fileName` if it's supported by this error object and + // a `source` was provided. + // The error will correctly point to `source` in Firefox. + e.fileName = source; + } + e.message += source + ':' + e.lineNumber + ':' + e.column; + } else { + e.message += location.href; + } + e.message += createSourceCodeErrorMessage(code, e); + throw e; + } var map = transformed.sourceMap.toJSON(); if (source == null) { @@ -98,7 +152,7 @@ var load = exports.load = function(url, callback) { runScripts = function() { var scripts = document.getElementsByTagName('script'); - + // Array.prototype.slice cannot be used on NodeList on IE8 var jsxScripts = []; for (var i = 0; i < scripts.length; i++) { @@ -106,7 +160,7 @@ runScripts = function() { jsxScripts.push(scripts.item(i)); } } - + console.warn("You are using the in-browser JSX transformer. Be sure to precompile your JSX for production - http://facebook.github.io/react/docs/tooling-integration.html#jsx"); jsxScripts.forEach(function(script) {