-
-
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
jsdom
v23: atob
(and btoa
) in Window.js
are recursive and always fail
#3628
Comments
see: jsdom/jsdom#3628 Signed-off-by: Jordan Shatford <jordanshatford@live.com>
see: jsdom/jsdom#3628 Signed-off-by: Jordan Shatford <jordanshatford@live.com>
I am also having this issue here: This change solved the issue locally for me: BacLuc@1173cfb |
Sorry about this. I can't believe we had no test coverage that would catch this; I assumed the refactoring I did would not cause an issue. I'll work on this and #3627 as soon as I can, but finding time in my nights has been difficult and it might take until the weekend. |
It is always the one test that's missing. The fact that you need a free night to work on this is terrible! Thanks for putting so much work into a lib that fuels so many test runners. |
What @frontendphil said - I'm sure there are many who have been bitten by that missing test, but there are also many who appreciate your efforts, and at the end of the day we've learned something and acquired another story to tell 🙂 |
I'm unable to reproduce this issue. Test case: "use strict";
const { JSDOM } = require("jsdom");
const dom1 = new JSDOM();
console.log(dom1.window.btoa("Hello"));
console.log(dom1.window.atob("SGVsbG8="));
const dom2 = new JSDOM(``, { runScripts: "outside-only" });
console.log(dom2.window.btoa("Hello"));
console.log(dom2.window.atob("SGVsbG8="));
const dom3 = new JSDOM(``, { runScripts: "dangerously" });
console.log(dom3.window.btoa("Hello"));
console.log(dom3.window.atob("SGVsbG8=")); It seems like this must be caused by something else in the software stack that people are using, so it's best to debug it in those tools that are built on top of jsdom. Whatever they are doing is messing with how name resolution works inside the definition of our I'll close this until someone is able to come up with a reproduction case that only involves jsdom, and not any layers on top. |
@domenic I'm having the same issue as well, and I'm pretty sure it's related to using jsdom-global, or at least code that's patching stuff on Node's this.atob = function (str) {
try {
return atob(str);
} catch (e) { }
}; is equivalent to this.atob = function (str) {
try {
return globalThis.atob(str);
} catch (e) { }
}; so when Minimum reproduction case is const { JSDOM } = require('jsdom');
const dom = new JSDOM('');
globalThis.atob = dom.window.atob;
globalThis.btoa = dom.window.btoa;
console.log(dom.window.btoa('Hello'));
console.log(dom.window.atob('SGVsbG8=')); I think this needs to be fixed on the side of jsdom though. It's as easy as adding const { atob, btoa } = require("node:buffer"); at the top of the file. This ensures both Not sure about the proper way to write a test case for this though as we want to avoid polluting I will file a PR to fix this. |
Just wanted to add the workaround I used in my project, perhaps that it can be useful for someone. I'm using jsdom to test a Vue.js project. I was relying on jsdom-global to setup the browser environment for my tests, which was indeed patching import { JSDOM } from 'jsdom';
const dom = new JSDOM('', {
url: 'https://www.example.com',
});
const keys = [
'document',
'navigator',
'window',
'SVGElement',
'Element',
];
Object.assign(globalThis, Object.fromEntries(
keys.map(key => [key, dom.window[key]]),
)); |
Instead of borrowing atob and btoa from `globalThis` which can still go wrong if the functions were overriden there as well, it should now be fixed by always explicitly requiring atob and btoa from `node:buffer`
This makes sense. Note that jsdom-global is a third-party package, and is explicitly doing what you are advised not to do when using jsdom, so it is not supported and we will not accept pull requests to work around its problems. If you would like to fix this in jsdom-global, please do so by sending pull requests to that repository, not to this one. |
@domenic I understand, and totally agree. I just wanted to point out that it's not only jsdom-global that's doing it, but also vitest (see https://github.com/vitest-dev/vitest/blob/main/packages/vitest/src/integrations/env/jsdom.ts#L140), although I think they restore the original global after running the test so that it doesn't pollute the global outside the test. Nevertheless, I still think there's an argument to add const { atob, btoa } = require("node:buffer"); in the |
Basic info:
Minimal reproduction case
See my comment on the offending PR: #3625 (comment)
Raising this issue mainly to make sure the comment gets looked at as the PR is already merged
Ultimately, it looks
atob
andbtoa
are now recursive and always fail with aRangeError: Maximum call stack size exceeded
when called. Verified by extracting the two functions and running themThe text was updated successfully, but these errors were encountered: