Skip to main content

Bug Tracker

Side navigation

#10251 closed bug (wontfix)

Opened September 12, 2011 09:14AM UTC

Closed January 18, 2012 03:29AM UTC

Last modified March 25, 2014 10:05AM UTC

an uncaught exception in one ready handler prevents all others from executing

Reported by: al_9x@yahoo.com Owned by:
Priority: low Milestone: None
Component: misc Version: 1.6.3
Keywords: Cc: jaubourg
Blocked by: Blocking:
Description
<script>
$(function() {
	alert('1st ready');
	throw "forced error";
});
</script>
<script>
$(function() {
	alert('2nd ready');
});
</script>

whereas when dealing with DOM directly, an uncaught exception in one DOMContentLoaded does not abort the others.

<script>
document.addEventListener("DOMContentLoaded", function() {
	alert('1st DOMContentLoaded');
	throw "forced error";
}, false);
</script>
<script>
document.addEventListener("DOMContentLoaded", function() {
	alert('2nd DOMContentLoaded');
}, false);
</script>

this forces dependencies, that need not exists, between often unrelated bits of code, making the page more brittle

Attachments (0)
Change History (17)

Changed September 12, 2011 11:27AM UTC by addyosmani comment:1

component: unfiledmisc
priority: undecidedlow
status: newopen

Confirmed. This also occurs with $.error: http://jsfiddle.net/st3Kj/1/, however I wonder if the reasoning behind this behaviour is that you're more likely to use a try/catch block with your throws (eg. this works fine http://jsfiddle.net/st3Kj/2/). Leaving open for further comment.

Changed November 16, 2011 08:11PM UTC by dmethvin comment:2

cc: → jaubourg
keywords: → 1.8-discuss

I don't think we can avoid this unless we run all the handlers asynchronously and independently via setImmediate/setTimeout. If we try/catch then we destroy important error information.

Changed November 16, 2011 08:24PM UTC by timmywil comment:3

-1, This is desired behavior imho.

Changed December 13, 2011 04:10PM UTC by jaubourg comment:4

description: {{{ \ <script> \ $(function() { \ alert('1st ready'); \ throw "forced error"; \ }); \ </script> \ <script> \ $(function() { \ alert('2nd ready'); \ }); \ </script> \ }}} \ \ whereas when dealing with DOM directly, an uncaught exception in one DOMContentLoaded does not abort the others. \ \ {{{ \ <script> \ document.addEventListener("DOMContentLoaded", function() { \ alert('1st DOMContentLoaded'); \ throw "forced error"; \ }, false); \ </script> \ <script> \ document.addEventListener("DOMContentLoaded", function() { \ alert('2nd DOMContentLoaded'); \ }, false); \ </script> \ }}} \ \ this forces dependencies, that need not exists, between often unrelated bits of code, making the page more brittle {{{\ <script>\ $(function() {\ alert('1st ready');\ throw "forced error";\ });\ </script>\ <script>\ $(function() {\ alert('2nd ready');\ });\ </script>\ }}}\ \ whereas when dealing with DOM directly, an uncaught exception in one DOMContentLoaded does not abort the others.\ \ {{{\ <script>\ document.addEventListener("DOMContentLoaded", function() {\ alert('1st DOMContentLoaded');\ throw "forced error";\ }, false);\ </script>\ <script>\ document.addEventListener("DOMContentLoaded", function() {\ alert('2nd DOMContentLoaded');\ }, false);\ </script>\ }}}\ \ this forces dependencies, that need not exists, between often unrelated bits of code, making the page more brittle

-1, This is prefect for debugging. If on handler throw an exception and it is expected behaviour, then it's easy enough to wrap it into a function with a try/catch.

Changed December 13, 2011 06:25PM UTC by dmethvin comment:5

description: {{{\ <script>\ $(function() {\ alert('1st ready');\ throw "forced error";\ });\ </script>\ <script>\ $(function() {\ alert('2nd ready');\ });\ </script>\ }}}\ \ whereas when dealing with DOM directly, an uncaught exception in one DOMContentLoaded does not abort the others.\ \ {{{\ <script>\ document.addEventListener("DOMContentLoaded", function() {\ alert('1st DOMContentLoaded');\ throw "forced error";\ }, false);\ </script>\ <script>\ document.addEventListener("DOMContentLoaded", function() {\ alert('2nd DOMContentLoaded');\ }, false);\ </script>\ }}}\ \ this forces dependencies, that need not exists, between often unrelated bits of code, making the page more brittle {{{ \ <script> \ $(function() { \ alert('1st ready'); \ throw "forced error"; \ }); \ </script> \ <script> \ $(function() { \ alert('2nd ready'); \ }); \ </script> \ }}} \ \ whereas when dealing with DOM directly, an uncaught exception in one DOMContentLoaded does not abort the others. \ \ {{{ \ <script> \ document.addEventListener("DOMContentLoaded", function() { \ alert('1st DOMContentLoaded'); \ throw "forced error"; \ }, false); \ </script> \ <script> \ document.addEventListener("DOMContentLoaded", function() { \ alert('2nd DOMContentLoaded'); \ }, false); \ </script> \ }}} \ \ this forces dependencies, that need not exists, between often unrelated bits of code, making the page more brittle

-1, Yeah, I agree with the OP that this is less than ideal, but the alternatives are less than idealer.

Changed December 14, 2011 01:01AM UTC by mikesherov comment:6

description: {{{ \ <script> \ $(function() { \ alert('1st ready'); \ throw "forced error"; \ }); \ </script> \ <script> \ $(function() { \ alert('2nd ready'); \ }); \ </script> \ }}} \ \ whereas when dealing with DOM directly, an uncaught exception in one DOMContentLoaded does not abort the others. \ \ {{{ \ <script> \ document.addEventListener("DOMContentLoaded", function() { \ alert('1st DOMContentLoaded'); \ throw "forced error"; \ }, false); \ </script> \ <script> \ document.addEventListener("DOMContentLoaded", function() { \ alert('2nd DOMContentLoaded'); \ }, false); \ </script> \ }}} \ \ this forces dependencies, that need not exists, between often unrelated bits of code, making the page more brittle {{{\ <script>\ $(function() {\ alert('1st ready');\ throw "forced error";\ });\ </script>\ <script>\ $(function() {\ alert('2nd ready');\ });\ </script>\ }}}\ \ whereas when dealing with DOM directly, an uncaught exception in one DOMContentLoaded does not abort the others.\ \ {{{\ <script>\ document.addEventListener("DOMContentLoaded", function() {\ alert('1st DOMContentLoaded');\ throw "forced error";\ }, false);\ </script>\ <script>\ document.addEventListener("DOMContentLoaded", function() {\ alert('2nd DOMContentLoaded');\ }, false);\ </script>\ }}}\ \ this forces dependencies, that need not exists, between often unrelated bits of code, making the page more brittle

-1, This sounds like a feature, not a bug. Uncaught exceptions should be handled eventually by the developer, no? What's the situation in which you would want the exception to go uncaught all the way up?

Changed December 14, 2011 04:06PM UTC by timmywil comment:7

-1

Changed December 19, 2011 05:28PM UTC by rwaldron comment:8

description: {{{\ <script>\ $(function() {\ alert('1st ready');\ throw "forced error";\ });\ </script>\ <script>\ $(function() {\ alert('2nd ready');\ });\ </script>\ }}}\ \ whereas when dealing with DOM directly, an uncaught exception in one DOMContentLoaded does not abort the others.\ \ {{{\ <script>\ document.addEventListener("DOMContentLoaded", function() {\ alert('1st DOMContentLoaded');\ throw "forced error";\ }, false);\ </script>\ <script>\ document.addEventListener("DOMContentLoaded", function() {\ alert('2nd DOMContentLoaded');\ }, false);\ </script>\ }}}\ \ this forces dependencies, that need not exists, between often unrelated bits of code, making the page more brittle {{{ \ <script> \ $(function() { \ alert('1st ready'); \ throw "forced error"; \ }); \ </script> \ <script> \ $(function() { \ alert('2nd ready'); \ }); \ </script> \ }}} \ \ whereas when dealing with DOM directly, an uncaught exception in one DOMContentLoaded does not abort the others. \ \ {{{ \ <script> \ document.addEventListener("DOMContentLoaded", function() { \ alert('1st DOMContentLoaded'); \ throw "forced error"; \ }, false); \ </script> \ <script> \ document.addEventListener("DOMContentLoaded", function() { \ alert('2nd DOMContentLoaded'); \ }, false); \ </script> \ }}} \ \ this forces dependencies, that need not exists, between often unrelated bits of code, making the page more brittle

-1

Changed January 18, 2012 03:29AM UTC by dmethvin comment:9

keywords: 1.8-discuss
resolution: → wontfix
status: openclosed

The best of the possible choices, unfortunately.

Changed February 21, 2012 01:05PM UTC by nr@nexxar.com comment:10

I do not know if my comment will be read because the bug is already closed.

But there is a big draw back for "wontfix". You might consider the case where the executed function from the readyList unwillingly, unintentionally creates an exception. eg. due to a "null" dereferencing.

Unfortunatedly you will never notice this exception! NO error message is being created! eg. FF failes completely silent because the function is executed in the background - within the context of an event. Any exception thrown intentionally by the function is silently discarded, too.

Rather than forcing every added function to be wrapped inside a try{}catch{} block you might consider wrapping added function inside such a block on adding them:

(jQuery 1.7)

--- jquery-1.7.1.js.orig	2012-02-21 13:44:42.313393019 +0100
+++ jquery-1.7.1.js	2012-02-21 14:01:02.683393031 +0100
@@ -276,7 +276,15 @@
 		jQuery.bindReady();
 
 		// Add the callback
-		readyList.add( fn );
+		readyList.add( function() { 
+                    try {
+                        fn.apply(this, arguments); 
+                    } catch(e) {
+                        // write to console log within another try{}catch{} because on IE using it failes 
+                        // whenever "developer tools" window is not open.
+                        try{console.log("error while executing document.ready function: " + e.message);} catch(e2){}
+                    }
+                });
 
 		return this;
 	},

