diff --git a/lib/browser/webapis-media-query.ts b/lib/browser/webapis-media-query.ts index 0bb841826..8db02cd0b 100644 --- a/lib/browser/webapis-media-query.ts +++ b/lib/browser/webapis-media-query.ts @@ -6,9 +6,60 @@ * found in the LICENSE file at https://angular.io/license */ Zone.__load_patch('mediaQuery', (global: any, Zone: ZoneType, api: _ZonePrivate) => { - if (!global['MediaQueryList']) { - return; + function patchAddListener(proto: any) { + api.patchMethod(proto, 'addListener', (delegate: Function) => (self: any, args: any[]) => { + const callback = args.length > 0 ? args[0] : null; + if (typeof callback === 'function') { + const wrapperedCallback = Zone.current.wrap(callback, 'MediaQuery'); + callback[api.symbol('mediaQueryCallback')] = wrapperedCallback; + return delegate.call(self, wrapperedCallback); + } else { + return delegate.apply(self, args); + } + }); + } + + function patchRemoveListener(proto: any) { + api.patchMethod(proto, 'removeListener', (delegate: Function) => (self: any, args: any[]) => { + const callback = args.length > 0 ? args[0] : null; + if (typeof callback === 'function') { + const wrapperedCallback = callback[api.symbol('mediaQueryCallback')]; + if (wrapperedCallback) { + return delegate.call(self, wrapperedCallback); + } else { + return delegate.apply(self, args); + } + } else { + return delegate.apply(self, args); + } + }); + } + + if (global['MediaQueryList']) { + const proto = global['MediaQueryList'].prototype; + patchAddListener(proto); + patchRemoveListener(proto); + } else if (global['matchMedia']) { + api.patchMethod(global, 'matchMedia', (delegate: Function) => (self: any, args: any[]) => { + const mql = delegate.apply(self, args); + if (mql) { + // try to patch MediaQueryList.prototype + const proto = Object.getPrototypeOf(mql); + if (proto && proto['addListener']) { + // try to patch proto, don't need to worry about patch + // multiple times, because, api.patchEventTarget will check it + patchAddListener(proto); + patchRemoveListener(proto); + patchAddListener(mql); + patchRemoveListener(mql); + } else if (mql['addListener']) { + // proto not exists, or proto has no addListener method + // try to patch mql instance + patchAddListener(mql); + patchRemoveListener(mql); + } + } + return mql; + }); } - api.patchEventTarget( - global, [global['MediaQueryList'].prototype], {add: 'addListener', rm: 'removeListener'}); }); diff --git a/test/test-env-setup-jasmine.ts b/test/test-env-setup-jasmine.ts index 955bb1e59..8cee81df5 100644 --- a/test/test-env-setup-jasmine.ts +++ b/test/test-env-setup-jasmine.ts @@ -6,5 +6,5 @@ * found in the LICENSE file at https://angular.io/license */ -(jasmine).DEFAULT_TIMEOUT_INTERVAL = 2000; +(jasmine).DEFAULT_TIMEOUT_INTERVAL = 5000; import '../lib/jasmine/jasmine';