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
This commit is contained in:
parent
6138bc2774
commit
27358eb60f
|
@ -4,7 +4,7 @@
|
||||||
"uncompressed": {
|
"uncompressed": {
|
||||||
"runtime-es2015": 1485,
|
"runtime-es2015": 1485,
|
||||||
"main-es2015": 140899,
|
"main-es2015": 140899,
|
||||||
"polyfills-es2015": 36571
|
"polyfills-es2015": 36964
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -22,7 +22,7 @@
|
||||||
"uncompressed": {
|
"uncompressed": {
|
||||||
"runtime-es2015": 1485,
|
"runtime-es2015": 1485,
|
||||||
"main-es2015": 146698,
|
"main-es2015": 146698,
|
||||||
"polyfills-es2015": 36571
|
"polyfills-es2015": 36964
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -31,7 +31,7 @@
|
||||||
"uncompressed": {
|
"uncompressed": {
|
||||||
"runtime-es2015": 1485,
|
"runtime-es2015": 1485,
|
||||||
"main-es2015": 136062,
|
"main-es2015": 136062,
|
||||||
"polyfills-es2015": 37392
|
"polyfills-es2015": 37641
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
@ -25,6 +25,15 @@ Zone.__load_patch('legacy', (global: any) => {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Zone.__load_patch('queueMicrotask', (global: any, Zone: ZoneType, api: _ZonePrivate) => {
|
||||||
|
api.patchMethod(global, 'queueMicrotask', delegate => {
|
||||||
|
return function(self: any, args: any[]) {
|
||||||
|
Zone.current.scheduleMicroTask('queueMicrotask', args[0]);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
Zone.__load_patch('timers', (global: any) => {
|
Zone.__load_patch('timers', (global: any) => {
|
||||||
const set = 'set';
|
const set = 'set';
|
||||||
const clear = 'clear';
|
const clear = 'clear';
|
||||||
|
|
|
@ -294,6 +294,34 @@ interface ZoneGlobalConfigurations {
|
||||||
*/
|
*/
|
||||||
__Zone_disable_requestAnimationFrame?: boolean;
|
__Zone_disable_requestAnimationFrame?: boolean;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Disable the monkey patching of the browser's `queueMicrotask()` API.
|
||||||
|
*
|
||||||
|
* By default, `zone.js` monkey patches the browser's `queueMicrotask()` API
|
||||||
|
* to ensure that `queueMicrotask()` callback is invoked in the same zone as zone used to invoke
|
||||||
|
* `queueMicrotask()`. And also the callback is running as `microTask` like
|
||||||
|
* `Promise.prototype.then()`.
|
||||||
|
*
|
||||||
|
* Consider the following example:
|
||||||
|
*
|
||||||
|
* ```
|
||||||
|
* const zone = Zone.current.fork({name: 'myZone'});
|
||||||
|
* zone.run(() => {
|
||||||
|
* queueMicrotask(() => {
|
||||||
|
* console.log('queueMicrotask() callback is invoked in the zone', Zone.current.name);
|
||||||
|
* // Since `queueMicrotask()` was invoked in `myZone`, same zone is restored
|
||||||
|
* // when 'queueMicrotask() callback is invoked, resulting in `myZone` being console logged.
|
||||||
|
* });
|
||||||
|
* });
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* If you set `__Zone_disable_queueMicrotask = true` before importing `zone.js`,
|
||||||
|
* `zone.js` does not monkey patch the `queueMicrotask()` API and the above code
|
||||||
|
* output will change to: 'queueMicrotask() callback is invoked in the zone <root>'.
|
||||||
|
*/
|
||||||
|
__Zone_disable_queueMicrotask?: boolean;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* Disable the monkey patch of the browser blocking APIs(`alert()`/`prompt()`/`confirm()`).
|
* Disable the monkey patch of the browser blocking APIs(`alert()`/`prompt()`/`confirm()`).
|
||||||
|
|
|
@ -0,0 +1,33 @@
|
||||||
|
/**
|
||||||
|
* @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.io/license
|
||||||
|
*/
|
||||||
|
|
||||||
|
import {ifEnvSupports} from '../test-util';
|
||||||
|
|
||||||
|
describe(
|
||||||
|
'queueMicrotask', ifEnvSupports('queueMicrotask', function() {
|
||||||
|
it('callback in the queueMicrotask should be scheduled as microTask in the zone',
|
||||||
|
(done: DoneFn) => {
|
||||||
|
const logs: string[] = [];
|
||||||
|
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();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}));
|
|
@ -29,3 +29,4 @@ import './mocha-patch.spec';
|
||||||
import './jasmine-patch.spec';
|
import './jasmine-patch.spec';
|
||||||
import './browser/messageport.spec';
|
import './browser/messageport.spec';
|
||||||
import './extra/cordova.spec';
|
import './extra/cordova.spec';
|
||||||
|
import './browser/queue-microtask.spec';
|
||||||
|
|
Loading…
Reference in New Issue