eval javascript, check for syntax error - javascript

I wanted to know if it is possible to find through javascript if a call to eval() has a syntax error or undefined variable, etc... so lets say I use eval for some arbitrary javascript is there a way to capture the error output of that eval?

You can test to see if an error is indeed a SyntaxError.
try {
eval(code);
} catch (e) {
if (e instanceof SyntaxError) {
alert(e.message);
}
}

When using try-catch for catching a particular type of error one should ensure that other types of exceptions are not suppressed. Otherwise if the evaluated code throws a different kind of exception it could disappear and cause unexpected behaviour of the code.
I would suggest writing code like this:
try {
eval(code);
} catch (e) {
if (e instanceof SyntaxError) {
alert(e.message);
} else {
throw e;
}
}
Please note the "else" section.

According to the Mozilla documentation for eval:
eval returns the value of the last expression evaluated.
So I think you may be out of luck. This same document also recommends against using eval:
eval() is a dangerous function, which executes the code it's passed with the privileges of the caller. If you run eval() with a string that could be affected by a malicious party, you may end up running malicious code on the user's machine with the permissions of your webpage / extension. More importantly, third party code can see the scope in which eval() was invoked, which can lead to possible attacks in ways of which the similar Function is not susceptible.
So regardless, please be aware of the risks before using this function.

You can use JsLint which contains a javascript parser written in javascript. It will give you lots of information about your code, it can be configured to be more relaxed or not, etc...

To continue using the code after validation, I use the following example:
var validCode = 1;
try {
eval( jsCode ); /* Code test */
} catch (e) {
if (e instanceof SyntaxError) {
validCode = 0;
console.warn(e.message);
}
} finally {
if(validCode){
"do some magic"
}
}

This Below code posted by go-oleg thanks to him
This code validate the correct syntax otherwise return error
Note:code is not vaildate run time error because it uses ast parser to analyze the correct syntax.
To Install
npm install esprima --save
code:
var esprima = require('esprima');
var userStringToTest = 'var a = 50;';
var isValid = isValidJs(userStringToTest);
if(isValid) {
alert('its validated!');
}
else {
console.log('its NOT valid syntax!');
}
function isValidJs(testString) {
var isValid = true;
try {
esprima.parse(testString);
}
catch(e) {
isValid = false;
}
return isValid;
}

put your desired value for b
//b="4+6";
try { eval(b); }
catch (err) {
if (err instanceof SyntaxError)
document.getElementById('screen').innerHTML = "<i>Syntax Error</i>";
/*In html make a div and put id "screen" in it for this to work
you can also replace this line with document.write or alert as per your wish*/
}
finally {
document.getElementById('screen').innerHTML = eval(b); //outputs answer
}

Related

How to know whether a piece of JS is executed in an ES Module or a regular script?

I want to know whether a piece of JavaScript is executed in an ES module or a simple script.
This is what I tried so far:
function isEsm1() {
try {
// Script gives a syntax error during parsing when script is not an esm
return Boolean(import.meta.url);
} catch(err) {
return false;
}
}
function isEsm2() {
// will always return false, because `eval` always seems to be executed in regular script context
try {
return eval('Boolean(import.meta.url)');
} catch(err) {
return false;
}
}
function isEsm3() {
// Of course doesn't work, but had to try 😉
return 'meta' in import;
}
Is the regular script executed in the browser or in another context?
In a browser, how about:
var anyvar = {};
var inModule = anyvar === window.anyvar;
If you're in a module, you are not declaring anything on the window...
In NodeJS you could do something similar with global or this:
let inModule = this === module.exports..
Did not try it yet.. but should work I guess...
After testing, just the check for this === undefined is enough to test if you're executing in or out of a module..
Inside a module, this is undefined (as per spec). In global scope this points to global this, which is the window object in the case of a browser context...
Thanks to the discussion in John Gorter's answer, I think we've found a way.
console.log('In module: ' + (this === undefined));
It's as simple as that. Inside a module (and only inside a module (I hope)), this will be undefined. I found it in the v8 documentation here: https://v8.dev/features/modules#intro

Any specific use of double negation (!!) before new?

