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

Commit eb121ac

Browse files
mvuksanojbdeboer
authored andcommitted
feat(VmTurnZone): VmTurnZone can handle scheduling microtasks.
To customize how VmTurnZone handles microtasks assign a function to VmTurnZone.onScheduleMicrotask. This method will then be used whenever a microtask is scheduled instead of the default implementation. Closes #976 Closes #979
1 parent 0199075 commit eb121ac

File tree

2 files changed

+115
-0
lines changed

2 files changed

+115
-0
lines changed

lib/core/zone.dart

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ typedef void ZoneOnTurnDone();
1010
*/
1111
typedef void ZoneOnTurnStart();
1212

13+
typedef void ZoneScheduleMicrotask(fn());
14+
1315
/**
1416
* Handles a [VmTurnZone] onError event.
1517
*/
@@ -58,6 +60,8 @@ class VmTurnZone {
5860
/// an "inner" [Zone], which is a child of the outer [Zone].
5961
async.Zone _innerZone;
6062

63+
ZoneScheduleMicrotask defaultOnScheduleMicrotask;
64+
6165
/**
6266
* Associates with this
6367
*
@@ -111,6 +115,10 @@ class VmTurnZone {
111115

112116
_onScheduleMicrotask(async.Zone self, async.ZoneDelegate delegate,
113117
async.Zone zone, fn()) {
118+
if (defaultOnScheduleMicrotask != null) {
119+
return defaultOnScheduleMicrotask(fn);
120+
}
121+
114122
_asyncQueue.add(() => delegate.run(zone, fn));
115123
if (_runningInTurn == 0 && !_inFinishTurn) _finishTurn(zone, delegate);
116124
}

test/core/zone_spec.dart

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -435,5 +435,112 @@ void main() {
435435
microLeap();
436436
})).toThrow('ssertion'); // Support both dart2js and the VM with half a word.
437437
});
438+
439+
group('microtask scheduler', () {
440+
441+
it('should execute microtask scheduled in onTurnDone before onTurnDone is complete',
442+
async((Logger log) {
443+
var microtaskResult = false;
444+
zone.onTurnStart = () {
445+
log('onTurnStart');
446+
};
447+
zone.onTurnDone = () {
448+
log('onTurnDone(begin)');
449+
scheduleMicrotask(() {
450+
log('executeMicrotask');
451+
return true;
452+
});
453+
log('onTurnDone(end)');
454+
};
455+
zone.defaultOnScheduleMicrotask = (microTaskFn) {
456+
log('onScheduleMicrotask(begin)');
457+
microtaskResult = microTaskFn();
458+
log('onScheduleMicrotask(end)');
459+
};
460+
zone.run(() {
461+
log('run');
462+
});
463+
464+
expect(log.result()).toEqual('onTurnStart; run; onTurnDone(begin); '
465+
'onScheduleMicrotask(begin); executeMicrotask; onScheduleMicrotask(end); onTurnDone(end)'
466+
);
467+
expect(microtaskResult).toBeTruthy();
468+
}));
469+
470+
it('should work with future scheduled in onTurnDone', async((Logger log) {
471+
zone.onTurnStart = () {
472+
log('onTurnStart');
473+
};
474+
zone.onTurnDone = () {
475+
log('onTurnDone(begin)');
476+
new Future.value('async').then((v) {
477+
log('executed ${v}');
478+
});
479+
log('onTurnDone(end)');
480+
};
481+
zone.defaultOnScheduleMicrotask = (microTaskFn) {
482+
log('onScheduleMicrotask(begin)');
483+
microTaskFn();
484+
log('onScheduleMicrotask(end)');
485+
};
486+
zone.run(() {
487+
log('run');
488+
});
489+
490+
expect(log.result()).toEqual('onTurnStart; run; onTurnDone(begin); '
491+
'onScheduleMicrotask(begin); onScheduleMicrotask(end); onScheduleMicrotask(begin);'
492+
' executed async; onScheduleMicrotask(end); onTurnDone(end)');
493+
}));
494+
495+
it('should execute microtask scheduled in run before onTurnDone starts',
496+
async((Logger log) {
497+
zone.onTurnStart = () {
498+
log('onTurnStart');
499+
};
500+
zone.onTurnDone = () {
501+
log('onTurnDone');
502+
};
503+
zone.defaultOnScheduleMicrotask = (microTaskFn) {
504+
log('onScheduleMicrotask(begin)');
505+
microTaskFn();
506+
log('onScheduleMicrotask(end)');
507+
};
508+
zone.run(() {
509+
log('run');
510+
scheduleMicrotask(() {
511+
log('executeMicrotask');
512+
return true;
513+
});
514+
});
515+
516+
expect(log.result()).toEqual('onTurnStart; run; onScheduleMicrotask(begin);'
517+
' executeMicrotask; onScheduleMicrotask(end); onTurnDone');
518+
}));
519+
520+
it('should execute microtask scheduled in onTurnStart before run',
521+
async((Logger log) {
522+
zone.onTurnStart = () {
523+
log('onTurnStart');
524+
scheduleMicrotask(() {
525+
log('executeMicrotask');
526+
});
527+
};
528+
zone.onTurnDone = () {
529+
log('onTurnDone');
530+
};
531+
zone.defaultOnScheduleMicrotask = (microTaskFn) {
532+
log('onScheduleMicrotask(begin)');
533+
microTaskFn();
534+
log('onScheduleMicrotask(end)');
535+
};
536+
zone.run(() {
537+
log('run');
538+
});
539+
540+
expect(log.result()).toEqual('onTurnStart; onScheduleMicrotask(begin); executeMicrotask;'
541+
' onScheduleMicrotask(end); run; onTurnDone');
542+
}));
543+
544+
});
438545
});
439546
}

0 commit comments

Comments
 (0)