We had a situation today where 1 small error (on line 500) in our JS library file (3000+ lines long) caused a runtime error (calling a method on an undefined object).
The error stoped further execution of all other code in the library file causing our site to not work properly.
My question is:
Since JS is single threaded, will splitting up our code into multiple files and scopes help resolve issues like that in the future?
If we don't split it up, how can we prevent this from happening.
thx,
You can't : js scripts are loaded at once.
The only way to prevent it is to design your code correctly, using try/catch and to write and run tests
Simple solution would be to check if the object exists before attempting to call the method on it.
if ( myObject && myObject.myObjectFunction )
myObject.myFunction();
else
return false;
If the object exists and the object has the function you want to call then it'll call the function, otherwise it'll return false and not attempt to call the function, thus avoiding the error entirely.
Related
I am running a Tampermonkey script on a website that I do not have the code for.
Sometimes it happens that I have a value that does not exist on the page and I get the following error:
"Cannot read property 'click' of null"
And the entire script stops. How can I tell get my script to ignore the error and just carry on to the next line of code?
Here is an example of a vanilla Javascript line that I work with:
document.querySelector('[value="xyz"]').click();
Only execute click() if the selector found something:
if(document.querySelector('[value="xyz"]'))
document.querySelector('[value="xyz"]').click();
You can't, and you shouldn't want to: errors are bad. They're not informative, they are a signal that the code has run into an unrecoverable error and the current code path should be terminated. If you were to ignore it, and keep running, now you're in a state where any subsequent line is just as likely to also throw an error.
Either actually fix things, by making your tampermonkey script not interfere with the way the page it's running on builds its DOM, or as a last resort, you can find out which function is throwing the error for the specific page(s) you're running into this, and then _specifically for those pages, find and rebind the entire function using a try/catch, such as:
const _old_fn = window.theFunctionInvolved;
window.theFunctionInvolved = function(...args) {
try { return _old_fn(...args); }
catch (e) {}
};
But of course, all you've now done is moved the buck: you'll have effectively guaranteed different errors later on, with the actual cause now permanently hidden.
So really: don't do this. Fix your tampermonkey script, or stop using it altogether.
Two aspects of my project's Javascript are interfering with each other. Not sure why, or how to resolve.
I have the following in my code, in order to allow for a URL hashtag action:
function getHashValue(key) {
return location.hash.match(new RegExp(key+'=([^&]*)'))[1];
}
var hash = getHashValue('hash');
console.log(hash);
I'm also running video.js and bigvideo.js within my Rails project. For some reason, the javascript code above prevents the other javascript (my bigvideo implementation) from functioning. Why? How do I resolve?
My bigvideo implementation is described here: https://stackoverflow.com/a/17581187/1318135
It seems possible that getHashValue is throwing an exception (array limit exceeded?) which could interfere prevent other code on the thread from running. Try enclosing the return statement in a try/catch.
Here's what you get: TypeError (exception) Cannot read property '1' of null.
Catch the exception and you'll be okay, I think.
I'd love to live in a lint free world. JSLint that is. But I'm having some problems that I'm not sure I should ignore or fix. Specifically I'm getting a number of:
[functionName] not defined
errors. I do recognise that you should always define the function before using it and I assume that's what the message is really warning against but here are two cases where I think there is a valid exception:
jQuery(document).ready(function($) {
// code goes here
}
In a simple file which starts with a typical noconflict wrapper for jQuery I get a warning saying that "jQuery(document).ready(function($) {" is not defined. Obviously jQuery is defined in a separate file that needs to stay separate. Does that make sense?
The second example is really quite similar although arguably it is more avoidable. In this case I have two JS files in my project. One that looks just like the one above (aka, it's a set of DOM triggered events wrapped inside of jQuery's "ready" event). The other has a number of helper functions that look like this:
function doSomethingImportant() { };
function doSomethingImpressive() { };
These functions are then called within the first JS file. JSLint doesn't like this and complains every time the first JS file calls a function defined in the second JS file: doSomethingImportant() { is not defined. Yet in reality, since the functions are defined at load time and the calls to those functions always happen afterward based on DOM events there never seems to be a real problem.
Anyway, open to ideas. Is this a case of filtering JSLint's advice or something I should fix in code?
You're getting these errors because JSLint assumes that at some point in the future you might do:
var doSomethingImpressive = function() { }
in which case you would get an error, because the file where the function is defined is included after the function call (as explained here)
The same goes for the jQuery call. You can either change the order of your scripts, or safely ignore the errors.
After using functionality from this question for debugging I am wondering is there a way to get the file name from which the function was invoked and may be the line.
May be I am asking for too much, but I know that in some of the languages it is possible.
If this is not possible can anyone mention why his functionality was not implemented?
I will try to rephrase the question, because I think I didn't make myself clear.
I have file.js in which on the 17-th line there is a declaration of the function:
...
function main()
{
Hello();
}
I have another file test.js, where I define function hello
function Hello()
{
...
which tells me the name of the file and a line in which the function which evoked it was defined
}
So for example if I will call
main(), it will tell me file.js, 17 line
It has nothing to do with firebug
If all your doing is debugging, hy not just use the debugger built into modern browsers?
debugger
That line is all you need. You can examine the callstack, inspect variable values, and even run code in the current scope.
Such functionality makes your request kind of unnecessary.
You don't mention what browser you are using.
In Chrome what I would suggest is inserting a breakpoint on the first line of the function. Then reload the page (or otherwise trigger the function call). When execution pauses at the breakpoint, check the Call Stack section in Chrome's Developer tools - it will give you a stack back-trace of the flow of execution.
I'm sure Firebug offers something similar if not identical, it's just been a while since I used it.
Cheers
I'm trying to make a PoC of reflected Cross-Site Scripting on a website that I'm testing right now. I've found a place inside of a Javascript code where commands can be injected, however the trouble is that there the previous block of code throws a 'not defined' error and therefore (at least I think so) my injected code is not executed. Is there any chance to execute the code anyway?
Here is the code:
UndefinedObject.Init({
Var1:"a",
Var2:"b",
Var3:"can_be_injected_with_JS_code")}
I can't inject any HTML tags as these are filtered by the application.
Many thanks!
Wrap them under try catch block.
In a sequence of execution, if the code fails, the remaining part will not be executed. Javascript errors ("Exceptions") can be caught using try...catch (if you are able to inject this try - catch also).
If there is a different flow (via another event), the code will continue.
You can either try using a try-catch, or if that won't help, try using window.onerror
Generally the right way of doing that is using try-catch-finally or try-finally:
If you make something about the error - log or do something else. Catch may be also used to execute your code, but not a good practice. You can do nothing about the error if you want, that`s why finally is used.
Finally is used when it is important to execute a piece of code, no matter if an error is thrown or not. For example in C++ or other language when you work with files inside finally the file is closed ( you can not leave it opened ). Look here for some examples.