Execution context library that persists across asynchronous operations for JavaScript applications
npx @tessl/cli install tessl/npm-zone-js@0.15.0Zone.js is an execution context library that persists across asynchronous operations, providing a mechanism to intercept and track asynchronous work. It implements the Zone concept inspired by Dart, enabling applications to maintain execution context across async boundaries such as setTimeout, Promise, DOM events, and XMLHttpRequest.
npm install zone.jsimport 'zone.js'; // Loads main zone.js with patchesFor specific bundles:
import 'zone.js/testing'; // Testing utilities
import 'zone.js/node'; // Node.js environment
import 'zone.js/mix'; // Mixed browser/node environmentCommonJS:
require('zone.js');
require('zone.js/testing');import 'zone.js';
// Get current zone
const currentZone = Zone.current;
console.log('Current zone:', currentZone.name);
// Create a new zone with custom properties
const myZone = Zone.current.fork({
name: 'myZone',
properties: { userId: 123 }
});
// Run code in the zone
myZone.run(() => {
console.log('Zone name:', Zone.current.name); // 'myZone'
console.log('User ID:', Zone.current.get('userId')); // 123
// Async operations maintain zone context
setTimeout(() => {
console.log('Still in zone:', Zone.current.name); // 'myZone'
}, 100);
});Zone.js is built around several key components:
Zone creation, execution context management, and basic zone operations for maintaining execution state across asynchronous boundaries.
interface Zone {
readonly parent: Zone | null;
readonly name: string;
get(key: string): any;
getZoneWith(key: string): Zone | null;
fork(zoneSpec: ZoneSpec): Zone;
wrap<F extends Function>(callback: F, source: string): F;
run<T>(callback: Function, applyThis?: any, applyArgs?: any[], source?: string): T;
runGuarded<T>(callback: Function, applyThis?: any, applyArgs?: any[], source?: string): T;
}
interface ZoneType {
readonly current: Zone;
readonly currentTask: Task | null;
readonly root: Zone;
assertZonePatched(): void;
__load_patch(name: string, fn: PatchFn, ignoreDuplicate?: boolean): void;
__symbol__(name: string): string;
}Zone configuration system for customizing zone behavior through lifecycle hooks, error handling, and task interception.
interface ZoneSpec {
name: string;
properties?: {[key: string]: any};
onFork?: (parentDelegate: ZoneDelegate, currentZone: Zone, targetZone: Zone, zoneSpec: ZoneSpec) => Zone;
onIntercept?: (parentDelegate: ZoneDelegate, currentZone: Zone, targetZone: Zone, delegate: Function, source: string) => Function;
onInvoke?: (parentDelegate: ZoneDelegate, currentZone: Zone, targetZone: Zone, delegate: Function, applyThis: any, applyArgs?: any[], source?: string) => any;
onHandleError?: (parentDelegate: ZoneDelegate, currentZone: Zone, targetZone: Zone, error: any) => boolean;
onScheduleTask?: (parentDelegate: ZoneDelegate, currentZone: Zone, targetZone: Zone, task: Task) => Task;
onInvokeTask?: (parentDelegate: ZoneDelegate, currentZone: Zone, targetZone: Zone, task: Task, applyThis: any, applyArgs?: any[]) => any;
onCancelTask?: (parentDelegate: ZoneDelegate, currentZone: Zone, targetZone: Zone, task: Task) => any;
onHasTask?: (parentDelegate: ZoneDelegate, currentZone: Zone, targetZone: Zone, hasTaskState: HasTaskState) => void;
}Asynchronous task scheduling and management system that categorizes async work into microtasks, macrotasks, and event tasks.
interface Task {
readonly type: TaskType;
state: TaskState;
readonly source: string;
readonly zone: Zone;
callback: Function;
data?: TaskData;
runCount: number;
cancelScheduleRequest(): void;
}
type TaskType = 'microTask' | 'macroTask' | 'eventTask';
type TaskState = 'notScheduled' | 'scheduling' | 'scheduled' | 'running' | 'canceling' | 'unknown';
interface MicroTask extends Task { type: 'microTask'; }
interface MacroTask extends Task { type: 'macroTask'; }
interface EventTask extends Task { type: 'eventTask'; }Comprehensive testing framework with fakeAsync, async testing zones, and task tracking for testing asynchronous code in a controlled environment.
function fakeAsync(fn: Function, options?: {flush?: boolean}): (...args: any[]) => any;
function tick(millis?: number, ignoreNestedTimeout?: boolean): void;
function flush(maxTurns?: number): number;
function flushMicrotasks(): void;
function discardPeriodicTasks(): void;
class FakeAsyncTestZoneSpec implements ZoneSpec {
name: 'fakeAsync';
tick(millis?: number, doTick?: (elapsed: number) => void): void;
flush(maxTurns?: number): number;
flushMicrotasks(): void;
}Monkey patching infrastructure for browser and Node.js APIs, enabling zone context preservation across various asynchronous operations.
type PatchFn = (global: Window, Zone: ZoneType, api: ZonePrivate) => void;
interface ZonePrivate {
patchEventTarget(global: any, api: ZonePrivate, apis: any[], options?: any): boolean[];
patchMethod(target: any, name: string, patchFn: Function): Function | null;
patchMacroTask(obj: any, funcName: string, metaCreator: Function): void;
patchOnProperties(obj: any, properties: string[] | null, prototype?: any): void;
bindArguments(args: any[], source: string): any[];
}Global configuration system for selectively disabling patches and customizing zone behavior across different environments and use cases.
interface ZoneGlobalConfigurations {
__Zone_disable_timers?: boolean;
__Zone_disable_Promise?: boolean;
__Zone_disable_EventTarget?: boolean;
__Zone_disable_requestAnimationFrame?: boolean;
__zone_symbol__UNPATCHED_EVENTS?: string[];
__zone_symbol__PASSIVE_EVENTS?: string[];
__Zone_ignore_on_properties?: Array<{target: any; ignoreProperties: string[]}>;
}interface ZoneDelegate {
readonly zone: Zone;
fork(targetZone: Zone, zoneSpec: ZoneSpec): Zone;
intercept(targetZone: Zone, callback: Function, source: string): Function;
invoke(targetZone: Zone, callback: Function, applyThis?: any, applyArgs?: any[], source?: string): any;
handleError(targetZone: Zone, error: any): boolean;
scheduleTask(targetZone: Zone, task: Task): Task;
invokeTask(targetZone: Zone, task: Task, applyThis?: any, applyArgs?: any[]): any;
cancelTask(targetZone: Zone, task: Task): any;
hasTask(targetZone: Zone, isEmpty: HasTaskState): void;
}
interface TaskData {
isPeriodic?: boolean;
isRefreshable?: boolean;
delay?: number;
handleId?: number;
handle?: any;
}
type HasTaskState = {
microTask: boolean;
macroTask: boolean;
eventTask: boolean;
change: TaskType;
};
interface UncaughtPromiseError extends Error {
zone: Zone;
task: Task;
promise: Promise<any>;
rejection: any;
throwOriginal?: boolean;
}