Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions integration_tests/__tests__/nested_event_loop.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
/**
* Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow
*/
'use strict';

const runJest = require('../runJest');

test('works with nested event loops', () => {
const result = runJest('nested_event_loop');
expect(result.status).toBe(0);
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/**
* Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @jest-environment jsdom
*/

/* eslint-env browser */

'use strict';

it('can assert on errors across nested event loops', () => {
const el = document.createElement('div');
el.addEventListener('fake', () => {
throw new Error('This should be caught.');
});
let caught = null;
window.addEventListener('error', e => {
caught = e.error;
});
expect(() => {
const evt = document.createEvent('Event');
evt.initEvent('fake', false, false);
el.dispatchEvent(evt);
if (caught) {
throw caught;
}
}).toThrow();
});
5 changes: 5 additions & 0 deletions integration_tests/nested_event_loop/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"jest": {
"testEnvironment": "jsdom"
}
}
21 changes: 20 additions & 1 deletion packages/jest-environment-jsdom/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -44,13 +44,32 @@ class JSDOMEnvironment {
};
}

// Report uncaught errors.
this.errorEventListener = event => {
if (event.error) {
if (userErrorListenerCount === 0 && event.error) {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of manual bookkeeping, can we just check the total number of listeners here?

e.g. this works in chrome:

window.getEventListeners(window).error.length // 1 on github.com

Copy link
Copy Markdown
Member

@SimenB SimenB Oct 26, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like getEventListeners is not available for jsdom@9 at least

EDIT: Or in 11

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm fine with upgrading to 11 and dropping node 4 now.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

process.emit('uncaughtException', event.error);
}
};
global.addEventListener('error', this.errorEventListener);

// However, don't report them as uncaught if the user listens to 'error' event.
// In that case, we assume the might have custom error handling logic.
const originalAddListener = global.addEventListener;
const originalRemoveListener = global.removeEventListener;
let userErrorListenerCount = 0;
global.addEventListener = function(name) {
if (name === 'error') {
userErrorListenerCount++;
}
return originalAddListener.apply(this, arguments);
};
global.removeEventListener = function(name) {
if (name === 'error') {
userErrorListenerCount--;
}
return originalRemoveListener.apply(this, arguments);
};

this.moduleMocker = new mock.ModuleMocker(global);

const timerConfig = {
Expand Down