-
Notifications
You must be signed in to change notification settings - Fork 518
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
fix: patch removeEventListener to properly remove patched callbacks #158
Changes from all commits
0a2a397
5117e4b
6b35ea8
559fd20
e238549
b56aa2b
a50f6cf
e6a0b97
f790b62
f529213
bfb3d67
4e6d498
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -89,6 +89,78 @@ describe('UserInteractionPlugin', () => { | |
context.disable(); | ||
}); | ||
|
||
it('should not break removeEventListener', () => { | ||
let called = false; | ||
const listener = function () { | ||
called = true; | ||
}; | ||
// add same listener three different ways | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm curious about one scenario. To check that can you modify this a bit to test the case with overwriting the previous event with the same callback
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. fixed my example There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yep, good catch and an easy fix for this one based on the tracking state. Pushing fix momentarily. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There is one more thing a bonus :). Currently you can call There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. and you can revert it add There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Argh. There's also the case that once:true shouldn't prevent us from allowing it to be adding later (it's not really a double-register). Will dive in and fix this one tomorrow. Thanks! There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. thx for taking this into deep details :) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Couldn't leave it alone; handled the |
||
document.body.addEventListener('bodyEvent', listener); | ||
document.body.addEventListener('bodyEvent2', listener); | ||
document.addEventListener('docEvent', listener); | ||
document.body.dispatchEvent(new Event('bodyEvent')); | ||
assert.strictEqual(called, true); | ||
called = false; | ||
// Remove first callback, second type should still fire | ||
document.body.removeEventListener('bodyEvent', listener); | ||
document.body.dispatchEvent(new Event('bodyEvent')); | ||
assert.strictEqual(called, false); | ||
document.body.dispatchEvent(new Event('bodyEvent2')); | ||
assert.strictEqual(called, true); | ||
called = false; | ||
// Remove doc callback, body 2 should still fire | ||
document.removeEventListener('docEvent', listener); | ||
document.dispatchEvent(new Event('docEvent')); | ||
assert.strictEqual(called, false); | ||
document.body.dispatchEvent(new Event('bodyEvent2')); | ||
assert.strictEqual(called, true); | ||
called = false; | ||
// Finally, remove the last one and nothing should fire | ||
document.body.removeEventListener('bodyEvent2', listener); | ||
document.body.dispatchEvent(new Event('bodyEvent')); | ||
document.body.dispatchEvent(new Event('bodyEvent2')); | ||
document.dispatchEvent(new Event('docEvent')); | ||
assert.strictEqual(called, false); | ||
}); | ||
|
||
it('should not double-register a listener', () => { | ||
let callCount = 0; | ||
const listener = function () { | ||
callCount++; | ||
}; | ||
// addEventListener semantics treat the second call as a no-op | ||
document.body.addEventListener('bodyEvent', listener); | ||
document.body.addEventListener('bodyEvent', listener); | ||
document.body.dispatchEvent(new Event('bodyEvent')); | ||
assert.strictEqual(callCount, 1); | ||
// now ensure remove still works | ||
callCount = 0; | ||
document.body.removeEventListener('bodyEvent', listener); | ||
document.body.dispatchEvent(new Event('bodyEvent')); | ||
assert.strictEqual(callCount, 0); | ||
}); | ||
|
||
it('should handle once-only callbacks', () => { | ||
let callCount = 0; | ||
const listener = function () { | ||
callCount++; | ||
}; | ||
// addEventListener semantics treat the second call as a no-op | ||
document.body.addEventListener('bodyEvent', listener, { once: true }); | ||
document.body.addEventListener('bodyEvent', listener); // considered a double-register | ||
document.body.dispatchEvent(new Event('bodyEvent')); | ||
assert.strictEqual(callCount, 1); | ||
// now that it's been dispatched once, it's been removed | ||
document.body.dispatchEvent(new Event('bodyEvent')); | ||
assert.strictEqual(callCount, 1); | ||
// should be able to re-add | ||
document.body.addEventListener('bodyEvent', listener); | ||
document.body.dispatchEvent(new Event('bodyEvent')); | ||
assert.strictEqual(callCount, 2); | ||
johnbley marked this conversation as resolved.
Show resolved
Hide resolved
|
||
document.body.dispatchEvent(new Event('bodyEvent')); | ||
assert.strictEqual(callCount, 3); | ||
}); | ||
|
||
it('should handle task without async operation', () => { | ||
fakeInteraction(); | ||
assert.equal(exportSpy.args.length, 1, 'should export one span'); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this going to be coerced into a
WeakMap
when you set it on_wrappedListeners
?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, though making the HTMLElement reference weak is a good idea. Unfortunately I don't see a way to do it since there are no iterators/size/isEmpty methods available on WeakMap and without it we'd definitely leak. I'll ponder this but I'd like to get this fix in as it is since it's clearly better than the current breaking of functional behavior.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Awesome, thanks for the clarification!