-
-
Notifications
You must be signed in to change notification settings - Fork 148
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
"TypeError: can't access dead object" exceptions within Firefox extension #361
Comments
See https://developer.mozilla.org/docs/Web/JavaScript/Reference/Erreurs/Dead_object After trying various versions of nightly builds, I see that the issue appeared after merging #354. |
When you say "randomly" is it not every link? Can you isolate which links are producing the error? It may have something to do with the event listeners? Might we have to revoke the listener in the click function? |
I mean, put removeEventListener (or jQuery off) as part of the redirection here: |
The bug happens on the Ray Charles archive for example.
|
Hmm, I've not been able to reproduce (yet) in Firefox Quantum on Ray Charles, or on the latest WikiMed. But I am getting a lot of CSP errors in console: I wonder if it's a race condition with the old DOM elements not being fully garbage collected before starting to access the new DOM. Strange that it's random. |
The stacktrace of the exception is : It seems to indicate it happens in a find() call of jQuery, line 1042 of app.js: Upgrading jQuery to its latest version (3.3.1) does not solve the issue. |
Ah, that looks like the old way of clearing the html... I'll check out that line. |
I think that line is a rogue accidentally left in the code. It shouldn't be needed to clear the body of the document as we're going to rewrite the whole thing. I'm trying commenting it out. |
If I comment this line, the same error happens a bit later in the code, line 873 : |
Well it's easy to change that line to a standard DOM method. |
Can't use forEach there. Trying loop. |
Supposedly can use forEach if we use querySelectorAll instead. However, loop will be faster, but will need to change ($this) references. Would you rather keep the jQuery here and see if the problem can be debugged another way? |
We're using a slightly more complex selector for CSS line 946, for which it might be more convenient to keep jQuery. |
I've got a candidate with minimal changes to that function. Will post to a new branch. |
Can you check if that still has the issue in that routine? a25645d |
It seems to work, but now fails with the same error in the same jQuery call of loadImagesJQuery (and probably in loadCSSJQuery). |
OK. Do you want to follow similar pattern? Also, we need to clear the body to blank out the screen while loading a new document. I'll change that to DOM method. Then I'll stop and let you take over and will check back later today. |
Sure. |
Yes, please go ahead. I just pushed a commit clearing the doc body with DOM method instead of jQuery. Not fully tested... |
Just FYI, Internet Explorer 11 doesn't support forEach. But go ahead and test with forEach, and we can change to standard loop later, and maybe use getElementsByTagName because it is said to be faster than querySelectorAll. forEach is a convenient way of testing whether the fix works in principle. |
Alternatively, the issue may be just with the jQuery "find" routine, searching up through dead elements... Might be possible just to access the iframe in a different way, but still use jQuery "each", which handles the browser differences (albeit more slowly than standard loop). |
Applying the same pattern on images and CSS selection seems to workaround the issue. That's good news. jQuery behaves as if it kept some references on elements of the iframe. |
I just pushed a commit da2ae9e that supports IE when using forEach. It's necessary to use Array.prototype.slice.call on the node list to fool IE into thinking it's a standard array. Doesn't seem to affect the other browsers at all. EDIT: Reference is https://developer.mozilla.org/en-US/docs/Web/API/NodeList |
I'm creating a testcase to reproduce the issue with jQuery and a minimal setup |
I managed to reproduce in a simple testcase, and posted that as a question on stackoverflow : https://stackoverflow.com/questions/50101246/typeerror-cant-access-dead-object-with-jquery-and-an-iframe-populated-with-d |
With the proposed fix for #366 , I think I've now isolated this problem to a version of NS_ERROR_UNEXPECTED which, according to various articles produced by a search for this error, is to do with elements being referenced in the DOM that no longer exist. A candidate solution, apart from reducing the setting up of jQuery event listeners on the iframe, is for us to tell jQuery explicitly that we're unloading the iframe, so that it clears its cache. Adding this, just before we overwrite the iframe, seems to help on my initial tests:
Once we've pushed the changes for #366 to master, I'll rebase this branch so that we can test with the above. It's looking hopeful in testing on my JavaScript branch which was running into an NS_ERROR_UNEXPECTED exception in jQuery-3.2.1.slim when run in Firefox. I'm 90% sure this is the same issue. EDIT: Further info on the need to remove jQuery elements with jQuery methods here: https://stackoverflow.com/questions/9304768/what-is-the-purpose-of-cache-in-jquery . Although this is a bit old now, and $.cache doesn't seem to exist in our current jQuery, some of the comments from 2016 seem pertinent, and suggest that using a jQuery method to remove the node, such as .empty(), will do some unlinking. |
Interesting. Putting the iframe inside a div, and emptying the div (with jQuery), as you suggested above, might have a good chance to work : maybe it would be worth testing it. |
Don't worry, I'll have a go with the div method of removing with jQuery. It would be good not to have to depend on document.write(). Enjoy your vacation! |
You'll probably have to set the class articleIFrame on the iframe each time you re-create it, and also to manually call resizeIFrame() |
OK, having done a lot of tests on different code, we have these issues with trying to inject the iframe either with .innerHTML or jQeury .html (which are basically the same thing):
Our choices are:
By the way, everywhere I looked I kept running into the assertion that the only cross-browser way to change the base href of an iframe document is to use |
Commit e57af21 is provided to show how far I got with this experiment. As mentioned, it works in Edge, but despite my workarounds added to the link parsing, it fails in Firefox due to the fact that FF doesn't use the injected base href with this way of creating the iframe. |
Thanks a lot @Jaifroid for all these tests and explanations. Regarding the possibilities you listed :
|
Thanks for the observations, which I agree with. I'll check out the use of a blank document (equivalent to dummyArticle) and how FFOS behaves with regard to the base tag when injecting the iframe in code. The issue will be to be sure that all browsers respect the new injected base tag (as they do with |
I've moved discussion to #366 . However, I've rebased the I've done a few timing tests with loading the Paris article in English Wikivoyage. Timings done using a console timer from the moment the article title is selected to the moment all images are sent to the decompressor (but not yet decompressed). On FFOS simulator, the speed improvement of using pure JavaScript is 21%, from an average of 987ms (JQuery) to an average of 777ms (JavaScript). In Edge, the improvement is 40% from an average of 2339ms (jQuery) to an average of 1474ms (JavaScript). Note that Edge runs slowly with the console open, these values are not typical of performance with the console closed (but with it closed, the timings are not reported). So there is an improvement, but it is an improvement of 200ms in FFOS simulator, which most users won't notice. Nevertheless, we could eke out some performance gains this way. I'm not strongly advocating for doing so, but in case you're interested, here is a discussion on why jQuery may no longer necessary with HTML5: https://blog.garstasio.com/you-dont-need-jquery/why-not/ . |
Very interesting article. |
It looks like a regression since 2.2
When running kiwix-js as a Firefox extension, I randomly get this exception when clicking on a link, leading to a "Error reading article with title xxx" instead of displaying the article.
The text was updated successfully, but these errors were encountered: