Skip to content

Commit

Permalink
fix: animationFrameScheduler and asapScheduler no longer executing ac…
Browse files Browse the repository at this point in the history
…tions

Fixes #6854
  • Loading branch information
ajafff committed Mar 14, 2022
1 parent ef416f0 commit 4319c90
Show file tree
Hide file tree
Showing 4 changed files with 48 additions and 6 deletions.
23 changes: 22 additions & 1 deletion spec/schedulers/AnimationFrameScheduler-spec.ts
@@ -1,6 +1,6 @@
import { expect } from 'chai';
import * as sinon from 'sinon';
import { animationFrameScheduler, Subscription, merge } from 'rxjs';
import {animationFrameScheduler, Subscription, merge, SchedulerAction} from 'rxjs';
import { delay } from 'rxjs/operators';
import { TestScheduler } from 'rxjs/testing';
import { observableMatcher } from '../helpers/observableMatcher';
Expand Down Expand Up @@ -238,4 +238,25 @@ describe('Scheduler.animationFrame', () => {
done();
});
});

it('should handle actions scheduled during flush before current action is rescheduled', (done) => {
const sandbox = sinon.createSandbox();

const result: string[] = [];
let reschedule = true;
function work(this: SchedulerAction<unknown>) {
result.push('work');
if (reschedule) {
animationFrameScheduler.schedule(() => result.push('task 1'));
animationFrameScheduler.schedule(() => result.push('task 2'));
this.schedule();
reschedule = false;
} else {
expect(result).to.deep.equal(['work', 'task 1', 'task 2', 'work']);
sandbox.restore();
done();
}
}
animationFrameScheduler.schedule(work);
});
});
23 changes: 22 additions & 1 deletion spec/schedulers/AsapScheduler-spec.ts
@@ -1,6 +1,6 @@
import { expect } from 'chai';
import * as sinon from 'sinon';
import { asapScheduler, Subscription, SchedulerAction, merge } from 'rxjs';
import {asapScheduler, Subscription, SchedulerAction, merge, animationFrameScheduler} from 'rxjs';
import { delay } from 'rxjs/operators';
import { TestScheduler } from 'rxjs/testing';
import { observableMatcher } from '../helpers/observableMatcher';
Expand Down Expand Up @@ -288,4 +288,25 @@ describe('Scheduler.asap', () => {
done();
});
});

it('should handle actions scheduled during flush before current action is rescheduled', (done) => {
const sandbox = sinon.createSandbox();

const result: string[] = [];
let reschedule = true;
function work(this: SchedulerAction<unknown>) {
result.push('work');
if (reschedule) {
asapScheduler.schedule(() => result.push('task 1'));
asapScheduler.schedule(() => result.push('task 2'));
this.schedule();
reschedule = false;
} else {
expect(result).to.deep.equal(['work', 'task 1', 'task 2', 'work']);
sandbox.restore();
done();
}
}
asapScheduler.schedule(work);
});
});
4 changes: 2 additions & 2 deletions src/internal/scheduler/AnimationFrameAction.ts
Expand Up @@ -27,10 +27,10 @@ export class AnimationFrameAction<T> extends AsyncAction<T> {
if ((delay != null && delay > 0) || (delay == null && this.delay > 0)) {
return super.recycleAsyncId(scheduler, id, delay);
}
// If the scheduler queue has no remaining actions with the same async id,
// If the scheduler queue has no remaining actions for the next schedule,
// cancel the requested animation frame and set the scheduled flag to
// undefined so the next AnimationFrameAction will request its own.
if (!scheduler.actions.some((action) => action.id === id)) {
if (scheduler._scheduled === id && !scheduler.actions.some((action) => action.id === id)) {
animationFrameProvider.cancelAnimationFrame(id);
scheduler._scheduled = undefined;
}
Expand Down
4 changes: 2 additions & 2 deletions src/internal/scheduler/AsapAction.ts
Expand Up @@ -27,10 +27,10 @@ export class AsapAction<T> extends AsyncAction<T> {
if ((delay != null && delay > 0) || (delay == null && this.delay > 0)) {
return super.recycleAsyncId(scheduler, id, delay);
}
// If the scheduler queue has no remaining actions with the same async id,
// If the scheduler queue has no remaining actions for the next schedule,
// cancel the requested microtask and set the scheduled flag to undefined
// so the next AsapAction will request its own.
if (!scheduler.actions.some((action) => action.id === id)) {
if (scheduler._scheduled === id && !scheduler.actions.some((action) => action.id === id)) {
immediateProvider.clearImmediate(id);
scheduler._scheduled = undefined;
}
Expand Down

0 comments on commit 4319c90

Please sign in to comment.