Skip to content

Commit 27358eb

Browse files
JiaLiPassionmhevery
authored andcommitted
feat(zone.js): monkey patches queueMicrotask() (#38904)
Close #38863 Monkey patches `queueMicrotask()` API, so the callback runs in the zone when scheduled, and also the task is run as `microTask`. ``` Zone.current.fork({ name: 'queueMicrotask', onScheduleTask: (delegate: ZoneDelegate, curr: Zone, target: Zone, task: Task) => { logs.push(task.type); logs.push(task.source); return delegate.scheduleTask(target, task); } }).run(() => { queueMicrotask(() => { expect(logs).toEqual(['microTask', 'queueMicrotask']); expect(Zone.current.name).toEqual('queueMicrotask'); done(); }); }); ``` PR Close #38904
1 parent 6138bc2 commit 27358eb

File tree

5 files changed

+74
-3
lines changed

5 files changed

+74
-3
lines changed

goldens/size-tracking/integration-payloads.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
"uncompressed": {
55
"runtime-es2015": 1485,
66
"main-es2015": 140899,
7-
"polyfills-es2015": 36571
7+
"polyfills-es2015": 36964
88
}
99
}
1010
},
@@ -22,7 +22,7 @@
2222
"uncompressed": {
2323
"runtime-es2015": 1485,
2424
"main-es2015": 146698,
25-
"polyfills-es2015": 36571
25+
"polyfills-es2015": 36964
2626
}
2727
}
2828
},
@@ -31,7 +31,7 @@
3131
"uncompressed": {
3232
"runtime-es2015": 1485,
3333
"main-es2015": 136062,
34-
"polyfills-es2015": 37392
34+
"polyfills-es2015": 37641
3535
}
3636
}
3737
},

packages/zone.js/lib/browser/browser.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,15 @@ Zone.__load_patch('legacy', (global: any) => {
2525
}
2626
});
2727

28+
Zone.__load_patch('queueMicrotask', (global: any, Zone: ZoneType, api: _ZonePrivate) => {
29+
api.patchMethod(global, 'queueMicrotask', delegate => {
30+
return function(self: any, args: any[]) {
31+
Zone.current.scheduleMicroTask('queueMicrotask', args[0]);
32+
}
33+
});
34+
});
35+
36+
2837
Zone.__load_patch('timers', (global: any) => {
2938
const set = 'set';
3039
const clear = 'clear';

packages/zone.js/lib/zone.configurations.api.ts

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -294,6 +294,34 @@ interface ZoneGlobalConfigurations {
294294
*/
295295
__Zone_disable_requestAnimationFrame?: boolean;
296296

297+
/**
298+
*
299+
* Disable the monkey patching of the browser's `queueMicrotask()` API.
300+
*
301+
* By default, `zone.js` monkey patches the browser's `queueMicrotask()` API
302+
* to ensure that `queueMicrotask()` callback is invoked in the same zone as zone used to invoke
303+
* `queueMicrotask()`. And also the callback is running as `microTask` like
304+
* `Promise.prototype.then()`.
305+
*
306+
* Consider the following example:
307+
*
308+
* ```
309+
* const zone = Zone.current.fork({name: 'myZone'});
310+
* zone.run(() => {
311+
* queueMicrotask(() => {
312+
* console.log('queueMicrotask() callback is invoked in the zone', Zone.current.name);
313+
* // Since `queueMicrotask()` was invoked in `myZone`, same zone is restored
314+
* // when 'queueMicrotask() callback is invoked, resulting in `myZone` being console logged.
315+
* });
316+
* });
317+
* ```
318+
*
319+
* If you set `__Zone_disable_queueMicrotask = true` before importing `zone.js`,
320+
* `zone.js` does not monkey patch the `queueMicrotask()` API and the above code
321+
* output will change to: 'queueMicrotask() callback is invoked in the zone <root>'.
322+
*/
323+
__Zone_disable_queueMicrotask?: boolean;
324+
297325
/**
298326
*
299327
* Disable the monkey patch of the browser blocking APIs(`alert()`/`prompt()`/`confirm()`).
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
/**
2+
* @license
3+
* Copyright Google LLC All Rights Reserved.
4+
*
5+
* Use of this source code is governed by an MIT-style license that can be
6+
* found in the LICENSE file at https://angular.io/license
7+
*/
8+
9+
import {ifEnvSupports} from '../test-util';
10+
11+
describe(
12+
'queueMicrotask', ifEnvSupports('queueMicrotask', function() {
13+
it('callback in the queueMicrotask should be scheduled as microTask in the zone',
14+
(done: DoneFn) => {
15+
const logs: string[] = [];
16+
Zone.current
17+
.fork({
18+
name: 'queueMicrotask',
19+
onScheduleTask: (delegate: ZoneDelegate, curr: Zone, target: Zone, task: Task) => {
20+
logs.push(task.type);
21+
logs.push(task.source);
22+
return delegate.scheduleTask(target, task);
23+
}
24+
})
25+
.run(() => {
26+
queueMicrotask(() => {
27+
expect(logs).toEqual(['microTask', 'queueMicrotask']);
28+
expect(Zone.current.name).toEqual('queueMicrotask');
29+
done();
30+
});
31+
});
32+
});
33+
}));

packages/zone.js/test/browser_entry_point.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,3 +29,4 @@ import './mocha-patch.spec';
2929
import './jasmine-patch.spec';
3030
import './browser/messageport.spec';
3131
import './extra/cordova.spec';
32+
import './browser/queue-microtask.spec';

0 commit comments

Comments
 (0)