Closed joshkel closed 10 months ago
Hm I didn't realize that about jsdom. I figured since it's in all the browsers and Node.js, then it'd be everywhere.
Annoying jsdom users is bad. But it's also nice to have no dependencies.
I wonder how many people are using this with jsdom vs without, that would make it more clear what the best decision is. Maybe for now I will leave this issue open and see if other people are affected.
And to save people the trouble of reading the jsdom issue for workarounds, seems that you can just add this above your fake-indexeddb import:
import 'core-js/stable/structured-clone';
I just implemented a workaround...which I've had to do a few times for JSDOM now.
In your jest.config you'll need to point the testEnvironment
to local file.
Then you'll need to extends JSDOMEnvironment
and add the node implementation for structuredClone to the JSDOM environment in the constructor.
Something like this:
import JSDOMEnvironment from "jest-environment-jsdom"
export default class FixJSDOMEnvironment extends JSDOMEnvironment {
constructor(...args: ConstructorParameters<typeof JSDOMEnvironment>) {
super(...args)
this.global.structuredClone = structuredClone
}
}
For a real world example, you can see my implementation in my project OMA3.
Yep, this just broke tests for me (Jest, jsdom, 5.0). Nice workaround though, thanks! Guessing you'll probably get a few more reports of this though.
This broke tests for us
I added the above workarounds to README.md, I think that is good enough to close this issue. Although feel free to comment if you think I'm wrong!
By the way this now seems to mean that objects returned are null-prototyped, which I don't think the real IndexedDB objects technically are. No big deal unless (like me!) your isObject code wasn't smart enough to allow those.
@jamesgpearce I tried this code:
import realisticStructuredClone from "realistic-structured-clone";
const x = {foo: 5};
const y = Object.create(null);
y.foo = 5;
console.log(Object.getPrototypeOf(x));
console.log(Object.getPrototypeOf(structuredClone(x)));
console.log(Object.getPrototypeOf(realisticStructuredClone(x)));
console.log(Object.getPrototypeOf(y));
console.log(Object.getPrototypeOf(structuredClone(y)));
console.log(Object.getPrototypeOf(realisticStructuredClone(y)));
And got this output:
[Object: null prototype] {}
[Object: null prototype] {}
[Object: null prototype] {}
null
[Object: null prototype] {}
[Object: null prototype] {}
So it seems the old (realisticStructuredClone) and new (structuredClone) are both doing the same thing to the prototype, which actually results in losing the null prototype when cloning.
If you think you're possibly seeing a bug, please create another issue with more info :)
I noticed that fakeIndexedDB 5.0 removes its structuredClone polyfill, since structuredClone is provided by Node 18, and fakeIndexedDB now depends on Node 18. However, as I understand it, a major use case of fakeIndexedDB is to simulate IndexedDB within jsdom (as used by, e.g., Jest), and jsdom does not implement structuredClone. (See https://github.com/jsdom/jsdom/issues/3363.)
Therefore, the removal of structuredClone may be premature?
I realize that this change may be completely intended (because workarounds are available - users of fakeIndexedDB can polyfill structuredClone themselves within their jsdom environments, as discussed in https://github.com/jsdom/jsdom/issues/3363); if so, feel free to close this issue.
Thank you.