Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions ext/node/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -501,6 +501,7 @@ deno_core::extension!(deno_node,
"internal/normalize_encoding.ts",
"internal/options.ts",
"internal/primordials.mjs",
"internal/priority_queue.ts",
"internal/process/per_thread.mjs",
"internal/process/report.ts",
"internal/process/warning.ts",
Expand Down
2 changes: 2 additions & 0 deletions ext/node/polyfills/01_require.js
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,7 @@ import internalFsUtils from "ext:deno_node/internal/fs/utils.mjs";
import internalHttp from "ext:deno_node/internal/http.ts";
import internalHttp2Core from "ext:deno_node/internal/http2/core.ts";
import internalHttp2Util from "ext:deno_node/internal/http2/util.ts";
import internalPriorityQueue from "ext:deno_node/internal/priority_queue.ts";
import internalReadlineUtils from "ext:deno_node/internal/readline/utils.mjs";
import internalStreamsAddAbortSignal from "ext:deno_node/internal/streams/add-abort-signal.js";
import internalStreamsLazyTransform from "ext:deno_node/internal/streams/lazy_transform.js";
Expand Down Expand Up @@ -239,6 +240,7 @@ function setupBuiltinModules() {
"internal/http": internalHttp,
"internal/http2/core": internalHttp2Core,
"internal/http2/util": internalHttp2Util,
"internal/priority_queue": internalPriorityQueue,
"internal/readline/utils": internalReadlineUtils,
"internal/streams/add-abort-signal": internalStreamsAddAbortSignal,
"internal/streams/lazy_transform": internalStreamsLazyTransform,
Expand Down
136 changes: 136 additions & 0 deletions ext/node/polyfills/internal/priority_queue.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
// Copyright 2018-2026 the Deno authors. MIT license.
// Copyright Joyent, Inc. and other Node contributors.

// The PriorityQueue is a basic implementation of a binary heap that accepts
// a custom sorting function via its constructor. This function is passed
// the two nodes to compare, similar to the native Array#sort. Crucially
// this enables priority queues that are based on a comparison of more than
// just a single criteria.

// deno-lint-ignore-file no-explicit-any

type Comparator<T> = (a: T, b: T) => number;
type SetPosition<T> = (node: T, pos: number) => void;

export class PriorityQueue<T = any> {
#compare: Comparator<T> = (a: any, b: any) => a - b;
#heap: (T | undefined)[] = [undefined, undefined];
#setPosition?: SetPosition<T>;
#size = 0;

constructor(comparator?: Comparator<T>, setPosition?: SetPosition<T>) {
if (comparator !== undefined) {
this.#compare = comparator;
}
if (setPosition !== undefined) {
this.#setPosition = setPosition;
}
}

insert(value: T): void {
const heap = this.#heap;
const pos = ++this.#size;
heap[pos] = value;

this.percolateUp(pos);
}

peek(): T | undefined {
return this.#heap[1];
}

peekBottom(): T | undefined {
return this.#heap[this.#size];
}

percolateDown(pos: number): void {
const compare = this.#compare;
const setPosition = this.#setPosition;
const hasSetPosition = setPosition !== undefined;
const heap = this.#heap;
const size = this.#size;
const hsize = size >> 1;
const item = heap[pos] as T;

while (pos <= hsize) {
let child = pos << 1;
const nextChild = child + 1;
let childItem = heap[child] as T;

if (nextChild <= size && compare(heap[nextChild] as T, childItem) < 0) {
child = nextChild;
childItem = heap[nextChild] as T;
}

if (compare(item, childItem) <= 0) break;

if (hasSetPosition) {
setPosition(childItem, pos);
}

heap[pos] = childItem;
pos = child;
}

heap[pos] = item;
if (hasSetPosition) {
setPosition(item, pos);
}
}

percolateUp(pos: number): void {
const heap = this.#heap;
const compare = this.#compare;
const setPosition = this.#setPosition;
const hasSetPosition = setPosition !== undefined;
const item = heap[pos] as T;

while (pos > 1) {
const parent = pos >> 1;
const parentItem = heap[parent] as T;
if (compare(parentItem, item) <= 0) {
break;
}
heap[pos] = parentItem;
if (hasSetPosition) {
setPosition(parentItem, pos);
}
pos = parent;
}

heap[pos] = item;
if (hasSetPosition) {
setPosition(item, pos);
}
}

removeAt(pos: number): void {
const heap = this.#heap;
let size = this.#size;
heap[pos] = heap[size];
heap[size] = undefined;
size = --this.#size;

if (size > 0 && pos <= size) {
if (pos > 1 && this.#compare(heap[pos >> 1] as T, heap[pos] as T) > 0) {
this.percolateUp(pos);
} else {
this.percolateDown(pos);
}
}
}

shift(): T | undefined {
const heap = this.#heap;
const value = heap[1];
if (value === undefined) {
return undefined;
}

this.removeAt(1);

return value;
}
}

export default PriorityQueue;
1 change: 1 addition & 0 deletions tests/node_compat/config.jsonc
Original file line number Diff line number Diff line change
Expand Up @@ -2503,6 +2503,7 @@
"ignore": true,
"reason": "Tests Node.js internal modules (require('internal/...')) which are not exposed in Deno"
},
"parallel/test-priority-queue.js": {},
"parallel/test-process-abort.js": {},
"parallel/test-process-argv-0.js": {},
"parallel/test-process-available-memory.js": {},
Expand Down
Loading