@@ -7,6 +7,7 @@ import babelParser from 'prettier/parser-babel';
77import htmlParser from 'prettier/parser-html' ;
88import cssParser from 'prettier/parser-postcss' ;
99import { withTranslation } from 'react-i18next' ;
10+ import StackTrace from 'stacktrace-js' ;
1011import 'codemirror/mode/css/css' ;
1112import 'codemirror/addon/selection/active-line' ;
1213import 'codemirror/addon/lint/lint' ;
@@ -115,7 +116,6 @@ class Editor extends React.Component {
115116 styleSelectedText : true ,
116117 lint : {
117118 onUpdateLinting : ( annotations ) => {
118- this . props . hideRuntimeErrorWarning ( ) ;
119119 this . updateLintingMessageAccessibility ( annotations ) ;
120120 } ,
121121 options : {
@@ -159,10 +159,11 @@ class Editor extends React.Component {
159159 'change' ,
160160 debounce ( ( ) => {
161161 this . props . setUnsavedChanges ( true ) ;
162+ this . props . hideRuntimeErrorWarning ( ) ;
162163 this . props . updateFileContent ( this . props . file . id , this . _cm . getValue ( ) ) ;
163164 if ( this . props . autorefresh && this . props . isPlaying ) {
164165 this . props . clearConsole ( ) ;
165- this . props . startRefreshSketch ( ) ;
166+ this . props . startSketch ( ) ;
166167 }
167168 } , 1000 )
168169 ) ;
@@ -246,41 +247,45 @@ class Editor extends React.Component {
246247 ) ;
247248 }
248249
249- if ( prevProps . consoleEvents !== this . props . consoleEvents ) {
250- this . props . showRuntimeErrorWarning ( ) ;
251- }
252- for ( let i = 0 ; i < this . _cm . lineCount ( ) ; i += 1 ) {
253- this . _cm . removeLineClass ( i , 'background' , 'line-runtime-error' ) ;
254- }
255250 if ( this . props . runtimeErrorWarningVisible ) {
256- this . props . consoleEvents . forEach ( ( consoleEvent ) => {
257- if ( consoleEvent . method === 'error' ) {
258- if (
259- consoleEvent . data &&
260- consoleEvent . data [ 0 ] &&
261- consoleEvent . data [ 0 ] . indexOf &&
262- consoleEvent . data [ 0 ] . indexOf ( ')' ) > - 1
263- ) {
264- const n = consoleEvent . data [ 0 ] . replace ( ')' , '' ) . split ( ' ' ) ;
265- const lineNumber = parseInt ( n [ n . length - 1 ] , 10 ) - 1 ;
266- const { source } = consoleEvent ;
267- const fileName = this . props . file . name ;
268- const errorFromJavaScriptFile = ` ${ source } .js` === fileName ;
269- const errorFromIndexHTML =
270- source === fileName && fileName === 'index.html' ;
271- if (
272- ! Number . isNaN ( lineNumber ) &&
273- ( errorFromJavaScriptFile || errorFromIndexHTML )
274- ) {
251+ if ( this . props . consoleEvents . length !== prevProps . consoleEvents . length ) {
252+ this . props . consoleEvents . forEach ( ( consoleEvent ) => {
253+ if ( consoleEvent . method === 'error' ) {
254+ // It doesn't work if you create a new Error, but this works
255+ // LOL
256+ const errorObj = { stack : consoleEvent . data [ 0 ] . toString ( ) } ;
257+ StackTrace . fromError ( errorObj ) . then ( ( stackLines ) => {
258+ this . props . expandConsole ( ) ;
259+ const line = stackLines . find (
260+ ( l ) => l . fileName && l . fileName . startsWith ( '/' )
261+ ) ;
262+ if ( ! line ) return ;
263+ const fileNameArray = line . fileName . split ( '/' ) ;
264+ const fileName = fileNameArray . slice ( - 1 ) [ 0 ] ;
265+ const filePath = fileNameArray . slice ( 0 , - 1 ) . join ( '/' ) ;
266+ const fileWithError = this . props . files . find (
267+ ( f ) => f . name === fileName && f . filePath === filePath
268+ ) ;
269+ this . props . setSelectedFile ( fileWithError . id ) ;
275270 this . _cm . addLineClass (
276- lineNumber ,
271+ line . lineNumber - 1 ,
277272 'background' ,
278273 'line-runtime-error'
279274 ) ;
280- }
275+ } ) ;
281276 }
277+ } ) ;
278+ } else {
279+ for ( let i = 0 ; i < this . _cm . lineCount ( ) ; i += 1 ) {
280+ this . _cm . removeLineClass ( i , 'background' , 'line-runtime-error' ) ;
282281 }
283- } ) ;
282+ }
283+ }
284+
285+ if ( this . props . file . id !== prevProps . file . id ) {
286+ for ( let i = 0 ; i < this . _cm . lineCount ( ) ; i += 1 ) {
287+ this . _cm . removeLineClass ( i , 'background' , 'line-runtime-error' ) ;
288+ }
284289 }
285290 }
286291
@@ -440,7 +445,7 @@ Editor.propTypes = {
440445 method : PropTypes . string . isRequired ,
441446 args : PropTypes . arrayOf ( PropTypes . string )
442447 } )
443- ) ,
448+ ) . isRequired ,
444449 updateLintMessage : PropTypes . func . isRequired ,
445450 clearLintMessage : PropTypes . func . isRequired ,
446451 updateFileContent : PropTypes . func . isRequired ,
@@ -453,7 +458,7 @@ Editor.propTypes = {
453458 url : PropTypes . string
454459 } ) . isRequired ,
455460 setUnsavedChanges : PropTypes . func . isRequired ,
456- startRefreshSketch : PropTypes . func . isRequired ,
461+ startSketch : PropTypes . func . isRequired ,
457462 autorefresh : PropTypes . bool . isRequired ,
458463 isPlaying : PropTypes . bool . isRequired ,
459464 theme : PropTypes . string . isRequired ,
@@ -471,15 +476,13 @@ Editor.propTypes = {
471476 expandSidebar : PropTypes . func . isRequired ,
472477 isUserOwner : PropTypes . bool . isRequired ,
473478 clearConsole : PropTypes . func . isRequired ,
474- showRuntimeErrorWarning : PropTypes . func . isRequired ,
479+ // showRuntimeErrorWarning: PropTypes.func.isRequired,
475480 hideRuntimeErrorWarning : PropTypes . func . isRequired ,
476481 runtimeErrorWarningVisible : PropTypes . bool . isRequired ,
477482 provideController : PropTypes . func . isRequired ,
478- t : PropTypes . func . isRequired
479- } ;
480-
481- Editor . defaultProps = {
482- consoleEvents : [ ]
483+ t : PropTypes . func . isRequired ,
484+ setSelectedFile : PropTypes . func . isRequired ,
485+ expandConsole : PropTypes . func . isRequired
483486} ;
484487
485488function mapStateToProps ( state ) {
@@ -496,7 +499,7 @@ function mapStateToProps(state) {
496499 user : state . user ,
497500 project : state . project ,
498501 toast : state . toast ,
499- console : state . console ,
502+ consoleEvents : state . console ,
500503
501504 ...state . preferences ,
502505 ...state . ide ,
0 commit comments