2

We've some user defined fields defining javascript functions and would like to show the user the position ( line, column ) when an error is thrown. For example :

userFunc = new Function('context',  '{  let a = 0; \n context.missingFunction(); return 2; }');

When evaluating userFunc

userFunc({});

an exception is thrown, that looks like :

 context.missingMeethod is not a function 

Is there a library to retrieve the position of the error in all modern browsers (e.g. : line 2, column 12 )

error-stack-parser library (from StacktraceJS) is not retrieving the information. In Chrome the stacktrace looks like (the position is in anonymous):

TypeError: context.missingMeethod is not a function
    at eval (eval at <anonymous> (http://localhost:3000/icCube/reporting/static/js/main.chunk.js:28541:66), <anonymous>:2:12)
ic3
  • 7,917
  • 14
  • 67
  • 115
  • There's an issue for this in error-stack-parser (https://github.com/stacktracejs/error-stack-parser/issues/32). If you're keen to contribute, you could help out literally hundreds of thousands of folks who use the library. Please write a unit test :) – Eric Wendelin May 29 '20 at 14:42

1 Answers1

1

This seems to be possible in Chrome, Firefox and Safari at least. I'm not sure how well this generalizes, but it might give you something to work from!

In Chrome:

getErrorPosition = (userFunc) => {
    try {
        userFunc({});
        return null;
    } catch (error) {
        const relevantLine = error.stack.split('\n')[1];
        const regex = /<anonymous>:(\d+):(\d+)\)/g;
        const match = regex.exec(relevantLine);
        if (match) {
            return {
                line: parseInt(match[1], 10),
                column: parseInt(match[2], 10)
            };
        } else {
            return null;
        }
    }
}

In Safari:

getErrorPosition = (userFunc) => {
    try {
        userFunc({});
        return null;
    } catch (error) {
        return {
            line: error.line,
            column: error.column,
        };
    }
}

In Firefox:

getErrorPosition = (userFunc) => {
    try {
        userFunc({});
        return null;
    } catch (error) {
        const relevantLine = error.stack.split('\n')[0];
        const regex = /Function:(\d+):(\d+)/g;
        const match = regex.exec(relevantLine);
        if (match) {
            return {
                line: parseInt(match[1], 10),
                column: parseInt(match[2], 10)
            };
        } else {
            return null;
        }
    }
}
Wouter Raateland
  • 1,007
  • 8
  • 13