Skip to content
This repository was archived by the owner on Feb 26, 2024. It is now read-only.

Commit 5258a1d

Browse files
committed
feat: make codebase more modular so that only parts of it can be loaded
1 parent 89132fd commit 5258a1d

File tree

13 files changed

+942
-869
lines changed

13 files changed

+942
-869
lines changed

karma-build.conf.js

+2
Original file line numberDiff line numberDiff line change
@@ -11,5 +11,7 @@ module.exports = function (config) {
1111
config.files.push('build/test/wtf_mock.js');
1212
config.files.push('build/test/custom_error.js');
1313
config.files.push('build/lib/zone.js');
14+
config.files.push('build/lib/common/promise.js');
15+
config.files.push('build/lib/common/error-rewrite.js');
1416
config.files.push('build/test/main.js');
1517
};

lib/browser/browser.ts

+164-151
Original file line numberDiff line numberDiff line change
@@ -15,168 +15,181 @@ import {eventTargetPatch} from './event-target';
1515
import {propertyDescriptorPatch} from './property-descriptor';
1616
import {registerElementPatch} from './register-element';
1717

18-
const set = 'set';
19-
const clear = 'clear';
20-
const blockingMethods = ['alert', 'prompt', 'confirm'];
21-
const _global: any =
22-
typeof window !== 'undefined' && window || typeof self !== 'undefined' && self || global;
23-
24-
patchTimer(_global, set, clear, 'Timeout');
25-
patchTimer(_global, set, clear, 'Interval');
26-
patchTimer(_global, set, clear, 'Immediate');
27-
patchTimer(_global, 'request', 'cancel', 'AnimationFrame');
28-
patchTimer(_global, 'mozRequest', 'mozCancel', 'AnimationFrame');
29-
patchTimer(_global, 'webkitRequest', 'webkitCancel', 'AnimationFrame');
30-
31-
for (let i = 0; i < blockingMethods.length; i++) {
32-
const name = blockingMethods[i];
33-
patchMethod(_global, name, (delegate, symbol, name) => {
34-
return function(s: any, args: any[]) {
35-
return Zone.current.run(delegate, _global, args, name);
36-
};
37-
});
38-
}
39-
40-
eventTargetPatch(_global);
41-
// patch XMLHttpRequestEventTarget's addEventListener/removeEventListener
42-
const XMLHttpRequestEventTarget = (_global as any)['XMLHttpRequestEventTarget'];
43-
if (XMLHttpRequestEventTarget && XMLHttpRequestEventTarget.prototype) {
44-
patchEventTargetMethods(XMLHttpRequestEventTarget.prototype);
45-
}
46-
propertyDescriptorPatch(_global);
47-
patchClass('MutationObserver');
48-
patchClass('WebKitMutationObserver');
49-
patchClass('FileReader');
50-
propertyPatch();
51-
registerElementPatch(_global);
52-
53-
// Treat XMLHTTPRequest as a macrotask.
54-
patchXHR(_global);
55-
56-
const XHR_TASK = zoneSymbol('xhrTask');
57-
const XHR_SYNC = zoneSymbol('xhrSync');
58-
const XHR_LISTENER = zoneSymbol('xhrListener');
59-
const XHR_SCHEDULED = zoneSymbol('xhrScheduled');
60-
61-
interface XHROptions extends TaskData {
62-
target: any;
63-
args: any[];
64-
aborted: boolean;
65-
}
66-
67-
function patchXHR(window: any) {
68-
function findPendingTask(target: any) {
69-
const pendingTask: Task = target[XHR_TASK];
70-
return pendingTask;
18+
Zone.__load_patch('timers', (global: any, Zone: ZoneType, api: _ZonePrivate) => {
19+
const set = 'set';
20+
const clear = 'clear';
21+
patchTimer(global, set, clear, 'Timeout');
22+
patchTimer(global, set, clear, 'Interval');
23+
patchTimer(global, set, clear, 'Immediate');
24+
patchTimer(global, 'request', 'cancel', 'AnimationFrame');
25+
patchTimer(global, 'mozRequest', 'mozCancel', 'AnimationFrame');
26+
patchTimer(global, 'webkitRequest', 'webkitCancel', 'AnimationFrame');
27+
});
28+
29+
Zone.__load_patch('blocking', (global: any, Zone: ZoneType, api: _ZonePrivate) => {
30+
const blockingMethods = ['alert', 'prompt', 'confirm'];
31+
for (let i = 0; i < blockingMethods.length; i++) {
32+
const name = blockingMethods[i];
33+
patchMethod(global, name, (delegate, symbol, name) => {
34+
return function(s: any, args: any[]) {
35+
return Zone.current.run(delegate, global, args, name);
36+
};
37+
});
38+
}
39+
});
40+
41+
Zone.__load_patch('EventTarget', (global: any, Zone: ZoneType, api: _ZonePrivate) => {
42+
eventTargetPatch(global);
43+
// patch XMLHttpRequestEventTarget's addEventListener/removeEventListener
44+
const XMLHttpRequestEventTarget = (global as any)['XMLHttpRequestEventTarget'];
45+
if (XMLHttpRequestEventTarget && XMLHttpRequestEventTarget.prototype) {
46+
patchEventTargetMethods(XMLHttpRequestEventTarget.prototype);
47+
}
48+
propertyDescriptorPatch(global);
49+
patchClass('MutationObserver');
50+
patchClass('WebKitMutationObserver');
51+
patchClass('FileReader');
52+
propertyPatch();
53+
registerElementPatch(global);
54+
});
55+
56+
Zone.__load_patch('XHR', (global: any, Zone: ZoneType, api: _ZonePrivate) => {
57+
// Treat XMLHTTPRequest as a macrotask.
58+
patchXHR(global);
59+
60+
const XHR_TASK = zoneSymbol('xhrTask');
61+
const XHR_SYNC = zoneSymbol('xhrSync');
62+
const XHR_LISTENER = zoneSymbol('xhrListener');
63+
const XHR_SCHEDULED = zoneSymbol('xhrScheduled');
64+
65+
interface XHROptions extends TaskData {
66+
target: any;
67+
args: any[];
68+
aborted: boolean;
7169
}
7270

73-
function scheduleTask(task: Task) {
74-
(XMLHttpRequest as any)[XHR_SCHEDULED] = false;
75-
const data = <XHROptions>task.data;
76-
// remove existing event listener
77-
const listener = data.target[XHR_LISTENER];
78-
if (listener) {
79-
data.target.removeEventListener('readystatechange', listener);
71+
function patchXHR(window: any) {
72+
function findPendingTask(target: any) {
73+
const pendingTask: Task = target[XHR_TASK];
74+
return pendingTask;
8075
}
81-
const newListener = data.target[XHR_LISTENER] = () => {
82-
if (data.target.readyState === data.target.DONE) {
83-
// sometimes on some browsers XMLHttpRequest will fire onreadystatechange with
84-
// readyState=4 multiple times, so we need to check task state here
85-
if (!data.aborted && (XMLHttpRequest as any)[XHR_SCHEDULED] && task.state === 'scheduled') {
86-
task.invoke();
87-
}
76+
77+
function scheduleTask(task: Task) {
78+
(XMLHttpRequest as any)[XHR_SCHEDULED] = false;
79+
const data = <XHROptions>task.data;
80+
// remove existing event listener
81+
const listener = data.target[XHR_LISTENER];
82+
if (listener) {
83+
data.target.removeEventListener('readystatechange', listener);
8884
}
89-
};
90-
data.target.addEventListener('readystatechange', newListener);
85+
const newListener = data.target[XHR_LISTENER] = () => {
86+
if (data.target.readyState === data.target.DONE) {
87+
// sometimes on some browsers XMLHttpRequest will fire onreadystatechange with
88+
// readyState=4 multiple times, so we need to check task state here
89+
if (!data.aborted && (XMLHttpRequest as any)[XHR_SCHEDULED] &&
90+
task.state === 'scheduled') {
91+
task.invoke();
92+
}
93+
}
94+
};
95+
data.target.addEventListener('readystatechange', newListener);
9196

92-
const storedTask: Task = data.target[XHR_TASK];
93-
if (!storedTask) {
94-
data.target[XHR_TASK] = task;
97+
const storedTask: Task = data.target[XHR_TASK];
98+
if (!storedTask) {
99+
data.target[XHR_TASK] = task;
100+
}
101+
sendNative.apply(data.target, data.args);
102+
(XMLHttpRequest as any)[XHR_SCHEDULED] = true;
103+
return task;
95104
}
96-
sendNative.apply(data.target, data.args);
97-
(XMLHttpRequest as any)[XHR_SCHEDULED] = true;
98-
return task;
99-
}
100105

101-
function placeholderCallback() {}
106+
function placeholderCallback() {}
102107

103-
function clearTask(task: Task) {
104-
const data = <XHROptions>task.data;
105-
// Note - ideally, we would call data.target.removeEventListener here, but it's too late
106-
// to prevent it from firing. So instead, we store info for the event listener.
107-
data.aborted = true;
108-
return abortNative.apply(data.target, data.args);
109-
}
110-
111-
const openNative: Function =
112-
patchMethod(window.XMLHttpRequest.prototype, 'open', () => function(self: any, args: any[]) {
113-
self[XHR_SYNC] = args[2] == false;
114-
return openNative.apply(self, args);
115-
});
116-
117-
const sendNative: Function =
118-
patchMethod(window.XMLHttpRequest.prototype, 'send', () => function(self: any, args: any[]) {
119-
const zone = Zone.current;
120-
if (self[XHR_SYNC]) {
121-
// if the XHR is sync there is no task to schedule, just execute the code.
122-
return sendNative.apply(self, args);
123-
} else {
124-
const options: XHROptions =
125-
{target: self, isPeriodic: false, delay: null, args: args, aborted: false};
126-
return zone.scheduleMacroTask(
127-
'XMLHttpRequest.send', placeholderCallback, options, scheduleTask, clearTask);
128-
}
129-
});
108+
function clearTask(task: Task) {
109+
const data = <XHROptions>task.data;
110+
// Note - ideally, we would call data.target.removeEventListener here, but it's too late
111+
// to prevent it from firing. So instead, we store info for the event listener.
112+
data.aborted = true;
113+
return abortNative.apply(data.target, data.args);
114+
}
130115

131-
const abortNative = patchMethod(
132-
window.XMLHttpRequest.prototype, 'abort',
133-
(delegate: Function) => function(self: any, args: any[]) {
134-
const task: Task = findPendingTask(self);
135-
if (task && typeof task.type == 'string') {
136-
// If the XHR has already completed, do nothing.
137-
// If the XHR has already been aborted, do nothing.
138-
// Fix #569, call abort multiple times before done will cause
139-
// macroTask task count be negative number
140-
if (task.cancelFn == null || (task.data && (<XHROptions>task.data).aborted)) {
141-
return;
116+
const openNative: Function = patchMethod(
117+
window.XMLHttpRequest.prototype, 'open', () => function(self: any, args: any[]) {
118+
self[XHR_SYNC] = args[2] == false;
119+
return openNative.apply(self, args);
120+
});
121+
122+
const sendNative: Function = patchMethod(
123+
window.XMLHttpRequest.prototype, 'send', () => function(self: any, args: any[]) {
124+
const zone = Zone.current;
125+
if (self[XHR_SYNC]) {
126+
// if the XHR is sync there is no task to schedule, just execute the code.
127+
return sendNative.apply(self, args);
128+
} else {
129+
const options: XHROptions =
130+
{target: self, isPeriodic: false, delay: null, args: args, aborted: false};
131+
return zone.scheduleMacroTask(
132+
'XMLHttpRequest.send', placeholderCallback, options, scheduleTask, clearTask);
142133
}
143-
task.zone.cancelTask(task);
134+
});
135+
136+
const abortNative = patchMethod(
137+
window.XMLHttpRequest.prototype, 'abort',
138+
(delegate: Function) => function(self: any, args: any[]) {
139+
const task: Task = findPendingTask(self);
140+
if (task && typeof task.type == 'string') {
141+
// If the XHR has already completed, do nothing.
142+
// If the XHR has already been aborted, do nothing.
143+
// Fix #569, call abort multiple times before done will cause
144+
// macroTask task count be negative number
145+
if (task.cancelFn == null || (task.data && (<XHROptions>task.data).aborted)) {
146+
return;
147+
}
148+
task.zone.cancelTask(task);
149+
}
150+
// Otherwise, we are trying to abort an XHR which has not yet been sent, so there is no
151+
// task
152+
// to cancel. Do nothing.
153+
});
154+
}
155+
});
156+
157+
Zone.__load_patch('geo', (global: any, Zone: ZoneType, api: _ZonePrivate) => {
158+
/// GEO_LOCATION
159+
if (global['navigator'] && global['navigator'].geolocation) {
160+
patchPrototype(global['navigator'].geolocation, ['getCurrentPosition', 'watchPosition']);
161+
}
162+
});
163+
164+
Zone.__load_patch('toString', (global: any, Zone: ZoneType, api: _ZonePrivate) => {
165+
// patch Func.prototype.toString to let them look like native
166+
patchFuncToString();
167+
// patch Object.prototype.toString to let them look like native
168+
patchObjectToString();
169+
});
170+
171+
Zone.__load_patch('promiseRejectionHandler', (global: any, Zone: ZoneType, api: _ZonePrivate) => {
172+
// handle unhandled promise rejection
173+
function findPromiseRejectionHandler(evtName: string) {
174+
return function(e: any) {
175+
const eventTasks = findEventTask(global, evtName);
176+
eventTasks.forEach(eventTask => {
177+
// windows has added unhandledrejection event listener
178+
// trigger the event listener
179+
const PromiseRejectionEvent = global['PromiseRejectionEvent'];
180+
if (PromiseRejectionEvent) {
181+
const evt = new PromiseRejectionEvent(evtName, {promise: e.promise, reason: e.rejection});
182+
eventTask.invoke(evt);
144183
}
145-
// Otherwise, we are trying to abort an XHR which has not yet been sent, so there is no task
146-
// to cancel. Do nothing.
147184
});
148-
}
149-
150-
/// GEO_LOCATION
151-
if (_global['navigator'] && _global['navigator'].geolocation) {
152-
patchPrototype(_global['navigator'].geolocation, ['getCurrentPosition', 'watchPosition']);
153-
}
154-
155-
// patch Func.prototype.toString to let them look like native
156-
patchFuncToString();
157-
// patch Object.prototype.toString to let them look like native
158-
patchObjectToString();
159-
160-
// handle unhandled promise rejection
161-
function findPromiseRejectionHandler(evtName: string) {
162-
return function(e: any) {
163-
const eventTasks = findEventTask(_global, evtName);
164-
eventTasks.forEach(eventTask => {
165-
// windows has added unhandledrejection event listener
166-
// trigger the event listener
167-
const PromiseRejectionEvent = _global['PromiseRejectionEvent'];
168-
if (PromiseRejectionEvent) {
169-
const evt = new PromiseRejectionEvent(evtName, {promise: e.promise, reason: e.rejection});
170-
eventTask.invoke(evt);
171-
}
172-
});
173-
};
174-
}
185+
};
186+
}
175187

176-
if (_global['PromiseRejectionEvent']) {
177-
(Zone as any)[zoneSymbol('unhandledPromiseRejectionHandler')] =
178-
findPromiseRejectionHandler('unhandledrejection');
188+
if (global['PromiseRejectionEvent']) {
189+
(Zone as any)[zoneSymbol('unhandledPromiseRejectionHandler')] =
190+
findPromiseRejectionHandler('unhandledrejection');
179191

180-
(Zone as any)[zoneSymbol('rejectionHandledHandler')] =
181-
findPromiseRejectionHandler('rejectionhandled');
182-
}
192+
(Zone as any)[zoneSymbol('rejectionHandledHandler')] =
193+
findPromiseRejectionHandler('rejectionhandled');
194+
}
195+
});

lib/browser/rollup-main.ts

+3-1
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,6 @@
88

99

1010
import '../zone';
11-
import './browser';
11+
import '../common/promise';
12+
import '../common/error-rewrite';
13+
import './browser';

lib/browser/websocket.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,6 @@ export function apply(_global: any) {
3939
return proxySocket;
4040
};
4141
for (const prop in WS) {
42-
_global.WebSocket[prop] = WS[prop];
42+
_global['WebSocket'][prop] = WS[prop];
4343
}
4444
}

0 commit comments

Comments
 (0)