I understand the basic concept of double-negation- conversion to bool - this is a question about the specific use before new.
I was looking for a way to detect blob support and came across this check on this page:
try { !!new Blob(); } catch (e) { return false; }
I created an example below to demonstrate the check always failing.
window.onload=function()
{
var inputBox = document.getElementById('inputBox');
try {
!!new Foo15514();
inputBox.value='supported';
} catch (e) {
inputBox.value='not supported';
}
}
<input id='inputBox' type=text/>
Without getting into whether this is a good approach for blob detection or not, the question I have is what is the point of the !! in this case? As far as I can tell it is superfluous, but I thought I would ask in case there is something I am missing.
!!new Foo15514(), new Foo15514(), var j = new Foo15514() all have the same result.
Update
Just to get the ball rolling - one thought I had is that this was done to force the javascript engine to evaluate this rather than skipping it since it has no effect, which seems like a bad approach if that was the case.
In this case, it is indeed superfluous. Using the ! operator twice just casts a value to boolean.
However, the code you read in that bug report is not complete (like a typo). It omitted an important part of what was actually meant. If you check the commit that was made, the picture looks different:
function test() {
try {
return !!new Blob();
} catch (e) {
return false;
}
}

javascript try catch vs if then else

I need to be able to run a bunch of code if a statement is successful. If javascript had a try/catch/else then I would put all the code in the else and be done with it. I don't want to use a Boolean to mimic the else in try/catch/else. My understanding is that try can handle an error but can't IF do the same? If so, I'll have to use the IF but I don't want my program to crash if the QueryInterface fails. So my question is, if the QueryInterface fails, then the else will be executed in the IF below correct? If so then I guess the only reason to use a try/catch is to snag the error condition.
existing method:
try {
channel = subject.QueryInterface(Ci.nsIHttpChannel);
} catch(err) {
booSuccess = false;
intErrorCount++
}
if (booSuccess == true) {
...bunch of stuff...
}
proposed method:
if (channel = subject.QueryInterface(Ci.nsIHttpChannel)) {
...bunch of stuff...
} else {
intErrorCount++
}
No, throwing an exception (which you catch with the first snippet) is very different from returning an error code (channel == 0, which the second snippet checks). They do not do the same.
What you might do to avoid that boolean variable is
try {
channel = subject.QueryInterface(Ci.nsIHttpChannel);
...bunch of stuff...
} catch(err) {
intErrorCount++
}
but that would also raise the error count if an exception happens in the bunch of stuff.
No you can't simply replace the try/catch with an if/else. If a line throws an error, the javascript interpreter will stop execution of that script.

JS try / catch generating jshint errors

Any suggestion as to why the following implementation works, but is considered a jshint error?
try {
map.childNodes.length;
} catch (err) {
console.log(err);
}
I just want to see if childNodes has a length before iterating.
Similar thing here:
try {
response.errors.length > 0;
deferred.reject(response);
} catch (e) {
deferred.resolve(response);
}
The warning from JSHint is:
Expected an assignment or function call and instead saw an expression.
The warning shows up even without the use of a try..catch. JSHint is letting you know that map.childNodes.length; as a standalone statement probably isn't useful, and is likely indicative of a coding mistake; i.e., in most cases, you want to do something with the value, not just access it as a standalone statement. For example, you get the same warning with the (useless) statement 5;.
Of course, sometimes it might be useful to access a property as the only behavior in a statement. For example, if you have a getter function defined on the property with Object.defineProperty, then accessing the property will trigger the getter function. However, it's vastly more likely that a value-only statement is coding error, so JSHint warns you about the suspicious code.
That said, your approach could be improved, assuming you're worried that response.error might be a falsey value (undefined, null) instead of an object:
if(response.errors && response.errors.length > 0) {
deferred.resolve(response);
} else {
deferred.reject(response);
}
Because you're abusing conditional operators that ought to be in if conditions. JSHint isn't meant to be approving of anything you can do in Javascript.
For the first, you could use an Array type check, such as:
if (toString.call(map.childNodes) === '[object Array]') {
//iterator
}
For the second, something like this perhaps:
if (response.errors && response.errors.length > 0) {
deferred.reject(response);
} else {
deferred.resolve(response);
}

Check syntax of JavaScript(jQuery) code before running jQuery.globalEval() or eval()

Continuing with topic: jQuery .globalEval() function
I use jQuery.globalEval(varwithJScode);
Now the problem starts when code in varwithJScode contains syntax or other error - the whole script stops.
jsFiddle does not support jQuery.globalEval(), but I used eval() instead to simulate.
http://jsfiddle.net/55FfW/
Try changing var codeforeval to some wrong javascript code and next command will fail.
Is there a way to avoid other JS code from stopping in case of error and/or is there a way to check syntax before eval?
Tried using this one:
try {
jQuery.globalEval(jscode);
} catch (e) {
if (e instanceof SyntaxError) {
alert('JS error!');
}
}
Does not work for me!
try {
jQuery.globalEval(data.js);
} catch(e) {
console.log(e);
}
You need not a heavy jQuery to do such a simple thing.
Just assign eval to a variable and then call it.
try{
var globalEval = eval;
globalEval(jscode); //execute in global scope
} catch(e) {
alert(e);
}

Categories