Skip to content
This repository was archived by the owner on Feb 26, 2024. It is now read-only.

Commit 61aee2e

Browse files
JiaLiPassionmhevery
authored andcommitted
feat(dom): fix #664, patch window,document,SVGElement onProperties (#687)
1 parent 5635ac0 commit 61aee2e

File tree

2 files changed

+95
-1
lines changed

2 files changed

+95
-1
lines changed

lib/browser/property-descriptor.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,11 @@ export function propertyDescriptorPatch(_global: any) {
2323
if (canPatchViaPropertyDescriptor()) {
2424
// for browsers that we can patch the descriptor: Chrome & Firefox
2525
if (isBrowser) {
26+
patchOnProperties(window, eventNames);
27+
patchOnProperties(Document.prototype, eventNames);
28+
if (typeof SVGElement !== 'undefined') {
29+
patchOnProperties(SVGElement.prototype, eventNames);
30+
}
2631
patchOnProperties(HTMLElement.prototype, eventNames);
2732
}
2833
patchOnProperties(XMLHttpRequest.prototype, null);

test/browser/browser.spec.ts

Lines changed: 90 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,10 @@
66
* found in the LICENSE file at https://angular.io/license
77
*/
88

9-
import {zoneSymbol} from '../../lib/common/utils';
9+
import {isBrowser, isMix, zoneSymbol} from '../../lib/common/utils';
1010
import {ifEnvSupports} from '../test-util';
11+
12+
import Spy = jasmine.Spy;
1113
declare const global: any;
1214

1315
function windowPrototype() {
@@ -18,6 +20,19 @@ function promiseUnhandleRejectionSupport() {
1820
return !!global['PromiseRejectionEvent'];
1921
}
2022

23+
function canPatchOnProperty(obj: any, prop: string) {
24+
if (!obj) {
25+
return false;
26+
}
27+
const desc = Object.getOwnPropertyDescriptor(obj, prop);
28+
if (!desc || !desc.configurable) {
29+
return false;
30+
}
31+
return true;
32+
}
33+
34+
(canPatchOnProperty as any).message = 'patchOnProperties';
35+
2136
describe('Zone', function() {
2237
const rootZone = Zone.current;
2338

@@ -51,6 +66,80 @@ describe('Zone', function() {
5166
expect(confirmSpy).toHaveBeenCalledWith('confirmMsg');
5267
});
5368

69+
describe('DOM onProperty hooks', ifEnvSupports(canPatchOnProperty, function() {
70+
let mouseEvent = document.createEvent('Event');
71+
let hookSpy: Spy, eventListenerSpy: Spy;
72+
const zone = rootZone.fork({
73+
name: 'spy',
74+
onScheduleTask: (parentZoneDelegate: ZoneDelegate, currentZone: Zone,
75+
targetZone: Zone, task: Task): any => {
76+
hookSpy();
77+
return parentZoneDelegate.scheduleTask(targetZone, task);
78+
}
79+
});
80+
81+
beforeEach(function() {
82+
mouseEvent.initEvent('mousedown', true, true);
83+
hookSpy = jasmine.createSpy('hook');
84+
eventListenerSpy = jasmine.createSpy('eventListener');
85+
});
86+
87+
it('window onclick should be in zone',
88+
ifEnvSupports(
89+
() => {
90+
return canPatchOnProperty(window, 'onmousedown');
91+
},
92+
function() {
93+
zone.run(function() {
94+
window.onmousedown = eventListenerSpy;
95+
});
96+
97+
window.dispatchEvent(mouseEvent);
98+
99+
expect(hookSpy).toHaveBeenCalled();
100+
expect(eventListenerSpy).toHaveBeenCalled();
101+
window.removeEventListener('mousedown', eventListenerSpy);
102+
}));
103+
104+
it('document onclick should be in zone',
105+
ifEnvSupports(
106+
() => {
107+
return canPatchOnProperty(Document.prototype, 'onmousedown');
108+
},
109+
function() {
110+
zone.run(function() {
111+
document.onmousedown = eventListenerSpy;
112+
});
113+
114+
document.dispatchEvent(mouseEvent);
115+
116+
expect(hookSpy).toHaveBeenCalled();
117+
expect(eventListenerSpy).toHaveBeenCalled();
118+
document.removeEventListener('mousedown', eventListenerSpy);
119+
}));
120+
121+
it('SVGElement onclick should be in zone',
122+
ifEnvSupports(
123+
() => {
124+
return typeof SVGElement !== 'undefined' &&
125+
canPatchOnProperty(SVGElement.prototype, 'onmousedown');
126+
},
127+
function() {
128+
const svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
129+
document.body.appendChild(svg);
130+
zone.run(function() {
131+
svg.onmousedown = eventListenerSpy;
132+
});
133+
134+
svg.dispatchEvent(mouseEvent);
135+
136+
expect(hookSpy).toHaveBeenCalled();
137+
expect(eventListenerSpy).toHaveBeenCalled();
138+
svg.removeEventListener('mouse', eventListenerSpy);
139+
document.body.removeChild(svg);
140+
}));
141+
}));
142+
54143
describe('eventListener hooks', function() {
55144
let button: HTMLButtonElement;
56145
let clickEvent: Event;

0 commit comments

Comments
 (0)