jsdom doesn't fire iframe.onload after iframe.contentDocument.close()
Basic info:
- Node.js version: 8.9.4
- jsdom version: 11.6.0
Minimal reproduction case
Apologies for the lack of jsdom setup in the repro case, I'm using Jest, which sets up the jsdom environment for me and I'm unfamiliar with setting up jsdom directly myself. I don't believe different setups would make any difference on this issue.
const JSDOM = require('jsdom').JSDOM;
const text = `<html><body></body></html>`;
const document = new JSDOM(text).window.document;
const ifr = document.createElement('iframe');
ifr.onload = () => console.log('loaded');
document.body.appendChild(ifr);
ifr.contentDocument.open();
ifr.contentDocument.write('hello');
ifr.contentDocument.close();
How does similar code behave in browsers?
In this JSBin, you will see two console logs that say "loaded". One for the initial append of the iframe, the second for the subsequent open(), write() and close(). With jsdom, only 1 string is logged—the one that is triggered by appending the iframe.
Hi, I'm trying to migrate to JSDOM to test epub.js library. I encountered a similar problem: iframe.onload event refuses to work. It's hard for me to assess what exactly is causing this behavior. However, this problem is not observed in the browser. For testing, I use only mocha framework. Here is my setup.js file for setting up global parameters.
The load function initiates the process of writing the source text via the iframe.write function:
load(contents) {
const loading = new Defer();
if (!this.iframe) {
loading.reject(new Error("No Iframe Available"));
return loading.promise;
}
this.container.appendChild(this.iframe);
this.document = this.iframe.contentDocument;
this.iframe.onload = (e) => this.onLoad(e, loading);
if (!this.document) {
loading.reject(new Error("No Document Available"));
return loading.promise;
} else if (this.method === "blobUrl") {
this.blobUrl = createBlobUrl(contents, "application/xhtml+xml");
this.iframe.src = this.blobUrl;
} else if (this.method === "srcdoc") {
this.iframe.srcdoc = contents;
} else {
this.document.open();
this.document.write("<!DOCTYPE html>");
this.document.write(contents);
this.document.close();
}
return loading.promise;
}
As you can see, the iframe.onload event is added after the this.iframe node is added to the container.
At the same time, I see that the innerHTML property contains data. That is, the write is successful.
How to reproduce the issue:
I created a new jsdom branch for testing. To reproduce the problem, you need to copy the test/rendition.js file to the tests/ directory, then start the server with the npm run start command, and then run the test with the npm run test command.
Basic info:
- Node.js version: 20.18.0
- jsdom version: 25.0.1