routie dev init since i didn't adhere to any proper guidance up until now

This commit is contained in:
2026-04-29 22:27:29 -06:00
commit e1dabb71e2
15301 changed files with 3562618 additions and 0 deletions
+20
View File
@@ -0,0 +1,20 @@
Copyright (c) 2024, Google LLC
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+133
View File
@@ -0,0 +1,133 @@
# `sync-message-port`
This package exposes a utility class that encapsulates the ability to send and
receive messages with arbitrary structure across Node.js worker boundaries. It
can be used as the building block for synchronous versions of APIs that are
traditionally only available asynchronously in the Node.js ecosystem by running
the asynchronous APIs in a worker and accessing their results synchronously from
the main thread.
See [the `sync-child-process` package] for an example of `sync-message-port` in
action.
[the `sync-child-process` package]: https://github.com/sass/sync-child-process
[**API Docs**]
[**API Docs**]: https://sass.github.io/sync-message-port/classes/SyncMessagePort.html
## Usage
1. Use [`SyncMessagePort.createChannel()`] to create a message channel that's
set up to be compatible with `SyncMessagePort`s. A normal `MessageChannel`
won't work!
2. You can send this `MessageChannel`'s ports across worker boundaries just like
any other `MessagePort`. Send one to the worker you want to communicate with
synchronously.
3. Once you're ready to start sending and receiving messages, wrap *both* ports
in [`new SyncMessagePort()`], even if one is only ever going to be sending
messages and not receiving them.
4. Use [`SyncMessagePort.postMessage()`] to send messages and
`SyncMessagePort.receiveMessage()` to receive them synchronously.
[`SyncMessagePort.createChannel()`]: https://sass.github.io/sync-message-port/classes/SyncMessagePort.html#createChannel
[`new SyncMessagePort()`]: https://sass.github.io/sync-message-port/classes/SyncMessagePort.html#constructor
[`SyncMessagePort.postMessage()`]: https://sass.github.io/sync-message-port/classes/SyncMessagePort.html#postMessage
[`SyncMessagePort.receiveMessage()`]: https://sass.github.io/sync-message-port/classes/SyncMessagePort.html#receiveMessage
```js
import {Worker} from 'node:worker_threads';
import {SyncMessagePort} from 'sync-message-port';
// or
// const {SyncMessagePort} = require('sync-message-port');
// Channels must be created using this function. A MessageChannel created by
// hand won't work.
const channel = SyncMessagePort.createChannel();
const localPort = new SyncMessagePort(channel.port1);
const worker = new Worker(`
import {workerData} from 'node:worker_threads';
import {SyncMessagePort} from 'sync-message-port';
const remotePort = new SyncMessagePort(workerData.port);
setTimeout(() => {
remotePort.postMessage("hello from worker!");
}, 2000);
`, {
workerData: {port: channel.port2},
transferList: [channel.port2],
eval: true,
});
// Note that because workers report errors asynchronously, this won't report an
// error if the worker fails to load because the main thread will be
// synchronously waiting for its first message.
worker.on('error', console.error);
console.log(localPort.receiveMessage());
```
## Why synchrony?
Although JavaScript in general and Node.js in particular are typically designed
to embrace asynchrony, there are a number of reasons why a synchronous API may
be preferable or even necessary.
### No a/synchronous polymorphism
Although `async`/`await` and the `Promise` API has substantially improved the
usability of writing asynchronous code in JavaScript, it doesn't address one
core issue: there's no way to write code that's *polymorphic* over asynchrony.
Put in simpler terms, there's no language-level way to write a complex function
that takes a callback and to run that functions synchronously if the callback is
synchronous and asynchronously otherwise. The only option is to write the
function twice.
This poses a real, practical problem when interacting with libraries. Suppose
you have a library that takes a callback option—for example, an HTML
sanitization library that takes a callback to determine how to handle a given
`<a href="...">`. The library doesn't need to do any IO itself, so it's written
synchronously. But what if your callback wants to make an HTTP request to
determine how to handle a tag? You're stuck unless you can make that request
synchronous. This library makes that possible.
### Performance considerations
Asynchrony is generally more performant in situations where there's a large
amount of concurrent IO happening. But when performance is CPU-bound, it's often
substantially worse due to the overhead of bouncing back and forth between the
event loop and user code.
As a real-world example, the Sass compiler API supports both synchronous and
asynchronous code paths to work around the polymorphism problem described above.
The logic of these paths is exactly the same—the only difference is that the
asynchronous path's functions all return `Promise`s instead of synchronous
values. Compiling with the asynchronous path often takes 2-3x longer than with
the synchronous path. This means that being able to run plugins synchronously
can provide a substantial overall performance gain, even if the plugins
themselves lose the benefit of concurrency.
## How does it work?
This uses [`Atomics`] and [`SharedArrayBuffer`] under the covers to signal
across threads when messages are available, and
[`worker_threads.receiveMessageOnPort()`] to actually retrieve messages.
[`Atomics`]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Atomics
[`SharedArrayBuffer`]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/SharedArrayBuffer
[`worker_threads.receiveMessageOnPort()`]: https://nodejs.org/api/worker_threads.html#workerreceivemessageonportport
### Can I use this in a browser?
Unfortunately, no. Browsers don't support any equivalent of
`worker_threads.receiveMessageOnPort()`, even within worker threads. You could
make a similar package that can transmit only binary data (or data that can be
encoded as binary) using only `SharedArrayBuffer`, but that's outside the scope
of this package.
Disclaimer: this is not an official Google product.
+35
View File
@@ -0,0 +1,35 @@
/**
* A counter that can be atomically incremented and decremented, and which
* callers can synchronously listen for it becoming non-zero.
*
* This can be "open" or "closed"; once it's closed, {@link wait} will no longer
* emit useful events.
*/
export declare class AtomicCounter {
/**
* The underlying BigInt64Array.
*
* The first BigInt64 represents the current value of the counter. The second
* BigInt64 is used to track the closed state.
*/
private readonly buffer;
constructor(buffer: SharedArrayBuffer);
/** Atomically decrement the current value by one. */
decrement(): void;
/** Atomically increment the current value by one. */
increment(): void;
/**
* Closes the counter.
*
* This will cause any outstanding calls to {@link wait} on any thread to
* return `true` immediately.
*/
close(): void;
/**
* Waits until the current value is not zero or the counter is closed.
*
* Returns `true` when the counter is non-zero *or* when it's closed. Returns
* `false` if the counter remains zero for `timeout` milliseconds.
*/
wait(timeout?: number): boolean;
}
+68
View File
@@ -0,0 +1,68 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.AtomicCounter = void 0;
/**
* A counter that can be atomically incremented and decremented, and which
* callers can synchronously listen for it becoming non-zero.
*
* This can be "open" or "closed"; once it's closed, {@link wait} will no longer
* emit useful events.
*/
class AtomicCounter {
/**
* The underlying BigInt64Array.
*
* The first BigInt64 represents the current value of the counter. The second
* BigInt64 is used to track the closed state.
*/
buffer;
constructor(buffer) {
if (buffer.byteLength !== 16) {
throw new Error('SharedArrayBuffer must have a byteLength of 16.');
}
this.buffer = new BigInt64Array(buffer);
}
/** Atomically decrement the current value by one. */
decrement() {
Atomics.sub(this.buffer, 0, 1n);
}
/** Atomically increment the current value by one. */
increment() {
if (Atomics.add(this.buffer, 0, 1n) === 0n) {
Atomics.notify(this.buffer, 0, 1);
}
}
/**
* Closes the counter.
*
* This will cause any outstanding calls to {@link wait} on any thread to
* return `true` immediately.
*/
close() {
// The current value is no longer relevant once closed, therefore set it to
// non-zero to prevent a potential deadlock when `Atomics.notify` is called
// immediately before `Atomics.wait`.
if (Atomics.compareExchange(this.buffer, 1, 0n, 1n) === 0n &&
Atomics.compareExchange(this.buffer, 0, 0n, 1n) === 0n) {
Atomics.notify(this.buffer, 0);
}
}
/**
* Waits until the current value is not zero or the counter is closed.
*
* Returns `true` when the counter is non-zero *or* when it's closed. Returns
* `false` if the counter remains zero for `timeout` milliseconds.
*/
wait(timeout) {
while (Atomics.load(this.buffer, 0) === 0n &&
Atomics.load(this.buffer, 1) === 0n) {
const result = Atomics.wait(this.buffer, 0, 0n, timeout);
if (result !== 'ok') {
return result !== 'timed-out';
}
}
return true;
}
}
exports.AtomicCounter = AtomicCounter;
//# sourceMappingURL=atomic_counter.js.map
@@ -0,0 +1 @@
{"version":3,"file":"atomic_counter.js","sourceRoot":"","sources":["../../lib/atomic_counter.ts"],"names":[],"mappings":";;;AAAA;;;;;;GAMG;AACH,MAAa,aAAa;IACxB;;;;;OAKG;IACc,MAAM,CAAgB;IAEvC,YAAY,MAAyB;QACnC,IAAI,MAAM,CAAC,UAAU,KAAK,EAAE,EAAE,CAAC;YAC7B,MAAM,IAAI,KAAK,CAAC,iDAAiD,CAAC,CAAC;QACrE,CAAC;QACD,IAAI,CAAC,MAAM,GAAG,IAAI,aAAa,CAAC,MAAM,CAAC,CAAC;IAC1C,CAAC;IAED,qDAAqD;IACrD,SAAS;QACP,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC;IAClC,CAAC;IAED,qDAAqD;IACrD,SAAS;QACP,IAAI,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC;YAC3C,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;QACpC,CAAC;IACH,CAAC;IAED;;;;;OAKG;IACH,KAAK;QACH,2EAA2E;QAC3E,2EAA2E;QAC3E,qCAAqC;QACrC,IACE,OAAO,CAAC,eAAe,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,EAAE,EAAE,CAAC,KAAK,EAAE;YACtD,OAAO,CAAC,eAAe,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,EAAE,EAAE,CAAC,KAAK,EAAE,EACtD,CAAC;YACD,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;QACjC,CAAC;IACH,CAAC;IAED;;;;;OAKG;IACH,IAAI,CAAC,OAAgB;QACnB,OACE,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC,KAAK,EAAE;YACnC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC,KAAK,EAAE,EACnC,CAAC;YACD,MAAM,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,EAAE,OAAO,CAAC,CAAC;YACzD,IAAI,MAAM,KAAK,IAAI,EAAE,CAAC;gBACpB,OAAO,MAAM,KAAK,WAAW,CAAC;YAChC,CAAC;QACH,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;CACF;AAhED,sCAgEC"}
+81
View File
@@ -0,0 +1,81 @@
import { EventEmitter } from 'events';
import { MessageChannel, MessagePort, Transferable } from 'worker_threads';
/**
* Options that can be passed to {@link SyncMessagePort.receiveMessage}.
*/
export interface ReceiveMessageOptions {
/**
* The time (in milliseconds) to wait for a message before returning {@link
* timeoutValue} (if set) or throwing a [TimeoutException] otherwise.
*/
timeout?: number;
/**
* If a message isn't received within {@link timeout} milliseconds, this value
* is returned. Ignored if {@link timeout} is not set.
*/
timeoutValue?: unknown;
/**
* If the underlying channel is closed before calling {@link
* SyncMessagePort.receiveMessage} or while a call is pending, return this
* value.
*/
closedValue?: unknown;
}
/**
* An exception thrown by {@link SyncMessagePort.receiveMessage} if a message
* isn't received within {@link ReceivedMessageOptions.timeout} milliseconds.
*/
export declare class TimeoutException extends Error {
constructor(message: string);
}
/**
* A communication port that can receive messages synchronously from another
* `SyncMessagePort`.
*
* This also emits the same asynchronous events as `MessagePort`. Messages are
* preferentially sent to {@link receiveMessage} if a call to it is outstanding,
* and only sent to the event handler if they weren't received synchronously.
*/
export declare class SyncMessagePort extends EventEmitter {
private readonly port;
/** Creates a channel whose ports can be passed to `new SyncMessagePort()`. */
static createChannel(): MessageChannel;
/**
* An atomic counter of messages posted yet to be received.
*/
private readonly postCounter;
/**
* An atomic counter of messages available to be received.
*/
private readonly receiveCounter;
/**
* Creates a new message port. The `port` must be created by
* `SyncMessagePort.createChannel()` and must connect to a port passed to
* another `SyncMessagePort` in another worker.
*/
constructor(port: MessagePort);
/** See `MessagePort.postMesage()`. */
postMessage(value: unknown, transferList?: Transferable[]): void;
/**
* Returns the message sent by the other port, if one is available. This *does
* not* block, and will return `undefined` immediately if no message is
* available. In order to distinguish between a message with value `undefined`
* and no message, a message is return in an object with a `message` field.
*
* It does *not* throw an error if the port is closed when this is called;
* instead, it just returns `undefined`.
*/
receiveMessageIfAvailable(): {
message: unknown;
} | undefined;
/**
* Blocks and returns the next message sent by the other port.
*
* Throws an error if the channel is closed and all messages are drained,
* including if it closes while this is waiting for a message, unless
* {@link ReceiveMessageOptions.closedValue} is passed.
*/
receiveMessage(options?: ReceiveMessageOptions): unknown;
/** See `MessagePort.close()`. */
close(): void;
}
+145
View File
@@ -0,0 +1,145 @@
"use strict";
// Copyright 2021 Google LLC. Use of this source code is governed by an
// MIT-style license that can be found in the LICENSE file or at
// https://opensource.org/licenses/MIT.
Object.defineProperty(exports, "__esModule", { value: true });
exports.SyncMessagePort = exports.TimeoutException = void 0;
const events_1 = require("events");
const worker_threads_1 = require("worker_threads");
const atomic_counter_1 = require("./atomic_counter");
/**
* An exception thrown by {@link SyncMessagePort.receiveMessage} if a message
* isn't received within {@link ReceivedMessageOptions.timeout} milliseconds.
*/
class TimeoutException extends Error {
constructor(message) {
super(message);
}
}
exports.TimeoutException = TimeoutException;
/**
* A communication port that can receive messages synchronously from another
* `SyncMessagePort`.
*
* This also emits the same asynchronous events as `MessagePort`. Messages are
* preferentially sent to {@link receiveMessage} if a call to it is outstanding,
* and only sent to the event handler if they weren't received synchronously.
*/
class SyncMessagePort extends events_1.EventEmitter {
port;
/** Creates a channel whose ports can be passed to `new SyncMessagePort()`. */
static createChannel() {
const channel = new worker_threads_1.MessageChannel();
// 16 bytes is required for `AtomicCounter`.
const buffer1 = new SharedArrayBuffer(16);
const buffer2 = new SharedArrayBuffer(16);
// Queue up messages on each port so the caller doesn't have to explicitly
// pass the buffer around along with them.
channel.port1.postMessage(buffer1);
channel.port1.postMessage(buffer2);
channel.port2.postMessage(buffer2);
channel.port2.postMessage(buffer1);
return channel;
}
/**
* An atomic counter of messages posted yet to be received.
*/
postCounter;
/**
* An atomic counter of messages available to be received.
*/
receiveCounter;
/**
* Creates a new message port. The `port` must be created by
* `SyncMessagePort.createChannel()` and must connect to a port passed to
* another `SyncMessagePort` in another worker.
*/
constructor(port) {
super();
this.port = port;
const buffer1 = (0, worker_threads_1.receiveMessageOnPort)(this.port)?.message;
const buffer2 = (0, worker_threads_1.receiveMessageOnPort)(this.port)?.message;
if (!buffer1 || !buffer2) {
throw new Error('new SyncMessagePort() must be passed a port from ' +
'SyncMessagePort.createChannel().');
}
this.postCounter = new atomic_counter_1.AtomicCounter(buffer1);
this.receiveCounter = new atomic_counter_1.AtomicCounter(buffer2);
const messageHandler = () => {
this.receiveCounter.wait();
this.receiveCounter.decrement();
};
this.port.on('messageerror', (error) => {
messageHandler();
if (!this.listenerCount('messageerror')) {
throw error;
}
});
this.on('newListener', (event, listener) => {
if (event === 'message' && !this.listenerCount(event)) {
this.port.on(event, messageHandler);
}
this.port.on(event, listener);
});
this.on('removeListener', (event, listener) => {
this.port.removeListener(event, listener);
if (event === 'message' && !this.listenerCount(event)) {
this.port.removeListener(event, messageHandler);
}
});
}
/** See `MessagePort.postMesage()`. */
postMessage(value, transferList) {
// @ts-expect-error: TypeScript gets confused with the overloads.
this.port.postMessage(value, transferList);
this.postCounter.increment();
}
/**
* Returns the message sent by the other port, if one is available. This *does
* not* block, and will return `undefined` immediately if no message is
* available. In order to distinguish between a message with value `undefined`
* and no message, a message is return in an object with a `message` field.
*
* It does *not* throw an error if the port is closed when this is called;
* instead, it just returns `undefined`.
*/
receiveMessageIfAvailable() {
const message = (0, worker_threads_1.receiveMessageOnPort)(this.port);
if (message) {
this.receiveCounter.wait();
this.receiveCounter.decrement();
}
return message;
}
/**
* Blocks and returns the next message sent by the other port.
*
* Throws an error if the channel is closed and all messages are drained,
* including if it closes while this is waiting for a message, unless
* {@link ReceiveMessageOptions.closedValue} is passed.
*/
receiveMessage(options) {
if (!this.receiveCounter.wait(options?.timeout)) {
if ('timeoutValue' in options)
return options.timeoutValue;
throw new TimeoutException('SyncMessagePort.receiveMessage() timed out.');
}
const message = (0, worker_threads_1.receiveMessageOnPort)(this.port);
if (message) {
this.receiveCounter.decrement();
return message.message;
}
// The port is closed and all remaining messages are drained.
if (options && 'closedValue' in options)
return options.closedValue;
throw new Error("The SyncMessagePort's channel is closed.");
}
/** See `MessagePort.close()`. */
close() {
this.port.close();
this.postCounter.close();
this.receiveCounter.close();
}
}
exports.SyncMessagePort = SyncMessagePort;
//# sourceMappingURL=index.js.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../lib/index.ts"],"names":[],"mappings":"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"}
File diff suppressed because one or more lines are too long
+42
View File
@@ -0,0 +1,42 @@
{
"name": "sync-message-port",
"version": "1.2.0",
"description": "A Node.js communication port that can pass messages synchronously between workers",
"repository": "sass/sync-message-port",
"author": "Google Inc.",
"license": "MIT",
"exports": {
"types": "./dist/lib/index.d.ts",
"default": "./dist/lib/index.js"
},
"main": "dist/lib/index.js",
"types": "dist/lib/index.d.ts",
"files": [
"dist/**/*"
],
"engines": {
"node": ">=16.0.0"
},
"scripts": {
"check": "npm-run-all check:gts check:tsc",
"check:gts": "gts check",
"check:tsc": "tsc --noEmit",
"clean": "gts clean",
"compile": "tsc -p tsconfig.build.json",
"doc": "typedoc lib/index.ts",
"fix": "gts fix",
"test": "jest"
},
"devDependencies": {
"@types/jest": "^30.0.0",
"@types/node": "^25.0.3",
"gts": "^7.0.0",
"jest": "^30.0.3",
"minipass": "7.1.2",
"npm-run-all": "^4.1.5",
"ts-jest": "^29.0.5",
"ts-node": "^10.2.1",
"typedoc": "^0.28.0",
"typescript": "^5.0.2"
}
}