Execution context library that persists across asynchronous operations for JavaScript applications
Monkey patching infrastructure for browser and Node.js APIs, enabling zone context preservation across various asynchronous operations.
Zone.js provides a comprehensive patching system to integrate with native APIs.
/**
* Patch function type for extending Zone.js functionality
* @param global - Global object (window, global, etc.)
* @param Zone - Zone constructor
* @param api - ZonePrivate API for patch utilities
*/
type PatchFn = (global: Window, Zone: ZoneType, api: ZonePrivate) => void;
/**
* Load a patch for specified native module
* @param name - Unique name for the patch
* @param fn - Patch function to execute
* @param ignoreDuplicate - Whether to ignore duplicate patch names
*/
__load_patch(name: string, fn: PatchFn, ignoreDuplicate?: boolean): void;Usage Examples:
import 'zone.js';
// Load a custom patch
Zone.__load_patch('custom-api', (global, Zone, api) => {
// Patch some custom API
const originalMethod = global.customAPI?.someMethod;
if (originalMethod) {
global.customAPI.someMethod = api.wrapWithCurrentZone(
originalMethod,
'customAPI.someMethod'
);
}
});
// Load browser patches
Zone.__load_patch('browser', (global, Zone, api) => {
patchBrowser(Zone);
});
// Load Node.js patches
Zone.__load_patch('node', (global, Zone, api) => {
patchNode(Zone);
});Internal API providing utilities for developing custom patches.
/**
* Private API for patch development
*/
interface ZonePrivate {
/** Get current zone frame information */
currentZoneFrame(): ZoneFrame;
/** Generate zone symbol with prefix */
symbol(name: string): string;
/** Schedule a microtask */
scheduleMicroTask(task?: MicroTask): void;
/** Handle unhandled errors */
onUnhandledError(error: Error): void;
/** Notify that microtask queue is drained */
microtaskDrainDone(): void;
/** Check if uncaught errors should be shown */
showUncaughtError(): boolean;
/** Patch EventTarget APIs */
patchEventTarget(global: any, api: ZonePrivate, apis: any[], options?: any): boolean[];
/** Patch object properties for event handlers */
patchOnProperties(obj: any, properties: string[] | null, prototype?: any): void;
/** Patch Promise.then method */
patchThen(ctor: Function): void;
/** Patch a method with zone awareness */
patchMethod(
target: any,
name: string,
patchFn: (delegate: Function, delegateName: string, name: string) => Function
): Function | null;
/** Bind arguments with zone context */
bindArguments(args: any[], source: string): any[];
/** Patch macrotask APIs (setTimeout, etc.) */
patchMacroTask(obj: any, funcName: string, metaCreator: Function): void;
/** Patch event prototype methods */
patchEventPrototype(global: any, api: ZonePrivate): void;
/** Check if running in IE or Edge */
isIEOrEdge(): boolean;
/** Object.defineProperty reference */
ObjectDefineProperty: typeof Object.defineProperty;
/** Object.getOwnPropertyDescriptor reference */
ObjectGetOwnPropertyDescriptor: typeof Object.getOwnPropertyDescriptor;
/** Object.create reference */
ObjectCreate: typeof Object.create;
/** Array.prototype.slice reference */
ArraySlice: typeof Array.prototype.slice;
/** Patch constructor class */
patchClass(className: string): void;
/** Wrap callback with current zone */
wrapWithCurrentZone(callback: any, source: string): any;
/** Filter properties for patching */
filterProperties(target: any, onProperties: string[], ignoreProperties: any[]): string[];
/** Attach origin reference to patched function */
attachOriginToPatched(target: any, origin: any): void;
/** Redefine property with descriptor */
_redefineProperty(target: any, callback: string, desc: any): void;
/** Native microtask scheduler */
nativeScheduleMicroTask(func: Function): void;
/** Get global objects and utilities */
getGlobalObjects(): {
globalSources: any;
zoneSymbolEventNames: any;
eventNames: string[];
isBrowser: boolean;
isMix: boolean;
isNode: boolean;
TRUE_STR: string;
FALSE_STR: string;
ZONE_SYMBOL_PREFIX: string;
ADD_EVENT_LISTENER_STR: string;
REMOVE_EVENT_LISTENER_STR: string;
} | undefined;
}Zone.js provides comprehensive patches for browser APIs.
/**
* Patch core browser APIs
* @param Zone - Zone constructor
*/
function patchBrowser(Zone: ZoneType): void;
/**
* Patch common browser APIs (timers, RAF, etc.)
* @param Zone - Zone constructor
*/
function patchCommon(Zone: ZoneType): void;
/**
* Patch EventTarget API
* @param global - Global object
* @param api - ZonePrivate API
*/
function eventTargetPatch(global: any, api: ZonePrivate): void;
/**
* Patch timer APIs (setTimeout, setInterval)
* @param window - Window object
* @param setName - Setter function name
* @param cancelName - Canceller function name
* @param nameSuffix - Name suffix for debugging
*/
function patchTimer(window: any, setName: string, cancelName: string, nameSuffix: string): void;
/**
* Patch Promise API
* @param Zone - Zone constructor
*/
function patchPromise(Zone: ZoneType): void;
/**
* Patch Fetch API
* @param Zone - Zone constructor
*/
function patchFetch(Zone: ZoneType): void;Usage Examples:
// Browser patches are typically loaded automatically
import 'zone.js'; // Loads browser patches
// Manual browser patching
Zone.__load_patch('browser', (global, Zone, api) => {
patchBrowser(Zone);
});
// Patch specific APIs
Zone.__load_patch('timers', (global, Zone, api) => {
patchTimer(global, 'setTimeout', 'clearTimeout', 'Timeout');
patchTimer(global, 'setInterval', 'clearInterval', 'Interval');
});
Zone.__load_patch('promise', (global, Zone, api) => {
patchPromise(Zone);
});Zone.js provides patches for Node.js APIs to enable zone context in server environments.
/**
* Patch core Node.js APIs
* @param Zone - Zone constructor
*/
function patchNode(Zone: ZoneType): void;
/**
* Patch EventEmitter API
* @param Zone - Zone constructor
*/
function patchEvents(Zone: ZoneType): void;
/**
* Patch File System API
* @param Zone - Zone constructor
*/
function patchFs(Zone: ZoneType): void;
/**
* Patch Node.js utilities
* @param Zone - Zone constructor
*/
function patchNodeUtil(Zone: ZoneType): void;Usage Examples:
// Node.js patches
import 'zone.js/node';
// Or load manually
Zone.__load_patch('node', (global, Zone, api) => {
patchNode(Zone);
});
// Patch specific Node.js APIs
Zone.__load_patch('events', (global, Zone, api) => {
patchEvents(Zone);
});
Zone.__load_patch('fs', (global, Zone, api) => {
patchFs(Zone);
});Extended patches for modern web APIs.
/**
* Patch Canvas API
* @param Zone - Zone constructor
*/
function patchCanvas(Zone: ZoneType): void;
/**
* Patch MessagePort API
* @param Zone - Zone constructor
*/
function patchMessagePort(Zone: ZoneType): void;
/**
* Patch MediaQuery API
* @param Zone - Zone constructor
*/
function patchMediaQuery(Zone: ZoneType): void;
/**
* Patch Notification API
* @param Zone - Zone constructor
*/
function patchNotifications(Zone: ZoneType): void;
/**
* Patch ResizeObserver API
* @param Zone - Zone constructor
*/
function patchResizeObserver(Zone: ZoneType): void;
/**
* Patch WebRTC PeerConnection API
* @param Zone - Zone constructor
*/
function patchRtcPeerConnection(Zone: ZoneType): void;
/**
* Patch getUserMedia API
* @param Zone - Zone constructor
*/
function patchUserMedia(Zone: ZoneType): void;
/**
* Patch WebSocket API
* @param global - Global object
* @param api - ZonePrivate API
*/
function apply(api: ZonePrivate, global: any): void;Usage Examples:
import 'zone.js';
// Load specific web API patches
Zone.__load_patch('canvas', (global, Zone, api) => {
patchCanvas(Zone);
});
Zone.__load_patch('webapis-notification', (global, Zone, api) => {
patchNotifications(Zone);
});
Zone.__load_patch('webapis-resize-observer', (global, Zone, api) => {
patchResizeObserver(Zone);
});
// Use patched APIs - zone context is preserved
const myZone = Zone.current.fork({ name: 'web-api-zone' });
myZone.run(() => {
// Notification API preserves zone context
new Notification('Test', {
body: 'Zone context preserved'
});
// ResizeObserver preserves zone context
const observer = new ResizeObserver((entries) => {
console.log('ResizeObserver in:', Zone.current.name); // 'web-api-zone'
});
observer.observe(document.body);
});Patches for test frameworks and libraries.
/**
* Patch Jasmine testing framework
* @param Zone - Zone constructor
*/
function patchJasmine(Zone: ZoneType): void;
/**
* Patch Jest testing framework
* @param Zone - Zone constructor
*/
function patchJest(Zone: ZoneType): void;
/**
* Patch Mocha testing framework
* @param Zone - Zone constructor
*/
function patchMocha(Zone: ZoneType): void;
/**
* Patch RxJS library
* @param Zone - Zone constructor
*/
function patchRxJs(Zone: ZoneType): void;Usage Examples:
// Framework patches are typically loaded with testing bundle
import 'zone.js/testing'; // Includes Jasmine patches
// Manual framework patching
Zone.__load_patch('jasmine', (global, Zone, api) => {
patchJasmine(Zone);
});
Zone.__load_patch('rxjs', (global, Zone, api) => {
patchRxJs(Zone);
});Utilities for developing custom patches.
/**
* Patch object properties for event handlers
* @param obj - Object to patch
* @param properties - Properties to patch
* @param prototype - Prototype to patch (optional)
*/
function patchOnProperties(obj: any, properties: string[] | null, prototype?: any): void;
/**
* Patch a single property
* @param obj - Object to patch
* @param prop - Property name to patch
* @param prototype - Prototype to patch (optional)
*/
function patchProperty(obj: any, prop: string, prototype?: any): void;
/**
* Patch method with zone awareness
* @param target - Object containing the method
* @param name - Method name
* @param patchFn - Function that returns the patched method
*/
function patchMethod(target: any, name: string, patchFn: Function): Function | null;
/**
* Patch microtask method
* @param obj - Object to patch
* @param funcName - Function name
* @param metaCreator - Function to create task metadata
*/
function patchMicroTask(obj: any, funcName: string, metaCreator: Function): void;
/**
* Patch macrotask method
* @param obj - Object to patch
* @param funcName - Function name
* @param metaCreator - Function to create task metadata
*/
function patchMacroTask(obj: any, funcName: string, metaCreator: Function): void;Usage Examples:
// Custom patch for a third-party library
Zone.__load_patch('custom-library', (global, Zone, api) => {
const CustomLib = global.CustomLib;
if (!CustomLib) return;
// Patch event properties
api.patchOnProperties(CustomLib.prototype, ['ondata', 'onerror', 'onend']);
// Patch async method
api.patchMethod(CustomLib.prototype, 'asyncMethod', (delegate, delegateName, name) => {
return function(this: any, ...args: any[]) {
const callback = args[args.length - 1];
if (typeof callback === 'function') {
args[args.length - 1] = api.wrapWithCurrentZone(callback, `${name}_callback`);
}
return delegate.apply(this, args);
};
});
// Patch timer-like method
api.patchMacroTask(CustomLib.prototype, 'delayedCall', (self: any, args: any[]) => {
return {
source: 'CustomLib.delayedCall',
delay: args[1] || 0,
callback: args[0],
args: []
};
});
});
// Use the patched library
const myZone = Zone.current.fork({ name: 'custom-lib-zone' });
myZone.run(() => {
const lib = new CustomLib();
// Event handlers preserve zone context
lib.ondata = (data) => {
console.log('Data received in:', Zone.current.name); // 'custom-lib-zone'
};
// Async methods preserve zone context
lib.asyncMethod((result) => {
console.log('Async result in:', Zone.current.name); // 'custom-lib-zone'
});
});Common utilities used in patch development.
/**
* Wrap callback with current zone context
* @param callback - Function to wrap
* @param source - Debug identifier
* @returns Wrapped function
*/
function wrapWithCurrentZone<T extends Function>(callback: T, source: string): T;
/**
* Generate zone symbol with prefix
* @param name - Symbol name
* @returns Prefixed symbol string
*/
function zoneSymbol(name: string): string;
/**
* Check if property is writable
* @param propertyDesc - Property descriptor
* @returns true if property is writable
*/
function isPropertyWritable(propertyDesc: any): boolean;
/**
* Copy symbol properties from source to destination
* @param src - Source object
* @param dest - Destination object
*/
function copySymbolProperties(src: any, dest: any): void;
/**
* Attach origin reference to patched function
* @param patched - Patched function
* @param original - Original function
*/
function attachOriginToPatched(patched: Function, original: any): void;Usage Examples:
// Utility usage in custom patches
Zone.__load_patch('utilities-example', (global, Zone, api) => {
const originalSetTimeout = global.setTimeout;
const timeoutSymbol = api.symbol('setTimeout');
// Store original function
global[timeoutSymbol] = originalSetTimeout;
// Create wrapped version
global.setTimeout = function(callback: Function, delay: number, ...args: any[]) {
const wrappedCallback = api.wrapWithCurrentZone(callback, 'setTimeout');
return originalSetTimeout.call(this, wrappedCallback, delay, ...args);
};
// Attach origin reference
api.attachOriginToPatched(global.setTimeout, originalSetTimeout);
// Copy any symbol properties
api.copySymbolProperties(originalSetTimeout, global.setTimeout);
});Install with Tessl CLI
npx tessl i tessl/npm-zone-js