Skip to content

Commit

Permalink
Do not reset global.document before CustomElement:disconnectedCallbac… (
Browse files Browse the repository at this point in the history
#11871)

* Do not reset global.document before CustomElement:disconnectedCallback has finished running, document should be accessible in this callback function

* Update CHANGELOG.md

Co-authored-by: dalvarezmartinez1 <example@example.com>
Co-authored-by: Simen Bekkhus <sbekkhus91@gmail.com>
  • Loading branch information
3 people authored Nov 8, 2021
1 parent 8f2cdad commit 7a34a69
Show file tree
Hide file tree
Showing 3 changed files with 31 additions and 1 deletion.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
- `[expect]` Allow again `expect.Matchers` generic with single value ([#11986](https://github.com/facebook/jest/pull/11986))
- `[jest-core]` Incorrect detection of open ZLIB handles ([#12022](https://github.com/facebook/jest/pull/12022))
- `[jest-environment-jsdom]` Add `@types/jsdom` dependency ([#11999](https://github.com/facebook/jest/pull/11999))
- `[jest-environment-jsdom]` Do not reset the global.document too early on teardown ([#11871](https://github.com/facebook/jest/pull/11871))
- `[jest-transform]` Improve error and warning messages ([#11998](https://github.com/facebook/jest/pull/11998))

### Chore & Maintenance
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,4 +39,28 @@ describe('JSDomEnvironment', () => {

expect(env.dom.window.navigator.userAgent).toEqual('foo');
});

/**
* When used in conjunction with Custom Elements (part of the WebComponents standard)
* setting the global.document to null too early is problematic because:
*
* CustomElement's disconnectedCallback method is called when a custom element
* is removed from the DOM. The disconnectedCallback could need the document
* in order to remove some listener for example.
*
* global.close calls jsdom's Window.js.close which does this._document.body.innerHTML = "".
* The custom element will be removed from the DOM at this point, therefore disconnectedCallback
* will be called, so please make sure the global.document is still available at this point.
*/
it('should not set the global.document to null too early', () => {
const env = new JSDomEnvironment(makeProjectConfig());

const originalCloseFn = env.global.close.bind(env.global);
env.global.close = () => {
originalCloseFn();
expect(env.global.document).not.toBeNull();
};

return env.teardown();
});
});
7 changes: 6 additions & 1 deletion packages/jest-environment-jsdom/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -132,9 +132,14 @@ class JSDOMEnvironment implements JestEnvironment<number> {
if (this.errorEventListener) {
this.global.removeEventListener('error', this.errorEventListener);
}
this.global.close();

// Dispose "document" to prevent "load" event from triggering.

// Note that this.global.close() will trigger the CustomElement::disconnectedCallback
// Do not reset the document before CustomElement disconnectedCallback function has finished running,
// document should be accessible within disconnectedCallback.
Object.defineProperty(this.global, 'document', {value: null});
this.global.close();
}
this.errorEventListener = null;
// @ts-expect-error
Expand Down

0 comments on commit 7a34a69

Please sign in to comment.