pull/4999/head
pushkine 5 years ago
parent 0ec763a215
commit d94d3bfc33

@ -10,79 +10,86 @@ export const frame = {
}; };
type TaskCallback = (t: number) => boolean; type TaskCallback = (t: number) => boolean;
type TaskCanceller = () => void; type TaskCanceller = () => void;
type TimeoutTask = { t: number; c: (now: number) => void };
const pending_sort: TimeoutTask[] = [];
const timed_tasks: TimeoutTask[] = [];
let i = 0; let i = 0;
let j = 0; let j = 0;
let n = 0; let t = 0;
let v: TaskCallback; let c: TaskCallback;
let running_frame: TaskCallback[] = []; let running_frame: TaskCallback[] = [];
let next_frame: TaskCallback[] = []; let next_frame: TaskCallback[] = [];
const run = (t: number) => { let this_task: TimeoutTask;
let that_task: TimeoutTask;
let l = -1;
let n = 0;
let p = 0;
const run = (time: number) => {
time = (frame.time = now());
if (0 !== n) {
[running_frame, next_frame] = [next_frame, running_frame]; [running_frame, next_frame] = [next_frame, running_frame];
for (t = (frame.time = now()), i = n = 0, j = running_frame.length; i < j; i++) { j = n;
if ((v = running_frame[i])(t)) { for (i = n = 0; i < j; i++) {
next_frame[n++] = v; c = running_frame[i];
if (c(time)) {
next_frame[n++] = c;
} }
} }
if ((running_frame.length = 0) < n) { running_frame.length = 0;
raf(run);
} }
}; if (-1 !== l) {
while (-1 !== l && time >= timed_tasks[l].t) {
type TimeoutTask = { timestamp: number; callback: (now: number) => void }; timed_tasks[l--].c(time);
const pending_insert_timed: TimeoutTask[] = [];
const timed_tasks: TimeoutTask[] = [];
let pending_inserts = false;
let running_timed = false;
const run_timed = (now: number) => {
let last_index = timed_tasks.length - 1;
while (-1 !== last_index && now >= timed_tasks[last_index].timestamp) {
timed_tasks[last_index--].callback(now);
} }
if (pending_inserts) { if (0 !== p) {
for (let i = 0, j = 0, this_task: TimeoutTask, that_task: TimeoutTask; i < pending_insert_timed.length; i++) { for (i = j = 0; i < p; i++) {
if (now >= (this_task = pending_insert_timed[i]).timestamp) { this_task = pending_sort[i];
this_task.callback(now); t = this_task.t;
} else { if (time >= t) {
for (j = last_index; -1 !== j && this_task.timestamp > (that_task = timed_tasks[j]).timestamp; j--) { this_task.c(time);
continue;
}
for (j = l++; -1 !== j; j--) {
that_task = timed_tasks[j];
if (t <= that_task.t) break;
timed_tasks[j + 1] = that_task; timed_tasks[j + 1] = that_task;
} }
timed_tasks[j + 1] = this_task; timed_tasks[j + 1] = this_task;
last_index++;
} }
pending_sort.length = p = 0;
} }
pending_insert_timed.length = 0; timed_tasks.length = l + 1;
pending_inserts = false; }
if (0 !== n || -1 !== l) {
raf(run);
} }
return (running_timed = !!(timed_tasks.length = last_index + 1));
};
const unsafe_loop = (fn) => {
if (0 === n) raf(run);
next_frame[n++] = fn;
}; };
export const loop = (fn) => { const loop = (fn) => {
let running = true; let running = true;
unsafe_loop((t) => running && fn(t)); if (0 === n) raf(run);
return () => void (running = false); next_frame[n++] = (t) => running && fn(t);
return () => {
running = false;
};
}; };
export const setFrameTimeout = (callback: (t: number) => void, timestamp: number): TaskCanceller => { export const setFrameTimeout = (c: (t: number) => void, t: number): TaskCanceller => {
const task: TimeoutTask = { callback, timestamp }; const task: TimeoutTask = { c, t };
if (running_timed) { if (-1 !== l) {
pending_inserts = !!pending_insert_timed.push(task); pending_sort[p++] = task;
} else { } else {
unsafe_loop(run_timed); if (0 === n) raf(run);
running_timed = true; timed_tasks[(l = 0)] = task;
timed_tasks.push(task);
} }
return () => { return () => {
task.callback = noop; task.c = noop;
}; };
}; };
export const setTweenTimeout = ( export const setTweenTimeout = (
@ -102,7 +109,12 @@ export const setTweenTimeout = (
/** tests only */ /** tests only */
export const clear_loops = () => { export const clear_loops = () => {
next_frame.length = running_frame.length = timed_tasks.length = pending_insert_timed.length = n = i = j = +(running_timed = pending_inserts = false); running_frame.length = 0;
pending_sort.length = 0;
timed_tasks.length = 0;
next_frame.length = 0;
i = j = t = n = p = 0;
l = -1;
tasks.clear(); tasks.clear();
}; };

Loading…
Cancel
Save