Therefore I vote for fixing instead of ignoring to give the developer the chance to detect exception in his document.ready functions.

Changed February 21, 2012 01:57PM UTC by jaubourg comment:11

Have you opened the console?

A very simple jsfiddle snippet actually does notify the exception in the console!

Replying to [comment:10 nr@…]:

I do not know if my comment will be read because the bug is already closed. But there is a big draw back for "wontfix". You might consider the case where the executed function from the readyList unwillingly, unintentionally creates an exception. eg. due to a "null" dereferencing. Unfortunatedly you will never notice this exception! NO error message is being created! eg. FF failes completely silent because the function is executed in the background - within the context of an event. Any exception thrown intentionally by the function is silently discarded, too. Rather than forcing every added function to be wrapped inside a try{}catch{} block you might consider wrapping added function inside such a block on adding them: (jQuery 1.7)
> --- jquery-1.7.1.js.orig	2012-02-21 13:44:42.313393019 +0100
> +++ jquery-1.7.1.js	2012-02-21 14:01:02.683393031 +0100
> @@ -276,7 +276,15 @@
>  		jQuery.bindReady();
>  
>  		// Add the callback
> -		readyList.add( fn );
> +		readyList.add( function() { 
> +                    try {
> +                        fn.apply(this, arguments); 
> +                    } catch(e) {
> +                        // write to console log within another try{}catch{} because on IE using it failes 
> +                        // whenever "developer tools" window is not open.
> +                        try{console.log("error while executing document.ready function: " + e.message);} catch(e2){}
> +                    }
> +                });
>  
>  		return this;
>  	},
> 
> 
Therefore I vote for fixing instead of ignoring to give the developer the chance to detect exception in his document.ready functions.

Changed April 02, 2012 09:59PM UTC by anonymous comment:12

It's all a matter of timing. If the onload already has fired - as in your example - everything works find. But consider this: http://jsfiddle.net/uAHv6/2/

I have used the load event to even more delay the firing. Thus the function to execute onload is saved in the queue and then later executed on the background - that is the problem. Only functions executed from the ready queue are affected.

Changed April 02, 2012 10:42PM UTC by nr@nexxar.com comment:13

Sorry, again (i have the feeling to be not clear enough in my previous post)

**The timing is the key to trigger the error.**

Using $(document).ready():

(a) If the onready event has already fired - the DOM-state is "ready" - then functions are not added to the onready-queue but executed immediately.

(b) but if the DOM is NOT yet ready and the ready event has not yet been fired, the function is added to the ready-queue and then executed later, in the background.

Only (b) is affected by the described error - only in that case! So if you have a lightweight HTML page, you'll never fall over this error. Only if you have a heavy-weight page with a lot of HTML and JS you may suffer from it.

Changed April 03, 2012 04:20AM UTC by anonymous comment:14

That sounds like an error in your code. The fiddle you provided uses $( document ).load which is incorrect - it should be using $( window ).load if you want to use the load event. http://jsfiddle.net/uAHv6/3/ throws an error as expected

Feel free to stop by the #jquery irc room on freenode to ask for help.

Changed April 03, 2012 10:09PM UTC by anonymous comment:15

OK. It's hard to create a good test. So see this real-life page, where you can experience the error.

page A: https://transfer.nexxar.com/public/jquery-test/welcome-jquery-test.html

page B: https://transfer.nexxar.com/public/jquery-test/welcome-jquery-test2.html

page B is correct and displays an allert. Secondly the accordeons at the right bottom are initialised and existing.

page A is incorrect but neither display an error on the FF console nor does the alert appear. the document-ready function with the alert is never executed because the ready queue is abandoned.

Thze only difference between page A and page B is:

--- welcome-jquery-test.html	2012-04-03 23:59:56.000000000 +0200
+++ welcome-jquery-test2.html	2012-04-04 00:00:49.000000000 +0200
@@ -152,7 +151,7 @@
 $(document).ready(function() {
 
    var tmp = {};
-   tmp.dereference();
+//   tmp.dereference();
 
 });
 

The code with the alert is:

$(document).ready(function() {

   var tmp = {};
   tmp.dereference();

});


$(document).ready(function() {   
   alert("function executed after null dereference");      
});

Changed April 03, 2012 10:30PM UTC by nr@nexxar.com comment:16

Here is an improved jsfiddle test code that mimics the behaviour of the ready queue.

The second function is NOT executed. http://jsfiddle.net/uAHv6/4/

Here it is executed http://jsfiddle.net/uAHv6/5/

Changed March 25, 2014 10:05AM UTC by Igor Baltiyskiy comment:17

This is a bug. If uncontrolled code adds a handler before your code and fails, your handler will not be executed and you can't do anything about that.

The reason for assuming this bug a "feature" was that it is helpful during debugging. Isn't jQuery supposed to be a production-ready library? In my opinion, all debugging aids should be optional. How about turning the existing behaviour on with a switch?