From 160531b2fb3d71d2dc52be4643bda4c9c67e040b Mon Sep 17 00:00:00 2001 From: JiaLiPassion Date: Mon, 10 Apr 2017 18:31:42 +0900 Subject: [PATCH] fix(patch): fix #719, window onproperty callback this is undefined (#723) --- lib/common/utils.ts | 36 +++++++++++++++++++++++++++--------- test/browser/browser.spec.ts | 15 +++++++++++++++ 2 files changed, 42 insertions(+), 9 deletions(-) diff --git a/lib/common/utils.ts b/lib/common/utils.ts index 166bb8bfa..8a28d24d3 100644 --- a/lib/common/utils.ts +++ b/lib/common/utils.ts @@ -81,8 +81,17 @@ export function patchProperty(obj: any, prop: string) { const _prop = zoneSymbol('_' + prop); desc.set = function(fn) { - if (this[_prop]) { - this.removeEventListener(eventName, this[_prop]); + // in some of windows's onproperty callback, this is undefined + // so we need to check it + let target = this; + if (!target && obj === _global) { + target = _global; + } + if (!target) { + return; + } + if (target[_prop]) { + target.removeEventListener(eventName, target[_prop]); } if (typeof fn === 'function') { @@ -96,17 +105,26 @@ export function patchProperty(obj: any, prop: string) { return result; }; - this[_prop] = wrapFn; - this.addEventListener(eventName, wrapFn, false); + target[_prop] = wrapFn; + target.addEventListener(eventName, wrapFn, false); } else { - this[_prop] = null; + target[_prop] = null; } }; // The getter would return undefined for unassigned properties but the default value of an // unassigned property is null desc.get = function() { - let r = this[_prop] || null; + // in some of windows's onproperty callback, this is undefined + // so we need to check it + let target = this; + if (!target && obj === _global) { + target = _global; + } + if (!target) { + return null; + } + let r = target[_prop] || null; // result will be null when use inline event attribute, // such as // because the onclick function is internal raw uncompiled handler @@ -118,13 +136,13 @@ export function patchProperty(obj: any, prop: string) { r = originalDesc.get.apply(this, arguments); if (r) { desc.set.apply(this, [r]); - if (typeof this['removeAttribute'] === 'function') { - this.removeAttribute(prop); + if (typeof target['removeAttribute'] === 'function') { + target.removeAttribute(prop); } } } } - return this[_prop] || null; + return target[_prop] || null; }; Object.defineProperty(obj, prop, desc); diff --git a/test/browser/browser.spec.ts b/test/browser/browser.spec.ts index dd234f330..f430692c8 100644 --- a/test/browser/browser.spec.ts +++ b/test/browser/browser.spec.ts @@ -138,6 +138,21 @@ describe('Zone', function() { svg.removeEventListener('mouse', eventListenerSpy); document.body.removeChild(svg); })); + + it('get window onerror should not throw error', + ifEnvSupports( + () => { + return canPatchOnProperty(window, 'onerror'); + }, + function() { + const testFn = function() { + let onerror = window.onerror; + window.onerror = function() {}; + onerror = window.onerror; + }; + expect(testFn()).not.toThrow(); + })); + })); describe('eventListener hooks', function() {