angular/packages/zone.js/lib/browser/property-descriptor.ts
Joey Perrott 9dbe6fc18b refactor: update license text to point to angular.dev (#57901)
Update license text to point to angular.dev instead of angular.io

PR Close #57901
2024-09-24 15:33:00 +02:00

129 lines
3.5 KiB
TypeScript

/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.dev/license
*/
/**
* @fileoverview
* @suppress {globalThis}
*/
import {
isBrowser,
isIE,
isMix,
isNode,
ObjectGetPrototypeOf,
patchOnProperties,
} from '../common/utils';
export interface IgnoreProperty {
target: any;
ignoreProperties: string[];
}
export function filterProperties(
target: any,
onProperties: string[],
ignoreProperties: IgnoreProperty[],
): string[] {
if (!ignoreProperties || ignoreProperties.length === 0) {
return onProperties;
}
const tip: IgnoreProperty[] = ignoreProperties.filter((ip) => ip.target === target);
if (!tip || tip.length === 0) {
return onProperties;
}
const targetIgnoreProperties: string[] = tip[0].ignoreProperties;
return onProperties.filter((op) => targetIgnoreProperties.indexOf(op) === -1);
}
export function patchFilteredProperties(
target: any,
onProperties: string[],
ignoreProperties: IgnoreProperty[],
prototype?: any,
) {
// check whether target is available, sometimes target will be undefined
// because different browser or some 3rd party plugin.
if (!target) {
return;
}
const filteredProperties: string[] = filterProperties(target, onProperties, ignoreProperties);
patchOnProperties(target, filteredProperties, prototype);
}
/**
* Get all event name properties which the event name startsWith `on`
* from the target object itself, inherited properties are not considered.
*/
export function getOnEventNames(target: Object) {
return Object.getOwnPropertyNames(target)
.filter((name) => name.startsWith('on') && name.length > 2)
.map((name) => name.substring(2));
}
export function propertyDescriptorPatch(api: _ZonePrivate, _global: any) {
if (isNode && !isMix) {
return;
}
if ((Zone as any)[api.symbol('patchEvents')]) {
// events are already been patched by legacy patch.
return;
}
const ignoreProperties: IgnoreProperty[] = _global['__Zone_ignore_on_properties'];
// for browsers that we can patch the descriptor: Chrome & Firefox
let patchTargets: string[] = [];
if (isBrowser) {
const internalWindow: any = window;
patchTargets = patchTargets.concat([
'Document',
'SVGElement',
'Element',
'HTMLElement',
'HTMLBodyElement',
'HTMLMediaElement',
'HTMLFrameSetElement',
'HTMLFrameElement',
'HTMLIFrameElement',
'HTMLMarqueeElement',
'Worker',
]);
const ignoreErrorProperties = isIE()
? [{target: internalWindow, ignoreProperties: ['error']}]
: [];
// in IE/Edge, onProp not exist in window object, but in WindowPrototype
// so we need to pass WindowPrototype to check onProp exist or not
patchFilteredProperties(
internalWindow,
getOnEventNames(internalWindow),
ignoreProperties ? ignoreProperties.concat(ignoreErrorProperties) : ignoreProperties,
ObjectGetPrototypeOf(internalWindow),
);
}
patchTargets = patchTargets.concat([
'XMLHttpRequest',
'XMLHttpRequestEventTarget',
'IDBIndex',
'IDBRequest',
'IDBOpenDBRequest',
'IDBDatabase',
'IDBTransaction',
'IDBCursor',
'WebSocket',
]);
for (let i = 0; i < patchTargets.length; i++) {
const target = _global[patchTargets[i]];
target &&
target.prototype &&
patchFilteredProperties(
target.prototype,
getOnEventNames(target.prototype),
ignoreProperties,
);
}
}