Skip to content
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(synthetic-shadow): make Event constructor handle composed #1676

Merged
merged 4 commits into from
Jan 21, 2020
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
Original file line number Diff line number Diff line change
Expand Up @@ -4,24 +4,28 @@
* SPDX-License-Identifier: MIT
* For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/MIT
*/
const OriginalCustomEvent = CustomEvent;
const CustomEventConstructor = CustomEvent;

function PatchedCustomEvent(this: Event, type: string, eventInitDict: CustomEventInit<any>): Event {
const event = new OriginalCustomEvent(type, eventInitDict);
// support for composed on custom events
function PatchedCustomEvent<T>(
this: Event,
type: string,
eventInitDict: CustomEventInit<T>
): CustomEvent<T> {
const event = new CustomEventConstructor(type, eventInitDict);

const isComposed = !!(eventInitDict && eventInitDict.composed);
Object.defineProperties(event, {
composed: {
// We can't use "value" here, because IE11 doesn't like mixing and matching
// value with get() from Event.prototype.
get() {
return !!(eventInitDict && (eventInitDict as any).composed);
return isComposed;
},
configurable: true,
enumerable: true,
},
});

return event;
}

PatchedCustomEvent.prototype = OriginalCustomEvent.prototype;
PatchedCustomEvent.prototype = CustomEventConstructor.prototype;
(window as any).CustomEvent = PatchedCustomEvent;
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,5 @@
* For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/MIT
*/
export default function detect(): boolean {
return Object.getOwnPropertyDescriptor(Event.prototype, 'composed') === undefined;
return new Event('test', { composed: true }).composed !== true;
}
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,35 @@ export default function apply() {
keypress: 1,
});

// Composed for Native events
const EventConstructor = Event;

// Patch Event constructor to add the composed property on events created via new Event.
function PatchedEvent(this: Event, type: string, eventInitDict?: EventInit): Event {
const event = new EventConstructor(type, eventInitDict);

const isComposed = !!(eventInitDict && eventInitDict.composed);
Object.defineProperties(event, {
composed: {
get(): boolean {
return isComposed;
},
configurable: true,
enumerable: true,
},
});

return event;
}

PatchedEvent.prototype = EventConstructor.prototype;
PatchedEvent.AT_TARGET = EventConstructor.AT_TARGET;
PatchedEvent.BUBBLING_PHASE = EventConstructor.BUBBLING_PHASE;
PatchedEvent.CAPTURING_PHASE = EventConstructor.CAPTURING_PHASE;
PatchedEvent.NONE = EventConstructor.NONE;

(window as any).Event = PatchedEvent;

// Patch the Event prototype to add the composed property on user agent dispatched event.
Object.defineProperties(Event.prototype, {
composed: {
get() {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,24 @@
// TODO [#938]: Standard event composed flag should not be set if the event is created manually.
xit('should not set composed to true if the event is not trusted', () => {
it('should not set composed to true if the event is not set during construction', () => {
const clickEvent = new Event('click');
expect(clickEvent.composed).toBe(false);
});

// TODO [#938]: Standard event composed flag should not be set if the event is created manually.
xit('should respect when the event composed flag is set during construction', () => {
it('should respect when the event composed flag is set during construction', () => {
const composedClickEvent = new Event('click', { composed: true });
expect(composedClickEvent.composed).toBe(true);

const notComposedClickEvent = new Event('click', { composed: false });
expect(notComposedClickEvent.composed).toBe(false);
});

it('should set composed to true for click events dispatched by the user agent', done => {
const elm = document.createElement('div');
document.body.appendChild(elm);

elm.addEventListener('click', evt => {
expect(evt.composed).toBe(true);
done();
});

elm.click();
});