Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

main-thread-scheduling

Package Overview
Dependencies
Maintainers
1
Versions
30
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

main-thread-scheduling - npm Package Compare versions

Comparing version 13.0.0 to 14.0.0

src/SchedulingTask.d.ts

3

index.d.ts

@@ -5,4 +5,1 @@ export { default as yieldOrContinue } from './src/yieldOrContinue';

export type { default as SchedulingStrategy } from './src/SchedulingStrategy';
export { default as queueTask } from './src/utils/queueTask';
export { default as withResolvers } from './src/utils/withResolvers';
export { default as afterFrame } from './src/utils/requestAfterFrame';

@@ -6,5 +6,1 @@ // primary

export { default as isTimeToYield } from './src/isTimeToYield';
// utility
export { default as queueTask } from './src/utils/queueTask';
export { default as withResolvers } from './src/utils/withResolvers';
export { default as afterFrame } from './src/utils/requestAfterFrame';
{
"name": "main-thread-scheduling",
"version": "13.0.0",
"version": "14.0.0",
"description": "Fast and consistently responsive apps using a single function call",

@@ -5,0 +5,0 @@ "license": "MIT",

@@ -86,10 +86,2 @@ <br>

#### `requestAfterFrame(callback)`
_This is a utility function, most people don't need to use it._ The same way `requestAnimationFrame()` queues a `callback` to be executed just before a frame is rendered `requestAfterFrame()` is called just after a frame is rendered.
#### `queueTask(callback)`
_This is a utility function, most people don't need to use it._ The same way `queueMicrotask()` queues a `callback` to be executed in the end of the current microtask, `queueTask()` queues the task for the next task. You learn more at [here](https://developer.mozilla.org/en-US/docs/Web/API/HTML_DOM_API/Microtask_guide#tasks_vs._microtasks).
### More complex scenarios

@@ -96,0 +88,0 @@

declare class FrameTracker {
#private;
constructor();
waitAnimationFrame(): Promise<void>;
waitAfterFrame(): Promise<void>;

@@ -6,0 +5,0 @@ start(): void;

@@ -1,56 +0,40 @@

var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
if (kind === "m") throw new TypeError("Private method is not writable");
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
};
var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
};
var _FrameTracker_instances, _FrameTracker_timeoutId, _FrameTracker_requestAnimationId, _FrameTracker_deferred, _FrameTracker_loop;
import withResolvers from './utils/withResolvers';
import { queueTask } from '../index';
import waitNextTask from './utils/waitNextTask';
class FrameTracker {
#timeoutId;
#requestAnimationId;
#deferred;
constructor() {
_FrameTracker_instances.add(this);
_FrameTracker_timeoutId.set(this, void 0);
_FrameTracker_requestAnimationId.set(this, void 0);
_FrameTracker_deferred.set(this, void 0);
__classPrivateFieldSet(this, _FrameTracker_deferred, withResolvers(), "f");
this.#deferred = withResolvers();
}
async waitAnimationFrame() {
return __classPrivateFieldGet(this, _FrameTracker_deferred, "f").promise;
}
async waitAfterFrame() {
await __classPrivateFieldGet(this, _FrameTracker_deferred, "f").promise;
await new Promise((resolve) => queueTask(resolve));
await this.#deferred.promise;
await waitNextTask();
}
start() {
clearTimeout(__classPrivateFieldGet(this, _FrameTracker_timeoutId, "f"));
__classPrivateFieldSet(this, _FrameTracker_timeoutId, undefined, "f");
__classPrivateFieldGet(this, _FrameTracker_instances, "m", _FrameTracker_loop).call(this);
clearTimeout(this.#timeoutId);
this.#timeoutId = undefined;
this.#loop();
}
requestStop() {
if (__classPrivateFieldGet(this, _FrameTracker_timeoutId, "f") === undefined) {
__classPrivateFieldSet(this, _FrameTracker_timeoutId, setTimeout(() => {
__classPrivateFieldSet(this, _FrameTracker_timeoutId, undefined, "f");
cancelAnimationFrame(__classPrivateFieldGet(this, _FrameTracker_requestAnimationId, "f"));
__classPrivateFieldSet(this, _FrameTracker_requestAnimationId, undefined, "f");
}, 200), "f");
if (this.#timeoutId === undefined) {
this.#timeoutId = setTimeout(() => {
this.#timeoutId = undefined;
cancelAnimationFrame(this.#requestAnimationId);
this.#requestAnimationId = undefined;
}, 200);
}
}
#loop() {
if (this.#requestAnimationId === undefined) {
this.#requestAnimationId = requestAnimationFrame(() => {
this.#requestAnimationId = undefined;
this.#deferred.resolve();
this.#deferred = withResolvers();
this.#loop();
});
}
}
}
_FrameTracker_timeoutId = new WeakMap(), _FrameTracker_requestAnimationId = new WeakMap(), _FrameTracker_deferred = new WeakMap(), _FrameTracker_instances = new WeakSet(), _FrameTracker_loop = function _FrameTracker_loop() {
if (__classPrivateFieldGet(this, _FrameTracker_requestAnimationId, "f") === undefined) {
__classPrivateFieldSet(this, _FrameTracker_requestAnimationId, requestAnimationFrame(() => {
__classPrivateFieldSet(this, _FrameTracker_requestAnimationId, undefined, "f");
__classPrivateFieldGet(this, _FrameTracker_deferred, "f").resolve();
__classPrivateFieldSet(this, _FrameTracker_deferred, withResolvers(), "f");
__classPrivateFieldGet(this, _FrameTracker_instances, "m", _FrameTracker_loop).call(this);
}), "f");
}
};
const frameTracker = new FrameTracker();
export default frameTracker;
import hasValidContext from './utils/hasValidContext';
import threadScheduler from './ThreadScheduler';
import toTask from './utils/toTask';
// #performance

@@ -29,4 +30,4 @@ // calling `isTimeToYield()` thousand of times is slow

cache.lastCallTime = now;
cache.lastResult = threadScheduler.isTimeToYield(strategy);
cache.lastResult = threadScheduler.isTimeToYield(toTask(strategy));
return cache.lastResult;
}

@@ -1,20 +0,8 @@

var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
if (kind === "m") throw new TypeError("Private method is not writable");
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
};
var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
};
var _RicTracker_idleCallbackId, _RicTracker_idleDeadline, _RicTracker_deferred;
import withResolvers from './utils/withResolvers';
class RicTracker {
#idleCallbackId;
#idleDeadline;
#deferred;
constructor() {
_RicTracker_idleCallbackId.set(this, void 0);
_RicTracker_idleDeadline.set(this, void 0);
_RicTracker_deferred.set(this, void 0);
__classPrivateFieldSet(this, _RicTracker_deferred, withResolvers(), "f");
this.#deferred = withResolvers();
}

@@ -25,26 +13,25 @@ get available() {

get deadline() {
return __classPrivateFieldGet(this, _RicTracker_idleDeadline, "f");
return this.#idleDeadline;
}
async waitIdleCallback() {
return __classPrivateFieldGet(this, _RicTracker_deferred, "f").promise;
return this.#deferred.promise;
}
start() {
if (!this.available || __classPrivateFieldGet(this, _RicTracker_idleCallbackId, "f") !== undefined) {
if (!this.available || this.#idleCallbackId !== undefined) {
return;
}
__classPrivateFieldSet(this, _RicTracker_idleCallbackId, requestIdleCallback((deadline) => {
__classPrivateFieldSet(this, _RicTracker_idleDeadline, deadline, "f");
__classPrivateFieldSet(this, _RicTracker_idleCallbackId, undefined, "f");
__classPrivateFieldGet(this, _RicTracker_deferred, "f").resolve(deadline);
__classPrivateFieldSet(this, _RicTracker_deferred, withResolvers(), "f");
this.#idleCallbackId = requestIdleCallback((deadline) => {
this.#idleDeadline = deadline;
this.#idleCallbackId = undefined;
this.#deferred.resolve(deadline);
this.#deferred = withResolvers();
this.start();
}), "f");
});
}
stop() {
cancelIdleCallback(__classPrivateFieldGet(this, _RicTracker_idleCallbackId, "f"));
__classPrivateFieldSet(this, _RicTracker_idleCallbackId, undefined, "f");
cancelIdleCallback(this.#idleCallbackId);
this.#idleCallbackId = undefined;
}
}
_RicTracker_idleCallbackId = new WeakMap(), _RicTracker_idleDeadline = new WeakMap(), _RicTracker_deferred = new WeakMap();
const ricTracker = new RicTracker();
export default ricTracker;

@@ -1,6 +0,7 @@

import SchedulingStrategy from './SchedulingStrategy';
import { PromiseWithResolvers } from './utils/withResolvers';
type ScheduledTask = PromiseWithResolvers & {
strategy: SchedulingStrategy;
import type SchedulingTask from './SchedulingTask';
type ScheduledTask = SchedulingTask & {
promise: Promise<void>;
resolve: () => void;
reject: (reason: DOMException) => void;
};
export default ScheduledTask;

@@ -1,10 +0,10 @@

import ScheduledTask from './ScheduledTask';
import SchedulingStrategy from './SchedulingStrategy';
import type ScheduledTask from './ScheduledTask';
import type SchedulingTask from './SchedulingTask';
declare class ThreadScheduler {
#private;
constructor();
createTask(strategy: SchedulingStrategy): ScheduledTask;
isTimeToYield(strategy: SchedulingStrategy): boolean;
schedule(task: SchedulingTask): ScheduledTask;
isTimeToYield(task: SchedulingTask): boolean;
}
declare const threadScheduler: ThreadScheduler;
export default threadScheduler;

@@ -1,72 +0,73 @@

var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
};
var _ThreadScheduler_instances, _ThreadScheduler_tasks, _ThreadScheduler_topTask, _ThreadScheduler_workCycleTracker, _ThreadScheduler_completeTask, _ThreadScheduler_insertTask, _ThreadScheduler_removeTask;
import WorkCycleTracker from './WorkCycleTracker';
import ReactiveTask from './utils/ReactiveTask';
import withResolvers from './utils/withResolvers';
import { requestPromiseEscape } from './utils/promiseEscape';
import ReactiveTask from './utils/ReactiveTask';
const strategyPriorities = {
interactive: 30,
smooth: 20,
idle: 10,
};
class ThreadScheduler {
#tasks = [];
#topTask = new ReactiveTask();
#workCycleTracker = new WorkCycleTracker();
constructor() {
_ThreadScheduler_instances.add(this);
_ThreadScheduler_tasks.set(this, []);
_ThreadScheduler_topTask.set(this, new ReactiveTask());
_ThreadScheduler_workCycleTracker.set(this, new WorkCycleTracker());
__classPrivateFieldGet(this, _ThreadScheduler_topTask, "f").setEffect(async (task, signal) => {
__classPrivateFieldGet(this, _ThreadScheduler_workCycleTracker, "f").startTracking();
await __classPrivateFieldGet(this, _ThreadScheduler_instances, "m", _ThreadScheduler_completeTask).call(this, task, signal);
if (__classPrivateFieldGet(this, _ThreadScheduler_tasks, "f").length === 0) {
__classPrivateFieldGet(this, _ThreadScheduler_workCycleTracker, "f").requestStopTracking();
this.#topTask.setEffect(async (task, signal) => {
this.#workCycleTracker.startTracking();
await this.#completeTask(task, signal);
if (this.#tasks.length === 0) {
this.#workCycleTracker.requestStopTracking();
}
});
}
createTask(strategy) {
const task = { ...withResolvers(), strategy };
__classPrivateFieldGet(this, _ThreadScheduler_instances, "m", _ThreadScheduler_insertTask).call(this, task);
return task;
schedule(task) {
const scheduled = { ...task, ...withResolvers() };
this.#insertTask(scheduled);
task.signal?.addEventListener('abort', () => {
this.#removeTask(scheduled);
scheduled.reject(new DOMException('The operation was aborted.', 'AbortError'));
}, { once: true });
return scheduled;
}
isTimeToYield(strategy) {
return !__classPrivateFieldGet(this, _ThreadScheduler_workCycleTracker, "f").canWorkMore(strategy);
isTimeToYield(task) {
return !this.#workCycleTracker.canWorkMore(task);
}
}
_ThreadScheduler_tasks = new WeakMap(), _ThreadScheduler_topTask = new WeakMap(), _ThreadScheduler_workCycleTracker = new WeakMap(), _ThreadScheduler_instances = new WeakSet(), _ThreadScheduler_completeTask = async function _ThreadScheduler_completeTask(task, signal) {
while (!__classPrivateFieldGet(this, _ThreadScheduler_workCycleTracker, "f").canWorkMore(task.strategy)) {
await __classPrivateFieldGet(this, _ThreadScheduler_workCycleTracker, "f").nextWorkCycle(task.strategy);
if (signal.aborted) {
return;
async #completeTask(task, signal) {
while (!this.#workCycleTracker.canWorkMore(task)) {
await this.#workCycleTracker.nextWorkCycle(task);
if (signal.aborted) {
return;
}
}
task.resolve();
// - wait for the user code to continue running to see if it will add more work to
// be done. we prefer this, over continuing to the next task immediately
// - if called at the end of an async method, it will wait for the async to get resolved in the
// parent method that called it and will execute the provided callback in the next microtask.
await new Promise((resolve) => {
queueMicrotask(() => {
queueMicrotask(() => {
resolve();
});
});
});
this.#removeTask(task);
}
task.resolve();
// wait for the user code to continue running the code to see if he will add more work to
// be done. we prefer this, other than continuing to the next task immediately
await new Promise((resolve) => requestPromiseEscape(resolve));
__classPrivateFieldGet(this, _ThreadScheduler_instances, "m", _ThreadScheduler_removeTask).call(this, task);
}, _ThreadScheduler_insertTask = function _ThreadScheduler_insertTask(task) {
const priority = strategyPriorities[task.strategy];
for (let i = 0; i < __classPrivateFieldGet(this, _ThreadScheduler_tasks, "f").length; i++) {
if (priority >= strategyPriorities[__classPrivateFieldGet(this, _ThreadScheduler_tasks, "f")[i].strategy]) {
__classPrivateFieldGet(this, _ThreadScheduler_tasks, "f").splice(i, 0, task);
__classPrivateFieldGet(this, _ThreadScheduler_topTask, "f").set(__classPrivateFieldGet(this, _ThreadScheduler_tasks, "f")[0]);
return;
#insertTask(task) {
const priority = task.priority;
for (let i = 0; i < this.#tasks.length; i++) {
if (priority >= this.#tasks[i].priority) {
this.#tasks.splice(i, 0, task);
this.#topTask.set(this.#tasks[0]);
return;
}
}
this.#tasks.push(task);
this.#topTask.set(this.#tasks[0]);
}
__classPrivateFieldGet(this, _ThreadScheduler_tasks, "f").push(task);
__classPrivateFieldGet(this, _ThreadScheduler_topTask, "f").set(__classPrivateFieldGet(this, _ThreadScheduler_tasks, "f")[0]);
}, _ThreadScheduler_removeTask = function _ThreadScheduler_removeTask(task) {
const index = __classPrivateFieldGet(this, _ThreadScheduler_tasks, "f").indexOf(task);
if (index !== -1) {
__classPrivateFieldGet(this, _ThreadScheduler_tasks, "f").splice(index, 1);
#removeTask(task) {
const index = this.#tasks.indexOf(task);
if (index !== -1) {
this.#tasks.splice(index, 1);
}
if (index === 0) {
this.#topTask.set(this.#tasks[0]);
}
}
if (index === 0) {
__classPrivateFieldGet(this, _ThreadScheduler_topTask, "f").set(__classPrivateFieldGet(this, _ThreadScheduler_tasks, "f")[0]);
}
};
}
const threadScheduler = new ThreadScheduler();
export default threadScheduler;

@@ -1,2 +0,2 @@

import ScheduledTask from '../ScheduledTask';
import type ScheduledTask from '../ScheduledTask';
export default class ReactiveTask {

@@ -3,0 +3,0 @@ #private;

@@ -1,37 +0,22 @@

var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
if (kind === "m") throw new TypeError("Private method is not writable");
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
};
var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
};
var _ReactiveTask_task, _ReactiveTask_controller, _ReactiveTask_effect;
// - reactivity for ScheduledTask
// - otherwise, we would have to use something heavier like solid-js
export default class ReactiveTask {
constructor() {
_ReactiveTask_task.set(this, void 0);
_ReactiveTask_controller.set(this, new AbortController());
_ReactiveTask_effect.set(this, () => { });
}
#task;
#controller = new AbortController();
#effect = () => { };
set(task) {
if (task === undefined) {
__classPrivateFieldSet(this, _ReactiveTask_task, undefined, "f");
__classPrivateFieldGet(this, _ReactiveTask_controller, "f").abort();
this.#task = undefined;
this.#controller.abort();
}
else if (__classPrivateFieldGet(this, _ReactiveTask_task, "f") !== task) {
__classPrivateFieldSet(this, _ReactiveTask_task, task, "f");
__classPrivateFieldGet(this, _ReactiveTask_controller, "f").abort();
__classPrivateFieldSet(this, _ReactiveTask_controller, new AbortController(), "f");
__classPrivateFieldGet(this, _ReactiveTask_effect, "f").call(this, __classPrivateFieldGet(this, _ReactiveTask_task, "f"), __classPrivateFieldGet(this, _ReactiveTask_controller, "f").signal);
else if (this.#task !== task) {
this.#task = task;
this.#controller.abort();
this.#controller = new AbortController();
this.#effect(this.#task, this.#controller.signal);
}
}
setEffect(effect) {
__classPrivateFieldSet(this, _ReactiveTask_effect, effect, "f");
this.#effect = effect;
}
}
_ReactiveTask_task = new WeakMap(), _ReactiveTask_controller = new WeakMap(), _ReactiveTask_effect = new WeakMap();

@@ -1,2 +0,2 @@

import SchedulingStrategy from './SchedulingStrategy';
import type SchedulingTask from './SchedulingTask';
export default class WorkCycleTracker {

@@ -6,4 +6,4 @@ #private;

requestStopTracking(): void;
canWorkMore(strategy: SchedulingStrategy): boolean;
nextWorkCycle(strategy: SchedulingStrategy): Promise<void>;
canWorkMore(task: SchedulingTask): boolean;
nextWorkCycle(task: SchedulingTask): Promise<void>;
}

@@ -1,20 +0,6 @@

var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
};
var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
if (kind === "m") throw new TypeError("Private method is not writable");
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
};
var _WorkCycleTracker_instances, _WorkCycleTracker_workCycleStart, _WorkCycleTracker_calculateDeadline;
import ricTracker from './ricTracker';
import frameTracker from './frameTracker';
import waitHiddenTask from './utils/waitHiddenTask';
export default class WorkCycleTracker {
constructor() {
_WorkCycleTracker_instances.add(this);
_WorkCycleTracker_workCycleStart.set(this, -1);
}
#workCycleStart = -1;
startTracking() {

@@ -28,15 +14,11 @@ ricTracker.start();

}
canWorkMore(strategy) {
var _a, _b;
const isInputPending = ((_b = (_a = navigator.scheduling) === null || _a === void 0 ? void 0 : _a.isInputPending) === null || _b === void 0 ? void 0 : _b.call(_a)) === true;
return !isInputPending && __classPrivateFieldGet(this, _WorkCycleTracker_instances, "m", _WorkCycleTracker_calculateDeadline).call(this, strategy) - Date.now() > 0;
canWorkMore(task) {
const isInputPending = navigator.scheduling?.isInputPending?.() === true;
return !isInputPending && this.#calculateDeadline(task) - Date.now() > 0;
}
async nextWorkCycle(strategy) {
if (strategy === 'interactive') {
await frameTracker.waitAfterFrame();
async nextWorkCycle(task) {
if (task.type === 'frame-based') {
await Promise.race([frameTracker.waitAfterFrame(), waitHiddenTask()]);
}
else if (strategy === 'smooth') {
await frameTracker.waitAfterFrame();
}
else if (strategy === 'idle') {
else if (task.type === 'idle-based') {
if (ricTracker.available) {

@@ -46,22 +28,24 @@ await ricTracker.waitIdleCallback();

else {
// todo: use waitHiddenTask() with a timeout
await frameTracker.waitAfterFrame();
}
}
__classPrivateFieldSet(this, _WorkCycleTracker_workCycleStart, Date.now(), "f");
this.#workCycleStart = Date.now();
}
#calculateDeadline(task) {
if (task.type === 'frame-based') {
// const timePerFrame = 1000 / fps.guessRefreshRate()
// const multiplier = timePerFrame / fps.guessRefreshRate()
// const maxWorkTime = fps.fps() * multiplier
// return this.#workCycleStart + maxWorkTime
return this.#workCycleStart + task.workTime;
}
else if (task.type === 'idle-based') {
const idleDeadline = ricTracker.deadline === undefined
? Number.MAX_SAFE_INTEGER
: Date.now() + ricTracker.deadline.timeRemaining();
return Math.min(this.#workCycleStart + task.workTime, idleDeadline);
}
return -1;
}
}
_WorkCycleTracker_workCycleStart = new WeakMap(), _WorkCycleTracker_instances = new WeakSet(), _WorkCycleTracker_calculateDeadline = function _WorkCycleTracker_calculateDeadline(strategy) {
if (strategy === 'interactive') {
return __classPrivateFieldGet(this, _WorkCycleTracker_workCycleStart, "f") + 83;
}
else if (strategy === 'smooth') {
return __classPrivateFieldGet(this, _WorkCycleTracker_workCycleStart, "f") + 13;
}
else if (strategy === 'idle') {
const idleDeadline = ricTracker.deadline === undefined
? Number.MAX_SAFE_INTEGER
: Date.now() + ricTracker.deadline.timeRemaining();
return Math.min(__classPrivateFieldGet(this, _WorkCycleTracker_workCycleStart, "f") + 5, idleDeadline);
}
return -1;
};

@@ -12,2 +12,2 @@ import SchedulingStrategy from './SchedulingStrategy';

*/
export default function yieldControl(strategy?: SchedulingStrategy): Promise<void>;
export default function yieldControl(strategy?: SchedulingStrategy, signal?: AbortSignal): Promise<void>;
import hasValidContext from './utils/hasValidContext';
import threadScheduler from './ThreadScheduler';
import toTask from './utils/toTask';
/**

@@ -13,8 +14,7 @@ * Waits for the browser to become idle again in order to resume work. Calling `yieldControl()`

*/
export default async function yieldControl(strategy = 'smooth') {
export default async function yieldControl(strategy = 'smooth', signal) {
if (!hasValidContext()) {
return;
}
const task = threadScheduler.createTask(strategy);
return task.promise;
return threadScheduler.schedule(toTask(strategy, signal)).promise;
}

@@ -14,2 +14,2 @@ import SchedulingStrategy from './SchedulingStrategy';

*/
export default function yieldOrContinue(priority?: SchedulingStrategy): Promise<void>;
export default function yieldOrContinue(priority?: SchedulingStrategy, signal?: AbortSignal): Promise<void>;

@@ -17,7 +17,7 @@ import yieldControl from './yieldControl';

// eslint-disable-next-line @typescript-eslint/promise-function-async
export default function yieldOrContinue(priority = 'smooth') {
if (isTimeToYield(priority)) {
return yieldControl(priority);
export default function yieldOrContinue(priority = 'smooth', signal) {
if (signal?.aborted !== true && isTimeToYield(priority)) {
return yieldControl(priority, signal);
}
return Promise.resolve();
}
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc