Skip to content

Commit

Permalink
feat(VmTurnZone): VmTurnZone can handle scheduling microtasks.
Browse files Browse the repository at this point in the history
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 dart-archive#976
  • Loading branch information
mvuksano committed Apr 29, 2014
1 parent b45ef59 commit 93b05bd
Show file tree
Hide file tree
Showing 2 changed files with 82 additions and 0 deletions.
8 changes: 8 additions & 0 deletions lib/core/zone.dart
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ typedef void ZoneOnTurnDone();
*/
typedef void ZoneOnTurnStart();

typedef void ZoneScheduleMicrotask(fn());

/**
* Handles an [VmTurnZone] onError event.
*/
Expand Down Expand Up @@ -58,6 +60,8 @@ class VmTurnZone {
/// an "inner" [Zone], which is a child of the outer [Zone].
async.Zone _innerZone;

ZoneScheduleMicrotask onScheduleMicrotask;

/**
* Associates with this
*
Expand Down Expand Up @@ -108,6 +112,10 @@ class VmTurnZone {

_onScheduleMicrotask(async.Zone self, async.ZoneDelegate delegate,
async.Zone zone, fn()) {
if (onScheduleMicrotask != null) {
return onScheduleMicrotask(fn);
}

_asyncQueue.add(() => delegate.run(zone, fn));
if (_runningInTurn == 0 && !_inFinishTurn) _finishTurn(zone, delegate);
}
Expand Down
74 changes: 74 additions & 0 deletions test/core/zone_spec.dart
Original file line number Diff line number Diff line change
Expand Up @@ -435,5 +435,79 @@ void main() {
microLeap();
})).toThrow('ssertion'); // Support both dart2js and the VM with half a word.
});

it('should allow Scope to handle scheduling of microtasks', async((Logger log) {
var microtaskResult = false;
zone.onTurnStart = () {
log('onTurnStart(begin)');
log('onTurnStart(end)');
};
zone.onTurnDone = () {
log('onTurnDone(begin)');
scheduleMicrotask(() {
log('executeMicrotask');
return true;
});
log('onTurnDone(end)');
};
zone.onScheduleMicrotask = (microTaskFn) {
log('onScheduleMicrotask(begin)');
microtaskResult = microTaskFn();
log('onScheduleMicrotask(end)');
};
zone.run(() {
log('run');
});
microLeap();

expect(log.result()).toEqual('onTurnStart(begin); onTurnStart(end); run; onTurnDone(begin); onScheduleMicrotask(begin); executeMicrotask; onScheduleMicrotask(end); onTurnDone(end)');
expect(microtaskResult).toBeTruthy();
}));

it('should allow Scope to handle Future.microtask too', async((Logger log) {
zone.onTurnStart = () {
log('onTurnStart(begin)');
log('onTurnStart(end)');
};
zone.onTurnDone = () {
log('onTurnDone(begin)');
new Future.microtask(() => log('schedule from future'));
log('onTurnDone(end)');
};
zone.onScheduleMicrotask = (microTaskFn) {
log('onScheduleMicrotask(begin)');
microTaskFn();
log('onScheduleMicrotask(end)');
};
zone.run(() {
log('run');
});
microLeap();

expect(log.result()).toEqual('onTurnStart(begin); onTurnStart(end); run; onTurnDone(begin); onScheduleMicrotask(begin); schedule from future; onScheduleMicrotask(end); onTurnDone(end)');
}));

it('should allow Scope to handle Future.value too', async((Logger log) {
zone.onTurnStart = () {
log('onTurnStart(begin)');
log('onTurnStart(end)');
};
zone.onTurnDone = () {
log('onTurnDone(begin)');
new Future.value('async').then((v) => log('executed ${v}'));
log('onTurnDone(end)');
};
zone.onScheduleMicrotask = (microTaskFn) {
log('onScheduleMicrotask(begin)');
microTaskFn();
log('onScheduleMicrotask(end)');
};
zone.run(() {
log('run');
});
microLeap();

expect(log.result()).toEqual('onTurnStart(begin); onTurnStart(end); run; onTurnDone(begin); onScheduleMicrotask(begin); onScheduleMicrotask(end); onScheduleMicrotask(begin); executed async; onScheduleMicrotask(end); onTurnDone(end)');
}));
});
}

0 comments on commit 93b05bd

Please sign in to comment.