JSDOM does not load <script> javascript code recursively
See original GitHub issueIf you have a script1 which create a script2 tag which itself create a script3 tag, then only script1 and script2 are listed in the DOM using the following code:
var jsdom = require('jsdom');
jsdom.defaultDocumentFeatures = {
FetchExternalResources : ['script'],
ProcessExternalResources : ['script'],
MutationEvents : '2.0',
};
var html = "<html><head><script src="script1.js"></script></head><body>test</body></html>";
var window = jsdom.jsdom( html ).createWindow();
window.addEventListener('load', function () {
/* Only two script nodes in the DOM */
});
It looks like jsdom does not evaluate the code of script2, so jsdom does not seem to work recursively. This is a problem in my case. How to fix that?
Issue Analytics
- State:
- Created 10 years ago
- Comments:8 (4 by maintainers)
Top Results From Across the Web
jsdom doesn't process script inside web page - Stack Overflow
I am new to nodejs. I want to use jsdom to parse some web pages which may contain script code inside. But I...
Read more >Easy Website Crawling with jsdom in Node.js
In the next step, we are initializing JSDOM with our string which converts it to an actual DOM, where we can work on....
Read more >Using enzyme with JSDOM - GitHub Pages
Using enzyme with JSDOM. JSDOM is a JavaScript based headless browser that can be used to create a realistic testing environment.
Read more >jsdom-fabricjs - npm Package Health Analysis | Snyk
If config.html and config.file are not provided, jsdom will load HTML from ... Similar to scripts , but it accepts JavaScript instead of...
Read more >Configuring Jest compiled - w3resource
This is because of the need to load the actual transformers (e.g. babel or typescript) to perform transformation. Example: // setup.js ```module ...
Read more >Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start FreeTop Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
Top GitHub Comments
It is true, dynamically inserted scripts load asynchronously. When the document fires the
load
event your dynamically injected script tags may not have finished executing but your hard coded scripts will have (by default). There are module loaders that use this method to shorten page load times. Basically, you’d write script tags in the page to start your loader and have it dynamically insert script tags so everything loaded asynchronously. The module loaders provide methods for defining dependencies, so if you absolutely have to wait for a certain script to load before beginning some dependent script, you can do that. The module loader will also provide some signal indicating when it is finished loading all of the scripts. So, unless you’ve rolled your own loader, you should be able to find documentation on what events fire and when. For your loader you’d just hook into whatever the “all scripts have fired” event is and proceed from there.There is no event defined to tell the browser when all dynamically generated script tags have loaded because there is no possible way for the browser to know how many script tags will be generated in the future.
Imagine it, you run a
setInterval
that generates a new script tag every 10 seconds. How is the browser to be expected to know that another script will be generated in ten seconds? When would it fire the “all dynamically generated and inserted scripts have executed”? When some idle time came up between intervals? Never? After every script dynamically inserted?The solution is either in the documentation of your module loader or, you will have to create your own signal letting you know that all the dynamic scripts have been loaded. Then, you’ll wait for this signal before asking jsdom to do whatever it is that you want it to do after all dynamically injected scripts have been executed. The equivalent user action is navigating to a page, waiting for it to load completely, and then viewing the “live” source of the page with
document.documentElement.innerHTML
or tools available in the browser. If you want to go the quick and dirty route, you could defer your actions with asetTimeout
that has some extremely long duration to ensure that a best effort has been made to execute the dynamically injected scripts before you take a snapshot or whatever.@domenic Maybe a wiki article about this would help? I understand not wanting to reiterate every tip and trick about dealing with the live dom and http protocols but this is something pretty basic that is often a cause of confusion for people first using a headless browser.
http://www.stevesouders.com/blog/2009/04/27/loading-scripts-without-blocking/ http://www.sitepoint.com/non-blocking-async-defer/
Closed in favor of #675.