-
-
Notifications
You must be signed in to change notification settings - Fork 1.7k
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
All classes are shared between separate jsdom windows #1453
Comments
This is intentional in the design of jsdom; we share a single DOM implementation across all jsdoms. We have considered a mode where we generate new classes for every window, but it would be a lot of work. |
Is there a "hack" so i can rebuild the DOM implementation ? |
You can use separate node processes, each with a different jsdom instance. |
Unfortunately , I run mocha tests with jsdom.jsdom() in beforeEach() tests. I'm not sure to be able to launch separate processes for each test. One way to do this "custom DOM implementation" without rebuilding the DOM would be to do something like this: magic_function(target,attr,newconf) :
magic_function(targe,attr)
On jsdom.jsdom, revert all changes. I guess that would solve my problem as test are not run in parallel, but it doesn't address the fact that All classes are shared. Maybe ES6 Proxies are even better but I'm not enough familiar with them. EDIT, this is close to what I tried to explain |
I also ran into this issue recently while trying to write tests for a DOM utility to make sure that it would work across nested browsing contexts. I realized that the tests were always passing, even when the utility just used the global DOM interfaces rather than the interfaces on the nested browsing context’s window object. I checked the HTML spec to try to figure out what the specific expected behaviors are for DOM interfaces. In the spec for creating browsing contexts, the steps specify to create new Window and Document objects, but don’t indicate whether that should include it’s own set of DOM interfaces, or if they can share the DOM interfaces of their parent browsing context. The documentation of I tried these assertions in Chrome, Safari, and Firefox: const iframe = document.createElement('iframe');
document.body.appendChild(iframe);
// Assertion 1 (DOM interface constructors are not the same actual variable)
console.assert(iframe.contentDocument.defaultView.Node !== Node, 'Iframe’s DOM interfaces are strict equals the same');
// Assertion 2 (DOM interface constructors have separate prototype chains)
console.assert(!(iframe.contentDocument.body instanceof Node), 'Iframe’s DOM interfaces has the global DOM interface in its prototype chain');
// Assertion 3 (Array constructor is not the same actual variable)
console.assert(iframe.contentDocument.defaultView.Array !== Array, 'Iframe’s Array constructor has the global Array constructor in its prototype chain');
// Assertion 4 (Array constructor has a separate prototype chain)
console.assert(!([] instanceof iframe.contentDocument.defaultView.Array), 'Iframe’s Array constructor has the global Array constructor in its prototype chain'); In Chrome and Safari, all of the assertions pass. In Firefox, assertion 2 fails, i.e. checking Wrote a short test for jsdom also: <!DOCTYPE HTML>
<title>Iframes get new and wholly separate execution contexts</title>
<link rel="help" href="https://www.w3.org/TR/html51/browsers.html#creating-a-new-browsing-context">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script>
"use strict";
test(() => {
const iframe = document.createElement('iframe');
document.body.appendChild(iframe);
assert_not_equals(iframe.contentDocument, document);
assert_not_equals(iframe.contentDocument.defaultView, window);
assert_equals(iframe.contentDocument.defaultView.Array === Array, false);
assert_equals([] instanceof iframe.contentDocument.defaultView.Array, false);
assert_equals(iframe.contentDocument.defaultView.Node === Node, false);
assert_equals(iframe.contentDocument.body instanceof Node, false);
}, "iframe's nested browsing context has its own Document, Window, and DOM interface implementations");
</script> As expected, the final two assertions fail. The rest of the assertions, including those checking the Array constructors, pass. Having the ability to create new DOM implementations would be pretty great and help bring the environment closer to what you get in real browsers, though I also get the performance tradeoff. But FWIW, I would also put a vote in for a refactor to allow this. |
To see a real-world example test I couldn’t write because of this limitation, check out facebook/fbjs#188 (comment) |
defineProperty on DOM Interfaces seems to survive new page load (via jsdom.jdom()).
Object.defineProperty(HTMLAnchorElement.prototype, "href" , {configurable : false});
After new jsdom.jsdom() this should be true:
Object.getOwnPropertyDescriptor(HTMLAnchorElement.prototype, "href").configurable === true;
maybe/probably related to 1207.
The text was updated successfully, but these errors were encountered: