Skip to content

Fix failing tests: patch XMLHttpRequest if no EventTarget; dispatch a 'proxy' if currentTarget is an own value property descriptor#519

Merged
bicknellr merged 9 commits intomasterfrom
shadydom-failing-event-tests
Aug 22, 2022
Merged

Fix failing tests: patch XMLHttpRequest if no EventTarget; dispatch a 'proxy' if currentTarget is an own value property descriptor#519
bicknellr merged 9 commits intomasterfrom
shadydom-failing-event-tests

Conversation

@bicknellr
Copy link
Copy Markdown
Collaborator

@bicknellr bicknellr commented Aug 12, 2022

In at least Chrome 41, events' currentTarget is an own property with a broken descriptor. Setting a new descriptor on one of these events makes it impossible to restore the default behavior of currentTarget for that event, making it useless to any later listeners. Shady DOM occasionally has to manually dispatch an event, which involves temporarily setting a new currentTarget descriptor to allow Shady DOM to update this property. With this PR, if the currentTarget property of events is broken as it is in Chrome 41, Shady DOM will create a new object with the event as its prototype, modify that new object's currentTarget descriptor, and pass that new object to listeners during the manual dispatch.

EventTarget doesn't exist in some older browsers, so objects that would normally have EventTarget.prototype in their prototype chain in modern browsers instead have separate copies of those properties on other prototypes. XMLHttpRequest is one of these objects with EventTarget-like properties, but these properties were unpatched until this PR.

Safari 9 both doesn't have working `Event.prototype` descriptors and doesn't
allow event property getter / function call context objects to be anything other
than exactly the original event, so `utils.settings.hasDescriptors` is not a
sufficient basis for deciding whether or not to use the proxy-like event object
wrapper.
@bicknellr bicknellr changed the title [ShadyDOM] Fix failing event tests Fix failing tests Aug 13, 2022
@bicknellr bicknellr changed the title Fix failing tests Fix failing tests: patch XMLHttpRequest if no EventTarget; dispatch a 'proxy' if currentTarget is an own value property descriptor Aug 15, 2022
@bicknellr bicknellr marked this pull request as ready for review August 15, 2022 18:55
@bicknellr bicknellr requested a review from aomarks as a code owner August 15, 2022 18:55
Comment on lines +381 to +384
// exists on a new `Event` and switch based off of that. Safari 9 both doesn't
// have working descriptors for `Event` properties and doesn't allow getter
// contexts to be anything other than the original event, so
// `utils.settings.hasDescriptors` is not a sufficient test for deciding this
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Hmm, so how does this not break Safari 9? Which path does it take?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Good catch, my comment is wrong. Safari 9 actually does have working Event descriptors, so it's OK to overwrite currentTarget on the original event. The real problem is that utils.settings.hasDescriptors is false in Safari 9 because it's set like this:

const desc = Object.getOwnPropertyDescriptor(Node.prototype, 'firstChild');
settings.hasDescriptors = Boolean(desc && desc.configurable && desc.get);

And Safari 9's firstChild descriptor is not configurable.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Updated.

Copy link
Copy Markdown
Collaborator

@kevinpschaaf kevinpschaaf left a comment

Choose a reason for hiding this comment

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

For posterity, because this took me a bit to grok:

On Safari 9, currentTarget is not an own property of Event, but the descriptor on the prototype is also not usable (making it somewhat unique, since the unusable descriptors are all normally ownPropertys). So Safari 9 does go through the "save instance descriptor / finally restore descriptor" logic, but because the original descriptor is undefined, we just delete the shimmed one off the instance, and the prototype-but-not-good-accessor one is allowed to work again.

@bicknellr bicknellr merged commit ad061f3 into master Aug 22, 2022
@bicknellr bicknellr deleted the shadydom-failing-event-tests branch August 22, 2022 23:57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants