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

frame-scheduling

Package Overview
Dependencies
Maintainers
1
Versions
13
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

frame-scheduling - npm Package Compare versions

Comparing version 0.7.0 to 0.7.1

dist/.DS_Store

4

dist/frameScheduling.d.ts

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

import { Defer } from "./defer";
export declare const P_LOWER = 1;

@@ -6,2 +7,5 @@ export declare const P_LOW = 3;

export declare const P_IMPORTANT = 10;
export declare const createFrameScheduling: (defer?: Defer, lifeFrame?: number) => (callback: () => void, { priority }?: {
priority?: number | undefined;
}) => void;
declare const _default: (callback: () => void, { priority }?: {

@@ -8,0 +12,0 @@ priority?: number | undefined;

115

dist/frameScheduling.esm.js

@@ -1,18 +0,5 @@

var context = typeof window !== "undefined" ? window : global;
var defer;
if ("requestAnimationFrame" in context) {
defer = requestAnimationFrame.bind(context);
}
else if ("setImmediate" in context) {
defer = setImmediate.bind(context);
}
else {
defer = setTimeout.bind(context);
}
var TIME_LIFE_FRAME = 16; // 16ms === 60fps
var P_LOWER = 1;
var P_LOW = 3;
var P_NORMAL = 5;
var P_HIGH = 7;
var P_IMPORTANT = 10;
var getParentIndex = function (childIndex) { return Math.floor((childIndex - 1) / 2); };
var getRightChildIndex = function (parentIndex) { return 2 * parentIndex + 2; };
var hasParent = function (childIndex) { return getParentIndex(childIndex) >= 0; };
var getLeftChildIndex = function (parentIndex) { return 2 * parentIndex + 1; };
var PriorityUniqQueue = /** @class */ (function () {

@@ -63,6 +50,6 @@ function PriorityUniqQueue() {

var currentIndex = customStartIndex || this.heapContainer.length - 1;
while (this.hasParent(currentIndex)
&& !this.pairIsInCorrectOrder(this.heapContainer[this.getParentIndex(currentIndex)], this.heapContainer[currentIndex])) {
this.swap(currentIndex, this.getParentIndex(currentIndex));
currentIndex = this.getParentIndex(currentIndex);
while (hasParent(currentIndex) &&
!this.pairIsInCorrectOrder(this.heapContainer[getParentIndex(currentIndex)], this.heapContainer[currentIndex])) {
this.swap(currentIndex, getParentIndex(currentIndex));
currentIndex = getParentIndex(currentIndex);
}

@@ -73,9 +60,9 @@ };

var nextIndex = null;
while (this.hasLeftChild(currentIndex)) {
if (this.hasRightChild(currentIndex)
&& this.pairIsInCorrectOrder(this.rightChild(currentIndex), this.leftChild(currentIndex))) {
nextIndex = this.getRightChildIndex(currentIndex);
while (getLeftChildIndex(currentIndex) < this.heapContainer.length) {
if (getRightChildIndex(currentIndex) < this.heapContainer.length &&
this.pairIsInCorrectOrder(this.heapContainer[getRightChildIndex(currentIndex)], this.heapContainer[getLeftChildIndex(currentIndex)])) {
nextIndex = getRightChildIndex(currentIndex);
}
else {
nextIndex = this.getLeftChildIndex(currentIndex);
nextIndex = getLeftChildIndex(currentIndex);
}

@@ -92,26 +79,2 @@ if (this.pairIsInCorrectOrder(this.heapContainer[currentIndex], this.heapContainer[nextIndex])) {

};
PriorityUniqQueue.prototype.getLeftChildIndex = function (parentIndex) {
return (2 * parentIndex) + 1;
};
PriorityUniqQueue.prototype.getRightChildIndex = function (parentIndex) {
return (2 * parentIndex) + 2;
};
PriorityUniqQueue.prototype.getParentIndex = function (childIndex) {
return Math.floor((childIndex - 1) / 2);
};
PriorityUniqQueue.prototype.hasParent = function (childIndex) {
return this.getParentIndex(childIndex) >= 0;
};
PriorityUniqQueue.prototype.hasLeftChild = function (parentIndex) {
return this.getLeftChildIndex(parentIndex) < this.heapContainer.length;
};
PriorityUniqQueue.prototype.hasRightChild = function (parentIndex) {
return this.getRightChildIndex(parentIndex) < this.heapContainer.length;
};
PriorityUniqQueue.prototype.leftChild = function (parentIndex) {
return this.heapContainer[this.getLeftChildIndex(parentIndex)];
};
PriorityUniqQueue.prototype.rightChild = function (parentIndex) {
return this.heapContainer[this.getRightChildIndex(parentIndex)];
};
PriorityUniqQueue.prototype.swap = function (indexOne, indexTwo) {

@@ -124,2 +87,3 @@ var tmp = this.heapContainer[indexTwo];

}());
var LinkedList = /** @class */ (function () {

@@ -134,3 +98,3 @@ function LinkedList() {

next: null,
value: value,
value: value
};

@@ -159,3 +123,24 @@ if (this.length === 0) {

}());
var frameScheduling = function () {
var context = typeof window !== "undefined" ? window : global;
var defer;
if ("requestAnimationFrame" in context) {
defer = requestAnimationFrame;
}
else if ("setImmediate" in context) {
defer = context.setImmediate;
}
else {
defer = setTimeout;
}
var TIME_LIFE_FRAME = 16; // 16ms === 60fps
var P_LOWER = 1;
var P_LOW = 3;
var P_NORMAL = 5;
var P_HIGH = 7;
var P_IMPORTANT = 10;
var createFrameScheduling = function (defer$1, lifeFrame) {
if (defer$1 === void 0) { defer$1 = defer; }
if (lifeFrame === void 0) { lifeFrame = TIME_LIFE_FRAME; }
var heapJobs = new PriorityUniqQueue();

@@ -165,14 +150,13 @@ var deferScheduled = false;

if (!deferScheduled) {
defer(runJobs);
deferScheduled = true;
defer$1(runJobs);
}
deferScheduled = true;
};
var addJob = function (callback, priority) {
var getJob = heapJobs.get(priority);
var newLinkedList;
if (!getJob) {
newLinkedList = new LinkedList();
heapJobs.add(priority, newLinkedList);
var job = heapJobs.get(priority);
if (!job) {
job = new LinkedList();
heapJobs.add(priority, job);
}
(getJob || newLinkedList).push(callback);
job.push(callback);
};

@@ -182,3 +166,3 @@ var runJobs = function () {

while (true) {
if (heapJobs.isEmpty() || Date.now() - timeRun > TIME_LIFE_FRAME) {
if (heapJobs.isEmpty() || Date.now() - timeRun > lifeFrame) {
break;

@@ -188,5 +172,4 @@ }

var jobs = heapJobs.peek();
var job = jobs.shift();
try {
job();
(jobs.shift())();
}

@@ -213,5 +196,5 @@ catch (e) {

};
var frameScheduling$1 = frameScheduling();
var frameScheduling = createFrameScheduling();
export default frameScheduling$1;
export { P_LOWER, P_LOW, P_NORMAL, P_HIGH, P_IMPORTANT };
export default frameScheduling;
export { P_HIGH, P_IMPORTANT, P_LOW, P_LOWER, P_NORMAL, createFrameScheduling };

@@ -1,18 +0,5 @@

const context = typeof window !== "undefined" ? window : global;
let defer;
if ("requestAnimationFrame" in context) {
defer = requestAnimationFrame.bind(context);
}
else if ("setImmediate" in context) {
defer = setImmediate.bind(context);
}
else {
defer = setTimeout.bind(context);
}
const TIME_LIFE_FRAME = 16; // 16ms === 60fps
const P_LOWER = 1;
const P_LOW = 3;
const P_NORMAL = 5;
const P_HIGH = 7;
const P_IMPORTANT = 10;
const getParentIndex = (childIndex) => Math.floor((childIndex - 1) / 2);
const getRightChildIndex = (parentIndex) => 2 * parentIndex + 2;
const hasParent = (childIndex) => getParentIndex(childIndex) >= 0;
const getLeftChildIndex = (parentIndex) => 2 * parentIndex + 1;
class PriorityUniqQueue {

@@ -63,6 +50,6 @@ constructor() {

let currentIndex = customStartIndex || this.heapContainer.length - 1;
while (this.hasParent(currentIndex)
&& !this.pairIsInCorrectOrder(this.heapContainer[this.getParentIndex(currentIndex)], this.heapContainer[currentIndex])) {
this.swap(currentIndex, this.getParentIndex(currentIndex));
currentIndex = this.getParentIndex(currentIndex);
while (hasParent(currentIndex) &&
!this.pairIsInCorrectOrder(this.heapContainer[getParentIndex(currentIndex)], this.heapContainer[currentIndex])) {
this.swap(currentIndex, getParentIndex(currentIndex));
currentIndex = getParentIndex(currentIndex);
}

@@ -73,9 +60,9 @@ }

let nextIndex = null;
while (this.hasLeftChild(currentIndex)) {
if (this.hasRightChild(currentIndex)
&& this.pairIsInCorrectOrder(this.rightChild(currentIndex), this.leftChild(currentIndex))) {
nextIndex = this.getRightChildIndex(currentIndex);
while (getLeftChildIndex(currentIndex) < this.heapContainer.length) {
if (getRightChildIndex(currentIndex) < this.heapContainer.length &&
this.pairIsInCorrectOrder(this.heapContainer[getRightChildIndex(currentIndex)], this.heapContainer[getLeftChildIndex(currentIndex)])) {
nextIndex = getRightChildIndex(currentIndex);
}
else {
nextIndex = this.getLeftChildIndex(currentIndex);
nextIndex = getLeftChildIndex(currentIndex);
}

@@ -92,26 +79,2 @@ if (this.pairIsInCorrectOrder(this.heapContainer[currentIndex], this.heapContainer[nextIndex])) {

}
getLeftChildIndex(parentIndex) {
return (2 * parentIndex) + 1;
}
getRightChildIndex(parentIndex) {
return (2 * parentIndex) + 2;
}
getParentIndex(childIndex) {
return Math.floor((childIndex - 1) / 2);
}
hasParent(childIndex) {
return this.getParentIndex(childIndex) >= 0;
}
hasLeftChild(parentIndex) {
return this.getLeftChildIndex(parentIndex) < this.heapContainer.length;
}
hasRightChild(parentIndex) {
return this.getRightChildIndex(parentIndex) < this.heapContainer.length;
}
leftChild(parentIndex) {
return this.heapContainer[this.getLeftChildIndex(parentIndex)];
}
rightChild(parentIndex) {
return this.heapContainer[this.getRightChildIndex(parentIndex)];
}
swap(indexOne, indexTwo) {

@@ -123,2 +86,3 @@ const tmp = this.heapContainer[indexTwo];

}
class LinkedList {

@@ -133,3 +97,3 @@ constructor() {

next: null,
value,
value
};

@@ -157,3 +121,22 @@ if (this.length === 0) {

}
const frameScheduling = () => {
const context = typeof window !== "undefined" ? window : global;
let defer;
if ("requestAnimationFrame" in context) {
defer = requestAnimationFrame;
}
else if ("setImmediate" in context) {
defer = context.setImmediate;
}
else {
defer = setTimeout;
}
const TIME_LIFE_FRAME = 16; // 16ms === 60fps
const P_LOWER = 1;
const P_LOW = 3;
const P_NORMAL = 5;
const P_HIGH = 7;
const P_IMPORTANT = 10;
const createFrameScheduling = (defer$1 = defer, lifeFrame = TIME_LIFE_FRAME) => {
const heapJobs = new PriorityUniqQueue();

@@ -163,14 +146,13 @@ let deferScheduled = false;

if (!deferScheduled) {
defer(runJobs);
deferScheduled = true;
defer$1(runJobs);
}
deferScheduled = true;
};
const addJob = (callback, priority) => {
const getJob = heapJobs.get(priority);
let newLinkedList;
if (!getJob) {
newLinkedList = new LinkedList();
heapJobs.add(priority, newLinkedList);
let job = heapJobs.get(priority);
if (!job) {
job = new LinkedList();
heapJobs.add(priority, job);
}
(getJob || newLinkedList).push(callback);
job.push(callback);
};

@@ -180,3 +162,3 @@ const runJobs = () => {

while (true) {
if (heapJobs.isEmpty() || Date.now() - timeRun > TIME_LIFE_FRAME) {
if (heapJobs.isEmpty() || Date.now() - timeRun > lifeFrame) {
break;

@@ -186,5 +168,4 @@ }

const jobs = heapJobs.peek();
const job = jobs.shift();
try {
job();
(jobs.shift())();
}

@@ -210,5 +191,5 @@ catch (e) {

};
var frameScheduling$1 = frameScheduling();
var frameScheduling = createFrameScheduling();
export default frameScheduling$1;
export { P_LOWER, P_LOW, P_NORMAL, P_HIGH, P_IMPORTANT };
export default frameScheduling;
export { P_HIGH, P_IMPORTANT, P_LOW, P_LOWER, P_NORMAL, createFrameScheduling };

@@ -5,19 +5,6 @@ 'use strict';

var context = typeof window !== "undefined" ? window : global;
var defer;
if ("requestAnimationFrame" in context) {
defer = requestAnimationFrame.bind(context);
}
else if ("setImmediate" in context) {
defer = setImmediate.bind(context);
}
else {
defer = setTimeout.bind(context);
}
var TIME_LIFE_FRAME = 16; // 16ms === 60fps
var P_LOWER = 1;
var P_LOW = 3;
var P_NORMAL = 5;
var P_HIGH = 7;
var P_IMPORTANT = 10;
var getParentIndex = function (childIndex) { return Math.floor((childIndex - 1) / 2); };
var getRightChildIndex = function (parentIndex) { return 2 * parentIndex + 2; };
var hasParent = function (childIndex) { return getParentIndex(childIndex) >= 0; };
var getLeftChildIndex = function (parentIndex) { return 2 * parentIndex + 1; };
var PriorityUniqQueue = /** @class */ (function () {

@@ -68,6 +55,6 @@ function PriorityUniqQueue() {

var currentIndex = customStartIndex || this.heapContainer.length - 1;
while (this.hasParent(currentIndex)
&& !this.pairIsInCorrectOrder(this.heapContainer[this.getParentIndex(currentIndex)], this.heapContainer[currentIndex])) {
this.swap(currentIndex, this.getParentIndex(currentIndex));
currentIndex = this.getParentIndex(currentIndex);
while (hasParent(currentIndex) &&
!this.pairIsInCorrectOrder(this.heapContainer[getParentIndex(currentIndex)], this.heapContainer[currentIndex])) {
this.swap(currentIndex, getParentIndex(currentIndex));
currentIndex = getParentIndex(currentIndex);
}

@@ -78,9 +65,9 @@ };

var nextIndex = null;
while (this.hasLeftChild(currentIndex)) {
if (this.hasRightChild(currentIndex)
&& this.pairIsInCorrectOrder(this.rightChild(currentIndex), this.leftChild(currentIndex))) {
nextIndex = this.getRightChildIndex(currentIndex);
while (getLeftChildIndex(currentIndex) < this.heapContainer.length) {
if (getRightChildIndex(currentIndex) < this.heapContainer.length &&
this.pairIsInCorrectOrder(this.heapContainer[getRightChildIndex(currentIndex)], this.heapContainer[getLeftChildIndex(currentIndex)])) {
nextIndex = getRightChildIndex(currentIndex);
}
else {
nextIndex = this.getLeftChildIndex(currentIndex);
nextIndex = getLeftChildIndex(currentIndex);
}

@@ -97,26 +84,2 @@ if (this.pairIsInCorrectOrder(this.heapContainer[currentIndex], this.heapContainer[nextIndex])) {

};
PriorityUniqQueue.prototype.getLeftChildIndex = function (parentIndex) {
return (2 * parentIndex) + 1;
};
PriorityUniqQueue.prototype.getRightChildIndex = function (parentIndex) {
return (2 * parentIndex) + 2;
};
PriorityUniqQueue.prototype.getParentIndex = function (childIndex) {
return Math.floor((childIndex - 1) / 2);
};
PriorityUniqQueue.prototype.hasParent = function (childIndex) {
return this.getParentIndex(childIndex) >= 0;
};
PriorityUniqQueue.prototype.hasLeftChild = function (parentIndex) {
return this.getLeftChildIndex(parentIndex) < this.heapContainer.length;
};
PriorityUniqQueue.prototype.hasRightChild = function (parentIndex) {
return this.getRightChildIndex(parentIndex) < this.heapContainer.length;
};
PriorityUniqQueue.prototype.leftChild = function (parentIndex) {
return this.heapContainer[this.getLeftChildIndex(parentIndex)];
};
PriorityUniqQueue.prototype.rightChild = function (parentIndex) {
return this.heapContainer[this.getRightChildIndex(parentIndex)];
};
PriorityUniqQueue.prototype.swap = function (indexOne, indexTwo) {

@@ -129,2 +92,3 @@ var tmp = this.heapContainer[indexTwo];

}());
var LinkedList = /** @class */ (function () {

@@ -139,3 +103,3 @@ function LinkedList() {

next: null,
value: value,
value: value
};

@@ -164,3 +128,24 @@ if (this.length === 0) {

}());
var frameScheduling = function () {
var context = typeof window !== "undefined" ? window : global;
var defer;
if ("requestAnimationFrame" in context) {
defer = requestAnimationFrame;
}
else if ("setImmediate" in context) {
defer = context.setImmediate;
}
else {
defer = setTimeout;
}
var TIME_LIFE_FRAME = 16; // 16ms === 60fps
var P_LOWER = 1;
var P_LOW = 3;
var P_NORMAL = 5;
var P_HIGH = 7;
var P_IMPORTANT = 10;
var createFrameScheduling = function (defer$1, lifeFrame) {
if (defer$1 === void 0) { defer$1 = defer; }
if (lifeFrame === void 0) { lifeFrame = TIME_LIFE_FRAME; }
var heapJobs = new PriorityUniqQueue();

@@ -170,14 +155,13 @@ var deferScheduled = false;

if (!deferScheduled) {
defer(runJobs);
deferScheduled = true;
defer$1(runJobs);
}
deferScheduled = true;
};
var addJob = function (callback, priority) {
var getJob = heapJobs.get(priority);
var newLinkedList;
if (!getJob) {
newLinkedList = new LinkedList();
heapJobs.add(priority, newLinkedList);
var job = heapJobs.get(priority);
if (!job) {
job = new LinkedList();
heapJobs.add(priority, job);
}
(getJob || newLinkedList).push(callback);
job.push(callback);
};

@@ -187,3 +171,3 @@ var runJobs = function () {

while (true) {
if (heapJobs.isEmpty() || Date.now() - timeRun > TIME_LIFE_FRAME) {
if (heapJobs.isEmpty() || Date.now() - timeRun > lifeFrame) {
break;

@@ -193,5 +177,4 @@ }

var jobs = heapJobs.peek();
var job = jobs.shift();
try {
job();
(jobs.shift())();
}

@@ -218,9 +201,10 @@ catch (e) {

};
var frameScheduling$1 = frameScheduling();
var frameScheduling = createFrameScheduling();
exports.P_HIGH = P_HIGH;
exports.P_IMPORTANT = P_IMPORTANT;
exports.P_LOW = P_LOW;
exports.P_LOWER = P_LOWER;
exports.P_LOW = P_LOW;
exports.P_NORMAL = P_NORMAL;
exports.P_HIGH = P_HIGH;
exports.P_IMPORTANT = P_IMPORTANT;
exports.default = frameScheduling$1;
exports.createFrameScheduling = createFrameScheduling;
exports.default = frameScheduling;
{
"name": "frame-scheduling",
"version": "0.7.0",
"version": "0.7.1",
"description": "Asynchronous start of functions in JS. Supports priority and interrupt execution every 16 milliseconds, to achieve 60fps.",
"scripts": {
"build": "rollup -c",
"size": "npm run build && size-limit",
"prepublishOnly": "npm run build",
"test": "jest",
"test": "npm run test:unit && npm run size",
"test:unit": "jest",
"test:coverage": "jest --coverage",

@@ -13,3 +15,6 @@ "test:watch": "jest --watch",

},
"files": [ "dist", "src" ],
"files": [
"dist",
"src"
],
"main": "dist/frameScheduling.js",

@@ -24,2 +29,8 @@ "module": "dist/frameScheduling.esm.js",

"keywords": [],
"size-limit": [
{
"path": "dist/frameScheduling.js",
"limit": "930 B"
}
],
"author": "Andey Marchenko <tom910ru@gmail.com>",

@@ -32,13 +43,14 @@ "license": "MIT",

"devDependencies": {
"@types/jest": "^21.1.4",
"@types/node": "^8.0.46",
"coveralls": "^3.0.0",
"jest": "^21.2.1",
"prettier": "1.7.4",
"rollup": "^0.64.1",
"rollup-plugin-typescript2": "^0.16.1",
"ts-jest": "^21.1.4",
"tslint": "^5.8.0",
"typescript": "^3.0.1"
"@types/jest": "^24.0.13",
"@types/node": "^12.0.4",
"coveralls": "^3.0.3",
"jest": "^24.8.0",
"prettier": "1.17.1",
"rollup": "^1.13.1",
"rollup-plugin-typescript2": "^0.21.1",
"size-limit": "^1.3.5",
"ts-jest": "^24.0.2",
"tslint": "^5.17.0",
"typescript": "^3.5.1"
}
}

@@ -1,11 +0,19 @@

# Frame Scheduling
[![Build Status](https://travis-ci.org/Tom910/frame-scheduling.svg?branch=master)](https://travis-ci.org/Tom910/frame-scheduling)
[![Coverage Status](https://coveralls.io/repos/github/Tom910/frame-scheduling/badge.svg?branch=master)](https://coveralls.io/github/Tom910/frame-scheduling?branch=master)
# Frame Scheduling
A tiny module which allows run a non-blocking layout many tasks.
* **Fast.** Contains low overhead and optimized for running lots of tasks without drop fps
* **Small.** 930 B (minified and gzipped). No dependencies. It uses [Size Limit](https://github.com/ai/size-limit) to control size.
* **Priority** Separate tasks into different priorities. Try to complete priority tasks as quickly as possible.
* **Isomorphic.** work in browser and node js.
```js
import frameScheduling, { P_IMPORTANT } from 'frame-scheduling';
frameScheduling(() => { Action() }, { priority: P_IMPORTANT });
frameScheduling(() => { console.log('async task') });
```
[Demo](https://codesandbox.io/s/admiring-ride-jdoq0)

@@ -24,4 +32,4 @@ Asynchronous running tasks in JavaScript based on requestAnimationFrame. Supports priority and interrupt execution every 16 milliseconds, to achieve 60fps.

## Example
### Priority
## Priority
```js

@@ -31,8 +39,11 @@ import frameScheduling, { P_IMPORTANT, P_LOW } from 'frame-scheduling';

frameScheduling(() => { result.push('Ember') }, { priority: P_LOW })
frameScheduling(() => { result.push('Angular') })
frameScheduling(() => { result.push('React') }, { priority: P_IMPORTANT })
frameScheduling(() => { result.push('A') }, { priority: P_LOW })
frameScheduling(() => { result.push('B') })
frameScheduling(() => { result.push('C') }, { priority: P_IMPORTANT })
frameScheduling(() => { result.push('D') }, { priority: 1000 })
console.log(result) // > ['React', 'Angular', 'Ember']
// after doing
console.log(result) // > ['D', 'C', 'B', 'A']
```
perform priority tasks first

@@ -43,17 +54,18 @@ ### framing

frameScheduling(() => 'function 1') // light < 1ms exec
frameScheduling(() => 'function 2') // heavy > 17ms exec
frameScheduling(() => 'function 3') // heavy > 17ms exec
frameScheduling(() => 'function 4') // light < 1ms exec
frameScheduling(() => 'function 5') // light < 1ms exec
frameScheduling(() => lightFunction()) // light < 1ms exec
frameScheduling(() => heavyFunction()) // heavy > 17ms exec
frameScheduling(() => heavyFunction2()) // heavy > 17ms exec
frameScheduling(() => lightFunction2()) // light < 1ms exec
frameScheduling(() => lightFunction3()) // light < 1ms exec
/*
Runs in frame
| function 1
| function 2
| function 3
| function 4
| function 5
| lightFunction
| heavyFunction
| heavyFunction2
| lightFunction2
| lightFunction3
*/
```
frame-scheduling aims to achieve 60 fps

@@ -60,0 +72,0 @@ ## Options

@@ -1,12 +0,5 @@

const context = typeof window !== "undefined" ? window : global;
import { PriorityUniqQueue } from "./priorityUniqQueue";
import { LinkedList } from "./linkedList";
import { defer as defaultDefer, Defer } from "./defer";
let defer: (f: () => void) => void;
if ("requestAnimationFrame" in context) {
defer = requestAnimationFrame.bind(context);
} else if ("setImmediate" in context) {
defer = setImmediate.bind(context);
} else {
defer = setTimeout.bind(context);
}
const TIME_LIFE_FRAME = 16; // 16ms === 60fps

@@ -20,196 +13,6 @@

interface QueueItem<T> { priority: number; value: T; }
class PriorityUniqQueue<T> {
private heapContainer: Array<QueueItem<T>>;
private hashPriority: Record<string, T>;
constructor() {
this.heapContainer = [];
this.hashPriority = Object.create(null);
}
public peek() {
return this.heapContainer[0].value;
}
public poll() {
let item;
if (this.heapContainer.length === 1) {
item = (this.heapContainer.pop() as QueueItem<T>);
} else {
item = this.heapContainer[0];
this.heapContainer[0] = (this.heapContainer.pop() as QueueItem<T>);
this.heapifyDown();
}
delete this.hashPriority[item.priority];
return item.value;
}
public add(priority: number, value: T) {
this.heapContainer.push({ priority, value });
this.heapifyUp();
this.hashPriority[priority] = value;
}
public isEmpty() {
return !this.heapContainer.length;
}
public get(priority: number) {
return this.hashPriority[priority];
}
public rising() {
const keys = Object.keys(this.hashPriority);
for (let i = keys.length; i > 0; i--) {
const key = keys[i - 1];
this.hashPriority[Number(key) + 1] = this.hashPriority[key];
delete this.hashPriority[key];
}
for (let j = 0; j < this.heapContainer.length; j++) {
this.heapContainer[j].priority += 1;
}
}
private heapifyUp(customStartIndex?: number) {
let currentIndex = customStartIndex || this.heapContainer.length - 1;
while (
this.hasParent(currentIndex)
&& !this.pairIsInCorrectOrder(
this.heapContainer[this.getParentIndex(currentIndex)],
this.heapContainer[currentIndex],
)
) {
this.swap(currentIndex, this.getParentIndex(currentIndex));
currentIndex = this.getParentIndex(currentIndex);
}
}
private heapifyDown(customStartIndex?: number) {
let currentIndex = customStartIndex || 0;
let nextIndex = null;
while (this.hasLeftChild(currentIndex)) {
if (
this.hasRightChild(currentIndex)
&& this.pairIsInCorrectOrder(this.rightChild(currentIndex), this.leftChild(currentIndex))
) {
nextIndex = this.getRightChildIndex(currentIndex);
} else {
nextIndex = this.getLeftChildIndex(currentIndex);
}
if (this.pairIsInCorrectOrder(
this.heapContainer[currentIndex],
this.heapContainer[nextIndex],
)) {
break;
}
this.swap(currentIndex, nextIndex);
currentIndex = nextIndex;
}
}
private pairIsInCorrectOrder(firstElement: QueueItem<T>, secondElement: QueueItem<T>) {
return firstElement.priority >= secondElement.priority;
}
private getLeftChildIndex(parentIndex: number) {
return (2 * parentIndex) + 1;
}
private getRightChildIndex(parentIndex: number) {
return (2 * parentIndex) + 2;
}
private getParentIndex(childIndex: number) {
return Math.floor((childIndex - 1) / 2);
}
private hasParent(childIndex: number) {
return this.getParentIndex(childIndex) >= 0;
}
private hasLeftChild(parentIndex: number) {
return this.getLeftChildIndex(parentIndex) < this.heapContainer.length;
}
private hasRightChild(parentIndex: number) {
return this.getRightChildIndex(parentIndex) < this.heapContainer.length;
}
private leftChild(parentIndex: number) {
return this.heapContainer[this.getLeftChildIndex(parentIndex)];
}
private rightChild(parentIndex: number) {
return this.heapContainer[this.getRightChildIndex(parentIndex)];
}
private swap(indexOne: number, indexTwo: number) {
const tmp = this.heapContainer[indexTwo];
this.heapContainer[indexTwo] = this.heapContainer[indexOne];
this.heapContainer[indexOne] = tmp;
}
}
interface ListNode {
value: () => void;
next: ListNode | null;
}
class LinkedList {
private length: number;
private head: ListNode | null;
private last: ListNode | null;
constructor() {
this.head = null;
this.last = null;
this.length = 0;
}
public push(value: () => void) {
const node: ListNode = {
next: null,
value,
};
if (this.length === 0) {
this.head = node;
this.last = node;
} else {
(this.last as ListNode).next = node;
this.last = node;
}
this.length++;
}
public shift() {
const currentHead = this.head as ListNode;
const value = currentHead.value;
this.head = currentHead.next;
this.length--;
return value;
}
public isEmpty() {
return this.length === 0;
}
}
const frameScheduling = () => {
export const createFrameScheduling = (
defer: Defer = defaultDefer,
lifeFrame: number = TIME_LIFE_FRAME
) => {
const heapJobs = new PriorityUniqQueue<LinkedList>();

@@ -220,18 +23,16 @@ let deferScheduled = false;

if (!deferScheduled) {
deferScheduled = true;
defer(runJobs);
}
deferScheduled = true;
};
const addJob = (callback: () => void, priority: number) => {
const getJob = heapJobs.get(priority);
let newLinkedList;
let job = heapJobs.get(priority);
if (!getJob) {
newLinkedList = new LinkedList();
heapJobs.add(priority, newLinkedList);
if (!job) {
job = new LinkedList();
heapJobs.add(priority, job);
}
((getJob || newLinkedList) as LinkedList).push(callback);
job.push(callback);
};

@@ -243,10 +44,9 @@

while (true) {
if (heapJobs.isEmpty() || Date.now() - timeRun > TIME_LIFE_FRAME) {
if (heapJobs.isEmpty() || Date.now() - timeRun > lifeFrame) {
break;
} else {
const jobs = heapJobs.peek();
const job = jobs.shift();
try {
job();
(jobs.shift())();
} catch (e) {

@@ -271,3 +71,6 @@ console.error(e); // tslint:disable-line

return function scheduling(callback: () => void, { priority = P_NORMAL } = {}) {
return function scheduling(
callback: () => void,
{ priority = P_NORMAL } = {}
) {
addJob(callback, priority);

@@ -279,2 +82,2 @@

export default frameScheduling();
export default createFrameScheduling();
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