-
Notifications
You must be signed in to change notification settings - Fork 141
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
🐛 [RUMF-1449] implement a workaround for Firefox memory leak
- Loading branch information
1 parent
ae1a975
commit 37efd06
Showing
9 changed files
with
181 additions
and
33 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
import { stubZoneJs } from '../../test/specHelper' | ||
import { noop } from '../tools/utils' | ||
|
||
import { addEventListener, DOM_EVENT, clearGetEventTargetOriginMethodsCache } from './addEventListener' | ||
|
||
describe('addEventListener', () => { | ||
describe('Zone.js support', () => { | ||
let zoneJsStub: ReturnType<typeof stubZoneJs> | ||
|
||
beforeEach(() => { | ||
zoneJsStub = stubZoneJs() | ||
}) | ||
|
||
afterEach(() => { | ||
zoneJsStub.restore() | ||
clearGetEventTargetOriginMethodsCache() | ||
}) | ||
|
||
it('uses the original addEventListener method instead of the method patched by Zone.js', () => { | ||
const zoneJsPatchedAddEventListener = jasmine.createSpy() | ||
zoneJsStub.replaceProperty(EventTarget.prototype, 'addEventListener', zoneJsPatchedAddEventListener) | ||
|
||
const eventTarget = document.createElement('div') | ||
addEventListener(eventTarget, DOM_EVENT.CLICK, noop) | ||
expect(zoneJsPatchedAddEventListener).not.toHaveBeenCalled() | ||
}) | ||
|
||
it('uses the original removeEventListener method instead of the method patched by Zone.js', () => { | ||
const zoneJsPatchedRemoveEventListener = jasmine.createSpy() | ||
zoneJsStub.replaceProperty(EventTarget.prototype, 'removeEventListener', zoneJsPatchedRemoveEventListener) | ||
|
||
const eventTarget = document.createElement('div') | ||
const { stop } = addEventListener(eventTarget, DOM_EVENT.CLICK, noop) | ||
stop() | ||
expect(zoneJsPatchedRemoveEventListener).not.toHaveBeenCalled() | ||
}) | ||
}) | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
import { stubZoneJs } from '../../test/specHelper' | ||
|
||
import { getZoneJsOriginalValue } from './getZoneJsOriginalValue' | ||
import { noop } from './utils' | ||
|
||
describe('getZoneJsOriginalValue', () => { | ||
let zoneJsStub: ReturnType<typeof stubZoneJs> | undefined | ||
|
||
afterEach(() => { | ||
zoneJsStub?.restore() | ||
}) | ||
|
||
it('returns undefined if Zone is not not defined', () => { | ||
expect(getZoneJsOriginalValue({ toto: noop }, 'toto')).toBeUndefined() | ||
}) | ||
|
||
it("returns undefined if Zone is defined but didn't patch that method", () => { | ||
zoneJsStub = stubZoneJs() | ||
expect(getZoneJsOriginalValue({ toto: noop }, 'toto')).toBeUndefined() | ||
}) | ||
|
||
it('returns the original value if Zone did patch the method', () => { | ||
zoneJsStub = stubZoneJs() | ||
|
||
const originalMethod = () => { | ||
// noop | ||
} | ||
expect(getZoneJsOriginalValue({ toto: noop, [zoneJsStub.getSymbol('toto')]: originalMethod }, 'toto')).toBe( | ||
originalMethod | ||
) | ||
}) | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
export interface BrowserWindowWithZoneJs extends Window { | ||
Zone?: { | ||
__symbol__: (name: string) => string | ||
} | ||
} | ||
|
||
/** | ||
* Gets the original value for a DOM API that was potentially patched by Zone.js. | ||
* | ||
* Zone.js[1] is a library that patches a bunch of JS and DOM APIs. It usually stores the original | ||
* value of the patched functions/constructors/methods in a hidden property prefixed by | ||
* __zone_symbol__. | ||
* | ||
* In multiple occasions, we observed that Zone.js is the culprit of important issues leading to | ||
* browser resource exhaustion (memory leak, high CPU usage). This method is used as a workaround to | ||
* use the original DOM API instead of the one patched by Zone.js. | ||
* | ||
* [1]: https://github.com/angular/angular/tree/main/packages/zone.js | ||
*/ | ||
export function getZoneJsOriginalValue<Target, Name extends keyof Target & string>( | ||
target: Target, | ||
name: Name | ||
): Target[Name] | undefined { | ||
const browserWindow = window as BrowserWindowWithZoneJs | ||
if (browserWindow.Zone) { | ||
return (target as any)[browserWindow.Zone.__symbol__(name)] as Target[Name] | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters