Big News: Socket raises $60M Series C at a $1B valuation to secure software supply chains for AI-driven development.Announcement
Sign In

@ayonli/jsext

Package Overview
Dependencies
Maintainers
1
Versions
171
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@ayonli/jsext - npm Package Compare versions

Comparing version
0.4.5
to
0.4.6
+23
-0
augment.ts

@@ -10,4 +10,22 @@ import "./string/augment";

import "./error/augment";
import { AsyncFunction, AsyncGeneratorFunction } from ".";
declare global {
const AsyncFunction: AsyncFunctionConstructor;
const AsyncGeneratorFunction: AsyncGeneratorFunctionConstructor;
export interface AsyncFunction {
(...args: any[]): Promise<unknown>;
readonly length: number;
readonly name: string;
}
export interface AsyncFunctionConstructor {
new(...args: any[]): AsyncFunction;
(...args: any[]): AsyncFunction;
readonly length: number;
readonly name: string;
readonly prototype: AsyncFunction;
}
interface Constructor<T> extends Function {

@@ -27,1 +45,6 @@ new(...args: any[]): T;

}
// @ts-ignore
globalThis["AsyncFunction"] = AsyncFunction;
// @ts-ignore
globalThis["AsyncGeneratorFunction"] = AsyncGeneratorFunction;

@@ -12,2 +12,7 @@ "use strict";

require("./error/augment");
const _1 = require(".");
// @ts-ignore
globalThis["AsyncFunction"] = _1.AsyncFunction;
// @ts-ignore
globalThis["AsyncGeneratorFunction"] = _1.AsyncGeneratorFunction;
//# sourceMappingURL=augment.js.map
+1
-1

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

{"version":3,"file":"augment.js","sourceRoot":"","sources":["../augment.ts"],"names":[],"mappings":";;AAAA,4BAA0B;AAC1B,4BAA0B;AAC1B,2BAAyB;AACzB,gCAA8B;AAC9B,4BAA0B;AAC1B,0BAAwB;AACxB,6BAA2B;AAC3B,iCAA+B;AAC/B,2BAAyB"}
{"version":3,"file":"augment.js","sourceRoot":"","sources":["../augment.ts"],"names":[],"mappings":";;AAAA,4BAA0B;AAC1B,4BAA0B;AAC1B,2BAAyB;AACzB,gCAA8B;AAC9B,4BAA0B;AAC1B,0BAAwB;AACxB,6BAA2B;AAC3B,iCAA+B;AAC/B,2BAAyB;AACzB,wBAA0D;AAmC1D,aAAa;AACb,UAAU,CAAC,eAAe,CAAC,GAAG,gBAAa,CAAC;AAC5C,aAAa;AACb,UAAU,CAAC,wBAAwB,CAAC,GAAG,yBAAsB,CAAC"}
+793
-741
"use strict";
var _a;
Object.defineProperty(exports, "__esModule", { value: true });
exports.run = exports.read = exports.isSubclassOf = exports.mixins = exports.throttle = exports.wrap = exports.func = exports._try = exports.AsyncGeneratorFunction = exports.AsyncFunction = void 0;
const check_iterable_1 = require("check-iterable");
const number_1 = require("./number");
const isNode = typeof process === "object" && !!((_a = process.versions) === null || _a === void 0 ? void 0 : _a.node);
const throttleCaches = new Map();
exports.AsyncFunction = (async function () { }).constructor;
exports.AsyncGeneratorFunction = (async function* () { }).constructor;
function _try(fn, ...args) {
if (typeof fn === "function") {
try {
return _try(fn.apply(void 0, args));
}
catch (err) {
return [err, undefined];
}
}
let returns = fn;
// Implementation details should be ordered from complex to simple.
if ((0, check_iterable_1.isAsyncGenerator)(returns)) {
return (async function* () {
let input;
let result;
// Use `while` loop instead of `for...of...` in order to
// retrieve the return value of a generator function.
while (true) {
try {
const { done, value } = await returns.next(input);
if (done) {
result = value;
break;
}
else {
// Receive any potential input value that passed
// to the outer `next()` call, and pass them to
// `res.next()` in the next call.
input = yield Promise.resolve([null, value]);
}
}
catch (err) {
// If any error occurs, yield that error as resolved
// and break the loop immediately, indicating the
// process is forced broken.
yield Promise.resolve([err, undefined]);
break;
}
}
return [null, result];
})();
}
else if ((0, check_iterable_1.isGenerator)(returns)) {
return (function* () {
let input;
let result;
while (true) {
try {
const { done, value } = returns.next(input);
if (done) {
result = value;
break;
}
else {
input = yield [null, value];
}
}
catch (err) {
yield [err, undefined];
break;
}
}
return [null, result];
})();
}
else if (typeof (returns === null || returns === void 0 ? void 0 : returns.then) === "function") {
returns = returns.then((value) => [null, value]);
return Promise.resolve(returns).catch((err) => [err, undefined]);
}
else {
return [null, returns];
}
}
exports._try = _try;
/**
* The maximum number of workers allowed to exist at the same time.
* Inspired by Golang, creates a function that receives a `defer` function which can be used
* to carry deferred jobs that will be run after the main function is complete.
*
* The primary purpose of the workers is not mean to run tasks in parallel, but run them in separate
* from the main thread, so that aborting tasks can be achieved by terminating the worker thread and
* it will not affect the main thread.
* Multiple calls of the `defer` function is supported, and the callbacks are called in the
* LIFO order. Callbacks can be async functions if the main function is an async function or
* an async generator function, and all the running procedures will be awaited.
*
* That said, the worker thread can still be used to achieve parallelism, but it should be noticed
* that only the numbers of tasks that equals to the CPU core numbers will be run at the same time.
* @example
* const getVersion = await jsext.func(async (defer) => {
* const file = await fs.open("./package.json", "r");
* defer(() => file.close());
*
* const content = await file.readFile("utf8");
* const pkg = JSON.parse(content);
*
* return pkg.version as string;
* });
*/
const maxWorkerNum = 16;
const workerIdCounter = (0, number_1.sequence)(1, Number.MAX_SAFE_INTEGER, 1, true);
let workerPool = [];
// The worker consumer queue is nothing but a callback list, once a worker is available, the runner
// pop a consumer and run the callback, which will retry gaining the worker and retry the task.
const workerConsumerQueue = [];
function func(fn) {
return function (...args) {
var _a;
const callbacks = [];
const defer = (cb) => void callbacks.push(cb);
let result;
try {
const returns = fn.call(this, defer, ...args);
if ((0, check_iterable_1.isAsyncGenerator)(returns)) {
const gen = (async function* () {
var _a;
let input;
// Use `while` loop instead of `for...of...` in order to
// retrieve the return value of a generator function.
while (true) {
try {
const { done, value } = await returns.next(input);
if (done) {
result = { value, error: null };
break;
}
else {
// Receive any potential input value that passed
// to the outer `next()` call, and pass them to
// `res.next()` in the next call.
input = yield Promise.resolve(value);
}
}
catch (error) {
// If any error occurs, capture that error and break
// the loop immediately, indicating the process is
// forced broken.
result = { value: void 0, error };
break;
}
}
for (let i = callbacks.length - 1; i >= 0; i--) {
await ((_a = callbacks[i]) === null || _a === void 0 ? void 0 : _a.call(callbacks));
}
if (result.error) {
throw result.error;
}
else {
return result.value;
}
})();
return gen;
}
else if ((0, check_iterable_1.isGenerator)(returns)) {
const gen = (function* () {
var _a;
let input;
while (true) {
try {
const { done, value } = returns.next(input);
if (done) {
result = { value, error: null };
break;
}
else {
input = yield value;
}
}
catch (error) {
result = { value: void 0, error };
break;
}
}
for (let i = callbacks.length - 1; i >= 0; i--) {
(_a = callbacks[i]) === null || _a === void 0 ? void 0 : _a.call(callbacks);
}
if (result.error) {
throw result.error;
}
else {
return result.value;
}
})();
return gen;
}
else if (typeof (returns === null || returns === void 0 ? void 0 : returns.then) === "function") {
return Promise.resolve(returns).then(value => ({
value,
error: null,
})).catch((error) => ({
value: void 0,
error,
})).then(async (result) => {
var _a;
for (let i = callbacks.length - 1; i >= 0; i--) {
await ((_a = callbacks[i]) === null || _a === void 0 ? void 0 : _a.call(callbacks));
}
if (result.error) {
throw result.error;
}
else {
return result.value;
}
});
}
else {
result = { value: returns, error: null };
}
}
catch (error) {
result = { value: void 0, error };
}
for (let i = callbacks.length - 1; i >= 0; i--) {
(_a = callbacks[i]) === null || _a === void 0 ? void 0 : _a.call(callbacks);
}
if (result.error) {
throw result.error;
}
else {
return result.value;
}
};
}
exports.func = func;
/**
* Wraps a function inside another function and returns a new function
* that copies the original function's name and properties.
*/
function wrap(fn, wrapper) {
const wrapped = function (...args) {
return wrapper.call(this, fn, ...args);
};
Object.defineProperty(wrapped, "name", Object.getOwnPropertyDescriptor(fn, "name"));
Object.defineProperty(wrapped, "length", Object.getOwnPropertyDescriptor(fn, "length"));
Object.defineProperty(wrapped, "toString", {
configurable: true,
enumerable: false,
writable: true,
value: fn.toString.bind(fn),
});
return wrapped;
}
exports.wrap = wrap;
const throttleCaches = new Map();
function throttle(handler, options) {
const key = typeof options === "number" ? null : options.for;
const duration = typeof options === "number" ? options : options.duration;
const handleCall = function (cache, ...args) {
var _a;
if (cache.result && Date.now() < ((_a = cache.expires) !== null && _a !== void 0 ? _a : 0)) {
if (cache.result.error) {
throw cache.result.error;
}
else {
return cache.result.value;
}
}
try {
const returns = handler.call(this, ...args);
cache.result = { value: returns };
cache.expires = Date.now() + duration;
return returns;
}
catch (error) {
cache.result = { error };
cache.expires = Date.now() + duration;
throw error;
}
};
if (!key) {
const cache = { for: null };
return function (...args) {
return handleCall.call(this, cache, ...args);
};
}
else {
let cache = throttleCaches.get(key);
if (!cache) {
cache = { for: key };
throttleCaches.set(key, cache);
}
return function (...args) {
return handleCall.call(this, cache, ...args);
};
}
}
exports.throttle = throttle;
/**
* Merges properties and methods only if they're missing in the class.

@@ -71,701 +331,430 @@ */

}
const jsext = {
try(fn, ...args) {
if (typeof fn === "function") {
try {
return jsext.try(fn.apply(void 0, args));
}
catch (err) {
return [err, undefined];
}
function mixins(base, ...mixins) {
const obj = { ctor: null };
obj.ctor = class extends base {
}; // make sure this class has no name
for (const mixin of mixins) {
if (typeof mixin == "function") {
mergeHierarchy(obj.ctor, mixin);
}
let returns = fn;
// Implementation details should be ordered from complex to simple.
if ((0, check_iterable_1.isAsyncGenerator)(returns)) {
return (async function* () {
let input;
let result;
// Use `while` loop instead of `for...of...` in order to
// retrieve the return value of a generator function.
while (true) {
try {
const { done, value } = await returns.next(input);
if (done) {
result = value;
break;
}
else {
// Receive any potential input value that passed
// to the outer `next()` call, and pass them to
// `res.next()` in the next call.
input = yield Promise.resolve([null, value]);
}
}
catch (err) {
// If any error occurs, yield that error as resolved
// and break the loop immediately, indicating the
// process is forced broken.
yield Promise.resolve([err, undefined]);
break;
}
}
return [null, result];
})();
else if (mixin && typeof mixin == "object") {
mergeIfNotExists(obj.ctor.prototype, mixin);
}
else if ((0, check_iterable_1.isGenerator)(returns)) {
return (function* () {
let input;
let result;
while (true) {
try {
const { done, value } = returns.next(input);
if (done) {
result = value;
break;
}
else {
input = yield [null, value];
}
}
catch (err) {
yield [err, undefined];
break;
}
}
return [null, result];
})();
}
else if (typeof (returns === null || returns === void 0 ? void 0 : returns.then) === "function") {
returns = returns.then((value) => [null, value]);
return Promise.resolve(returns).catch((err) => [err, undefined]);
}
else {
return [null, returns];
throw new TypeError("mixin must be a constructor or an object");
}
},
func(fn) {
return function (...args) {
var _a;
const callbacks = [];
const defer = (cb) => void callbacks.push(cb);
let result;
try {
const returns = fn.call(this, defer, ...args);
if ((0, check_iterable_1.isAsyncGenerator)(returns)) {
const gen = (async function* () {
var _a;
let input;
// Use `while` loop instead of `for...of...` in order to
// retrieve the return value of a generator function.
while (true) {
try {
const { done, value } = await returns.next(input);
if (done) {
result = { value, error: null };
break;
}
else {
// Receive any potential input value that passed
// to the outer `next()` call, and pass them to
// `res.next()` in the next call.
input = yield Promise.resolve(value);
}
}
catch (error) {
// If any error occurs, capture that error and break
// the loop immediately, indicating the process is
// forced broken.
result = { value: void 0, error };
break;
}
}
for (let i = callbacks.length - 1; i >= 0; i--) {
await ((_a = callbacks[i]) === null || _a === void 0 ? void 0 : _a.call(callbacks));
}
if (result.error) {
throw result.error;
}
else {
return result.value;
}
})();
return gen;
}
return obj.ctor;
}
exports.mixins = mixins;
/** Checks if a class is a subclass of another class. */
function isSubclassOf(ctor1, ctor2) {
return typeof ctor1 === "function"
&& typeof ctor2 === "function"
&& ctor1.prototype instanceof ctor2;
}
exports.isSubclassOf = isSubclassOf;
function read(source, eventMap = undefined) {
var _a;
if (typeof source[Symbol.asyncIterator] === "function") {
return source;
}
const iterable = {
ended: false,
error: null,
queue: [],
consumers: [],
next() {
return new Promise((resolve, reject) => {
if (this.error && !this.ended) {
// If there is error occurred during the last transmission and the iterator
// hasn't been closed, reject that error and stop the iterator immediately.
reject(this.error);
this.ended = true;
}
else if ((0, check_iterable_1.isGenerator)(returns)) {
const gen = (function* () {
var _a;
let input;
while (true) {
try {
const { done, value } = returns.next(input);
if (done) {
result = { value, error: null };
break;
}
else {
input = yield value;
}
}
catch (error) {
result = { value: void 0, error };
break;
}
}
for (let i = callbacks.length - 1; i >= 0; i--) {
(_a = callbacks[i]) === null || _a === void 0 ? void 0 : _a.call(callbacks);
}
if (result.error) {
throw result.error;
}
else {
return result.value;
}
})();
return gen;
else if (this.ended && !this.queue.length) {
// If the iterator has is closed, resolve the pending consumer with void
// value.
resolve({ value: void 0, done: true });
}
else if (typeof (returns === null || returns === void 0 ? void 0 : returns.then) === "function") {
return Promise.resolve(returns).then(value => ({
value,
error: null,
})).catch((error) => ({
value: void 0,
error,
})).then(async (result) => {
var _a;
for (let i = callbacks.length - 1; i >= 0; i--) {
await ((_a = callbacks[i]) === null || _a === void 0 ? void 0 : _a.call(callbacks));
}
if (result.error) {
throw result.error;
}
else {
return result.value;
}
});
else if (this.queue.length > 0) {
// If there are data in the queue, resolve the the first piece immediately.
resolve({ value: this.queue.shift(), done: false });
}
else {
result = { value: returns, error: null };
// If there are no queued data, push the consumer to a waiting queue.
this.consumers.push({ resolve, reject });
}
}
catch (error) {
result = { value: void 0, error };
}
for (let i = callbacks.length - 1; i >= 0; i--) {
(_a = callbacks[i]) === null || _a === void 0 ? void 0 : _a.call(callbacks);
}
if (result.error) {
throw result.error;
}
else {
return result.value;
}
};
},
wrap(fn, wrapper) {
const wrapped = function (...args) {
return wrapper.call(this, fn, ...args);
};
Object.defineProperty(wrapped, "name", Object.getOwnPropertyDescriptor(fn, "name"));
Object.defineProperty(wrapped, "length", Object.getOwnPropertyDescriptor(fn, "length"));
Object.defineProperty(wrapped, "toString", {
configurable: true,
enumerable: false,
writable: true,
value: fn.toString.bind(fn),
});
return wrapped;
},
throttle(handler, options) {
const key = typeof options === "number" ? null : options.for;
const duration = typeof options === "number" ? options : options.duration;
const handleCall = function (cache, ...args) {
var _a;
if (cache.result && Date.now() < ((_a = cache.expires) !== null && _a !== void 0 ? _a : 0)) {
if (cache.result.error) {
throw cache.result.error;
}
else {
return cache.result.value;
}
}
try {
const returns = handler.call(this, ...args);
cache.result = { value: returns };
cache.expires = Date.now() + duration;
return returns;
}
catch (error) {
cache.result = { error };
cache.expires = Date.now() + duration;
throw error;
}
};
if (!key) {
const cache = { for: null };
return function (...args) {
return handleCall.call(this, cache, ...args);
};
});
}
};
const handleMessage = (data) => {
var _a;
if (iterable.consumers.length > 0) {
(_a = iterable.consumers.shift()) === null || _a === void 0 ? void 0 : _a.resolve({ value: data, done: false });
}
else {
let cache = throttleCaches.get(key);
if (!cache) {
cache = { for: key };
throttleCaches.set(key, cache);
}
return function (...args) {
return handleCall.call(this, cache, ...args);
};
iterable.queue.push(data);
}
},
mixins(base, ...mixins) {
const obj = { ctor: null };
obj.ctor = class extends base {
}; // make sure this class has no name
for (const mixin of mixins) {
if (typeof mixin == "function") {
mergeHierarchy(obj.ctor, mixin);
}
else if (mixin && typeof mixin == "object") {
mergeIfNotExists(obj.ctor.prototype, mixin);
}
else {
throw new TypeError("mixin must be a constructor or an object");
}
};
const handleClose = () => {
iterable.ended = true;
let consumer;
while (consumer = iterable.consumers.shift()) {
consumer.resolve({ value: undefined, done: true });
}
return obj.ctor;
},
isSubclassOf(ctor1, ctor2) {
return typeof ctor1 === "function"
&& typeof ctor2 === "function"
&& ctor1.prototype instanceof ctor2;
},
read(source, eventMap = undefined) {
var _a;
if (typeof source[Symbol.asyncIterator] === "function") {
return source;
};
const handleError = (err) => {
iterable.error = err;
if (iterable.consumers.length > 0) {
iterable.consumers.forEach(item => {
item.reject(err);
});
iterable.consumers = [];
}
const iterable = {
ended: false,
error: null,
queue: [],
consumers: [],
next() {
return new Promise((resolve, reject) => {
if (this.error && !this.ended) {
// If there is error occurred during the last transmission and the iterator
// hasn't been closed, reject that error and stop the iterator immediately.
reject(this.error);
this.ended = true;
}
else if (this.ended && !this.queue.length) {
// If the iterator has is closed, resolve the pending consumer with void
// value.
resolve({ value: void 0, done: true });
}
else if (this.queue.length > 0) {
// If there are data in the queue, resolve the the first piece immediately.
resolve({ value: this.queue.shift(), done: false });
}
else {
// If there are no queued data, push the consumer to a waiting queue.
this.consumers.push({ resolve, reject });
}
});
}
};
const handleMessage = (data) => {
var _a;
if (iterable.consumers.length > 0) {
(_a = iterable.consumers.shift()) === null || _a === void 0 ? void 0 : _a.resolve({ value: data, done: false });
}
else {
iterable.queue.push(data);
}
};
const handleClose = () => {
iterable.ended = true;
let consumer;
while (consumer = iterable.consumers.shift()) {
consumer.resolve({ value: undefined, done: true });
}
};
const handleError = (err) => {
iterable.error = err;
if (iterable.consumers.length > 0) {
iterable.consumers.forEach(item => {
item.reject(err);
});
iterable.consumers = [];
}
};
const handleBrowserErrorEvent = (ev) => {
let err;
if (ev instanceof ErrorEvent) {
err = ev.error || new Error(ev.message);
}
else {
// @ts-ignore
err = new Error("something went wrong", { cause: ev });
}
handleError(err);
};
const proto = Object.getPrototypeOf(source);
const msgDesc = Object.getOwnPropertyDescriptor(proto, "onmessage");
if ((msgDesc === null || msgDesc === void 0 ? void 0 : msgDesc.set) && typeof source.close === "function") { // WebSocket or EventSource
const errDesc = Object.getOwnPropertyDescriptor(proto, "onerror");
const closeDesc = Object.getOwnPropertyDescriptor(proto, "onclose");
let cleanup;
if ((eventMap === null || eventMap === void 0 ? void 0 : eventMap.event) &&
(eventMap === null || eventMap === void 0 ? void 0 : eventMap.event) !== "message" &&
typeof source["addEventListener"] === "function") { // for EventSource listening on custom events
const es = source;
const eventName = eventMap.event;
const msgListener = (ev) => {
handleMessage(ev.data);
};
es.addEventListener(eventName, msgListener);
cleanup = () => {
es.removeEventListener(eventName, msgListener);
};
}
else {
msgDesc.set.call(source, (ev) => {
handleMessage(ev.data);
});
cleanup = () => {
var _a;
(_a = msgDesc.set) === null || _a === void 0 ? void 0 : _a.call(source, null);
};
}
(_a = errDesc === null || errDesc === void 0 ? void 0 : errDesc.set) === null || _a === void 0 ? void 0 : _a.call(source, handleBrowserErrorEvent);
if (closeDesc === null || closeDesc === void 0 ? void 0 : closeDesc.set) { // WebSocket
closeDesc.set.call(source, () => {
var _a, _b;
handleClose();
(_a = closeDesc.set) === null || _a === void 0 ? void 0 : _a.call(source, null);
(_b = errDesc === null || errDesc === void 0 ? void 0 : errDesc.set) === null || _b === void 0 ? void 0 : _b.call(source, null);
cleanup === null || cleanup === void 0 ? void 0 : cleanup();
});
}
else if (!(closeDesc === null || closeDesc === void 0 ? void 0 : closeDesc.set) && typeof source.close === "function") { // EventSource
// EventSource by default does not trigger close event, we need to make sure when
// it calls the close() function, the iterator is automatically closed.
const es = source;
const _close = es.close;
es.close = function close() {
var _a;
_close.call(es);
handleClose();
es.close = _close;
(_a = errDesc === null || errDesc === void 0 ? void 0 : errDesc.set) === null || _a === void 0 ? void 0 : _a.call(source, null);
cleanup === null || cleanup === void 0 ? void 0 : cleanup();
};
}
};
const handleBrowserErrorEvent = (ev) => {
let err;
if (ev instanceof ErrorEvent) {
err = ev.error || new Error(ev.message);
}
else if (typeof source.send === "function" && typeof source.close === "function") {
// non-standard WebSocket implementation
const ws = source;
ws.onmessage = (ev) => {
else {
// @ts-ignore
err = new Error("something went wrong", { cause: ev });
}
handleError(err);
};
const proto = Object.getPrototypeOf(source);
const msgDesc = Object.getOwnPropertyDescriptor(proto, "onmessage");
if ((msgDesc === null || msgDesc === void 0 ? void 0 : msgDesc.set) && typeof source.close === "function") { // WebSocket or EventSource
const errDesc = Object.getOwnPropertyDescriptor(proto, "onerror");
const closeDesc = Object.getOwnPropertyDescriptor(proto, "onclose");
let cleanup;
if ((eventMap === null || eventMap === void 0 ? void 0 : eventMap.event) &&
(eventMap === null || eventMap === void 0 ? void 0 : eventMap.event) !== "message" &&
typeof source["addEventListener"] === "function") { // for EventSource listening on custom events
const es = source;
const eventName = eventMap.event;
const msgListener = (ev) => {
handleMessage(ev.data);
};
ws.onerror = handleBrowserErrorEvent;
ws.onclose = () => {
handleClose();
ws.onclose = null;
ws.onerror = null;
ws.onmessage = null;
es.addEventListener(eventName, msgListener);
cleanup = () => {
es.removeEventListener(eventName, msgListener);
};
}
else if (typeof source["addEventListener"] === "function") { // EventTarget
const target = source;
const msgEvent = (eventMap === null || eventMap === void 0 ? void 0 : eventMap.message) || "message";
const errEvent = (eventMap === null || eventMap === void 0 ? void 0 : eventMap.error) || "error";
const closeEvent = (eventMap === null || eventMap === void 0 ? void 0 : eventMap.close) || "close";
const msgListener = (ev) => {
if (ev instanceof MessageEvent) {
handleMessage(ev.data);
}
else {
msgDesc.set.call(source, (ev) => {
handleMessage(ev.data);
});
cleanup = () => {
var _a;
(_a = msgDesc.set) === null || _a === void 0 ? void 0 : _a.call(source, null);
};
target.addEventListener(msgEvent, msgListener);
target.addEventListener(errEvent, handleBrowserErrorEvent);
target.addEventListener(closeEvent, function closeListener() {
}
(_a = errDesc === null || errDesc === void 0 ? void 0 : errDesc.set) === null || _a === void 0 ? void 0 : _a.call(source, handleBrowserErrorEvent);
if (closeDesc === null || closeDesc === void 0 ? void 0 : closeDesc.set) { // WebSocket
closeDesc.set.call(source, () => {
var _a, _b;
handleClose();
target.removeEventListener(closeEvent, closeListener);
target.removeEventListener(msgEvent, msgListener);
target.removeEventListener(errEvent, handleBrowserErrorEvent);
(_a = closeDesc.set) === null || _a === void 0 ? void 0 : _a.call(source, null);
(_b = errDesc === null || errDesc === void 0 ? void 0 : errDesc.set) === null || _b === void 0 ? void 0 : _b.call(source, null);
cleanup === null || cleanup === void 0 ? void 0 : cleanup();
});
}
else if (typeof source["on"] === "function") { // EventEmitter
const target = source;
const dataEvent = (eventMap === null || eventMap === void 0 ? void 0 : eventMap.data) || "data";
const errEvent = (eventMap === null || eventMap === void 0 ? void 0 : eventMap.error) || "error";
const endEvent = (eventMap === null || eventMap === void 0 ? void 0 : eventMap.close) || "close";
target.on(dataEvent, handleMessage);
target.once(errEvent, handleError);
target.once(endEvent, () => {
else if (!(closeDesc === null || closeDesc === void 0 ? void 0 : closeDesc.set) && typeof source.close === "function") { // EventSource
// EventSource by default does not trigger close event, we need to make sure when
// it calls the close() function, the iterator is automatically closed.
const es = source;
const _close = es.close;
es.close = function close() {
var _a;
_close.call(es);
handleClose();
target.off(dataEvent, handleMessage);
target.off(dataEvent, handleError);
});
es.close = _close;
(_a = errDesc === null || errDesc === void 0 ? void 0 : errDesc.set) === null || _a === void 0 ? void 0 : _a.call(source, null);
cleanup === null || cleanup === void 0 ? void 0 : cleanup();
};
}
else {
throw new TypeError("the input source cannot be read as an AsyncIterable object");
}
return {
[Symbol.asyncIterator]() {
return iterable;
}
else if (typeof source.send === "function" && typeof source.close === "function") {
// non-standard WebSocket implementation
const ws = source;
ws.onmessage = (ev) => {
handleMessage(ev.data);
};
ws.onerror = handleBrowserErrorEvent;
ws.onclose = () => {
handleClose();
ws.onclose = null;
ws.onerror = null;
ws.onmessage = null;
};
}
else if (typeof source["addEventListener"] === "function") { // EventTarget
const target = source;
const msgEvent = (eventMap === null || eventMap === void 0 ? void 0 : eventMap.message) || "message";
const errEvent = (eventMap === null || eventMap === void 0 ? void 0 : eventMap.error) || "error";
const closeEvent = (eventMap === null || eventMap === void 0 ? void 0 : eventMap.close) || "close";
const msgListener = (ev) => {
if (ev instanceof MessageEvent) {
handleMessage(ev.data);
}
};
},
async run(script, args = undefined, options = undefined) {
var _a, _b;
const msg = {
type: "ffi",
script,
baseUrl: "",
fn: (options === null || options === void 0 ? void 0 : options.fn) || "default",
args: args !== null && args !== void 0 ? args : [],
};
if (typeof Deno === "object") {
msg.baseUrl = "file://" + Deno.cwd() + "/";
target.addEventListener(msgEvent, msgListener);
target.addEventListener(errEvent, handleBrowserErrorEvent);
target.addEventListener(closeEvent, function closeListener() {
handleClose();
target.removeEventListener(closeEvent, closeListener);
target.removeEventListener(msgEvent, msgListener);
target.removeEventListener(errEvent, handleBrowserErrorEvent);
});
}
else if (typeof source["on"] === "function") { // EventEmitter
const target = source;
const dataEvent = (eventMap === null || eventMap === void 0 ? void 0 : eventMap.data) || "data";
const errEvent = (eventMap === null || eventMap === void 0 ? void 0 : eventMap.error) || "error";
const endEvent = (eventMap === null || eventMap === void 0 ? void 0 : eventMap.close) || "close";
target.on(dataEvent, handleMessage);
target.once(errEvent, handleError);
target.once(endEvent, () => {
handleClose();
target.off(dataEvent, handleMessage);
target.off(dataEvent, handleError);
});
}
else {
throw new TypeError("the input source cannot be read as an AsyncIterable object");
}
return {
[Symbol.asyncIterator]() {
return iterable;
}
else if (isNode) {
msg.baseUrl = "file://" + process.cwd() + "/";
};
}
exports.read = read;
const isNode = typeof process === "object" && !!((_a = process.versions) === null || _a === void 0 ? void 0 : _a.node);
/**
* The maximum number of workers allowed to exist at the same time.
*
* The primary purpose of the workers is not mean to run tasks in parallel, but run them in separate
* from the main thread, so that aborting tasks can be achieved by terminating the worker thread and
* it will not affect the main thread.
*
* That said, the worker thread can still be used to achieve parallelism, but it should be noticed
* that only the numbers of tasks that equals to the CPU core numbers will be run at the same time.
*/
const maxWorkerNum = 16;
const workerIdCounter = (0, number_1.sequence)(1, Number.MAX_SAFE_INTEGER, 1, true);
let workerPool = [];
// The worker consumer queue is nothing but a callback list, once a worker is available, the runner
// pop a consumer and run the callback, which will retry gaining the worker and retry the task.
const workerConsumerQueue = [];
/**
* Runs a task in the `script` in a worker thread that can be aborted during runtime.
*
* In Node.js, the `script` can be either a CommonJS module or an ES module, and is relative to
* the current working directory if not absolute.
*
* In browser or Deno, the `script` can only be an ES module, and is relative to the current URL
* (or working directory for Deno) if not absolute.
*/
async function run(script, args = undefined, options = undefined) {
var _a, _b;
const msg = {
type: "ffi",
script,
baseUrl: "",
fn: (options === null || options === void 0 ? void 0 : options.fn) || "default",
args: args !== null && args !== void 0 ? args : [],
};
if (typeof Deno === "object") {
msg.baseUrl = "file://" + Deno.cwd() + "/";
}
else if (isNode) {
msg.baseUrl = "file://" + process.cwd() + "/";
}
else if (typeof location === "object") {
msg.baseUrl = location.href;
}
// `buffer` is used to store data pieces yielded by generator functions before they are
// consumed. `error` and `result` serves similar purposes for function results.
const buffer = [];
let error = null;
let result;
let resolver;
let iterator;
let workerId;
let poolRecord;
let release;
let terminate = () => Promise.resolve(void 0);
const timeout = (options === null || options === void 0 ? void 0 : options.timeout) ? setTimeout(() => {
const err = new Error(`operation timeout after ${options.timeout}ms`);
if (resolver) {
resolver.reject(err);
}
else if (typeof location === "object") {
msg.baseUrl = location.href;
else {
error = err;
}
// `buffer` is used to store data pieces yielded by generator functions before they are
// consumed. `error` and `result` serves similar purposes for function results.
const buffer = [];
let error = null;
let result;
let resolver;
let iterator;
let workerId;
let poolRecord;
let release;
let terminate = () => Promise.resolve(void 0);
const timeout = (options === null || options === void 0 ? void 0 : options.timeout) ? setTimeout(() => {
const err = new Error(`operation timeout after ${options.timeout}ms`);
if (resolver) {
resolver.reject(err);
terminate();
}, options.timeout) : null;
const handleMessage = (msg) => {
var _a;
if (msg && typeof msg === "object" && typeof msg.type === "string") {
if (msg.type === "error") {
return handleError(msg.error);
}
else {
error = err;
else if (msg.type === "return") {
if (options === null || options === void 0 ? void 0 : options.keepAlive) {
// Release before resolve.
release === null || release === void 0 ? void 0 : release();
if (workerConsumerQueue.length) {
// Queued consumer now has chance to gain the worker.
(_a = workerConsumerQueue.shift()) === null || _a === void 0 ? void 0 : _a();
}
}
else {
terminate();
}
if (resolver) {
resolver.resolve(msg.value);
}
else {
result = { value: msg.value };
}
}
terminate();
}, options.timeout) : null;
const handleMessage = (msg) => {
var _a;
if (msg && typeof msg === "object" && typeof msg.type === "string") {
if (msg.type === "error") {
return handleError(msg.error);
else if (msg.type === "yield") {
if (msg.done) {
// The final message of yield event is the return value.
handleMessage({ type: "return", value: msg.value });
}
else if (msg.type === "return") {
if (options === null || options === void 0 ? void 0 : options.keepAlive) {
// Release before resolve.
release === null || release === void 0 ? void 0 : release();
if (workerConsumerQueue.length) {
// Queued consumer now has chance to gain the worker.
(_a = workerConsumerQueue.shift()) === null || _a === void 0 ? void 0 : _a();
}
else {
if (iterator) {
iterator.emit("data", msg.value);
}
else {
terminate();
buffer.push(msg.value);
}
if (resolver) {
resolver.resolve(msg.value);
}
else {
result = { value: msg.value };
}
}
else if (msg.type === "yield") {
if (msg.done) {
// The final message of yield event is the return value.
handleMessage({ type: "return", value: msg.value });
}
else {
if (iterator) {
iterator.emit("data", msg.value);
}
else {
buffer.push(msg.value);
}
}
}
}
};
const handleError = (err) => {
if (resolver) {
resolver.reject(err);
}
};
const handleError = (err) => {
if (resolver) {
resolver.reject(err);
}
else if (iterator) {
iterator.emit("error", err);
}
else {
error = err;
}
};
const handleExit = () => {
var _a;
if (poolRecord) {
// Clean the pool before resolve.
workerPool = workerPool.filter(record => record !== poolRecord);
if (workerConsumerQueue.length) {
// Queued consumer now has chance to create new worker.
(_a = workerConsumerQueue.shift()) === null || _a === void 0 ? void 0 : _a();
}
else if (iterator) {
iterator.emit("error", err);
}
else {
error = err;
}
};
const handleExit = () => {
var _a;
}
if (resolver) {
resolver.resolve(void 0);
}
else if (iterator) {
iterator.emit("close");
}
else if (!error && !result) {
result = { value: void 0 };
}
};
if (isNode) {
const path = await Promise.resolve().then(() => require("path"));
const { fileURLToPath } = await Promise.resolve().then(() => require("url"));
let _filename;
let _dirname;
let entry;
if (typeof __filename === "string") {
_filename = __filename;
_dirname = __dirname;
}
else {
// This file URL will be replace with `import.meta.url` by Rollup plugin.
_filename = fileURLToPath("file://{__filename}");
_dirname = path.dirname(_filename);
}
if (["cjs", "esm"].includes(path.basename(_dirname))) { // compiled
entry = path.join(path.dirname(_dirname), "worker.mjs");
}
else {
entry = path.join(_dirname, "worker.mjs");
}
if ((options === null || options === void 0 ? void 0 : options.adapter) === "child_process") {
let worker;
let ok = true;
poolRecord = workerPool.find(item => {
return item.adapter === "child_process" && !item.busy;
});
if (poolRecord) {
// Clean the pool before resolve.
workerPool = workerPool.filter(record => record !== poolRecord);
if (workerConsumerQueue.length) {
// Queued consumer now has chance to create new worker.
(_a = workerConsumerQueue.shift()) === null || _a === void 0 ? void 0 : _a();
}
worker = poolRecord.worker;
workerId = poolRecord.workerId;
poolRecord.busy = true;
}
if (resolver) {
resolver.resolve(void 0);
}
else if (iterator) {
iterator.emit("close");
}
else if (!error && !result) {
result = { value: void 0 };
}
};
if (isNode) {
const path = await Promise.resolve().then(() => require("path"));
const { fileURLToPath } = await Promise.resolve().then(() => require("url"));
let _filename;
let _dirname;
let entry;
if (typeof __filename === "string") {
_filename = __filename;
_dirname = __dirname;
}
else {
// This file URL will be replace with `import.meta.url` by Rollup plugin.
_filename = fileURLToPath("file://{__filename}");
_dirname = path.dirname(_filename);
}
if (["cjs", "esm"].includes(path.basename(_dirname))) { // compiled
entry = path.join(path.dirname(_dirname), "worker.mjs");
}
else {
entry = path.join(_dirname, "worker.mjs");
}
if ((options === null || options === void 0 ? void 0 : options.adapter) === "child_process") {
let worker;
let ok = true;
poolRecord = workerPool.find(item => {
return item.adapter === "child_process" && !item.busy;
else if (workerPool.length < maxWorkerNum) {
const { fork } = await Promise.resolve().then(() => require("child_process"));
const isPrior14 = parseInt(process.version.slice(1)) < 14;
worker = fork(entry, {
stdio: "inherit",
serialization: isPrior14 ? "advanced" : "json",
});
if (poolRecord) {
worker = poolRecord.worker;
workerId = poolRecord.workerId;
poolRecord.busy = true;
}
else if (workerPool.length < maxWorkerNum) {
const { fork } = await Promise.resolve().then(() => require("child_process"));
const isPrior14 = parseInt(process.version.slice(1)) < 14;
worker = fork(entry, {
stdio: "inherit",
serialization: isPrior14 ? "advanced" : "json",
workerId = worker.pid;
ok = await new Promise((resolve) => {
worker.once("exit", () => {
if (error) {
// The child process took too long to start and cause timeout error.
resolve(false);
}
});
workerId = worker.pid;
ok = await new Promise((resolve) => {
worker.once("exit", () => {
if (error) {
// The child process took too long to start and cause timeout error.
resolve(false);
}
});
worker.once("message", () => {
worker.removeAllListeners("exit");
resolve(true);
});
worker.once("message", () => {
worker.removeAllListeners("exit");
resolve(true);
});
// Fill the worker pool regardless the current call should keep-alive or not,
// this will make sure that the total number of workers will not exceed the
// maxWorkerNum. If the the call doesn't keep-alive the worker, it will be
// cleaned after the call.
ok && workerPool.push(poolRecord = {
workerId,
worker,
adapter: "child_process",
busy: true,
});
}
else {
// Put the current call in the consumer queue if there are no workers available,
// once an existing call finishes, the queue will pop the its head consumer and
// retry.
return new Promise((resolve) => {
workerConsumerQueue.push(resolve);
}).then(() => jsext.run(script, args, options));
}
release = () => {
// Remove the event listener so that later calls will not mess up.
worker.off("message", handleMessage);
poolRecord && (poolRecord.busy = false);
};
terminate = () => Promise.resolve(void worker.kill(1));
if (ok) {
worker.send(msg);
worker.on("message", handleMessage);
worker.once("error", handleError);
worker.once("exit", handleExit);
}
});
// Fill the worker pool regardless the current call should keep-alive or not,
// this will make sure that the total number of workers will not exceed the
// maxWorkerNum. If the the call doesn't keep-alive the worker, it will be
// cleaned after the call.
ok && workerPool.push(poolRecord = {
workerId,
worker,
adapter: "child_process",
busy: true,
});
}
else {
let worker;
let ok = true;
poolRecord = workerPool.find(item => {
return item.adapter === "worker_threads" && !item.busy;
});
if (poolRecord) {
worker = poolRecord.worker;
workerId = poolRecord.workerId;
poolRecord.busy = true;
}
else if (workerPool.length < maxWorkerNum) {
const { Worker } = await Promise.resolve().then(() => require("worker_threads"));
worker = new Worker(entry);
// `threadId` may not exist in Bun.
workerId = (_a = worker.threadId) !== null && _a !== void 0 ? _a : workerIdCounter.next().value;
ok = await new Promise((resolve) => {
worker.once("exit", () => {
if (error) {
// The child process took too long to start and cause timeout error.
resolve(false);
}
});
worker.once("online", () => {
worker.removeAllListeners("exit");
resolve(true);
});
});
ok && workerPool.push(poolRecord = {
workerId,
worker,
adapter: "worker_threads",
busy: true,
});
}
else {
return new Promise((resolve) => {
workerConsumerQueue.push(resolve);
}).then(() => jsext.run(script, args, options));
}
release = () => {
worker.off("message", handleMessage);
poolRecord && (poolRecord.busy = false);
};
terminate = async () => void (await worker.terminate());
if (ok) {
worker.postMessage(msg);
worker.on("message", handleMessage);
worker.once("error", handleError);
worker.once("messageerror", handleError);
worker.once("exit", handleExit);
}
// Put the current call in the consumer queue if there are no workers available,
// once an existing call finishes, the queue will pop the its head consumer and
// retry.
return new Promise((resolve) => {
workerConsumerQueue.push(resolve);
}).then(() => run(script, args, options));
}
release = () => {
// Remove the event listener so that later calls will not mess up.
worker.off("message", handleMessage);
poolRecord && (poolRecord.busy = false);
};
terminate = () => Promise.resolve(void worker.kill(1));
if (ok) {
worker.send(msg);
worker.on("message", handleMessage);
worker.once("error", handleError);
worker.once("exit", handleExit);
}
}
else {
let worker;
let ok = true;
poolRecord = workerPool.find(item => {

@@ -780,29 +769,19 @@ return item.adapter === "worker_threads" && !item.busy;

else if (workerPool.length < maxWorkerNum) {
let url;
if (typeof Deno === "object") {
// Deno can load the module regardless of MINE type.
url = [
...("file://{__filename}".split("/").slice(0, -1)),
"worker-web.mjs"
].join("/");
}
else {
const _url = (options === null || options === void 0 ? void 0 : options.webWorkerEntry)
|| "https://raw.githubusercontent.com/ayonli/jsext/main/esm/worker-web.mjs";
const res = await fetch(_url);
let blob;
if ((_b = res.headers.get("content-type")) === null || _b === void 0 ? void 0 : _b.startsWith("application/javascript")) {
blob = await res.blob();
}
else {
const buf = await res.arrayBuffer();
blob = new Blob([new Uint8Array(buf)], {
type: "application/javascript",
});
}
url = URL.createObjectURL(blob);
}
worker = new Worker(url, { type: "module" });
workerId = workerIdCounter.next().value;
workerPool.push(poolRecord = {
const { Worker } = await Promise.resolve().then(() => require("worker_threads"));
worker = new Worker(entry);
// `threadId` may not exist in Bun.
workerId = (_a = worker.threadId) !== null && _a !== void 0 ? _a : workerIdCounter.next().value;
ok = await new Promise((resolve) => {
worker.once("exit", () => {
if (error) {
// The child process took too long to start and cause timeout error.
resolve(false);
}
});
worker.once("online", () => {
worker.removeAllListeners("exit");
resolve(true);
});
});
ok && workerPool.push(poolRecord = {
workerId,

@@ -817,64 +796,137 @@ worker,

workerConsumerQueue.push(resolve);
}).then(() => jsext.run(script, args, options));
}).then(() => run(script, args, options));
}
release = () => {
worker.onmessage = null;
worker.off("message", handleMessage);
poolRecord && (poolRecord.busy = false);
};
terminate = async () => {
await Promise.resolve(worker.terminate());
handleExit();
};
worker.postMessage(msg);
worker.onmessage = (ev) => handleMessage(ev.data);
worker.onerror = (ev) => handleMessage(ev.error || new Error(ev.message));
worker.onmessageerror = () => {
handleError(new Error("unable to deserialize the message"));
};
terminate = async () => void (await worker.terminate());
if (ok) {
worker.postMessage(msg);
worker.on("message", handleMessage);
worker.once("error", handleError);
worker.once("messageerror", handleError);
worker.once("exit", handleExit);
}
}
return {
workerId,
async abort() {
timeout && clearTimeout(timeout);
await terminate();
},
async result() {
return await new Promise((resolve, reject) => {
if (error) {
reject(error);
}
else if (result) {
resolve(result.value);
}
else {
resolver = { resolve, reject };
}
});
},
async *iterate() {
if (resolver) {
throw new Error("result() has been called");
}
else {
let worker;
poolRecord = workerPool.find(item => {
return item.adapter === "worker_threads" && !item.busy;
});
if (poolRecord) {
worker = poolRecord.worker;
workerId = poolRecord.workerId;
poolRecord.busy = true;
}
else if (workerPool.length < maxWorkerNum) {
let url;
if (typeof Deno === "object") {
// Deno can load the module regardless of MINE type.
url = [
...("file://{__filename}".split("/").slice(0, -1)),
"worker-web.mjs"
].join("/");
}
else {
const _url = (options === null || options === void 0 ? void 0 : options.webWorkerEntry)
|| "https://raw.githubusercontent.com/ayonli/jsext/main/esm/worker-web.mjs";
const res = await fetch(_url);
let blob;
if ((_b = res.headers.get("content-type")) === null || _b === void 0 ? void 0 : _b.startsWith("application/javascript")) {
blob = await res.blob();
}
else {
const buf = await res.arrayBuffer();
blob = new Blob([new Uint8Array(buf)], {
type: "application/javascript",
});
}
url = URL.createObjectURL(blob);
}
worker = new Worker(url, { type: "module" });
workerId = workerIdCounter.next().value;
workerPool.push(poolRecord = {
workerId,
worker,
adapter: "worker_threads",
busy: true,
});
}
else {
return new Promise((resolve) => {
workerConsumerQueue.push(resolve);
}).then(() => run(script, args, options));
}
release = () => {
worker.onmessage = null;
poolRecord && (poolRecord.busy = false);
};
terminate = async () => {
await Promise.resolve(worker.terminate());
handleExit();
};
worker.postMessage(msg);
worker.onmessage = (ev) => handleMessage(ev.data);
worker.onerror = (ev) => handleMessage(ev.error || new Error(ev.message));
worker.onmessageerror = () => {
handleError(new Error("unable to deserialize the message"));
};
}
return {
workerId,
async abort() {
timeout && clearTimeout(timeout);
await terminate();
},
async result() {
return await new Promise((resolve, reject) => {
if (error) {
reject(error);
}
else if (result) {
throw new TypeError("the response is not iterable");
resolve(result.value);
}
const { EventEmitter } = await Promise.resolve().then(() => require("events"));
iterator = new EventEmitter();
if (buffer.length) {
(async () => {
await Promise.resolve(null);
let msg;
while (msg = buffer.shift()) {
iterator.emit("data", msg);
}
})().catch(console.error);
else {
resolver = { resolve, reject };
}
for await (const msg of jsext.read(iterator)) {
yield msg;
}
},
};
}
});
},
async *iterate() {
if (resolver) {
throw new Error("result() has been called");
}
else if (result) {
throw new TypeError("the response is not iterable");
}
const { EventEmitter } = await Promise.resolve().then(() => require("events"));
iterator = new EventEmitter();
if (buffer.length) {
(async () => {
await Promise.resolve(null);
let msg;
while (msg = buffer.shift()) {
iterator.emit("data", msg);
}
})().catch(console.error);
}
for await (const msg of read(iterator)) {
yield msg;
}
},
};
}
exports.run = run;
const jsext = {
try: _try,
func,
wrap,
throttle,
mixins,
isSubclassOf,
read,
run,
};
exports.default = jsext;
//# sourceMappingURL=index.js.map

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

{"version":3,"file":"index.js","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"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"}
{"version":3,"file":"index.js","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"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"}

@@ -14,2 +14,3 @@ "use strict";

Object.as = _1.as;
Object.isValid = _1.isValid;
//# sourceMappingURL=augment.js.map

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

{"version":3,"file":"augment.js","sourceRoot":"","sources":["../../object/augment.ts"],"names":[],"mappings":";;AAAA,wBAAgE;AA+ChE,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE;IAChB,MAAM,CAAC,MAAM,GAAG,SAAM,CAAC;CAC1B;AAED,IAAI,CAAC,MAAM,CAAC,YAAY,EAAE;IACtB,MAAM,CAAC,YAAY,GAAG,eAAY,CAAC;CACtC;AAED,MAAM,CAAC,KAAK,GAAG,QAAK,CAAC;AACrB,MAAM,CAAC,IAAI,GAAG,OAAI,CAAC;AACnB,MAAM,CAAC,IAAI,GAAG,OAAI,CAAC;AACnB,MAAM,CAAC,EAAE,GAAG,KAAE,CAAC"}
{"version":3,"file":"augment.js","sourceRoot":"","sources":["../../object/augment.ts"],"names":[],"mappings":";;AAAA,wBAAyE;AAwDzE,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE;IAChB,MAAM,CAAC,MAAM,GAAG,SAAM,CAAC;CAC1B;AAED,IAAI,CAAC,MAAM,CAAC,YAAY,EAAE;IACtB,MAAM,CAAC,YAAY,GAAG,eAAY,CAAC;CACtC;AAED,MAAM,CAAC,KAAK,GAAG,QAAK,CAAC;AACrB,MAAM,CAAC,IAAI,GAAG,OAAI,CAAC;AACnB,MAAM,CAAC,IAAI,GAAG,OAAI,CAAC;AACnB,MAAM,CAAC,EAAE,GAAG,KAAE,CAAC;AACf,MAAM,CAAC,OAAO,GAAG,UAAO,CAAC"}
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.as = exports.omit = exports.pick = exports.patch = exports.hasOwnMethod = exports.hasOwn = void 0;
exports.isValid = exports.as = exports.omit = exports.pick = exports.patch = exports.hasOwnMethod = exports.hasOwn = void 0;
function hasOwn(obj, key) {

@@ -61,3 +61,3 @@ return Object.prototype.hasOwnProperty.call(obj, key);

exports.omit = omit;
function as(obj, type) {
function as(value, type) {
if (typeof type !== "function") {

@@ -74,12 +74,12 @@ throw new TypeError("type must be a valid constructor");

};
if (obj instanceof type) {
if (value instanceof type) {
if ([String, Number, Boolean].includes(type)) {
return obj.valueOf(); // make sure the primitives are returned.
return value.valueOf(); // make sure the primitives are returned.
}
else {
return obj;
return value;
}
}
else if ((_type = typeof obj) && primitiveMap[_type] === type) {
return obj;
else if ((_type = typeof value) && primitiveMap[_type] === type) {
return value;
}

@@ -89,2 +89,17 @@ return null;

exports.as = as;
/**
* Returns `true` if the given value is valid. Thee following values are considered invalid:
*
* - `undefined`
* - `null`
* - `NaN`
* - `Invalid Date`
*/
function isValid(value) {
return value !== undefined
&& value !== null
&& !Object.is(value, NaN)
&& !(value instanceof Date && value.toString() === "Invalid Date");
}
exports.isValid = isValid;
//# sourceMappingURL=index.js.map

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

{"version":3,"file":"index.js","sourceRoot":"","sources":["../../object/index.ts"],"names":[],"mappings":"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"}
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../object/index.ts"],"names":[],"mappings":"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"}

@@ -10,2 +10,8 @@ import './string/augment.js';

import './error/augment.js';
import { AsyncFunction, AsyncGeneratorFunction } from './index.js';
// @ts-ignore
globalThis["AsyncFunction"] = AsyncFunction;
// @ts-ignore
globalThis["AsyncGeneratorFunction"] = AsyncGeneratorFunction;
//# sourceMappingURL=augment.js.map

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

{"version":3,"file":"augment.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;"}
{"version":3,"file":"augment.js","sources":["../augment.ts"],"sourcesContent":["import \"./string/augment\";\nimport \"./number/augment\";\nimport \"./array/augment\";\nimport \"./uint8array/augment\";\nimport \"./object/augment\";\nimport \"./math/augment\";\nimport \"./promise/augment\";\nimport \"./collections/augment\";\nimport \"./error/augment\";\nimport { AsyncFunction, AsyncGeneratorFunction } from \".\";\n// @ts-ignore\nglobalThis[\"AsyncFunction\"] = AsyncFunction;\n// @ts-ignore\nglobalThis[\"AsyncGeneratorFunction\"] = AsyncGeneratorFunction;\n//# sourceMappingURL=augment.js.map"],"names":[],"mappings":";;;;;;;;;;;AAUA;AACA,UAAU,CAAC,eAAe,CAAC,GAAG,aAAa,CAAC;AAC5C;AACA,UAAU,CAAC,wBAAwB,CAAC,GAAG,sBAAsB"}
+785
-742

@@ -5,21 +5,276 @@ import { isAsyncGenerator as isAsyncGenerator_1, isGenerator as isGenerator_1 } from './_external/check-iterable/index.js';

var _a;
const isNode = typeof process === "object" && !!((_a = process.versions) === null || _a === void 0 ? void 0 : _a.node);
const throttleCaches = new Map();
const AsyncFunction = (async function () { }).constructor;
const AsyncGeneratorFunction = (async function* () { }).constructor;
function _try(fn, ...args) {
if (typeof fn === "function") {
try {
return _try(fn.apply(void 0, args));
}
catch (err) {
return [err, undefined];
}
}
let returns = fn;
// Implementation details should be ordered from complex to simple.
if (isAsyncGenerator_1(returns)) {
return (async function* () {
let input;
let result;
// Use `while` loop instead of `for...of...` in order to
// retrieve the return value of a generator function.
while (true) {
try {
const { done, value } = await returns.next(input);
if (done) {
result = value;
break;
}
else {
// Receive any potential input value that passed
// to the outer `next()` call, and pass them to
// `res.next()` in the next call.
input = yield Promise.resolve([null, value]);
}
}
catch (err) {
// If any error occurs, yield that error as resolved
// and break the loop immediately, indicating the
// process is forced broken.
yield Promise.resolve([err, undefined]);
break;
}
}
return [null, result];
})();
}
else if (isGenerator_1(returns)) {
return (function* () {
let input;
let result;
while (true) {
try {
const { done, value } = returns.next(input);
if (done) {
result = value;
break;
}
else {
input = yield [null, value];
}
}
catch (err) {
yield [err, undefined];
break;
}
}
return [null, result];
})();
}
else if (typeof (returns === null || returns === void 0 ? void 0 : returns.then) === "function") {
returns = returns.then((value) => [null, value]);
return Promise.resolve(returns).catch((err) => [err, undefined]);
}
else {
return [null, returns];
}
}
/**
* The maximum number of workers allowed to exist at the same time.
* Inspired by Golang, creates a function that receives a `defer` function which can be used
* to carry deferred jobs that will be run after the main function is complete.
*
* The primary purpose of the workers is not mean to run tasks in parallel, but run them in separate
* from the main thread, so that aborting tasks can be achieved by terminating the worker thread and
* it will not affect the main thread.
* Multiple calls of the `defer` function is supported, and the callbacks are called in the
* LIFO order. Callbacks can be async functions if the main function is an async function or
* an async generator function, and all the running procedures will be awaited.
*
* That said, the worker thread can still be used to achieve parallelism, but it should be noticed
* that only the numbers of tasks that equals to the CPU core numbers will be run at the same time.
* @example
* const getVersion = await jsext.func(async (defer) => {
* const file = await fs.open("./package.json", "r");
* defer(() => file.close());
*
* const content = await file.readFile("utf8");
* const pkg = JSON.parse(content);
*
* return pkg.version as string;
* });
*/
const maxWorkerNum = 16;
const workerIdCounter = sequence(1, Number.MAX_SAFE_INTEGER, 1, true);
let workerPool = [];
// The worker consumer queue is nothing but a callback list, once a worker is available, the runner
// pop a consumer and run the callback, which will retry gaining the worker and retry the task.
const workerConsumerQueue = [];
function func(fn) {
return function (...args) {
var _a;
const callbacks = [];
const defer = (cb) => void callbacks.push(cb);
let result;
try {
const returns = fn.call(this, defer, ...args);
if (isAsyncGenerator_1(returns)) {
const gen = (async function* () {
var _a;
let input;
// Use `while` loop instead of `for...of...` in order to
// retrieve the return value of a generator function.
while (true) {
try {
const { done, value } = await returns.next(input);
if (done) {
result = { value, error: null };
break;
}
else {
// Receive any potential input value that passed
// to the outer `next()` call, and pass them to
// `res.next()` in the next call.
input = yield Promise.resolve(value);
}
}
catch (error) {
// If any error occurs, capture that error and break
// the loop immediately, indicating the process is
// forced broken.
result = { value: void 0, error };
break;
}
}
for (let i = callbacks.length - 1; i >= 0; i--) {
await ((_a = callbacks[i]) === null || _a === void 0 ? void 0 : _a.call(callbacks));
}
if (result.error) {
throw result.error;
}
else {
return result.value;
}
})();
return gen;
}
else if (isGenerator_1(returns)) {
const gen = (function* () {
var _a;
let input;
while (true) {
try {
const { done, value } = returns.next(input);
if (done) {
result = { value, error: null };
break;
}
else {
input = yield value;
}
}
catch (error) {
result = { value: void 0, error };
break;
}
}
for (let i = callbacks.length - 1; i >= 0; i--) {
(_a = callbacks[i]) === null || _a === void 0 ? void 0 : _a.call(callbacks);
}
if (result.error) {
throw result.error;
}
else {
return result.value;
}
})();
return gen;
}
else if (typeof (returns === null || returns === void 0 ? void 0 : returns.then) === "function") {
return Promise.resolve(returns).then(value => ({
value,
error: null,
})).catch((error) => ({
value: void 0,
error,
})).then(async (result) => {
var _a;
for (let i = callbacks.length - 1; i >= 0; i--) {
await ((_a = callbacks[i]) === null || _a === void 0 ? void 0 : _a.call(callbacks));
}
if (result.error) {
throw result.error;
}
else {
return result.value;
}
});
}
else {
result = { value: returns, error: null };
}
}
catch (error) {
result = { value: void 0, error };
}
for (let i = callbacks.length - 1; i >= 0; i--) {
(_a = callbacks[i]) === null || _a === void 0 ? void 0 : _a.call(callbacks);
}
if (result.error) {
throw result.error;
}
else {
return result.value;
}
};
}
/**
* Wraps a function inside another function and returns a new function
* that copies the original function's name and properties.
*/
function wrap(fn, wrapper) {
const wrapped = function (...args) {
return wrapper.call(this, fn, ...args);
};
Object.defineProperty(wrapped, "name", Object.getOwnPropertyDescriptor(fn, "name"));
Object.defineProperty(wrapped, "length", Object.getOwnPropertyDescriptor(fn, "length"));
Object.defineProperty(wrapped, "toString", {
configurable: true,
enumerable: false,
writable: true,
value: fn.toString.bind(fn),
});
return wrapped;
}
const throttleCaches = new Map();
function throttle(handler, options) {
const key = typeof options === "number" ? null : options.for;
const duration = typeof options === "number" ? options : options.duration;
const handleCall = function (cache, ...args) {
var _a;
if (cache.result && Date.now() < ((_a = cache.expires) !== null && _a !== void 0 ? _a : 0)) {
if (cache.result.error) {
throw cache.result.error;
}
else {
return cache.result.value;
}
}
try {
const returns = handler.call(this, ...args);
cache.result = { value: returns };
cache.expires = Date.now() + duration;
return returns;
}
catch (error) {
cache.result = { error };
cache.expires = Date.now() + duration;
throw error;
}
};
if (!key) {
const cache = { for: null };
return function (...args) {
return handleCall.call(this, cache, ...args);
};
}
else {
let cache = throttleCaches.get(key);
if (!cache) {
cache = { for: key };
throttleCaches.set(key, cache);
}
return function (...args) {
return handleCall.call(this, cache, ...args);
};
}
}
/**
* Merges properties and methods only if they're missing in the class.

@@ -71,701 +326,427 @@ */

}
const jsext = {
try(fn, ...args) {
if (typeof fn === "function") {
try {
return jsext.try(fn.apply(void 0, args));
}
catch (err) {
return [err, undefined];
}
function mixins(base, ...mixins) {
const obj = { ctor: null };
obj.ctor = class extends base {
}; // make sure this class has no name
for (const mixin of mixins) {
if (typeof mixin == "function") {
mergeHierarchy(obj.ctor, mixin);
}
let returns = fn;
// Implementation details should be ordered from complex to simple.
if (isAsyncGenerator_1(returns)) {
return (async function* () {
let input;
let result;
// Use `while` loop instead of `for...of...` in order to
// retrieve the return value of a generator function.
while (true) {
try {
const { done, value } = await returns.next(input);
if (done) {
result = value;
break;
}
else {
// Receive any potential input value that passed
// to the outer `next()` call, and pass them to
// `res.next()` in the next call.
input = yield Promise.resolve([null, value]);
}
}
catch (err) {
// If any error occurs, yield that error as resolved
// and break the loop immediately, indicating the
// process is forced broken.
yield Promise.resolve([err, undefined]);
break;
}
}
return [null, result];
})();
else if (mixin && typeof mixin == "object") {
mergeIfNotExists(obj.ctor.prototype, mixin);
}
else if (isGenerator_1(returns)) {
return (function* () {
let input;
let result;
while (true) {
try {
const { done, value } = returns.next(input);
if (done) {
result = value;
break;
}
else {
input = yield [null, value];
}
}
catch (err) {
yield [err, undefined];
break;
}
}
return [null, result];
})();
}
else if (typeof (returns === null || returns === void 0 ? void 0 : returns.then) === "function") {
returns = returns.then((value) => [null, value]);
return Promise.resolve(returns).catch((err) => [err, undefined]);
}
else {
return [null, returns];
throw new TypeError("mixin must be a constructor or an object");
}
},
func(fn) {
return function (...args) {
var _a;
const callbacks = [];
const defer = (cb) => void callbacks.push(cb);
let result;
try {
const returns = fn.call(this, defer, ...args);
if (isAsyncGenerator_1(returns)) {
const gen = (async function* () {
var _a;
let input;
// Use `while` loop instead of `for...of...` in order to
// retrieve the return value of a generator function.
while (true) {
try {
const { done, value } = await returns.next(input);
if (done) {
result = { value, error: null };
break;
}
else {
// Receive any potential input value that passed
// to the outer `next()` call, and pass them to
// `res.next()` in the next call.
input = yield Promise.resolve(value);
}
}
catch (error) {
// If any error occurs, capture that error and break
// the loop immediately, indicating the process is
// forced broken.
result = { value: void 0, error };
break;
}
}
for (let i = callbacks.length - 1; i >= 0; i--) {
await ((_a = callbacks[i]) === null || _a === void 0 ? void 0 : _a.call(callbacks));
}
if (result.error) {
throw result.error;
}
else {
return result.value;
}
})();
return gen;
}
return obj.ctor;
}
/** Checks if a class is a subclass of another class. */
function isSubclassOf(ctor1, ctor2) {
return typeof ctor1 === "function"
&& typeof ctor2 === "function"
&& ctor1.prototype instanceof ctor2;
}
function read(source, eventMap = undefined) {
var _a;
if (typeof source[Symbol.asyncIterator] === "function") {
return source;
}
const iterable = {
ended: false,
error: null,
queue: [],
consumers: [],
next() {
return new Promise((resolve, reject) => {
if (this.error && !this.ended) {
// If there is error occurred during the last transmission and the iterator
// hasn't been closed, reject that error and stop the iterator immediately.
reject(this.error);
this.ended = true;
}
else if (isGenerator_1(returns)) {
const gen = (function* () {
var _a;
let input;
while (true) {
try {
const { done, value } = returns.next(input);
if (done) {
result = { value, error: null };
break;
}
else {
input = yield value;
}
}
catch (error) {
result = { value: void 0, error };
break;
}
}
for (let i = callbacks.length - 1; i >= 0; i--) {
(_a = callbacks[i]) === null || _a === void 0 ? void 0 : _a.call(callbacks);
}
if (result.error) {
throw result.error;
}
else {
return result.value;
}
})();
return gen;
else if (this.ended && !this.queue.length) {
// If the iterator has is closed, resolve the pending consumer with void
// value.
resolve({ value: void 0, done: true });
}
else if (typeof (returns === null || returns === void 0 ? void 0 : returns.then) === "function") {
return Promise.resolve(returns).then(value => ({
value,
error: null,
})).catch((error) => ({
value: void 0,
error,
})).then(async (result) => {
var _a;
for (let i = callbacks.length - 1; i >= 0; i--) {
await ((_a = callbacks[i]) === null || _a === void 0 ? void 0 : _a.call(callbacks));
}
if (result.error) {
throw result.error;
}
else {
return result.value;
}
});
else if (this.queue.length > 0) {
// If there are data in the queue, resolve the the first piece immediately.
resolve({ value: this.queue.shift(), done: false });
}
else {
result = { value: returns, error: null };
// If there are no queued data, push the consumer to a waiting queue.
this.consumers.push({ resolve, reject });
}
}
catch (error) {
result = { value: void 0, error };
}
for (let i = callbacks.length - 1; i >= 0; i--) {
(_a = callbacks[i]) === null || _a === void 0 ? void 0 : _a.call(callbacks);
}
if (result.error) {
throw result.error;
}
else {
return result.value;
}
};
},
wrap(fn, wrapper) {
const wrapped = function (...args) {
return wrapper.call(this, fn, ...args);
};
Object.defineProperty(wrapped, "name", Object.getOwnPropertyDescriptor(fn, "name"));
Object.defineProperty(wrapped, "length", Object.getOwnPropertyDescriptor(fn, "length"));
Object.defineProperty(wrapped, "toString", {
configurable: true,
enumerable: false,
writable: true,
value: fn.toString.bind(fn),
});
return wrapped;
},
throttle(handler, options) {
const key = typeof options === "number" ? null : options.for;
const duration = typeof options === "number" ? options : options.duration;
const handleCall = function (cache, ...args) {
var _a;
if (cache.result && Date.now() < ((_a = cache.expires) !== null && _a !== void 0 ? _a : 0)) {
if (cache.result.error) {
throw cache.result.error;
}
else {
return cache.result.value;
}
}
try {
const returns = handler.call(this, ...args);
cache.result = { value: returns };
cache.expires = Date.now() + duration;
return returns;
}
catch (error) {
cache.result = { error };
cache.expires = Date.now() + duration;
throw error;
}
};
if (!key) {
const cache = { for: null };
return function (...args) {
return handleCall.call(this, cache, ...args);
};
});
}
};
const handleMessage = (data) => {
var _a;
if (iterable.consumers.length > 0) {
(_a = iterable.consumers.shift()) === null || _a === void 0 ? void 0 : _a.resolve({ value: data, done: false });
}
else {
let cache = throttleCaches.get(key);
if (!cache) {
cache = { for: key };
throttleCaches.set(key, cache);
}
return function (...args) {
return handleCall.call(this, cache, ...args);
};
iterable.queue.push(data);
}
},
mixins(base, ...mixins) {
const obj = { ctor: null };
obj.ctor = class extends base {
}; // make sure this class has no name
for (const mixin of mixins) {
if (typeof mixin == "function") {
mergeHierarchy(obj.ctor, mixin);
}
else if (mixin && typeof mixin == "object") {
mergeIfNotExists(obj.ctor.prototype, mixin);
}
else {
throw new TypeError("mixin must be a constructor or an object");
}
};
const handleClose = () => {
iterable.ended = true;
let consumer;
while (consumer = iterable.consumers.shift()) {
consumer.resolve({ value: undefined, done: true });
}
return obj.ctor;
},
isSubclassOf(ctor1, ctor2) {
return typeof ctor1 === "function"
&& typeof ctor2 === "function"
&& ctor1.prototype instanceof ctor2;
},
read(source, eventMap = undefined) {
var _a;
if (typeof source[Symbol.asyncIterator] === "function") {
return source;
};
const handleError = (err) => {
iterable.error = err;
if (iterable.consumers.length > 0) {
iterable.consumers.forEach(item => {
item.reject(err);
});
iterable.consumers = [];
}
const iterable = {
ended: false,
error: null,
queue: [],
consumers: [],
next() {
return new Promise((resolve, reject) => {
if (this.error && !this.ended) {
// If there is error occurred during the last transmission and the iterator
// hasn't been closed, reject that error and stop the iterator immediately.
reject(this.error);
this.ended = true;
}
else if (this.ended && !this.queue.length) {
// If the iterator has is closed, resolve the pending consumer with void
// value.
resolve({ value: void 0, done: true });
}
else if (this.queue.length > 0) {
// If there are data in the queue, resolve the the first piece immediately.
resolve({ value: this.queue.shift(), done: false });
}
else {
// If there are no queued data, push the consumer to a waiting queue.
this.consumers.push({ resolve, reject });
}
});
}
};
const handleMessage = (data) => {
var _a;
if (iterable.consumers.length > 0) {
(_a = iterable.consumers.shift()) === null || _a === void 0 ? void 0 : _a.resolve({ value: data, done: false });
}
else {
iterable.queue.push(data);
}
};
const handleClose = () => {
iterable.ended = true;
let consumer;
while (consumer = iterable.consumers.shift()) {
consumer.resolve({ value: undefined, done: true });
}
};
const handleError = (err) => {
iterable.error = err;
if (iterable.consumers.length > 0) {
iterable.consumers.forEach(item => {
item.reject(err);
});
iterable.consumers = [];
}
};
const handleBrowserErrorEvent = (ev) => {
let err;
if (ev instanceof ErrorEvent) {
err = ev.error || new Error(ev.message);
}
else {
// @ts-ignore
err = new Error("something went wrong", { cause: ev });
}
handleError(err);
};
const proto = Object.getPrototypeOf(source);
const msgDesc = Object.getOwnPropertyDescriptor(proto, "onmessage");
if ((msgDesc === null || msgDesc === void 0 ? void 0 : msgDesc.set) && typeof source.close === "function") { // WebSocket or EventSource
const errDesc = Object.getOwnPropertyDescriptor(proto, "onerror");
const closeDesc = Object.getOwnPropertyDescriptor(proto, "onclose");
let cleanup;
if ((eventMap === null || eventMap === void 0 ? void 0 : eventMap.event) &&
(eventMap === null || eventMap === void 0 ? void 0 : eventMap.event) !== "message" &&
typeof source["addEventListener"] === "function") { // for EventSource listening on custom events
const es = source;
const eventName = eventMap.event;
const msgListener = (ev) => {
handleMessage(ev.data);
};
es.addEventListener(eventName, msgListener);
cleanup = () => {
es.removeEventListener(eventName, msgListener);
};
}
else {
msgDesc.set.call(source, (ev) => {
handleMessage(ev.data);
});
cleanup = () => {
var _a;
(_a = msgDesc.set) === null || _a === void 0 ? void 0 : _a.call(source, null);
};
}
(_a = errDesc === null || errDesc === void 0 ? void 0 : errDesc.set) === null || _a === void 0 ? void 0 : _a.call(source, handleBrowserErrorEvent);
if (closeDesc === null || closeDesc === void 0 ? void 0 : closeDesc.set) { // WebSocket
closeDesc.set.call(source, () => {
var _a, _b;
handleClose();
(_a = closeDesc.set) === null || _a === void 0 ? void 0 : _a.call(source, null);
(_b = errDesc === null || errDesc === void 0 ? void 0 : errDesc.set) === null || _b === void 0 ? void 0 : _b.call(source, null);
cleanup === null || cleanup === void 0 ? void 0 : cleanup();
});
}
else if (!(closeDesc === null || closeDesc === void 0 ? void 0 : closeDesc.set) && typeof source.close === "function") { // EventSource
// EventSource by default does not trigger close event, we need to make sure when
// it calls the close() function, the iterator is automatically closed.
const es = source;
const _close = es.close;
es.close = function close() {
var _a;
_close.call(es);
handleClose();
es.close = _close;
(_a = errDesc === null || errDesc === void 0 ? void 0 : errDesc.set) === null || _a === void 0 ? void 0 : _a.call(source, null);
cleanup === null || cleanup === void 0 ? void 0 : cleanup();
};
}
};
const handleBrowserErrorEvent = (ev) => {
let err;
if (ev instanceof ErrorEvent) {
err = ev.error || new Error(ev.message);
}
else if (typeof source.send === "function" && typeof source.close === "function") {
// non-standard WebSocket implementation
const ws = source;
ws.onmessage = (ev) => {
else {
// @ts-ignore
err = new Error("something went wrong", { cause: ev });
}
handleError(err);
};
const proto = Object.getPrototypeOf(source);
const msgDesc = Object.getOwnPropertyDescriptor(proto, "onmessage");
if ((msgDesc === null || msgDesc === void 0 ? void 0 : msgDesc.set) && typeof source.close === "function") { // WebSocket or EventSource
const errDesc = Object.getOwnPropertyDescriptor(proto, "onerror");
const closeDesc = Object.getOwnPropertyDescriptor(proto, "onclose");
let cleanup;
if ((eventMap === null || eventMap === void 0 ? void 0 : eventMap.event) &&
(eventMap === null || eventMap === void 0 ? void 0 : eventMap.event) !== "message" &&
typeof source["addEventListener"] === "function") { // for EventSource listening on custom events
const es = source;
const eventName = eventMap.event;
const msgListener = (ev) => {
handleMessage(ev.data);
};
ws.onerror = handleBrowserErrorEvent;
ws.onclose = () => {
handleClose();
ws.onclose = null;
ws.onerror = null;
ws.onmessage = null;
es.addEventListener(eventName, msgListener);
cleanup = () => {
es.removeEventListener(eventName, msgListener);
};
}
else if (typeof source["addEventListener"] === "function") { // EventTarget
const target = source;
const msgEvent = (eventMap === null || eventMap === void 0 ? void 0 : eventMap.message) || "message";
const errEvent = (eventMap === null || eventMap === void 0 ? void 0 : eventMap.error) || "error";
const closeEvent = (eventMap === null || eventMap === void 0 ? void 0 : eventMap.close) || "close";
const msgListener = (ev) => {
if (ev instanceof MessageEvent) {
handleMessage(ev.data);
}
else {
msgDesc.set.call(source, (ev) => {
handleMessage(ev.data);
});
cleanup = () => {
var _a;
(_a = msgDesc.set) === null || _a === void 0 ? void 0 : _a.call(source, null);
};
target.addEventListener(msgEvent, msgListener);
target.addEventListener(errEvent, handleBrowserErrorEvent);
target.addEventListener(closeEvent, function closeListener() {
}
(_a = errDesc === null || errDesc === void 0 ? void 0 : errDesc.set) === null || _a === void 0 ? void 0 : _a.call(source, handleBrowserErrorEvent);
if (closeDesc === null || closeDesc === void 0 ? void 0 : closeDesc.set) { // WebSocket
closeDesc.set.call(source, () => {
var _a, _b;
handleClose();
target.removeEventListener(closeEvent, closeListener);
target.removeEventListener(msgEvent, msgListener);
target.removeEventListener(errEvent, handleBrowserErrorEvent);
(_a = closeDesc.set) === null || _a === void 0 ? void 0 : _a.call(source, null);
(_b = errDesc === null || errDesc === void 0 ? void 0 : errDesc.set) === null || _b === void 0 ? void 0 : _b.call(source, null);
cleanup === null || cleanup === void 0 ? void 0 : cleanup();
});
}
else if (typeof source["on"] === "function") { // EventEmitter
const target = source;
const dataEvent = (eventMap === null || eventMap === void 0 ? void 0 : eventMap.data) || "data";
const errEvent = (eventMap === null || eventMap === void 0 ? void 0 : eventMap.error) || "error";
const endEvent = (eventMap === null || eventMap === void 0 ? void 0 : eventMap.close) || "close";
target.on(dataEvent, handleMessage);
target.once(errEvent, handleError);
target.once(endEvent, () => {
else if (!(closeDesc === null || closeDesc === void 0 ? void 0 : closeDesc.set) && typeof source.close === "function") { // EventSource
// EventSource by default does not trigger close event, we need to make sure when
// it calls the close() function, the iterator is automatically closed.
const es = source;
const _close = es.close;
es.close = function close() {
var _a;
_close.call(es);
handleClose();
target.off(dataEvent, handleMessage);
target.off(dataEvent, handleError);
});
es.close = _close;
(_a = errDesc === null || errDesc === void 0 ? void 0 : errDesc.set) === null || _a === void 0 ? void 0 : _a.call(source, null);
cleanup === null || cleanup === void 0 ? void 0 : cleanup();
};
}
else {
throw new TypeError("the input source cannot be read as an AsyncIterable object");
}
return {
[Symbol.asyncIterator]() {
return iterable;
}
else if (typeof source.send === "function" && typeof source.close === "function") {
// non-standard WebSocket implementation
const ws = source;
ws.onmessage = (ev) => {
handleMessage(ev.data);
};
ws.onerror = handleBrowserErrorEvent;
ws.onclose = () => {
handleClose();
ws.onclose = null;
ws.onerror = null;
ws.onmessage = null;
};
}
else if (typeof source["addEventListener"] === "function") { // EventTarget
const target = source;
const msgEvent = (eventMap === null || eventMap === void 0 ? void 0 : eventMap.message) || "message";
const errEvent = (eventMap === null || eventMap === void 0 ? void 0 : eventMap.error) || "error";
const closeEvent = (eventMap === null || eventMap === void 0 ? void 0 : eventMap.close) || "close";
const msgListener = (ev) => {
if (ev instanceof MessageEvent) {
handleMessage(ev.data);
}
};
},
async run(script, args = undefined, options = undefined) {
var _a, _b;
const msg = {
type: "ffi",
script,
baseUrl: "",
fn: (options === null || options === void 0 ? void 0 : options.fn) || "default",
args: args !== null && args !== void 0 ? args : [],
};
if (typeof Deno === "object") {
msg.baseUrl = "file://" + Deno.cwd() + "/";
target.addEventListener(msgEvent, msgListener);
target.addEventListener(errEvent, handleBrowserErrorEvent);
target.addEventListener(closeEvent, function closeListener() {
handleClose();
target.removeEventListener(closeEvent, closeListener);
target.removeEventListener(msgEvent, msgListener);
target.removeEventListener(errEvent, handleBrowserErrorEvent);
});
}
else if (typeof source["on"] === "function") { // EventEmitter
const target = source;
const dataEvent = (eventMap === null || eventMap === void 0 ? void 0 : eventMap.data) || "data";
const errEvent = (eventMap === null || eventMap === void 0 ? void 0 : eventMap.error) || "error";
const endEvent = (eventMap === null || eventMap === void 0 ? void 0 : eventMap.close) || "close";
target.on(dataEvent, handleMessage);
target.once(errEvent, handleError);
target.once(endEvent, () => {
handleClose();
target.off(dataEvent, handleMessage);
target.off(dataEvent, handleError);
});
}
else {
throw new TypeError("the input source cannot be read as an AsyncIterable object");
}
return {
[Symbol.asyncIterator]() {
return iterable;
}
else if (isNode) {
msg.baseUrl = "file://" + process.cwd() + "/";
};
}
const isNode = typeof process === "object" && !!((_a = process.versions) === null || _a === void 0 ? void 0 : _a.node);
/**
* The maximum number of workers allowed to exist at the same time.
*
* The primary purpose of the workers is not mean to run tasks in parallel, but run them in separate
* from the main thread, so that aborting tasks can be achieved by terminating the worker thread and
* it will not affect the main thread.
*
* That said, the worker thread can still be used to achieve parallelism, but it should be noticed
* that only the numbers of tasks that equals to the CPU core numbers will be run at the same time.
*/
const maxWorkerNum = 16;
const workerIdCounter = sequence(1, Number.MAX_SAFE_INTEGER, 1, true);
let workerPool = [];
// The worker consumer queue is nothing but a callback list, once a worker is available, the runner
// pop a consumer and run the callback, which will retry gaining the worker and retry the task.
const workerConsumerQueue = [];
/**
* Runs a task in the `script` in a worker thread that can be aborted during runtime.
*
* In Node.js, the `script` can be either a CommonJS module or an ES module, and is relative to
* the current working directory if not absolute.
*
* In browser or Deno, the `script` can only be an ES module, and is relative to the current URL
* (or working directory for Deno) if not absolute.
*/
async function run(script, args = undefined, options = undefined) {
var _a, _b;
const msg = {
type: "ffi",
script,
baseUrl: "",
fn: (options === null || options === void 0 ? void 0 : options.fn) || "default",
args: args !== null && args !== void 0 ? args : [],
};
if (typeof Deno === "object") {
msg.baseUrl = "file://" + Deno.cwd() + "/";
}
else if (isNode) {
msg.baseUrl = "file://" + process.cwd() + "/";
}
else if (typeof location === "object") {
msg.baseUrl = location.href;
}
// `buffer` is used to store data pieces yielded by generator functions before they are
// consumed. `error` and `result` serves similar purposes for function results.
const buffer = [];
let error = null;
let result;
let resolver;
let iterator;
let workerId;
let poolRecord;
let release;
let terminate = () => Promise.resolve(void 0);
const timeout = (options === null || options === void 0 ? void 0 : options.timeout) ? setTimeout(() => {
const err = new Error(`operation timeout after ${options.timeout}ms`);
if (resolver) {
resolver.reject(err);
}
else if (typeof location === "object") {
msg.baseUrl = location.href;
else {
error = err;
}
// `buffer` is used to store data pieces yielded by generator functions before they are
// consumed. `error` and `result` serves similar purposes for function results.
const buffer = [];
let error = null;
let result;
let resolver;
let iterator;
let workerId;
let poolRecord;
let release;
let terminate = () => Promise.resolve(void 0);
const timeout = (options === null || options === void 0 ? void 0 : options.timeout) ? setTimeout(() => {
const err = new Error(`operation timeout after ${options.timeout}ms`);
if (resolver) {
resolver.reject(err);
terminate();
}, options.timeout) : null;
const handleMessage = (msg) => {
var _a;
if (msg && typeof msg === "object" && typeof msg.type === "string") {
if (msg.type === "error") {
return handleError(msg.error);
}
else {
error = err;
else if (msg.type === "return") {
if (options === null || options === void 0 ? void 0 : options.keepAlive) {
// Release before resolve.
release === null || release === void 0 ? void 0 : release();
if (workerConsumerQueue.length) {
// Queued consumer now has chance to gain the worker.
(_a = workerConsumerQueue.shift()) === null || _a === void 0 ? void 0 : _a();
}
}
else {
terminate();
}
if (resolver) {
resolver.resolve(msg.value);
}
else {
result = { value: msg.value };
}
}
terminate();
}, options.timeout) : null;
const handleMessage = (msg) => {
var _a;
if (msg && typeof msg === "object" && typeof msg.type === "string") {
if (msg.type === "error") {
return handleError(msg.error);
else if (msg.type === "yield") {
if (msg.done) {
// The final message of yield event is the return value.
handleMessage({ type: "return", value: msg.value });
}
else if (msg.type === "return") {
if (options === null || options === void 0 ? void 0 : options.keepAlive) {
// Release before resolve.
release === null || release === void 0 ? void 0 : release();
if (workerConsumerQueue.length) {
// Queued consumer now has chance to gain the worker.
(_a = workerConsumerQueue.shift()) === null || _a === void 0 ? void 0 : _a();
}
else {
if (iterator) {
iterator.emit("data", msg.value);
}
else {
terminate();
buffer.push(msg.value);
}
if (resolver) {
resolver.resolve(msg.value);
}
else {
result = { value: msg.value };
}
}
else if (msg.type === "yield") {
if (msg.done) {
// The final message of yield event is the return value.
handleMessage({ type: "return", value: msg.value });
}
else {
if (iterator) {
iterator.emit("data", msg.value);
}
else {
buffer.push(msg.value);
}
}
}
}
};
const handleError = (err) => {
if (resolver) {
resolver.reject(err);
}
};
const handleError = (err) => {
if (resolver) {
resolver.reject(err);
}
else if (iterator) {
iterator.emit("error", err);
}
else {
error = err;
}
};
const handleExit = () => {
var _a;
if (poolRecord) {
// Clean the pool before resolve.
workerPool = workerPool.filter(record => record !== poolRecord);
if (workerConsumerQueue.length) {
// Queued consumer now has chance to create new worker.
(_a = workerConsumerQueue.shift()) === null || _a === void 0 ? void 0 : _a();
}
else if (iterator) {
iterator.emit("error", err);
}
else {
error = err;
}
};
const handleExit = () => {
var _a;
}
if (resolver) {
resolver.resolve(void 0);
}
else if (iterator) {
iterator.emit("close");
}
else if (!error && !result) {
result = { value: void 0 };
}
};
if (isNode) {
const path = await import('path');
const { fileURLToPath } = await import('url');
let _filename;
let _dirname;
let entry;
if (typeof __filename === "string") {
_filename = __filename;
_dirname = __dirname;
}
else {
// This file URL will be replace with `import.meta.url` by Rollup plugin.
_filename = fileURLToPath(import.meta.url);
_dirname = path.dirname(_filename);
}
if (["cjs", "esm"].includes(path.basename(_dirname))) { // compiled
entry = path.join(path.dirname(_dirname), "worker.mjs");
}
else {
entry = path.join(_dirname, "worker.mjs");
}
if ((options === null || options === void 0 ? void 0 : options.adapter) === "child_process") {
let worker;
let ok = true;
poolRecord = workerPool.find(item => {
return item.adapter === "child_process" && !item.busy;
});
if (poolRecord) {
// Clean the pool before resolve.
workerPool = workerPool.filter(record => record !== poolRecord);
if (workerConsumerQueue.length) {
// Queued consumer now has chance to create new worker.
(_a = workerConsumerQueue.shift()) === null || _a === void 0 ? void 0 : _a();
}
worker = poolRecord.worker;
workerId = poolRecord.workerId;
poolRecord.busy = true;
}
if (resolver) {
resolver.resolve(void 0);
}
else if (iterator) {
iterator.emit("close");
}
else if (!error && !result) {
result = { value: void 0 };
}
};
if (isNode) {
const path = await import('path');
const { fileURLToPath } = await import('url');
let _filename;
let _dirname;
let entry;
if (typeof __filename === "string") {
_filename = __filename;
_dirname = __dirname;
}
else {
// This file URL will be replace with `import.meta.url` by Rollup plugin.
_filename = fileURLToPath(import.meta.url);
_dirname = path.dirname(_filename);
}
if (["cjs", "esm"].includes(path.basename(_dirname))) { // compiled
entry = path.join(path.dirname(_dirname), "worker.mjs");
}
else {
entry = path.join(_dirname, "worker.mjs");
}
if ((options === null || options === void 0 ? void 0 : options.adapter) === "child_process") {
let worker;
let ok = true;
poolRecord = workerPool.find(item => {
return item.adapter === "child_process" && !item.busy;
else if (workerPool.length < maxWorkerNum) {
const { fork } = await import('child_process');
const isPrior14 = parseInt(process.version.slice(1)) < 14;
worker = fork(entry, {
stdio: "inherit",
serialization: isPrior14 ? "advanced" : "json",
});
if (poolRecord) {
worker = poolRecord.worker;
workerId = poolRecord.workerId;
poolRecord.busy = true;
}
else if (workerPool.length < maxWorkerNum) {
const { fork } = await import('child_process');
const isPrior14 = parseInt(process.version.slice(1)) < 14;
worker = fork(entry, {
stdio: "inherit",
serialization: isPrior14 ? "advanced" : "json",
workerId = worker.pid;
ok = await new Promise((resolve) => {
worker.once("exit", () => {
if (error) {
// The child process took too long to start and cause timeout error.
resolve(false);
}
});
workerId = worker.pid;
ok = await new Promise((resolve) => {
worker.once("exit", () => {
if (error) {
// The child process took too long to start and cause timeout error.
resolve(false);
}
});
worker.once("message", () => {
worker.removeAllListeners("exit");
resolve(true);
});
worker.once("message", () => {
worker.removeAllListeners("exit");
resolve(true);
});
// Fill the worker pool regardless the current call should keep-alive or not,
// this will make sure that the total number of workers will not exceed the
// maxWorkerNum. If the the call doesn't keep-alive the worker, it will be
// cleaned after the call.
ok && workerPool.push(poolRecord = {
workerId,
worker,
adapter: "child_process",
busy: true,
});
}
else {
// Put the current call in the consumer queue if there are no workers available,
// once an existing call finishes, the queue will pop the its head consumer and
// retry.
return new Promise((resolve) => {
workerConsumerQueue.push(resolve);
}).then(() => jsext.run(script, args, options));
}
release = () => {
// Remove the event listener so that later calls will not mess up.
worker.off("message", handleMessage);
poolRecord && (poolRecord.busy = false);
};
terminate = () => Promise.resolve(void worker.kill(1));
if (ok) {
worker.send(msg);
worker.on("message", handleMessage);
worker.once("error", handleError);
worker.once("exit", handleExit);
}
});
// Fill the worker pool regardless the current call should keep-alive or not,
// this will make sure that the total number of workers will not exceed the
// maxWorkerNum. If the the call doesn't keep-alive the worker, it will be
// cleaned after the call.
ok && workerPool.push(poolRecord = {
workerId,
worker,
adapter: "child_process",
busy: true,
});
}
else {
let worker;
let ok = true;
poolRecord = workerPool.find(item => {
return item.adapter === "worker_threads" && !item.busy;
});
if (poolRecord) {
worker = poolRecord.worker;
workerId = poolRecord.workerId;
poolRecord.busy = true;
}
else if (workerPool.length < maxWorkerNum) {
const { Worker } = await import('worker_threads');
worker = new Worker(entry);
// `threadId` may not exist in Bun.
workerId = (_a = worker.threadId) !== null && _a !== void 0 ? _a : workerIdCounter.next().value;
ok = await new Promise((resolve) => {
worker.once("exit", () => {
if (error) {
// The child process took too long to start and cause timeout error.
resolve(false);
}
});
worker.once("online", () => {
worker.removeAllListeners("exit");
resolve(true);
});
});
ok && workerPool.push(poolRecord = {
workerId,
worker,
adapter: "worker_threads",
busy: true,
});
}
else {
return new Promise((resolve) => {
workerConsumerQueue.push(resolve);
}).then(() => jsext.run(script, args, options));
}
release = () => {
worker.off("message", handleMessage);
poolRecord && (poolRecord.busy = false);
};
terminate = async () => void (await worker.terminate());
if (ok) {
worker.postMessage(msg);
worker.on("message", handleMessage);
worker.once("error", handleError);
worker.once("messageerror", handleError);
worker.once("exit", handleExit);
}
// Put the current call in the consumer queue if there are no workers available,
// once an existing call finishes, the queue will pop the its head consumer and
// retry.
return new Promise((resolve) => {
workerConsumerQueue.push(resolve);
}).then(() => run(script, args, options));
}
release = () => {
// Remove the event listener so that later calls will not mess up.
worker.off("message", handleMessage);
poolRecord && (poolRecord.busy = false);
};
terminate = () => Promise.resolve(void worker.kill(1));
if (ok) {
worker.send(msg);
worker.on("message", handleMessage);
worker.once("error", handleError);
worker.once("exit", handleExit);
}
}
else {
let worker;
let ok = true;
poolRecord = workerPool.find(item => {

@@ -780,29 +761,19 @@ return item.adapter === "worker_threads" && !item.busy;

else if (workerPool.length < maxWorkerNum) {
let url;
if (typeof Deno === "object") {
// Deno can load the module regardless of MINE type.
url = [
...(import.meta.url.split("/").slice(0, -1)),
"worker-web.mjs"
].join("/");
}
else {
const _url = (options === null || options === void 0 ? void 0 : options.webWorkerEntry)
|| "https://raw.githubusercontent.com/ayonli/jsext/main/esm/worker-web.mjs";
const res = await fetch(_url);
let blob;
if ((_b = res.headers.get("content-type")) === null || _b === void 0 ? void 0 : _b.startsWith("application/javascript")) {
blob = await res.blob();
}
else {
const buf = await res.arrayBuffer();
blob = new Blob([new Uint8Array(buf)], {
type: "application/javascript",
});
}
url = URL.createObjectURL(blob);
}
worker = new Worker(url, { type: "module" });
workerId = workerIdCounter.next().value;
workerPool.push(poolRecord = {
const { Worker } = await import('worker_threads');
worker = new Worker(entry);
// `threadId` may not exist in Bun.
workerId = (_a = worker.threadId) !== null && _a !== void 0 ? _a : workerIdCounter.next().value;
ok = await new Promise((resolve) => {
worker.once("exit", () => {
if (error) {
// The child process took too long to start and cause timeout error.
resolve(false);
}
});
worker.once("online", () => {
worker.removeAllListeners("exit");
resolve(true);
});
});
ok && workerPool.push(poolRecord = {
workerId,

@@ -817,65 +788,137 @@ worker,

workerConsumerQueue.push(resolve);
}).then(() => jsext.run(script, args, options));
}).then(() => run(script, args, options));
}
release = () => {
worker.onmessage = null;
worker.off("message", handleMessage);
poolRecord && (poolRecord.busy = false);
};
terminate = async () => {
await Promise.resolve(worker.terminate());
handleExit();
};
worker.postMessage(msg);
worker.onmessage = (ev) => handleMessage(ev.data);
worker.onerror = (ev) => handleMessage(ev.error || new Error(ev.message));
worker.onmessageerror = () => {
handleError(new Error("unable to deserialize the message"));
};
terminate = async () => void (await worker.terminate());
if (ok) {
worker.postMessage(msg);
worker.on("message", handleMessage);
worker.once("error", handleError);
worker.once("messageerror", handleError);
worker.once("exit", handleExit);
}
}
return {
workerId,
async abort() {
timeout && clearTimeout(timeout);
await terminate();
},
async result() {
return await new Promise((resolve, reject) => {
if (error) {
reject(error);
}
else if (result) {
resolve(result.value);
}
else {
resolver = { resolve, reject };
}
});
},
async *iterate() {
if (resolver) {
throw new Error("result() has been called");
}
else {
let worker;
poolRecord = workerPool.find(item => {
return item.adapter === "worker_threads" && !item.busy;
});
if (poolRecord) {
worker = poolRecord.worker;
workerId = poolRecord.workerId;
poolRecord.busy = true;
}
else if (workerPool.length < maxWorkerNum) {
let url;
if (typeof Deno === "object") {
// Deno can load the module regardless of MINE type.
url = [
...(import.meta.url.split("/").slice(0, -1)),
"worker-web.mjs"
].join("/");
}
else {
const _url = (options === null || options === void 0 ? void 0 : options.webWorkerEntry)
|| "https://raw.githubusercontent.com/ayonli/jsext/main/esm/worker-web.mjs";
const res = await fetch(_url);
let blob;
if ((_b = res.headers.get("content-type")) === null || _b === void 0 ? void 0 : _b.startsWith("application/javascript")) {
blob = await res.blob();
}
else {
const buf = await res.arrayBuffer();
blob = new Blob([new Uint8Array(buf)], {
type: "application/javascript",
});
}
url = URL.createObjectURL(blob);
}
worker = new Worker(url, { type: "module" });
workerId = workerIdCounter.next().value;
workerPool.push(poolRecord = {
workerId,
worker,
adapter: "worker_threads",
busy: true,
});
}
else {
return new Promise((resolve) => {
workerConsumerQueue.push(resolve);
}).then(() => run(script, args, options));
}
release = () => {
worker.onmessage = null;
poolRecord && (poolRecord.busy = false);
};
terminate = async () => {
await Promise.resolve(worker.terminate());
handleExit();
};
worker.postMessage(msg);
worker.onmessage = (ev) => handleMessage(ev.data);
worker.onerror = (ev) => handleMessage(ev.error || new Error(ev.message));
worker.onmessageerror = () => {
handleError(new Error("unable to deserialize the message"));
};
}
return {
workerId,
async abort() {
timeout && clearTimeout(timeout);
await terminate();
},
async result() {
return await new Promise((resolve, reject) => {
if (error) {
reject(error);
}
else if (result) {
throw new TypeError("the response is not iterable");
resolve(result.value);
}
const { EventEmitter } = await import('events');
iterator = new EventEmitter();
if (buffer.length) {
(async () => {
await Promise.resolve(null);
let msg;
while (msg = buffer.shift()) {
iterator.emit("data", msg);
}
})().catch(console.error);
else {
resolver = { resolve, reject };
}
for await (const msg of jsext.read(iterator)) {
yield msg;
}
},
};
}
});
},
async *iterate() {
if (resolver) {
throw new Error("result() has been called");
}
else if (result) {
throw new TypeError("the response is not iterable");
}
const { EventEmitter } = await import('events');
iterator = new EventEmitter();
if (buffer.length) {
(async () => {
await Promise.resolve(null);
let msg;
while (msg = buffer.shift()) {
iterator.emit("data", msg);
}
})().catch(console.error);
}
for await (const msg of read(iterator)) {
yield msg;
}
},
};
}
const jsext = {
try: _try,
func,
wrap,
throttle,
mixins,
isSubclassOf,
read,
run,
};
export { jsext as default };
export { AsyncFunction, AsyncGeneratorFunction, _try, jsext as default, func, isSubclassOf, mixins, read, run, throttle, wrap };
//# sourceMappingURL=index.js.map

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

{"version":3,"file":"index.js","sources":["../index.ts"],"sourcesContent":["var _a;\nimport { isAsyncGenerator, isGenerator } from \"check-iterable\";\nimport { sequence } from \"./number\";\nconst isNode = typeof process === \"object\" && !!((_a = process.versions) === null || _a === void 0 ? void 0 : _a.node);\nconst throttleCaches = new Map();\n/**\n * The maximum number of workers allowed to exist at the same time.\n *\n * The primary purpose of the workers is not mean to run tasks in parallel, but run them in separate\n * from the main thread, so that aborting tasks can be achieved by terminating the worker thread and\n * it will not affect the main thread.\n *\n * That said, the worker thread can still be used to achieve parallelism, but it should be noticed\n * that only the numbers of tasks that equals to the CPU core numbers will be run at the same time.\n */\nconst maxWorkerNum = 16;\nconst workerIdCounter = sequence(1, Number.MAX_SAFE_INTEGER, 1, true);\nlet workerPool = [];\n// The worker consumer queue is nothing but a callback list, once a worker is available, the runner\n// pop a consumer and run the callback, which will retry gaining the worker and retry the task.\nconst workerConsumerQueue = [];\n/**\n * Merges properties and methods only if they're missing in the class.\n */\nfunction mergeIfNotExists(proto, source, mergeSuper = false) {\n const props = Reflect.ownKeys(source);\n for (const prop of props) {\n if (prop == \"constructor\") {\n continue;\n }\n else if (mergeSuper) {\n // When merging properties from super classes, the properties in the\n // base class has the first priority and shall not be overwrite.\n if (!(prop in proto)) {\n setProp(proto, source, prop);\n }\n }\n else if (!proto.hasOwnProperty(prop)) {\n setProp(proto, source, prop);\n }\n }\n return proto;\n}\n/**\n * Merges properties and methods across the prototype chain.\n */\nfunction mergeHierarchy(ctor, mixin, mergeSuper = false) {\n mergeIfNotExists(ctor.prototype, mixin.prototype, mergeSuper);\n const _super = Object.getPrototypeOf(mixin);\n // Every user defined class or functions that can be instantiated have their\n // own names, if no name appears, that means the function has traveled to \n // the root of the hierarchical tree.\n if (_super.name) {\n mergeHierarchy(ctor, _super, true);\n }\n}\n/**\n * Sets property for prototype based on the given source and prop name properly.\n */\nfunction setProp(proto, source, prop) {\n const desc = Object.getOwnPropertyDescriptor(source, prop);\n if (desc) {\n Object.defineProperty(proto, prop, desc);\n }\n else {\n proto[prop] = source[prop];\n }\n}\nconst jsext = {\n try(fn, ...args) {\n if (typeof fn === \"function\") {\n try {\n return jsext.try(fn.apply(void 0, args));\n }\n catch (err) {\n return [err, undefined];\n }\n }\n let returns = fn;\n // Implementation details should be ordered from complex to simple.\n if (isAsyncGenerator(returns)) {\n return (async function* () {\n let input;\n let result;\n // Use `while` loop instead of `for...of...` in order to\n // retrieve the return value of a generator function.\n while (true) {\n try {\n const { done, value } = await returns.next(input);\n if (done) {\n result = value;\n break;\n }\n else {\n // Receive any potential input value that passed\n // to the outer `next()` call, and pass them to\n // `res.next()` in the next call.\n input = yield Promise.resolve([null, value]);\n }\n }\n catch (err) {\n // If any error occurs, yield that error as resolved\n // and break the loop immediately, indicating the\n // process is forced broken.\n yield Promise.resolve([err, undefined]);\n break;\n }\n }\n return [null, result];\n })();\n }\n else if (isGenerator(returns)) {\n return (function* () {\n let input;\n let result;\n while (true) {\n try {\n const { done, value } = returns.next(input);\n if (done) {\n result = value;\n break;\n }\n else {\n input = yield [null, value];\n }\n }\n catch (err) {\n yield [err, undefined];\n break;\n }\n }\n return [null, result];\n })();\n }\n else if (typeof (returns === null || returns === void 0 ? void 0 : returns.then) === \"function\") {\n returns = returns.then((value) => [null, value]);\n return Promise.resolve(returns).catch((err) => [err, undefined]);\n }\n else {\n return [null, returns];\n }\n },\n func(fn) {\n return function (...args) {\n var _a;\n const callbacks = [];\n const defer = (cb) => void callbacks.push(cb);\n let result;\n try {\n const returns = fn.call(this, defer, ...args);\n if (isAsyncGenerator(returns)) {\n const gen = (async function* () {\n var _a;\n let input;\n // Use `while` loop instead of `for...of...` in order to\n // retrieve the return value of a generator function.\n while (true) {\n try {\n const { done, value } = await returns.next(input);\n if (done) {\n result = { value, error: null };\n break;\n }\n else {\n // Receive any potential input value that passed\n // to the outer `next()` call, and pass them to\n // `res.next()` in the next call.\n input = yield Promise.resolve(value);\n }\n }\n catch (error) {\n // If any error occurs, capture that error and break\n // the loop immediately, indicating the process is\n // forced broken.\n result = { value: void 0, error };\n break;\n }\n }\n for (let i = callbacks.length - 1; i >= 0; i--) {\n await ((_a = callbacks[i]) === null || _a === void 0 ? void 0 : _a.call(callbacks));\n }\n if (result.error) {\n throw result.error;\n }\n else {\n return result.value;\n }\n })();\n return gen;\n }\n else if (isGenerator(returns)) {\n const gen = (function* () {\n var _a;\n let input;\n while (true) {\n try {\n const { done, value } = returns.next(input);\n if (done) {\n result = { value, error: null };\n break;\n }\n else {\n input = yield value;\n }\n }\n catch (error) {\n result = { value: void 0, error };\n break;\n }\n }\n for (let i = callbacks.length - 1; i >= 0; i--) {\n (_a = callbacks[i]) === null || _a === void 0 ? void 0 : _a.call(callbacks);\n }\n if (result.error) {\n throw result.error;\n }\n else {\n return result.value;\n }\n })();\n return gen;\n }\n else if (typeof (returns === null || returns === void 0 ? void 0 : returns.then) === \"function\") {\n return Promise.resolve(returns).then(value => ({\n value,\n error: null,\n })).catch((error) => ({\n value: void 0,\n error,\n })).then(async (result) => {\n var _a;\n for (let i = callbacks.length - 1; i >= 0; i--) {\n await ((_a = callbacks[i]) === null || _a === void 0 ? void 0 : _a.call(callbacks));\n }\n if (result.error) {\n throw result.error;\n }\n else {\n return result.value;\n }\n });\n }\n else {\n result = { value: returns, error: null };\n }\n }\n catch (error) {\n result = { value: void 0, error };\n }\n for (let i = callbacks.length - 1; i >= 0; i--) {\n (_a = callbacks[i]) === null || _a === void 0 ? void 0 : _a.call(callbacks);\n }\n if (result.error) {\n throw result.error;\n }\n else {\n return result.value;\n }\n };\n },\n wrap(fn, wrapper) {\n const wrapped = function (...args) {\n return wrapper.call(this, fn, ...args);\n };\n Object.defineProperty(wrapped, \"name\", Object.getOwnPropertyDescriptor(fn, \"name\"));\n Object.defineProperty(wrapped, \"length\", Object.getOwnPropertyDescriptor(fn, \"length\"));\n Object.defineProperty(wrapped, \"toString\", {\n configurable: true,\n enumerable: false,\n writable: true,\n value: fn.toString.bind(fn),\n });\n return wrapped;\n },\n throttle(handler, options) {\n const key = typeof options === \"number\" ? null : options.for;\n const duration = typeof options === \"number\" ? options : options.duration;\n const handleCall = function (cache, ...args) {\n var _a;\n if (cache.result && Date.now() < ((_a = cache.expires) !== null && _a !== void 0 ? _a : 0)) {\n if (cache.result.error) {\n throw cache.result.error;\n }\n else {\n return cache.result.value;\n }\n }\n try {\n const returns = handler.call(this, ...args);\n cache.result = { value: returns };\n cache.expires = Date.now() + duration;\n return returns;\n }\n catch (error) {\n cache.result = { error };\n cache.expires = Date.now() + duration;\n throw error;\n }\n };\n if (!key) {\n const cache = { for: null };\n return function (...args) {\n return handleCall.call(this, cache, ...args);\n };\n }\n else {\n let cache = throttleCaches.get(key);\n if (!cache) {\n cache = { for: key };\n throttleCaches.set(key, cache);\n }\n return function (...args) {\n return handleCall.call(this, cache, ...args);\n };\n }\n },\n mixins(base, ...mixins) {\n const obj = { ctor: null };\n obj.ctor = class extends base {\n }; // make sure this class has no name\n for (const mixin of mixins) {\n if (typeof mixin == \"function\") {\n mergeHierarchy(obj.ctor, mixin);\n }\n else if (mixin && typeof mixin == \"object\") {\n mergeIfNotExists(obj.ctor.prototype, mixin);\n }\n else {\n throw new TypeError(\"mixin must be a constructor or an object\");\n }\n }\n return obj.ctor;\n },\n isSubclassOf(ctor1, ctor2) {\n return typeof ctor1 === \"function\"\n && typeof ctor2 === \"function\"\n && ctor1.prototype instanceof ctor2;\n },\n read(source, eventMap = undefined) {\n var _a;\n if (typeof source[Symbol.asyncIterator] === \"function\") {\n return source;\n }\n const iterable = {\n ended: false,\n error: null,\n queue: [],\n consumers: [],\n next() {\n return new Promise((resolve, reject) => {\n if (this.error && !this.ended) {\n // If there is error occurred during the last transmission and the iterator\n // hasn't been closed, reject that error and stop the iterator immediately.\n reject(this.error);\n this.ended = true;\n }\n else if (this.ended && !this.queue.length) {\n // If the iterator has is closed, resolve the pending consumer with void\n // value.\n resolve({ value: void 0, done: true });\n }\n else if (this.queue.length > 0) {\n // If there are data in the queue, resolve the the first piece immediately.\n resolve({ value: this.queue.shift(), done: false });\n }\n else {\n // If there are no queued data, push the consumer to a waiting queue.\n this.consumers.push({ resolve, reject });\n }\n });\n }\n };\n const handleMessage = (data) => {\n var _a;\n if (iterable.consumers.length > 0) {\n (_a = iterable.consumers.shift()) === null || _a === void 0 ? void 0 : _a.resolve({ value: data, done: false });\n }\n else {\n iterable.queue.push(data);\n }\n };\n const handleClose = () => {\n iterable.ended = true;\n let consumer;\n while (consumer = iterable.consumers.shift()) {\n consumer.resolve({ value: undefined, done: true });\n }\n };\n const handleError = (err) => {\n iterable.error = err;\n if (iterable.consumers.length > 0) {\n iterable.consumers.forEach(item => {\n item.reject(err);\n });\n iterable.consumers = [];\n }\n };\n const handleBrowserErrorEvent = (ev) => {\n let err;\n if (ev instanceof ErrorEvent) {\n err = ev.error || new Error(ev.message);\n }\n else {\n // @ts-ignore\n err = new Error(\"something went wrong\", { cause: ev });\n }\n handleError(err);\n };\n const proto = Object.getPrototypeOf(source);\n const msgDesc = Object.getOwnPropertyDescriptor(proto, \"onmessage\");\n if ((msgDesc === null || msgDesc === void 0 ? void 0 : msgDesc.set) && typeof source.close === \"function\") { // WebSocket or EventSource\n const errDesc = Object.getOwnPropertyDescriptor(proto, \"onerror\");\n const closeDesc = Object.getOwnPropertyDescriptor(proto, \"onclose\");\n let cleanup;\n if ((eventMap === null || eventMap === void 0 ? void 0 : eventMap.event) &&\n (eventMap === null || eventMap === void 0 ? void 0 : eventMap.event) !== \"message\" &&\n typeof source[\"addEventListener\"] === \"function\") { // for EventSource listening on custom events\n const es = source;\n const eventName = eventMap.event;\n const msgListener = (ev) => {\n handleMessage(ev.data);\n };\n es.addEventListener(eventName, msgListener);\n cleanup = () => {\n es.removeEventListener(eventName, msgListener);\n };\n }\n else {\n msgDesc.set.call(source, (ev) => {\n handleMessage(ev.data);\n });\n cleanup = () => {\n var _a;\n (_a = msgDesc.set) === null || _a === void 0 ? void 0 : _a.call(source, null);\n };\n }\n (_a = errDesc === null || errDesc === void 0 ? void 0 : errDesc.set) === null || _a === void 0 ? void 0 : _a.call(source, handleBrowserErrorEvent);\n if (closeDesc === null || closeDesc === void 0 ? void 0 : closeDesc.set) { // WebSocket\n closeDesc.set.call(source, () => {\n var _a, _b;\n handleClose();\n (_a = closeDesc.set) === null || _a === void 0 ? void 0 : _a.call(source, null);\n (_b = errDesc === null || errDesc === void 0 ? void 0 : errDesc.set) === null || _b === void 0 ? void 0 : _b.call(source, null);\n cleanup === null || cleanup === void 0 ? void 0 : cleanup();\n });\n }\n else if (!(closeDesc === null || closeDesc === void 0 ? void 0 : closeDesc.set) && typeof source.close === \"function\") { // EventSource\n // EventSource by default does not trigger close event, we need to make sure when\n // it calls the close() function, the iterator is automatically closed.\n const es = source;\n const _close = es.close;\n es.close = function close() {\n var _a;\n _close.call(es);\n handleClose();\n es.close = _close;\n (_a = errDesc === null || errDesc === void 0 ? void 0 : errDesc.set) === null || _a === void 0 ? void 0 : _a.call(source, null);\n cleanup === null || cleanup === void 0 ? void 0 : cleanup();\n };\n }\n }\n else if (typeof source.send === \"function\" && typeof source.close === \"function\") {\n // non-standard WebSocket implementation\n const ws = source;\n ws.onmessage = (ev) => {\n handleMessage(ev.data);\n };\n ws.onerror = handleBrowserErrorEvent;\n ws.onclose = () => {\n handleClose();\n ws.onclose = null;\n ws.onerror = null;\n ws.onmessage = null;\n };\n }\n else if (typeof source[\"addEventListener\"] === \"function\") { // EventTarget\n const target = source;\n const msgEvent = (eventMap === null || eventMap === void 0 ? void 0 : eventMap.message) || \"message\";\n const errEvent = (eventMap === null || eventMap === void 0 ? void 0 : eventMap.error) || \"error\";\n const closeEvent = (eventMap === null || eventMap === void 0 ? void 0 : eventMap.close) || \"close\";\n const msgListener = (ev) => {\n if (ev instanceof MessageEvent) {\n handleMessage(ev.data);\n }\n };\n target.addEventListener(msgEvent, msgListener);\n target.addEventListener(errEvent, handleBrowserErrorEvent);\n target.addEventListener(closeEvent, function closeListener() {\n handleClose();\n target.removeEventListener(closeEvent, closeListener);\n target.removeEventListener(msgEvent, msgListener);\n target.removeEventListener(errEvent, handleBrowserErrorEvent);\n });\n }\n else if (typeof source[\"on\"] === \"function\") { // EventEmitter\n const target = source;\n const dataEvent = (eventMap === null || eventMap === void 0 ? void 0 : eventMap.data) || \"data\";\n const errEvent = (eventMap === null || eventMap === void 0 ? void 0 : eventMap.error) || \"error\";\n const endEvent = (eventMap === null || eventMap === void 0 ? void 0 : eventMap.close) || \"close\";\n target.on(dataEvent, handleMessage);\n target.once(errEvent, handleError);\n target.once(endEvent, () => {\n handleClose();\n target.off(dataEvent, handleMessage);\n target.off(dataEvent, handleError);\n });\n }\n else {\n throw new TypeError(\"the input source cannot be read as an AsyncIterable object\");\n }\n return {\n [Symbol.asyncIterator]() {\n return iterable;\n }\n };\n },\n async run(script, args = undefined, options = undefined) {\n var _a, _b;\n const msg = {\n type: \"ffi\",\n script,\n baseUrl: \"\",\n fn: (options === null || options === void 0 ? void 0 : options.fn) || \"default\",\n args: args !== null && args !== void 0 ? args : [],\n };\n if (typeof Deno === \"object\") {\n msg.baseUrl = \"file://\" + Deno.cwd() + \"/\";\n }\n else if (isNode) {\n msg.baseUrl = \"file://\" + process.cwd() + \"/\";\n }\n else if (typeof location === \"object\") {\n msg.baseUrl = location.href;\n }\n // `buffer` is used to store data pieces yielded by generator functions before they are\n // consumed. `error` and `result` serves similar purposes for function results.\n const buffer = [];\n let error = null;\n let result;\n let resolver;\n let iterator;\n let workerId;\n let poolRecord;\n let release;\n let terminate = () => Promise.resolve(void 0);\n const timeout = (options === null || options === void 0 ? void 0 : options.timeout) ? setTimeout(() => {\n const err = new Error(`operation timeout after ${options.timeout}ms`);\n if (resolver) {\n resolver.reject(err);\n }\n else {\n error = err;\n }\n terminate();\n }, options.timeout) : null;\n const handleMessage = (msg) => {\n var _a;\n if (msg && typeof msg === \"object\" && typeof msg.type === \"string\") {\n if (msg.type === \"error\") {\n return handleError(msg.error);\n }\n else if (msg.type === \"return\") {\n if (options === null || options === void 0 ? void 0 : options.keepAlive) {\n // Release before resolve.\n release === null || release === void 0 ? void 0 : release();\n if (workerConsumerQueue.length) {\n // Queued consumer now has chance to gain the worker.\n (_a = workerConsumerQueue.shift()) === null || _a === void 0 ? void 0 : _a();\n }\n }\n else {\n terminate();\n }\n if (resolver) {\n resolver.resolve(msg.value);\n }\n else {\n result = { value: msg.value };\n }\n }\n else if (msg.type === \"yield\") {\n if (msg.done) {\n // The final message of yield event is the return value.\n handleMessage({ type: \"return\", value: msg.value });\n }\n else {\n if (iterator) {\n iterator.emit(\"data\", msg.value);\n }\n else {\n buffer.push(msg.value);\n }\n }\n }\n }\n };\n const handleError = (err) => {\n if (resolver) {\n resolver.reject(err);\n }\n else if (iterator) {\n iterator.emit(\"error\", err);\n }\n else {\n error = err;\n }\n };\n const handleExit = () => {\n var _a;\n if (poolRecord) {\n // Clean the pool before resolve.\n workerPool = workerPool.filter(record => record !== poolRecord);\n if (workerConsumerQueue.length) {\n // Queued consumer now has chance to create new worker.\n (_a = workerConsumerQueue.shift()) === null || _a === void 0 ? void 0 : _a();\n }\n }\n if (resolver) {\n resolver.resolve(void 0);\n }\n else if (iterator) {\n iterator.emit(\"close\");\n }\n else if (!error && !result) {\n result = { value: void 0 };\n }\n };\n if (isNode) {\n const path = await import(\"path\");\n const { fileURLToPath } = await import(\"url\");\n let _filename;\n let _dirname;\n let entry;\n if (typeof __filename === \"string\") {\n _filename = __filename;\n _dirname = __dirname;\n }\n else {\n // This file URL will be replace with `import.meta.url` by Rollup plugin.\n _filename = fileURLToPath(\"file://{__filename}\");\n _dirname = path.dirname(_filename);\n }\n if ([\"cjs\", \"esm\"].includes(path.basename(_dirname))) { // compiled\n entry = path.join(path.dirname(_dirname), \"worker.mjs\");\n }\n else {\n entry = path.join(_dirname, \"worker.mjs\");\n }\n if ((options === null || options === void 0 ? void 0 : options.adapter) === \"child_process\") {\n let worker;\n let ok = true;\n poolRecord = workerPool.find(item => {\n return item.adapter === \"child_process\" && !item.busy;\n });\n if (poolRecord) {\n worker = poolRecord.worker;\n workerId = poolRecord.workerId;\n poolRecord.busy = true;\n }\n else if (workerPool.length < maxWorkerNum) {\n const { fork } = await import(\"child_process\");\n const isPrior14 = parseInt(process.version.slice(1)) < 14;\n worker = fork(entry, {\n stdio: \"inherit\",\n serialization: isPrior14 ? \"advanced\" : \"json\",\n });\n workerId = worker.pid;\n ok = await new Promise((resolve) => {\n worker.once(\"exit\", () => {\n if (error) {\n // The child process took too long to start and cause timeout error.\n resolve(false);\n }\n });\n worker.once(\"message\", () => {\n worker.removeAllListeners(\"exit\");\n resolve(true);\n });\n });\n // Fill the worker pool regardless the current call should keep-alive or not,\n // this will make sure that the total number of workers will not exceed the\n // maxWorkerNum. If the the call doesn't keep-alive the worker, it will be\n // cleaned after the call.\n ok && workerPool.push(poolRecord = {\n workerId,\n worker,\n adapter: \"child_process\",\n busy: true,\n });\n }\n else {\n // Put the current call in the consumer queue if there are no workers available,\n // once an existing call finishes, the queue will pop the its head consumer and\n // retry.\n return new Promise((resolve) => {\n workerConsumerQueue.push(resolve);\n }).then(() => jsext.run(script, args, options));\n }\n release = () => {\n // Remove the event listener so that later calls will not mess up.\n worker.off(\"message\", handleMessage);\n poolRecord && (poolRecord.busy = false);\n };\n terminate = () => Promise.resolve(void worker.kill(1));\n if (ok) {\n worker.send(msg);\n worker.on(\"message\", handleMessage);\n worker.once(\"error\", handleError);\n worker.once(\"exit\", handleExit);\n }\n }\n else {\n let worker;\n let ok = true;\n poolRecord = workerPool.find(item => {\n return item.adapter === \"worker_threads\" && !item.busy;\n });\n if (poolRecord) {\n worker = poolRecord.worker;\n workerId = poolRecord.workerId;\n poolRecord.busy = true;\n }\n else if (workerPool.length < maxWorkerNum) {\n const { Worker } = await import(\"worker_threads\");\n worker = new Worker(entry);\n // `threadId` may not exist in Bun.\n workerId = (_a = worker.threadId) !== null && _a !== void 0 ? _a : workerIdCounter.next().value;\n ok = await new Promise((resolve) => {\n worker.once(\"exit\", () => {\n if (error) {\n // The child process took too long to start and cause timeout error.\n resolve(false);\n }\n });\n worker.once(\"online\", () => {\n worker.removeAllListeners(\"exit\");\n resolve(true);\n });\n });\n ok && workerPool.push(poolRecord = {\n workerId,\n worker,\n adapter: \"worker_threads\",\n busy: true,\n });\n }\n else {\n return new Promise((resolve) => {\n workerConsumerQueue.push(resolve);\n }).then(() => jsext.run(script, args, options));\n }\n release = () => {\n worker.off(\"message\", handleMessage);\n poolRecord && (poolRecord.busy = false);\n };\n terminate = async () => void (await worker.terminate());\n if (ok) {\n worker.postMessage(msg);\n worker.on(\"message\", handleMessage);\n worker.once(\"error\", handleError);\n worker.once(\"messageerror\", handleError);\n worker.once(\"exit\", handleExit);\n }\n }\n }\n else {\n let worker;\n poolRecord = workerPool.find(item => {\n return item.adapter === \"worker_threads\" && !item.busy;\n });\n if (poolRecord) {\n worker = poolRecord.worker;\n workerId = poolRecord.workerId;\n poolRecord.busy = true;\n }\n else if (workerPool.length < maxWorkerNum) {\n let url;\n if (typeof Deno === \"object\") {\n // Deno can load the module regardless of MINE type.\n url = [\n ...(\"file://{__filename}\".split(\"/\").slice(0, -1)),\n \"worker-web.mjs\"\n ].join(\"/\");\n }\n else {\n const _url = (options === null || options === void 0 ? void 0 : options.webWorkerEntry)\n || \"https://raw.githubusercontent.com/ayonli/jsext/main/esm/worker-web.mjs\";\n const res = await fetch(_url);\n let blob;\n if ((_b = res.headers.get(\"content-type\")) === null || _b === void 0 ? void 0 : _b.startsWith(\"application/javascript\")) {\n blob = await res.blob();\n }\n else {\n const buf = await res.arrayBuffer();\n blob = new Blob([new Uint8Array(buf)], {\n type: \"application/javascript\",\n });\n }\n url = URL.createObjectURL(blob);\n }\n worker = new Worker(url, { type: \"module\" });\n workerId = workerIdCounter.next().value;\n workerPool.push(poolRecord = {\n workerId,\n worker,\n adapter: \"worker_threads\",\n busy: true,\n });\n }\n else {\n return new Promise((resolve) => {\n workerConsumerQueue.push(resolve);\n }).then(() => jsext.run(script, args, options));\n }\n release = () => {\n worker.onmessage = null;\n poolRecord && (poolRecord.busy = false);\n };\n terminate = async () => {\n await Promise.resolve(worker.terminate());\n handleExit();\n };\n worker.postMessage(msg);\n worker.onmessage = (ev) => handleMessage(ev.data);\n worker.onerror = (ev) => handleMessage(ev.error || new Error(ev.message));\n worker.onmessageerror = () => {\n handleError(new Error(\"unable to deserialize the message\"));\n };\n }\n return {\n workerId,\n async abort() {\n timeout && clearTimeout(timeout);\n await terminate();\n },\n async result() {\n return await new Promise((resolve, reject) => {\n if (error) {\n reject(error);\n }\n else if (result) {\n resolve(result.value);\n }\n else {\n resolver = { resolve, reject };\n }\n });\n },\n async *iterate() {\n if (resolver) {\n throw new Error(\"result() has been called\");\n }\n else if (result) {\n throw new TypeError(\"the response is not iterable\");\n }\n const { EventEmitter } = await import(\"events\");\n iterator = new EventEmitter();\n if (buffer.length) {\n (async () => {\n await Promise.resolve(null);\n let msg;\n while (msg = buffer.shift()) {\n iterator.emit(\"data\", msg);\n }\n })().catch(console.error);\n }\n for await (const msg of jsext.read(iterator)) {\n yield msg;\n }\n },\n };\n }\n};\nexport default jsext;\n//# sourceMappingURL=index.js.map"],"names":[],"mappings":";;;AAAA;AAGA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACK;AACL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,0CAA0C,eAAqB;AAC/D;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,4BAA4B,eAAqB;AACjD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;"}
{"version":3,"file":"index.js","sources":["../index.ts"],"sourcesContent":["var _a;\nimport { isAsyncGenerator, isGenerator } from \"check-iterable\";\nimport { sequence } from \"./number\";\nexport const AsyncFunction = (async function () { }).constructor;\nexport const AsyncGeneratorFunction = (async function* () { }).constructor;\nexport function _try(fn, ...args) {\n if (typeof fn === \"function\") {\n try {\n return _try(fn.apply(void 0, args));\n }\n catch (err) {\n return [err, undefined];\n }\n }\n let returns = fn;\n // Implementation details should be ordered from complex to simple.\n if (isAsyncGenerator(returns)) {\n return (async function* () {\n let input;\n let result;\n // Use `while` loop instead of `for...of...` in order to\n // retrieve the return value of a generator function.\n while (true) {\n try {\n const { done, value } = await returns.next(input);\n if (done) {\n result = value;\n break;\n }\n else {\n // Receive any potential input value that passed\n // to the outer `next()` call, and pass them to\n // `res.next()` in the next call.\n input = yield Promise.resolve([null, value]);\n }\n }\n catch (err) {\n // If any error occurs, yield that error as resolved\n // and break the loop immediately, indicating the\n // process is forced broken.\n yield Promise.resolve([err, undefined]);\n break;\n }\n }\n return [null, result];\n })();\n }\n else if (isGenerator(returns)) {\n return (function* () {\n let input;\n let result;\n while (true) {\n try {\n const { done, value } = returns.next(input);\n if (done) {\n result = value;\n break;\n }\n else {\n input = yield [null, value];\n }\n }\n catch (err) {\n yield [err, undefined];\n break;\n }\n }\n return [null, result];\n })();\n }\n else if (typeof (returns === null || returns === void 0 ? void 0 : returns.then) === \"function\") {\n returns = returns.then((value) => [null, value]);\n return Promise.resolve(returns).catch((err) => [err, undefined]);\n }\n else {\n return [null, returns];\n }\n}\n/**\n * Inspired by Golang, creates a function that receives a `defer` function which can be used\n * to carry deferred jobs that will be run after the main function is complete.\n *\n * Multiple calls of the `defer` function is supported, and the callbacks are called in the\n * LIFO order. Callbacks can be async functions if the main function is an async function or\n * an async generator function, and all the running procedures will be awaited.\n *\n * @example\n * const getVersion = await jsext.func(async (defer) => {\n * const file = await fs.open(\"./package.json\", \"r\");\n * defer(() => file.close());\n *\n * const content = await file.readFile(\"utf8\");\n * const pkg = JSON.parse(content);\n *\n * return pkg.version as string;\n * });\n */\nexport function func(fn) {\n return function (...args) {\n var _a;\n const callbacks = [];\n const defer = (cb) => void callbacks.push(cb);\n let result;\n try {\n const returns = fn.call(this, defer, ...args);\n if (isAsyncGenerator(returns)) {\n const gen = (async function* () {\n var _a;\n let input;\n // Use `while` loop instead of `for...of...` in order to\n // retrieve the return value of a generator function.\n while (true) {\n try {\n const { done, value } = await returns.next(input);\n if (done) {\n result = { value, error: null };\n break;\n }\n else {\n // Receive any potential input value that passed\n // to the outer `next()` call, and pass them to\n // `res.next()` in the next call.\n input = yield Promise.resolve(value);\n }\n }\n catch (error) {\n // If any error occurs, capture that error and break\n // the loop immediately, indicating the process is\n // forced broken.\n result = { value: void 0, error };\n break;\n }\n }\n for (let i = callbacks.length - 1; i >= 0; i--) {\n await ((_a = callbacks[i]) === null || _a === void 0 ? void 0 : _a.call(callbacks));\n }\n if (result.error) {\n throw result.error;\n }\n else {\n return result.value;\n }\n })();\n return gen;\n }\n else if (isGenerator(returns)) {\n const gen = (function* () {\n var _a;\n let input;\n while (true) {\n try {\n const { done, value } = returns.next(input);\n if (done) {\n result = { value, error: null };\n break;\n }\n else {\n input = yield value;\n }\n }\n catch (error) {\n result = { value: void 0, error };\n break;\n }\n }\n for (let i = callbacks.length - 1; i >= 0; i--) {\n (_a = callbacks[i]) === null || _a === void 0 ? void 0 : _a.call(callbacks);\n }\n if (result.error) {\n throw result.error;\n }\n else {\n return result.value;\n }\n })();\n return gen;\n }\n else if (typeof (returns === null || returns === void 0 ? void 0 : returns.then) === \"function\") {\n return Promise.resolve(returns).then(value => ({\n value,\n error: null,\n })).catch((error) => ({\n value: void 0,\n error,\n })).then(async (result) => {\n var _a;\n for (let i = callbacks.length - 1; i >= 0; i--) {\n await ((_a = callbacks[i]) === null || _a === void 0 ? void 0 : _a.call(callbacks));\n }\n if (result.error) {\n throw result.error;\n }\n else {\n return result.value;\n }\n });\n }\n else {\n result = { value: returns, error: null };\n }\n }\n catch (error) {\n result = { value: void 0, error };\n }\n for (let i = callbacks.length - 1; i >= 0; i--) {\n (_a = callbacks[i]) === null || _a === void 0 ? void 0 : _a.call(callbacks);\n }\n if (result.error) {\n throw result.error;\n }\n else {\n return result.value;\n }\n };\n}\n/**\n * Wraps a function inside another function and returns a new function\n * that copies the original function's name and properties.\n */\nexport function wrap(fn, wrapper) {\n const wrapped = function (...args) {\n return wrapper.call(this, fn, ...args);\n };\n Object.defineProperty(wrapped, \"name\", Object.getOwnPropertyDescriptor(fn, \"name\"));\n Object.defineProperty(wrapped, \"length\", Object.getOwnPropertyDescriptor(fn, \"length\"));\n Object.defineProperty(wrapped, \"toString\", {\n configurable: true,\n enumerable: false,\n writable: true,\n value: fn.toString.bind(fn),\n });\n return wrapped;\n}\nconst throttleCaches = new Map();\nexport function throttle(handler, options) {\n const key = typeof options === \"number\" ? null : options.for;\n const duration = typeof options === \"number\" ? options : options.duration;\n const handleCall = function (cache, ...args) {\n var _a;\n if (cache.result && Date.now() < ((_a = cache.expires) !== null && _a !== void 0 ? _a : 0)) {\n if (cache.result.error) {\n throw cache.result.error;\n }\n else {\n return cache.result.value;\n }\n }\n try {\n const returns = handler.call(this, ...args);\n cache.result = { value: returns };\n cache.expires = Date.now() + duration;\n return returns;\n }\n catch (error) {\n cache.result = { error };\n cache.expires = Date.now() + duration;\n throw error;\n }\n };\n if (!key) {\n const cache = { for: null };\n return function (...args) {\n return handleCall.call(this, cache, ...args);\n };\n }\n else {\n let cache = throttleCaches.get(key);\n if (!cache) {\n cache = { for: key };\n throttleCaches.set(key, cache);\n }\n return function (...args) {\n return handleCall.call(this, cache, ...args);\n };\n }\n}\n/**\n * Merges properties and methods only if they're missing in the class.\n */\nfunction mergeIfNotExists(proto, source, mergeSuper = false) {\n const props = Reflect.ownKeys(source);\n for (const prop of props) {\n if (prop == \"constructor\") {\n continue;\n }\n else if (mergeSuper) {\n // When merging properties from super classes, the properties in the\n // base class has the first priority and shall not be overwrite.\n if (!(prop in proto)) {\n setProp(proto, source, prop);\n }\n }\n else if (!proto.hasOwnProperty(prop)) {\n setProp(proto, source, prop);\n }\n }\n return proto;\n}\n/**\n * Merges properties and methods across the prototype chain.\n */\nfunction mergeHierarchy(ctor, mixin, mergeSuper = false) {\n mergeIfNotExists(ctor.prototype, mixin.prototype, mergeSuper);\n const _super = Object.getPrototypeOf(mixin);\n // Every user defined class or functions that can be instantiated have their\n // own names, if no name appears, that means the function has traveled to \n // the root of the hierarchical tree.\n if (_super.name) {\n mergeHierarchy(ctor, _super, true);\n }\n}\n/**\n * Sets property for prototype based on the given source and prop name properly.\n */\nfunction setProp(proto, source, prop) {\n const desc = Object.getOwnPropertyDescriptor(source, prop);\n if (desc) {\n Object.defineProperty(proto, prop, desc);\n }\n else {\n proto[prop] = source[prop];\n }\n}\nexport function mixins(base, ...mixins) {\n const obj = { ctor: null };\n obj.ctor = class extends base {\n }; // make sure this class has no name\n for (const mixin of mixins) {\n if (typeof mixin == \"function\") {\n mergeHierarchy(obj.ctor, mixin);\n }\n else if (mixin && typeof mixin == \"object\") {\n mergeIfNotExists(obj.ctor.prototype, mixin);\n }\n else {\n throw new TypeError(\"mixin must be a constructor or an object\");\n }\n }\n return obj.ctor;\n}\n/** Checks if a class is a subclass of another class. */\nexport function isSubclassOf(ctor1, ctor2) {\n return typeof ctor1 === \"function\"\n && typeof ctor2 === \"function\"\n && ctor1.prototype instanceof ctor2;\n}\nexport function read(source, eventMap = undefined) {\n var _a;\n if (typeof source[Symbol.asyncIterator] === \"function\") {\n return source;\n }\n const iterable = {\n ended: false,\n error: null,\n queue: [],\n consumers: [],\n next() {\n return new Promise((resolve, reject) => {\n if (this.error && !this.ended) {\n // If there is error occurred during the last transmission and the iterator\n // hasn't been closed, reject that error and stop the iterator immediately.\n reject(this.error);\n this.ended = true;\n }\n else if (this.ended && !this.queue.length) {\n // If the iterator has is closed, resolve the pending consumer with void\n // value.\n resolve({ value: void 0, done: true });\n }\n else if (this.queue.length > 0) {\n // If there are data in the queue, resolve the the first piece immediately.\n resolve({ value: this.queue.shift(), done: false });\n }\n else {\n // If there are no queued data, push the consumer to a waiting queue.\n this.consumers.push({ resolve, reject });\n }\n });\n }\n };\n const handleMessage = (data) => {\n var _a;\n if (iterable.consumers.length > 0) {\n (_a = iterable.consumers.shift()) === null || _a === void 0 ? void 0 : _a.resolve({ value: data, done: false });\n }\n else {\n iterable.queue.push(data);\n }\n };\n const handleClose = () => {\n iterable.ended = true;\n let consumer;\n while (consumer = iterable.consumers.shift()) {\n consumer.resolve({ value: undefined, done: true });\n }\n };\n const handleError = (err) => {\n iterable.error = err;\n if (iterable.consumers.length > 0) {\n iterable.consumers.forEach(item => {\n item.reject(err);\n });\n iterable.consumers = [];\n }\n };\n const handleBrowserErrorEvent = (ev) => {\n let err;\n if (ev instanceof ErrorEvent) {\n err = ev.error || new Error(ev.message);\n }\n else {\n // @ts-ignore\n err = new Error(\"something went wrong\", { cause: ev });\n }\n handleError(err);\n };\n const proto = Object.getPrototypeOf(source);\n const msgDesc = Object.getOwnPropertyDescriptor(proto, \"onmessage\");\n if ((msgDesc === null || msgDesc === void 0 ? void 0 : msgDesc.set) && typeof source.close === \"function\") { // WebSocket or EventSource\n const errDesc = Object.getOwnPropertyDescriptor(proto, \"onerror\");\n const closeDesc = Object.getOwnPropertyDescriptor(proto, \"onclose\");\n let cleanup;\n if ((eventMap === null || eventMap === void 0 ? void 0 : eventMap.event) &&\n (eventMap === null || eventMap === void 0 ? void 0 : eventMap.event) !== \"message\" &&\n typeof source[\"addEventListener\"] === \"function\") { // for EventSource listening on custom events\n const es = source;\n const eventName = eventMap.event;\n const msgListener = (ev) => {\n handleMessage(ev.data);\n };\n es.addEventListener(eventName, msgListener);\n cleanup = () => {\n es.removeEventListener(eventName, msgListener);\n };\n }\n else {\n msgDesc.set.call(source, (ev) => {\n handleMessage(ev.data);\n });\n cleanup = () => {\n var _a;\n (_a = msgDesc.set) === null || _a === void 0 ? void 0 : _a.call(source, null);\n };\n }\n (_a = errDesc === null || errDesc === void 0 ? void 0 : errDesc.set) === null || _a === void 0 ? void 0 : _a.call(source, handleBrowserErrorEvent);\n if (closeDesc === null || closeDesc === void 0 ? void 0 : closeDesc.set) { // WebSocket\n closeDesc.set.call(source, () => {\n var _a, _b;\n handleClose();\n (_a = closeDesc.set) === null || _a === void 0 ? void 0 : _a.call(source, null);\n (_b = errDesc === null || errDesc === void 0 ? void 0 : errDesc.set) === null || _b === void 0 ? void 0 : _b.call(source, null);\n cleanup === null || cleanup === void 0 ? void 0 : cleanup();\n });\n }\n else if (!(closeDesc === null || closeDesc === void 0 ? void 0 : closeDesc.set) && typeof source.close === \"function\") { // EventSource\n // EventSource by default does not trigger close event, we need to make sure when\n // it calls the close() function, the iterator is automatically closed.\n const es = source;\n const _close = es.close;\n es.close = function close() {\n var _a;\n _close.call(es);\n handleClose();\n es.close = _close;\n (_a = errDesc === null || errDesc === void 0 ? void 0 : errDesc.set) === null || _a === void 0 ? void 0 : _a.call(source, null);\n cleanup === null || cleanup === void 0 ? void 0 : cleanup();\n };\n }\n }\n else if (typeof source.send === \"function\" && typeof source.close === \"function\") {\n // non-standard WebSocket implementation\n const ws = source;\n ws.onmessage = (ev) => {\n handleMessage(ev.data);\n };\n ws.onerror = handleBrowserErrorEvent;\n ws.onclose = () => {\n handleClose();\n ws.onclose = null;\n ws.onerror = null;\n ws.onmessage = null;\n };\n }\n else if (typeof source[\"addEventListener\"] === \"function\") { // EventTarget\n const target = source;\n const msgEvent = (eventMap === null || eventMap === void 0 ? void 0 : eventMap.message) || \"message\";\n const errEvent = (eventMap === null || eventMap === void 0 ? void 0 : eventMap.error) || \"error\";\n const closeEvent = (eventMap === null || eventMap === void 0 ? void 0 : eventMap.close) || \"close\";\n const msgListener = (ev) => {\n if (ev instanceof MessageEvent) {\n handleMessage(ev.data);\n }\n };\n target.addEventListener(msgEvent, msgListener);\n target.addEventListener(errEvent, handleBrowserErrorEvent);\n target.addEventListener(closeEvent, function closeListener() {\n handleClose();\n target.removeEventListener(closeEvent, closeListener);\n target.removeEventListener(msgEvent, msgListener);\n target.removeEventListener(errEvent, handleBrowserErrorEvent);\n });\n }\n else if (typeof source[\"on\"] === \"function\") { // EventEmitter\n const target = source;\n const dataEvent = (eventMap === null || eventMap === void 0 ? void 0 : eventMap.data) || \"data\";\n const errEvent = (eventMap === null || eventMap === void 0 ? void 0 : eventMap.error) || \"error\";\n const endEvent = (eventMap === null || eventMap === void 0 ? void 0 : eventMap.close) || \"close\";\n target.on(dataEvent, handleMessage);\n target.once(errEvent, handleError);\n target.once(endEvent, () => {\n handleClose();\n target.off(dataEvent, handleMessage);\n target.off(dataEvent, handleError);\n });\n }\n else {\n throw new TypeError(\"the input source cannot be read as an AsyncIterable object\");\n }\n return {\n [Symbol.asyncIterator]() {\n return iterable;\n }\n };\n}\nconst isNode = typeof process === \"object\" && !!((_a = process.versions) === null || _a === void 0 ? void 0 : _a.node);\n/**\n * The maximum number of workers allowed to exist at the same time.\n *\n * The primary purpose of the workers is not mean to run tasks in parallel, but run them in separate\n * from the main thread, so that aborting tasks can be achieved by terminating the worker thread and\n * it will not affect the main thread.\n *\n * That said, the worker thread can still be used to achieve parallelism, but it should be noticed\n * that only the numbers of tasks that equals to the CPU core numbers will be run at the same time.\n */\nconst maxWorkerNum = 16;\nconst workerIdCounter = sequence(1, Number.MAX_SAFE_INTEGER, 1, true);\nlet workerPool = [];\n// The worker consumer queue is nothing but a callback list, once a worker is available, the runner\n// pop a consumer and run the callback, which will retry gaining the worker and retry the task.\nconst workerConsumerQueue = [];\n/**\n * Runs a task in the `script` in a worker thread that can be aborted during runtime.\n *\n * In Node.js, the `script` can be either a CommonJS module or an ES module, and is relative to\n * the current working directory if not absolute.\n *\n * In browser or Deno, the `script` can only be an ES module, and is relative to the current URL\n * (or working directory for Deno) if not absolute.\n */\nexport async function run(script, args = undefined, options = undefined) {\n var _a, _b;\n const msg = {\n type: \"ffi\",\n script,\n baseUrl: \"\",\n fn: (options === null || options === void 0 ? void 0 : options.fn) || \"default\",\n args: args !== null && args !== void 0 ? args : [],\n };\n if (typeof Deno === \"object\") {\n msg.baseUrl = \"file://\" + Deno.cwd() + \"/\";\n }\n else if (isNode) {\n msg.baseUrl = \"file://\" + process.cwd() + \"/\";\n }\n else if (typeof location === \"object\") {\n msg.baseUrl = location.href;\n }\n // `buffer` is used to store data pieces yielded by generator functions before they are\n // consumed. `error` and `result` serves similar purposes for function results.\n const buffer = [];\n let error = null;\n let result;\n let resolver;\n let iterator;\n let workerId;\n let poolRecord;\n let release;\n let terminate = () => Promise.resolve(void 0);\n const timeout = (options === null || options === void 0 ? void 0 : options.timeout) ? setTimeout(() => {\n const err = new Error(`operation timeout after ${options.timeout}ms`);\n if (resolver) {\n resolver.reject(err);\n }\n else {\n error = err;\n }\n terminate();\n }, options.timeout) : null;\n const handleMessage = (msg) => {\n var _a;\n if (msg && typeof msg === \"object\" && typeof msg.type === \"string\") {\n if (msg.type === \"error\") {\n return handleError(msg.error);\n }\n else if (msg.type === \"return\") {\n if (options === null || options === void 0 ? void 0 : options.keepAlive) {\n // Release before resolve.\n release === null || release === void 0 ? void 0 : release();\n if (workerConsumerQueue.length) {\n // Queued consumer now has chance to gain the worker.\n (_a = workerConsumerQueue.shift()) === null || _a === void 0 ? void 0 : _a();\n }\n }\n else {\n terminate();\n }\n if (resolver) {\n resolver.resolve(msg.value);\n }\n else {\n result = { value: msg.value };\n }\n }\n else if (msg.type === \"yield\") {\n if (msg.done) {\n // The final message of yield event is the return value.\n handleMessage({ type: \"return\", value: msg.value });\n }\n else {\n if (iterator) {\n iterator.emit(\"data\", msg.value);\n }\n else {\n buffer.push(msg.value);\n }\n }\n }\n }\n };\n const handleError = (err) => {\n if (resolver) {\n resolver.reject(err);\n }\n else if (iterator) {\n iterator.emit(\"error\", err);\n }\n else {\n error = err;\n }\n };\n const handleExit = () => {\n var _a;\n if (poolRecord) {\n // Clean the pool before resolve.\n workerPool = workerPool.filter(record => record !== poolRecord);\n if (workerConsumerQueue.length) {\n // Queued consumer now has chance to create new worker.\n (_a = workerConsumerQueue.shift()) === null || _a === void 0 ? void 0 : _a();\n }\n }\n if (resolver) {\n resolver.resolve(void 0);\n }\n else if (iterator) {\n iterator.emit(\"close\");\n }\n else if (!error && !result) {\n result = { value: void 0 };\n }\n };\n if (isNode) {\n const path = await import(\"path\");\n const { fileURLToPath } = await import(\"url\");\n let _filename;\n let _dirname;\n let entry;\n if (typeof __filename === \"string\") {\n _filename = __filename;\n _dirname = __dirname;\n }\n else {\n // This file URL will be replace with `import.meta.url` by Rollup plugin.\n _filename = fileURLToPath(\"file://{__filename}\");\n _dirname = path.dirname(_filename);\n }\n if ([\"cjs\", \"esm\"].includes(path.basename(_dirname))) { // compiled\n entry = path.join(path.dirname(_dirname), \"worker.mjs\");\n }\n else {\n entry = path.join(_dirname, \"worker.mjs\");\n }\n if ((options === null || options === void 0 ? void 0 : options.adapter) === \"child_process\") {\n let worker;\n let ok = true;\n poolRecord = workerPool.find(item => {\n return item.adapter === \"child_process\" && !item.busy;\n });\n if (poolRecord) {\n worker = poolRecord.worker;\n workerId = poolRecord.workerId;\n poolRecord.busy = true;\n }\n else if (workerPool.length < maxWorkerNum) {\n const { fork } = await import(\"child_process\");\n const isPrior14 = parseInt(process.version.slice(1)) < 14;\n worker = fork(entry, {\n stdio: \"inherit\",\n serialization: isPrior14 ? \"advanced\" : \"json\",\n });\n workerId = worker.pid;\n ok = await new Promise((resolve) => {\n worker.once(\"exit\", () => {\n if (error) {\n // The child process took too long to start and cause timeout error.\n resolve(false);\n }\n });\n worker.once(\"message\", () => {\n worker.removeAllListeners(\"exit\");\n resolve(true);\n });\n });\n // Fill the worker pool regardless the current call should keep-alive or not,\n // this will make sure that the total number of workers will not exceed the\n // maxWorkerNum. If the the call doesn't keep-alive the worker, it will be\n // cleaned after the call.\n ok && workerPool.push(poolRecord = {\n workerId,\n worker,\n adapter: \"child_process\",\n busy: true,\n });\n }\n else {\n // Put the current call in the consumer queue if there are no workers available,\n // once an existing call finishes, the queue will pop the its head consumer and\n // retry.\n return new Promise((resolve) => {\n workerConsumerQueue.push(resolve);\n }).then(() => run(script, args, options));\n }\n release = () => {\n // Remove the event listener so that later calls will not mess up.\n worker.off(\"message\", handleMessage);\n poolRecord && (poolRecord.busy = false);\n };\n terminate = () => Promise.resolve(void worker.kill(1));\n if (ok) {\n worker.send(msg);\n worker.on(\"message\", handleMessage);\n worker.once(\"error\", handleError);\n worker.once(\"exit\", handleExit);\n }\n }\n else {\n let worker;\n let ok = true;\n poolRecord = workerPool.find(item => {\n return item.adapter === \"worker_threads\" && !item.busy;\n });\n if (poolRecord) {\n worker = poolRecord.worker;\n workerId = poolRecord.workerId;\n poolRecord.busy = true;\n }\n else if (workerPool.length < maxWorkerNum) {\n const { Worker } = await import(\"worker_threads\");\n worker = new Worker(entry);\n // `threadId` may not exist in Bun.\n workerId = (_a = worker.threadId) !== null && _a !== void 0 ? _a : workerIdCounter.next().value;\n ok = await new Promise((resolve) => {\n worker.once(\"exit\", () => {\n if (error) {\n // The child process took too long to start and cause timeout error.\n resolve(false);\n }\n });\n worker.once(\"online\", () => {\n worker.removeAllListeners(\"exit\");\n resolve(true);\n });\n });\n ok && workerPool.push(poolRecord = {\n workerId,\n worker,\n adapter: \"worker_threads\",\n busy: true,\n });\n }\n else {\n return new Promise((resolve) => {\n workerConsumerQueue.push(resolve);\n }).then(() => run(script, args, options));\n }\n release = () => {\n worker.off(\"message\", handleMessage);\n poolRecord && (poolRecord.busy = false);\n };\n terminate = async () => void (await worker.terminate());\n if (ok) {\n worker.postMessage(msg);\n worker.on(\"message\", handleMessage);\n worker.once(\"error\", handleError);\n worker.once(\"messageerror\", handleError);\n worker.once(\"exit\", handleExit);\n }\n }\n }\n else {\n let worker;\n poolRecord = workerPool.find(item => {\n return item.adapter === \"worker_threads\" && !item.busy;\n });\n if (poolRecord) {\n worker = poolRecord.worker;\n workerId = poolRecord.workerId;\n poolRecord.busy = true;\n }\n else if (workerPool.length < maxWorkerNum) {\n let url;\n if (typeof Deno === \"object\") {\n // Deno can load the module regardless of MINE type.\n url = [\n ...(\"file://{__filename}\".split(\"/\").slice(0, -1)),\n \"worker-web.mjs\"\n ].join(\"/\");\n }\n else {\n const _url = (options === null || options === void 0 ? void 0 : options.webWorkerEntry)\n || \"https://raw.githubusercontent.com/ayonli/jsext/main/esm/worker-web.mjs\";\n const res = await fetch(_url);\n let blob;\n if ((_b = res.headers.get(\"content-type\")) === null || _b === void 0 ? void 0 : _b.startsWith(\"application/javascript\")) {\n blob = await res.blob();\n }\n else {\n const buf = await res.arrayBuffer();\n blob = new Blob([new Uint8Array(buf)], {\n type: \"application/javascript\",\n });\n }\n url = URL.createObjectURL(blob);\n }\n worker = new Worker(url, { type: \"module\" });\n workerId = workerIdCounter.next().value;\n workerPool.push(poolRecord = {\n workerId,\n worker,\n adapter: \"worker_threads\",\n busy: true,\n });\n }\n else {\n return new Promise((resolve) => {\n workerConsumerQueue.push(resolve);\n }).then(() => run(script, args, options));\n }\n release = () => {\n worker.onmessage = null;\n poolRecord && (poolRecord.busy = false);\n };\n terminate = async () => {\n await Promise.resolve(worker.terminate());\n handleExit();\n };\n worker.postMessage(msg);\n worker.onmessage = (ev) => handleMessage(ev.data);\n worker.onerror = (ev) => handleMessage(ev.error || new Error(ev.message));\n worker.onmessageerror = () => {\n handleError(new Error(\"unable to deserialize the message\"));\n };\n }\n return {\n workerId,\n async abort() {\n timeout && clearTimeout(timeout);\n await terminate();\n },\n async result() {\n return await new Promise((resolve, reject) => {\n if (error) {\n reject(error);\n }\n else if (result) {\n resolve(result.value);\n }\n else {\n resolver = { resolve, reject };\n }\n });\n },\n async *iterate() {\n if (resolver) {\n throw new Error(\"result() has been called\");\n }\n else if (result) {\n throw new TypeError(\"the response is not iterable\");\n }\n const { EventEmitter } = await import(\"events\");\n iterator = new EventEmitter();\n if (buffer.length) {\n (async () => {\n await Promise.resolve(null);\n let msg;\n while (msg = buffer.shift()) {\n iterator.emit(\"data\", msg);\n }\n })().catch(console.error);\n }\n for await (const msg of read(iterator)) {\n yield msg;\n }\n },\n };\n}\nconst jsext = {\n try: _try,\n func,\n wrap,\n throttle,\n mixins,\n isSubclassOf,\n read,\n run,\n};\nexport default jsext;\n//# sourceMappingURL=index.js.map"],"names":[],"mappings":";;;AAAA;AAGY;AACA;AACL;AACP;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACO;AACP;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACO;AACP;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACO;AACP;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACO;AACP;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACO;AACP;AACA;AACA;AACA;AACO;AACP;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACO;AACP;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,sCAAsC,eAAqB;AAC3D;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,wBAAwB,eAAqB;AAC7C;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACK;AACL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;"}

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

import { hasOwn, hasOwnMethod, patch, pick, omit, as } from './index.js';
import { hasOwn, hasOwnMethod, patch, pick, omit, as, isValid } from './index.js';

@@ -13,2 +13,3 @@ if (!Object.hasOwn) {

Object.as = as;
Object.isValid = isValid;
//# sourceMappingURL=augment.js.map

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

{"version":3,"file":"augment.js","sources":["../../object/augment.ts"],"sourcesContent":["import { hasOwn, hasOwnMethod, omit, patch, pick, as } from \".\";\nif (!Object.hasOwn) {\n Object.hasOwn = hasOwn;\n}\nif (!Object.hasOwnMethod) {\n Object.hasOwnMethod = hasOwnMethod;\n}\nObject.patch = patch;\nObject.pick = pick;\nObject.omit = omit;\nObject.as = as;\n//# sourceMappingURL=augment.js.map"],"names":[],"mappings":";;AACA,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE;AACpB,IAAI,MAAM,CAAC,MAAM,GAAG,MAAM,CAAC;AAC3B,CAAC;AACD,IAAI,CAAC,MAAM,CAAC,YAAY,EAAE;AAC1B,IAAI,MAAM,CAAC,YAAY,GAAG,YAAY,CAAC;AACvC,CAAC;AACD,MAAM,CAAC,KAAK,GAAG,KAAK,CAAC;AACrB,MAAM,CAAC,IAAI,GAAG,IAAI,CAAC;AACnB,MAAM,CAAC,IAAI,GAAG,IAAI,CAAC;AACnB,MAAM,CAAC,EAAE,GAAG,EAAE"}
{"version":3,"file":"augment.js","sources":["../../object/augment.ts"],"sourcesContent":["import { hasOwn, hasOwnMethod, omit, patch, pick, as, isValid } from \".\";\nif (!Object.hasOwn) {\n Object.hasOwn = hasOwn;\n}\nif (!Object.hasOwnMethod) {\n Object.hasOwnMethod = hasOwnMethod;\n}\nObject.patch = patch;\nObject.pick = pick;\nObject.omit = omit;\nObject.as = as;\nObject.isValid = isValid;\n//# sourceMappingURL=augment.js.map"],"names":[],"mappings":";;AACA,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE;AACpB,IAAI,MAAM,CAAC,MAAM,GAAG,MAAM,CAAC;AAC3B,CAAC;AACD,IAAI,CAAC,MAAM,CAAC,YAAY,EAAE;AAC1B,IAAI,MAAM,CAAC,YAAY,GAAG,YAAY,CAAC;AACvC,CAAC;AACD,MAAM,CAAC,KAAK,GAAG,KAAK,CAAC;AACrB,MAAM,CAAC,IAAI,GAAG,IAAI,CAAC;AACnB,MAAM,CAAC,IAAI,GAAG,IAAI,CAAC;AACnB,MAAM,CAAC,EAAE,GAAG,EAAE,CAAC;AACf,MAAM,CAAC,OAAO,GAAG,OAAO"}

@@ -51,3 +51,3 @@ function hasOwn(obj, key) {

}
function as(obj, type) {
function as(value, type) {
if (typeof type !== "function") {

@@ -64,17 +64,31 @@ throw new TypeError("type must be a valid constructor");

};
if (obj instanceof type) {
if (value instanceof type) {
if ([String, Number, Boolean].includes(type)) {
return obj.valueOf(); // make sure the primitives are returned.
return value.valueOf(); // make sure the primitives are returned.
}
else {
return obj;
return value;
}
}
else if ((_type = typeof obj) && primitiveMap[_type] === type) {
return obj;
else if ((_type = typeof value) && primitiveMap[_type] === type) {
return value;
}
return null;
}
/**
* Returns `true` if the given value is valid. Thee following values are considered invalid:
*
* - `undefined`
* - `null`
* - `NaN`
* - `Invalid Date`
*/
function isValid(value) {
return value !== undefined
&& value !== null
&& !Object.is(value, NaN)
&& !(value instanceof Date && value.toString() === "Invalid Date");
}
export { as, hasOwn, hasOwnMethod, omit, patch, pick };
export { as, hasOwn, hasOwnMethod, isValid, omit, patch, pick };
//# sourceMappingURL=index.js.map

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

{"version":3,"file":"index.js","sources":["../../object/index.ts"],"sourcesContent":["export function hasOwn(obj, key) {\n return Object.prototype.hasOwnProperty.call(obj, key);\n}\n;\n/**\n * Returns `true` if the specified object has the indicated method as its own method (in its own\n * prototype). If the method is inherited, or is not in the prototype, or does not exist, this\n * function returns `false`.\n */\nexport function hasOwnMethod(obj, method) {\n var _a;\n const proto = Object.getPrototypeOf(obj);\n if (!proto || !hasOwn(proto, method)) {\n return false;\n }\n return typeof ((_a = Object.getOwnPropertyDescriptor(proto, method)) === null || _a === void 0 ? void 0 : _a.value) === \"function\";\n}\nexport function patch(target, ...sources) {\n for (const source of sources) {\n for (const key of Reflect.ownKeys(source)) {\n if (!hasOwn(target, key) || target[key] === undefined) {\n target[key] = source[key];\n }\n }\n }\n return target;\n}\n;\nexport function pick(obj, keys) {\n return keys.reduce((result, key) => {\n if (key in obj && obj[key] !== undefined) {\n result[key] = obj[key];\n }\n return result;\n }, {});\n}\nexport function omit(obj, keys) {\n const allKeys = Reflect.ownKeys(obj);\n const keptKeys = allKeys.filter(key => !keys.includes(key));\n const result = pick(obj, keptKeys);\n // special treatment for Error types\n if (obj instanceof Error) {\n [\"name\", \"message\", \"cause\"].forEach(key => {\n if (!keys.includes(key) &&\n obj[key] !== undefined &&\n !hasOwn(result, key)) {\n result[key] = obj[key];\n }\n });\n }\n return result;\n}\nexport function as(obj, type) {\n if (typeof type !== \"function\") {\n throw new TypeError(\"type must be a valid constructor\");\n }\n let _type;\n const primitiveMap = {\n \"string\": String,\n \"number\": Number,\n \"bigint\": BigInt,\n \"boolean\": Boolean,\n \"symbol\": Symbol\n };\n if (obj instanceof type) {\n if ([String, Number, Boolean].includes(type)) {\n return obj.valueOf(); // make sure the primitives are returned.\n }\n else {\n return obj;\n }\n }\n else if ((_type = typeof obj) && primitiveMap[_type] === type) {\n return obj;\n }\n return null;\n}\n//# sourceMappingURL=index.js.map"],"names":[],"mappings":"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"}
{"version":3,"file":"index.js","sources":["../../object/index.ts"],"sourcesContent":["export function hasOwn(obj, key) {\n return Object.prototype.hasOwnProperty.call(obj, key);\n}\n;\n/**\n * Returns `true` if the specified object has the indicated method as its own method (in its own\n * prototype). If the method is inherited, or is not in the prototype, or does not exist, this\n * function returns `false`.\n */\nexport function hasOwnMethod(obj, method) {\n var _a;\n const proto = Object.getPrototypeOf(obj);\n if (!proto || !hasOwn(proto, method)) {\n return false;\n }\n return typeof ((_a = Object.getOwnPropertyDescriptor(proto, method)) === null || _a === void 0 ? void 0 : _a.value) === \"function\";\n}\nexport function patch(target, ...sources) {\n for (const source of sources) {\n for (const key of Reflect.ownKeys(source)) {\n if (!hasOwn(target, key) || target[key] === undefined) {\n target[key] = source[key];\n }\n }\n }\n return target;\n}\n;\nexport function pick(obj, keys) {\n return keys.reduce((result, key) => {\n if (key in obj && obj[key] !== undefined) {\n result[key] = obj[key];\n }\n return result;\n }, {});\n}\nexport function omit(obj, keys) {\n const allKeys = Reflect.ownKeys(obj);\n const keptKeys = allKeys.filter(key => !keys.includes(key));\n const result = pick(obj, keptKeys);\n // special treatment for Error types\n if (obj instanceof Error) {\n [\"name\", \"message\", \"cause\"].forEach(key => {\n if (!keys.includes(key) &&\n obj[key] !== undefined &&\n !hasOwn(result, key)) {\n result[key] = obj[key];\n }\n });\n }\n return result;\n}\nexport function as(value, type) {\n if (typeof type !== \"function\") {\n throw new TypeError(\"type must be a valid constructor\");\n }\n let _type;\n const primitiveMap = {\n \"string\": String,\n \"number\": Number,\n \"bigint\": BigInt,\n \"boolean\": Boolean,\n \"symbol\": Symbol\n };\n if (value instanceof type) {\n if ([String, Number, Boolean].includes(type)) {\n return value.valueOf(); // make sure the primitives are returned.\n }\n else {\n return value;\n }\n }\n else if ((_type = typeof value) && primitiveMap[_type] === type) {\n return value;\n }\n return null;\n}\n/**\n * Returns `true` if the given value is valid. Thee following values are considered invalid:\n *\n * - `undefined`\n * - `null`\n * - `NaN`\n * - `Invalid Date`\n */\nexport function isValid(value) {\n return value !== undefined\n && value !== null\n && !Object.is(value, NaN)\n && !(value instanceof Date && value.toString() === \"Invalid Date\");\n}\n//# sourceMappingURL=index.js.map"],"names":[],"mappings":"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"}
+955
-916

@@ -6,2 +6,19 @@ import { isAsyncGenerator, isGenerator } from "check-iterable";

export const AsyncFunction = (async function () { }).constructor as AsyncFunctionConstructor;
export const AsyncGeneratorFunction = (async function* () { }).constructor as AsyncGeneratorFunctionConstructor;
export interface AsyncFunction {
(...args: any[]): Promise<unknown>;
readonly length: number;
readonly name: string;
}
export interface AsyncFunctionConstructor {
new(...args: any[]): AsyncFunction;
(...args: any[]): AsyncFunction;
readonly length: number;
readonly name: string;
readonly prototype: AsyncFunction;
}
export interface Constructor<T> extends Function {

@@ -21,7 +38,288 @@ new(...args: any[]): T;

export type UnionToIntersection<U> = (U extends any ? (k: U) => void : never) extends ((k: infer I) => void) ? I : never;
/**
* Invokes an async generator function and renders its yield value and result in a `[err, val]` tuple.
*/
export function _try<E = Error, T = any, A extends any[] = any[], TReturn = any, TNext = unknown>(
fn: (...args: A) => AsyncGenerator<T, TReturn, TNext>,
...args: A
): AsyncGenerator<[E | null, T], [E | null, TReturn], TNext>;
/**
* Invokes a generator function and renders its yield value and result in a `[err, val]` tuple.
*/
export function _try<E = Error, T = any, A extends any[] = any[], TReturn = any, TNext = unknown>(
fn: (...args: A) => Generator<T, TReturn, TNext>,
...args: A
): Generator<[E | null, T], [E | null, TReturn], TNext>;
/**
* Invokes an async function and renders its result in a `[err, val]` tuple.
*/
export function _try<E = Error, R = any, A extends any[] = any[]>(
fn: (...args: A) => Promise<R>,
...args: A
): Promise<[E | null, R]>;
/**
* Invokes a function and renders its result in a `[err, val]` tuple.
*/
export function _try<E = Error, R = any, A extends any[] = any[]>(
fn: (...args: A) => R,
...args: A
): [E | null, R];
/**
* Resolves an async generator and renders its yield value and result in a `[err, val]` tuple.
*/
export function _try<E = Error, T = any, TReturn = any, TNext = unknown>(
gen: AsyncGenerator<T, TReturn, TNext>
): AsyncGenerator<[E | null, T], [E | null, TReturn], TNext>;
/**
* Resolves a generator and renders its yield value and result in a `[err, val]` tuple.
*/
export function _try<E = Error, T = any, TReturn = any, TNext = unknown>(
gen: Generator<T, TReturn, TNext>
): Generator<[E | null, T], [E | null, TReturn], TNext>;
/**
* Resolves a promise and renders its result in a `[err, res]` tuple.
*/
export function _try<E = Error, R = any>(job: Promise<R>): Promise<[E | null, R]>;
export function _try(fn: any, ...args: any[]) {
if (typeof fn === "function") {
try {
return _try(fn.apply(void 0, args));
} catch (err) {
return [err, undefined];
}
}
const isNode = typeof process === "object" && !!process.versions?.node;
declare var Deno: any;
let returns = fn;
// Implementation details should be ordered from complex to simple.
if (isAsyncGenerator(returns)) {
return (async function* () {
let input: unknown;
let result: any;
// Use `while` loop instead of `for...of...` in order to
// retrieve the return value of a generator function.
while (true) {
try {
const { done, value } = await returns.next(input);
if (done) {
result = value;
break;
} else {
// Receive any potential input value that passed
// to the outer `next()` call, and pass them to
// `res.next()` in the next call.
input = yield Promise.resolve([null, value]);
}
} catch (err) {
// If any error occurs, yield that error as resolved
// and break the loop immediately, indicating the
// process is forced broken.
yield Promise.resolve([err, undefined]);
break;
}
}
return [null, result];
})() as AsyncGenerator<unknown, any, unknown>;
} else if (isGenerator(returns)) {
return (function* () {
let input: unknown;
let result: any;
while (true) {
try {
const { done, value } = returns.next(input);
if (done) {
result = value;
break;
} else {
input = yield [null, value];
}
} catch (err) {
yield [err, undefined];
break;
}
}
return [null, result];
})() as Generator<unknown, any, unknown>;
} else if (typeof returns?.then === "function") {
returns = (returns as PromiseLike<any>).then((value: any) => [null, value]);
return Promise.resolve(returns).catch((err: unknown) => [err, undefined]) as any;
} else {
return [null, returns];
}
}
/**
* Inspired by Golang, creates a function that receives a `defer` function which can be used
* to carry deferred jobs that will be run after the main function is complete.
*
* Multiple calls of the `defer` function is supported, and the callbacks are called in the
* LIFO order. Callbacks can be async functions if the main function is an async function or
* an async generator function, and all the running procedures will be awaited.
*
* @example
* const getVersion = await jsext.func(async (defer) => {
* const file = await fs.open("./package.json", "r");
* defer(() => file.close());
*
* const content = await file.readFile("utf8");
* const pkg = JSON.parse(content);
*
* return pkg.version as string;
* });
*/
export function func<T, R = any, A extends any[] = any[]>(
fn: (this: T, defer: (cb: () => void) => void, ...args: A) => R
): (this: T, ...args: A) => R {
return function (this: T, ...args: A) {
const callbacks: (() => void)[] = [];
const defer = (cb: () => void) => void callbacks.push(cb);
type Result = { value?: Awaited<R>; error: unknown; };
let result: Result | undefined;
try {
const returns = fn.call(this, defer, ...args) as any;
if (isAsyncGenerator(returns)) {
const gen = (async function* () {
let input: unknown;
// Use `while` loop instead of `for...of...` in order to
// retrieve the return value of a generator function.
while (true) {
try {
const { done, value } = await returns.next(input);
if (done) {
result = { value, error: null };
break;
} else {
// Receive any potential input value that passed
// to the outer `next()` call, and pass them to
// `res.next()` in the next call.
input = yield Promise.resolve(value);
}
} catch (error) {
// If any error occurs, capture that error and break
// the loop immediately, indicating the process is
// forced broken.
result = { value: void 0, error } as Result;
break;
}
}
for (let i = callbacks.length - 1; i >= 0; i--) {
await (callbacks[i] as () => void | Promise<void>)?.();
}
if (result.error) {
throw result.error;
} else {
return result.value;
}
})() as AsyncGenerator<unknown, any, unknown>;
return gen as R;
} else if (isGenerator(returns)) {
const gen = (function* () {
let input: unknown;
while (true) {
try {
const { done, value } = returns.next(input);
if (done) {
result = { value, error: null };
break;
} else {
input = yield value;
}
} catch (error) {
result = { value: void 0, error } as Result;
break;
}
}
for (let i = callbacks.length - 1; i >= 0; i--) {
callbacks[i]?.();
}
if (result.error) {
throw result.error;
} else {
return result.value;
}
})() as Generator<unknown, R, unknown>;
return gen as R;
} else if (typeof returns?.then === "function") {
return Promise.resolve(returns as PromiseLike<R>).then(value => ({
value,
error: null,
} as Result)).catch((error: unknown) => ({
value: void 0,
error,
} as Result)).then(async result => {
for (let i = callbacks.length - 1; i >= 0; i--) {
await (callbacks[i] as () => void | Promise<void>)?.();
}
if (result.error) {
throw result.error;
} else {
return result.value;
}
}) as R;
} else {
result = { value: returns, error: null } as Result;
}
} catch (error) {
result = { value: void 0, error } as Result;
}
for (let i = callbacks.length - 1; i >= 0; i--) {
callbacks[i]?.();
}
if (result.error) {
throw result.error;
} else {
return result.value as R;
}
};
}
/**
* Wraps a function inside another function and returns a new function
* that copies the original function's name and properties.
*/
export function wrap<T, Fn extends (this: T, ...args: any[]) => any>(
fn: Fn,
wrapper: (this: T, fn: Fn, ...args: Parameters<Fn>) => ReturnType<Fn>
): Fn {
const wrapped = function (this: any, ...args: Parameters<Fn>): ReturnType<Fn> {
return wrapper.call(this, fn, ...args);
};
Object.defineProperty(wrapped,
"name",
Object.getOwnPropertyDescriptor(fn, "name") as PropertyDescriptor);
Object.defineProperty(wrapped,
"length",
Object.getOwnPropertyDescriptor(fn, "length") as PropertyDescriptor);
Object.defineProperty(wrapped, "toString", {
configurable: true,
enumerable: false,
writable: true,
value: fn.toString.bind(fn),
});
return wrapped as Fn;
}
type ThrottleCache = {

@@ -35,25 +333,76 @@ for: any;

/**
* The maximum number of workers allowed to exist at the same time.
* Creates a throttled function that will only be run once in a certain amount of time.
*
* The primary purpose of the workers is not mean to run tasks in parallel, but run them in separate
* from the main thread, so that aborting tasks can be achieved by terminating the worker thread and
* it will not affect the main thread.
*
* That said, the worker thread can still be used to achieve parallelism, but it should be noticed
* that only the numbers of tasks that equals to the CPU core numbers will be run at the same time.
* If a subsequent call happens within the `duration`, the previous result will be returned and
* the `handler` function will not be invoked.
*/
const maxWorkerNum = 16;
export function throttle<T, Fn extends (this: T, ...args: any[]) => any>(
handler: Fn,
duration: number
): Fn;
export function throttle<T, Fn extends (this: T, ...args: any[]) => any>(handler: Fn, options: {
duration: number;
/**
* Use the throttle strategy `for` the given key, this will keep the result in a global
* cache, binding new `handler` function for the same key will result in the same result
* as the previous, unless the duration has passed. This mechanism guarantees that both
* creating the throttled function in function scopes and overwriting the handler are
* possible.
*/
for?: any;
}): Fn;
export function throttle(handler: (this: any, ...args: any[]) => any, options: number | {
duration: number;
for?: any;
}) {
const key = typeof options === "number" ? null : options.for;
const duration = typeof options === "number" ? options : options.duration;
const workerIdCounter = sequence(1, Number.MAX_SAFE_INTEGER, 1, true);
let workerPool: {
workerId: number;
worker: Worker | NodeWorker | ChildProcess;
adapter: "worker_threads" | "child_process";
busy: boolean;
}[] = [];
const handleCall = function (
this: any,
cache: ThrottleCache,
...args: any[]
) {
if (cache.result && Date.now() < (cache.expires ?? 0)) {
if (cache.result.error) {
throw cache.result.error;
} else {
return cache.result.value;
}
}
// The worker consumer queue is nothing but a callback list, once a worker is available, the runner
// pop a consumer and run the callback, which will retry gaining the worker and retry the task.
const workerConsumerQueue: (() => void)[] = [];
try {
const returns = handler.call(this, ...args);
cache.result = { value: returns };
cache.expires = Date.now() + duration;
return returns;
} catch (error) {
cache.result = { error };
cache.expires = Date.now() + duration;
throw error;
}
};
if (!key) {
const cache: ThrottleCache = { for: null };
return function (this: any, ...args: any[]) {
return handleCall.call(this, cache, ...args);
};
} else {
let cache = throttleCaches.get(key);
if (!cache) {
cache = { for: key };
throttleCaches.set(key, cache);
}
return function (this: any, ...args: any[]) {
return handleCall.call(this, cache as ThrottleCache, ...args);
};
}
}
export type UnionToIntersection<U> = (
U extends any ? (k: U) => void : never) extends ((k: infer I) => void) ? I : never;
/**

@@ -111,130 +460,285 @@ * Merges properties and methods only if they're missing in the class.

export interface JsExt {
/**
* Runs a function and catches any error happens inside it, returns the error and result
* in a `[err, res]` tuple.
*/
try<E = Error, T = any, A extends any[] = any[], TReturn = any, TNext = unknown>(
fn: (...args: A) => AsyncGenerator<T, TReturn, TNext>,
...args: A
): AsyncGenerator<[E | null, T], [E | null, TReturn], TNext>;
try<E = Error, T = any, A extends any[] = any[], TReturn = any, TNext = unknown>(
fn: (...args: A) => Generator<T, TReturn, TNext>,
...args: A
): Generator<[E | null, T], [E | null, TReturn], TNext>;
try<E = Error, R = any, A extends any[] = any[]>(
fn: (...args: A) => Promise<R>,
...args: A
): Promise<[E | null, R]>;
try<E = Error, R = any, A extends any[] = any[]>(
fn: (...args: A) => R,
...args: A
): [E | null, R];
/** Resolves a generator and renders its yield value in a `[err, val]` tuple. */
try<E = Error, T = any, TReturn = any, TNext = unknown>(
gen: AsyncGenerator<T, TReturn, TNext>
): AsyncGenerator<[E | null, T], [E | null, TReturn], TNext>;
try<E = Error, T = any, TReturn = any, TNext = unknown>(
gen: Generator<T, TReturn, TNext>
): Generator<[E | null, T], [E | null, TReturn], TNext>;
/** Resolves a promise and returns the error and result in a `[err, res]` tuple. */
try<E = Error, R = any>(job: Promise<R>): Promise<[E | null, R]>;
/**
* Returns an extended class that combines all mixin methods.
*
* This function does not mutates the base class but create a pivot class
* instead.
*/
export function mixins<T extends Constructor<any>, M extends any[]>(
base: T,
...mixins: { [X in keyof M]: Constructor<M[X]> }
): T & Constructor<UnionToIntersection<FlatArray<M, 1>>>;
export function mixins<T extends Constructor<any>, M extends any[]>(
base: T,
...mixins: M
): T & Constructor<UnionToIntersection<FlatArray<M, 1>>>;
export function mixins(base: Constructor<any>, ...mixins: any[]) {
const obj = { ctor: null as any as Constructor<any> };
obj.ctor = class extends (<any>base) { }; // make sure this class has no name
/**
* Inspired by Golang, creates a function that receives a `defer` function which can be used
* to carry deferred jobs that will be run after the main function is complete.
*
* Multiple calls of the `defer` function is supported, and the callbacks are called in the
* LIFO order. Callbacks can be async functions if the main function is an async function or
* an async generator function, and all the running procedures will be awaited.
*
* @example
* const getVersion = await jsext.func(async (defer) => {
* const file = await fs.open("./package.json", "r");
* defer(() => file.close());
*
* const content = await file.readFile("utf8");
* const pkg = JSON.parse(content);
*
* return pkg.version as string;
* });
*/
func<T, R = any, A extends any[] = any[]>(
fn: (this: T, defer: (cb: () => void) => void, ...args: A) => R
): (this: T, ...args: A) => R;
for (const mixin of mixins) {
if (typeof mixin == "function") {
mergeHierarchy(obj.ctor, mixin);
} else if (mixin && typeof mixin == "object") {
mergeIfNotExists(obj.ctor.prototype, mixin);
} else {
throw new TypeError("mixin must be a constructor or an object");
}
}
/**
* Wraps a function inside another function and returns a new function
* that copies the original function's name and properties.
*/
wrap<T, Fn extends (this: T, ...args: any[]) => any>(
fn: Fn,
wrapper: (this: T, fn: Fn, ...args: Parameters<Fn>) => ReturnType<Fn>
): Fn;
return obj.ctor as Constructor<any>;
}
/**
* Creates a throttled function that will only be run once in a certain amount of time.
*
* If a subsequent call happens within the `duration`, the previous result will be returned and
* the `handler` function will not be invoked.
*/
throttle<T, Fn extends (this: T, ...args: any[]) => any>(handler: Fn, duration: number): Fn;
throttle<T, Fn extends (this: T, ...args: any[]) => any>(handler: Fn, options: {
duration: number;
/**
* Use the throttle strategy `for` the given key, this will keep the result in a global
* cache, binding new `handler` function for the same key will result in the same result
* as the previous, unless the duration has passed. This mechanism guarantees that both
* creating the throttled function in function scopes and overwriting the handler are
* possible.
*/
for?: any;
}): Fn;
/** Checks if a class is a subclass of another class. */
export function isSubclassOf<T, B>(ctor1: Constructor<T>, ctor2: Constructor<B>): boolean {
return typeof ctor1 === "function"
&& typeof ctor2 === "function"
&& ctor1.prototype instanceof ctor2;
}
/**
* Returns an extended class that combines all mixin methods.
*
* This function does not mutates the base class but create a pivot class
* instead.
*/
mixins<T extends Constructor<any>, M extends any[]>(
base: T,
...mixins: { [X in keyof M]: Constructor<M[X]> }
): T & Constructor<UnionToIntersection<FlatArray<M, 1>>>;
mixins<T extends Constructor<any>, M extends any[]>(
base: T,
...mixins: M
): T & Constructor<UnionToIntersection<FlatArray<M, 1>>>;
/**
* Wraps a source as an AsyncIterable object that can be used in the `for...await...` loop
* for reading streaming data.
*/
export function read<I extends AsyncIterable<any>>(iterable: I): I;
export function read(es: EventSource, options?: { event?: string; }): AsyncIterable<string>;
export function read<T extends Uint8Array | string>(ws: WebSocket): AsyncIterable<T>;
export function read<T>(target: EventTarget, eventMap?: {
message?: string;
error?: string;
close?: string;
}): AsyncIterable<T>;
export function read<T>(target: NodeJS.EventEmitter, eventMap?: {
data?: string;
error?: string;
close?: string;
}): AsyncIterable<T>;
export function read<T>(source: any, eventMap: {
event?: string; // for EventSource custom event
message?: string;
data?: string;
error?: string;
close?: string;
} | undefined = undefined): AsyncIterable<T> {
if (typeof source[Symbol.asyncIterator] === "function") {
return source;
}
/** Checks if a class is a subclass of another class. */
isSubclassOf<T, B>(ctor1: Constructor<T>, ctor2: Constructor<B>): boolean;
const iterable = {
ended: false,
error: null as Error | null,
queue: [] as T[],
consumers: [] as {
resolve: (data: IteratorResult<T>) => void;
reject: (err: any) => void;
}[],
next() {
return new Promise<IteratorResult<T>>((resolve, reject) => {
if (this.error && !this.ended) {
// If there is error occurred during the last transmission and the iterator
// hasn't been closed, reject that error and stop the iterator immediately.
reject(this.error);
this.ended = true;
} else if (this.ended && !this.queue.length) {
// If the iterator has is closed, resolve the pending consumer with void
// value.
resolve({ value: void 0 as T, done: true });
} else if (this.queue.length > 0) {
// If there are data in the queue, resolve the the first piece immediately.
resolve({ value: this.queue.shift() as T, done: false });
} else {
// If there are no queued data, push the consumer to a waiting queue.
this.consumers.push({ resolve, reject });
}
});
}
};
/**
* Wraps a source as an AsyncIterable object that can be used in the `for...await...` loop
* for reading streaming data.
*/
read<I extends AsyncIterable<any>>(iterable: I): I;
read(es: EventSource, options?: { event?: string; }): AsyncIterable<string>;
read<T extends Uint8Array | string>(ws: WebSocket): AsyncIterable<T>;
read<T>(target: EventTarget, eventMap?: {
message?: string;
error?: string;
close?: string;
}): AsyncIterable<T>;
read<T>(target: NodeJS.EventEmitter, eventMap?: {
data?: string;
error?: string;
close?: string;
}): AsyncIterable<T>;
const handleMessage = (data: T) => {
if (iterable.consumers.length > 0) {
iterable.consumers.shift()?.resolve({ value: data, done: false });
} else {
iterable.queue.push(data);
}
};
const handleClose = () => {
iterable.ended = true;
let consumer: typeof iterable["consumers"][0] | undefined;
/**
* Runs a task in the `script` in a worker thread that can be aborted during runtime.
*
* In Node.js, the `script` can be either a CommonJS module or an ES module, and is relative to
* the current working directory if not absolute.
*
* In browser or Deno, the `script` can only be an ES module, and is relative to the current URL
* (or working directory for Deno) if not absolute.
*/
run<T, A extends any[] = any[]>(script: string, args?: A, options?: {
while (consumer = iterable.consumers.shift()) {
consumer.resolve({ value: undefined, done: true });
}
};
const handleError = (err: Error) => {
iterable.error = err;
if (iterable.consumers.length > 0) {
iterable.consumers.forEach(item => {
item.reject(err);
});
iterable.consumers = [];
}
};
const handleBrowserErrorEvent = (ev: Event) => {
let err: Error;
if (ev instanceof ErrorEvent) {
err = ev.error || new Error(ev.message);
} else {
// @ts-ignore
err = new Error("something went wrong", { cause: ev });
}
handleError(err);
};
const proto = Object.getPrototypeOf(source);
const msgDesc = Object.getOwnPropertyDescriptor(proto, "onmessage");
if (msgDesc?.set && typeof source.close === "function") { // WebSocket or EventSource
const errDesc = Object.getOwnPropertyDescriptor(proto, "onerror");
const closeDesc = Object.getOwnPropertyDescriptor(proto, "onclose");
let cleanup: () => void;
if (eventMap?.event &&
eventMap?.event !== "message" &&
typeof source["addEventListener"] === "function"
) { // for EventSource listening on custom events
const es = source as EventSource;
const eventName = eventMap.event;
const msgListener = (ev: MessageEvent<T>) => {
handleMessage(ev.data);
};
es.addEventListener(eventName, msgListener);
cleanup = () => {
es.removeEventListener(eventName, msgListener);
};
} else {
msgDesc.set.call(source, (ev: MessageEvent<T>) => {
handleMessage(ev.data);
});
cleanup = () => {
msgDesc.set?.call(source, null);
};
}
errDesc?.set?.call(source, handleBrowserErrorEvent);
if (closeDesc?.set) { // WebSocket
closeDesc.set.call(source, () => {
handleClose();
closeDesc.set?.call(source, null);
errDesc?.set?.call(source, null);
cleanup?.();
});
} else if (!closeDesc?.set && typeof source.close === "function") { // EventSource
// EventSource by default does not trigger close event, we need to make sure when
// it calls the close() function, the iterator is automatically closed.
const es = source as EventSource;
const _close = es.close;
es.close = function close() {
_close.call(es);
handleClose();
es.close = _close;
errDesc?.set?.call(source, null);
cleanup?.();
};
}
} else if (typeof source.send === "function" && typeof source.close === "function") {
// non-standard WebSocket implementation
const ws = source as WebSocket;
ws.onmessage = (ev: MessageEvent<T>) => {
handleMessage(ev.data);
};
ws.onerror = handleBrowserErrorEvent;
ws.onclose = () => {
handleClose();
ws.onclose = null;
ws.onerror = null;
ws.onmessage = null;
};
} else if (typeof source["addEventListener"] === "function") { // EventTarget
const target = source as EventTarget;
const msgEvent = eventMap?.message || "message";
const errEvent = eventMap?.error || "error";
const closeEvent = eventMap?.close || "close";
const msgListener = (ev: Event) => {
if (ev instanceof MessageEvent) {
handleMessage(ev.data);
}
};
target.addEventListener(msgEvent, msgListener);
target.addEventListener(errEvent, handleBrowserErrorEvent);
target.addEventListener(closeEvent, function closeListener() {
handleClose();
target.removeEventListener(closeEvent, closeListener);
target.removeEventListener(msgEvent, msgListener);
target.removeEventListener(errEvent, handleBrowserErrorEvent);
});
} else if (typeof source["on"] === "function") { // EventEmitter
const target = source as NodeJS.EventEmitter;
const dataEvent = eventMap?.data || "data";
const errEvent = eventMap?.error || "error";
const endEvent = eventMap?.close || "close";
target.on(dataEvent, handleMessage);
target.once(errEvent, handleError);
target.once(endEvent, () => {
handleClose();
target.off(dataEvent, handleMessage);
target.off(dataEvent, handleError);
});
} else {
throw new TypeError("the input source cannot be read as an AsyncIterable object");
}
return {
[Symbol.asyncIterator]() {
return iterable;
}
};
}
const isNode = typeof process === "object" && !!process.versions?.node;
declare var Deno: any;
/**
* The maximum number of workers allowed to exist at the same time.
*
* The primary purpose of the workers is not mean to run tasks in parallel, but run them in separate
* from the main thread, so that aborting tasks can be achieved by terminating the worker thread and
* it will not affect the main thread.
*
* That said, the worker thread can still be used to achieve parallelism, but it should be noticed
* that only the numbers of tasks that equals to the CPU core numbers will be run at the same time.
*/
const maxWorkerNum = 16;
const workerIdCounter = sequence(1, Number.MAX_SAFE_INTEGER, 1, true);
let workerPool: {
workerId: number;
worker: Worker | NodeWorker | ChildProcess;
adapter: "worker_threads" | "child_process";
busy: boolean;
}[] = [];
// The worker consumer queue is nothing but a callback list, once a worker is available, the runner
// pop a consumer and run the callback, which will retry gaining the worker and retry the task.
const workerConsumerQueue: (() => void)[] = [];
/**
* Runs a task in the `script` in a worker thread that can be aborted during runtime.
*
* In Node.js, the `script` can be either a CommonJS module or an ES module, and is relative to
* the current working directory if not absolute.
*
* In browser or Deno, the `script` can only be an ES module, and is relative to the current URL
* (or working directory for Deno) if not absolute.
*/
export async function run<T, A extends any[] = any[]>(
script: string,
args: A | undefined = undefined,
options: {
/** If not set, runs the default function, otherwise runs the specific function. */

@@ -263,736 +767,209 @@ fn?: string;

webWorkerEntry?: string;
}): Promise<{
workerId: number;
/** Terminates the worker and abort the task. */
abort(): Promise<void>;
/** Retrieves the return value of the function. */
result(): Promise<T>;
/** Iterates the yield value if the function returns a generator. */
iterate(): AsyncIterable<T>;
}>;
}
} | undefined = undefined
): Promise<{
workerId: number;
/** Terminates the worker and abort the task. */
abort(): Promise<void>;
/** Retrieves the return value of the function. */
result(): Promise<T>;
/** Iterates the yield value if the function returns a generator. */
iterate(): AsyncIterable<T>;
}> {
const msg = {
type: "ffi",
script,
baseUrl: "",
fn: options?.fn || "default",
args: args ?? [],
};
const jsext: JsExt = {
try(fn: any, ...args: any[]) {
if (typeof fn === "function") {
try {
return jsext.try(fn.apply(void 0, args));
} catch (err) {
return [err, undefined];
}
}
if (typeof Deno === "object") {
msg.baseUrl = "file://" + Deno.cwd() + "/";
} else if (isNode) {
msg.baseUrl = "file://" + process.cwd() + "/";
} else if (typeof location === "object") {
msg.baseUrl = location.href;
}
let returns = fn;
// Implementation details should be ordered from complex to simple.
// `buffer` is used to store data pieces yielded by generator functions before they are
// consumed. `error` and `result` serves similar purposes for function results.
const buffer: any[] = [];
let error: Error | null = null;
let result: { value: any; } | undefined;
let resolver: {
resolve: (data: any) => void;
reject: (err: unknown) => void;
} | undefined;
let iterator: NodeJS.EventEmitter | undefined;
let workerId: number | undefined;
let poolRecord: typeof workerPool[0] | undefined;
let release: () => void;
let terminate = () => Promise.resolve<void>(void 0);
const timeout = options?.timeout ? setTimeout(() => {
const err = new Error(`operation timeout after ${options.timeout}ms`);
if (isAsyncGenerator(returns)) {
return (async function* () {
let input: unknown;
let result: any;
// Use `while` loop instead of `for...of...` in order to
// retrieve the return value of a generator function.
while (true) {
try {
const { done, value } = await returns.next(input);
if (done) {
result = value;
break;
} else {
// Receive any potential input value that passed
// to the outer `next()` call, and pass them to
// `res.next()` in the next call.
input = yield Promise.resolve([null, value]);
}
} catch (err) {
// If any error occurs, yield that error as resolved
// and break the loop immediately, indicating the
// process is forced broken.
yield Promise.resolve([err, undefined]);
break;
}
}
return [null, result];
})() as AsyncGenerator<unknown, any, unknown>;
} else if (isGenerator(returns)) {
return (function* () {
let input: unknown;
let result: any;
while (true) {
try {
const { done, value } = returns.next(input);
if (done) {
result = value;
break;
} else {
input = yield [null, value];
}
} catch (err) {
yield [err, undefined];
break;
}
}
return [null, result];
})() as Generator<unknown, any, unknown>;
} else if (typeof returns?.then === "function") {
returns = (returns as PromiseLike<any>).then((value: any) => [null, value]);
return Promise.resolve(returns).catch((err: unknown) => [err, undefined]) as any;
if (resolver) {
resolver.reject(err);
} else {
return [null, returns];
error = err;
}
},
func<T, R = any, A extends any[] = any[]>(
fn: (this: T, defer: (cb: () => void) => void, ...args: A) => R
): (this: T, ...args: A) => R {
return function (this: any, ...args: A) {
const callbacks: (() => void)[] = [];
const defer = (cb: () => void) => void callbacks.push(cb);
type Result = { value?: Awaited<R>; error: unknown; };
let result: Result | undefined;
try {
const returns = fn.call(this, defer, ...args) as any;
terminate();
}, options.timeout) : null;
if (isAsyncGenerator(returns)) {
const gen = (async function* () {
let input: unknown;
const handleMessage = (msg: any) => {
if (msg && typeof msg === "object" && typeof msg.type === "string") {
if (msg.type === "error") {
return handleError(msg.error);
} else if (msg.type === "return") {
if (options?.keepAlive) {
// Release before resolve.
release?.();
// Use `while` loop instead of `for...of...` in order to
// retrieve the return value of a generator function.
while (true) {
try {
const { done, value } = await returns.next(input);
if (done) {
result = { value, error: null };
break;
} else {
// Receive any potential input value that passed
// to the outer `next()` call, and pass them to
// `res.next()` in the next call.
input = yield Promise.resolve(value);
}
} catch (error) {
// If any error occurs, capture that error and break
// the loop immediately, indicating the process is
// forced broken.
result = { value: void 0, error } as Result;
break;
}
}
for (let i = callbacks.length - 1; i >= 0; i--) {
await (callbacks[i] as () => void | Promise<void>)?.();
}
if (result.error) {
throw result.error;
} else {
return result.value;
}
})() as AsyncGenerator<unknown, any, unknown>;
return gen as R;
} else if (isGenerator(returns)) {
const gen = (function* () {
let input: unknown;
while (true) {
try {
const { done, value } = returns.next(input);
if (done) {
result = { value, error: null };
break;
} else {
input = yield value;
}
} catch (error) {
result = { value: void 0, error } as Result;
break;
}
}
for (let i = callbacks.length - 1; i >= 0; i--) {
callbacks[i]?.();
}
if (result.error) {
throw result.error;
} else {
return result.value;
}
})() as Generator<unknown, R, unknown>;
return gen as R;
} else if (typeof returns?.then === "function") {
return Promise.resolve(returns as PromiseLike<R>).then(value => ({
value,
error: null,
} as Result)).catch((error: unknown) => ({
value: void 0,
error,
} as Result)).then(async result => {
for (let i = callbacks.length - 1; i >= 0; i--) {
await (callbacks[i] as () => void | Promise<void>)?.();
}
if (result.error) {
throw result.error;
} else {
return result.value;
}
}) as R;
if (workerConsumerQueue.length) {
// Queued consumer now has chance to gain the worker.
workerConsumerQueue.shift()?.();
}
} else {
result = { value: returns, error: null } as Result;
terminate();
}
} catch (error) {
result = { value: void 0, error } as Result;
}
for (let i = callbacks.length - 1; i >= 0; i--) {
callbacks[i]?.();
}
if (result.error) {
throw result.error;
} else {
return result.value as R;
}
};
},
wrap<T, Fn extends (this: T, ...args: any[]) => any>(
fn: Fn,
wrapper: (this: T, fn: Fn, ...args: Parameters<Fn>) => ReturnType<Fn>
): Fn {
const wrapped = function (this: any, ...args: Parameters<Fn>): ReturnType<Fn> {
return wrapper.call(this, fn, ...args);
};
Object.defineProperty(wrapped,
"name",
Object.getOwnPropertyDescriptor(fn, "name") as PropertyDescriptor);
Object.defineProperty(wrapped,
"length",
Object.getOwnPropertyDescriptor(fn, "length") as PropertyDescriptor);
Object.defineProperty(wrapped, "toString", {
configurable: true,
enumerable: false,
writable: true,
value: fn.toString.bind(fn),
});
return wrapped as Fn;
},
throttle(handler, options) {
const key = typeof options === "number" ? null : options.for;
const duration = typeof options === "number" ? options : options.duration;
const handleCall = function (
this: any,
cache: ThrottleCache,
...args: any[]
) {
if (cache.result && Date.now() < (cache.expires ?? 0)) {
if (cache.result.error) {
throw cache.result.error;
if (resolver) {
resolver.resolve(msg.value);
} else {
return cache.result.value;
result = { value: msg.value };
}
} else if (msg.type === "yield") {
if (msg.done) {
// The final message of yield event is the return value.
handleMessage({ type: "return", value: msg.value });
} else {
if (iterator) {
iterator.emit("data", msg.value);
} else {
buffer.push(msg.value);
}
}
}
}
};
try {
const returns = handler.call(this, ...args);
cache.result = { value: returns };
cache.expires = Date.now() + duration;
return returns;
} catch (error) {
cache.result = { error };
cache.expires = Date.now() + duration;
throw error;
}
};
if (!key) {
const cache: ThrottleCache = { for: null };
return function (this: any, ...args: any[]) {
return handleCall.call(this, cache, ...args);
};
const handleError = (err: Error | null) => {
if (resolver) {
resolver.reject(err);
} else if (iterator) {
iterator.emit("error", err);
} else {
let cache = throttleCaches.get(key);
if (!cache) {
cache = { for: key };
throttleCaches.set(key, cache);
}
return function (this: any, ...args: any[]) {
return handleCall.call(this, cache as ThrottleCache, ...args);
};
error = err;
}
},
mixins(base, ...mixins) {
const obj = { ctor: null as any as Constructor<any> };
obj.ctor = class extends (<any>base) { }; // make sure this class has no name
};
const handleExit = () => {
if (poolRecord) {
// Clean the pool before resolve.
workerPool = workerPool.filter(record => record !== poolRecord);
for (const mixin of mixins) {
if (typeof mixin == "function") {
mergeHierarchy(obj.ctor, mixin);
} else if (mixin && typeof mixin == "object") {
mergeIfNotExists(obj.ctor.prototype, mixin);
} else {
throw new TypeError("mixin must be a constructor or an object");
if (workerConsumerQueue.length) {
// Queued consumer now has chance to create new worker.
workerConsumerQueue.shift()?.();
}
}
return obj.ctor as Constructor<any>;
},
isSubclassOf(ctor1, ctor2) {
return typeof ctor1 === "function"
&& typeof ctor2 === "function"
&& ctor1.prototype instanceof ctor2;
},
read<T>(source: any, eventMap: {
event?: string; // for EventSource custom event
message?: string;
data?: string;
error?: string;
close?: string;
} | undefined = undefined): AsyncIterable<T> {
if (typeof source[Symbol.asyncIterator] === "function") {
return source;
if (resolver) {
resolver.resolve(void 0);
} else if (iterator) {
iterator.emit("close");
} else if (!error && !result) {
result = { value: void 0 };
}
};
const iterable = {
ended: false,
error: null as Error | null,
queue: [] as T[],
consumers: [] as {
resolve: (data: IteratorResult<T>) => void;
reject: (err: any) => void;
}[],
next() {
return new Promise<IteratorResult<T>>((resolve, reject) => {
if (this.error && !this.ended) {
// If there is error occurred during the last transmission and the iterator
// hasn't been closed, reject that error and stop the iterator immediately.
reject(this.error);
this.ended = true;
} else if (this.ended && !this.queue.length) {
// If the iterator has is closed, resolve the pending consumer with void
// value.
resolve({ value: void 0 as T, done: true });
} else if (this.queue.length > 0) {
// If there are data in the queue, resolve the the first piece immediately.
resolve({ value: this.queue.shift() as T, done: false });
} else {
// If there are no queued data, push the consumer to a waiting queue.
this.consumers.push({ resolve, reject });
}
});
}
};
if (isNode) {
const path = await import("path");
const { fileURLToPath } = await import("url");
let _filename: string;
let _dirname: string;
let entry: string;
const handleMessage = (data: T) => {
if (iterable.consumers.length > 0) {
iterable.consumers.shift()?.resolve({ value: data, done: false });
} else {
iterable.queue.push(data);
}
};
const handleClose = () => {
iterable.ended = true;
let consumer: typeof iterable["consumers"][0] | undefined;
while (consumer = iterable.consumers.shift()) {
consumer.resolve({ value: undefined, done: true });
}
};
const handleError = (err: Error) => {
iterable.error = err;
if (iterable.consumers.length > 0) {
iterable.consumers.forEach(item => {
item.reject(err);
});
iterable.consumers = [];
}
};
const handleBrowserErrorEvent = (ev: Event) => {
let err: Error;
if (ev instanceof ErrorEvent) {
err = ev.error || new Error(ev.message);
} else {
// @ts-ignore
err = new Error("something went wrong", { cause: ev });
}
handleError(err);
};
const proto = Object.getPrototypeOf(source);
const msgDesc = Object.getOwnPropertyDescriptor(proto, "onmessage");
if (msgDesc?.set && typeof source.close === "function") { // WebSocket or EventSource
const errDesc = Object.getOwnPropertyDescriptor(proto, "onerror");
const closeDesc = Object.getOwnPropertyDescriptor(proto, "onclose");
let cleanup: () => void;
if (eventMap?.event &&
eventMap?.event !== "message" &&
typeof source["addEventListener"] === "function"
) { // for EventSource listening on custom events
const es = source as EventSource;
const eventName = eventMap.event;
const msgListener = (ev: MessageEvent<T>) => {
handleMessage(ev.data);
};
es.addEventListener(eventName, msgListener);
cleanup = () => {
es.removeEventListener(eventName, msgListener);
};
} else {
msgDesc.set.call(source, (ev: MessageEvent<T>) => {
handleMessage(ev.data);
});
cleanup = () => {
msgDesc.set?.call(source, null);
};
}
errDesc?.set?.call(source, handleBrowserErrorEvent);
if (closeDesc?.set) { // WebSocket
closeDesc.set.call(source, () => {
handleClose();
closeDesc.set?.call(source, null);
errDesc?.set?.call(source, null);
cleanup?.();
});
} else if (!closeDesc?.set && typeof source.close === "function") { // EventSource
// EventSource by default does not trigger close event, we need to make sure when
// it calls the close() function, the iterator is automatically closed.
const es = source as EventSource;
const _close = es.close;
es.close = function close() {
_close.call(es);
handleClose();
es.close = _close;
errDesc?.set?.call(source, null);
cleanup?.();
};
}
} else if (typeof source.send === "function" && typeof source.close === "function") {
// non-standard WebSocket implementation
const ws = source as WebSocket;
ws.onmessage = (ev: MessageEvent<T>) => {
handleMessage(ev.data);
};
ws.onerror = handleBrowserErrorEvent;
ws.onclose = () => {
handleClose();
ws.onclose = null;
ws.onerror = null;
ws.onmessage = null;
};
} else if (typeof source["addEventListener"] === "function") { // EventTarget
const target = source as EventTarget;
const msgEvent = eventMap?.message || "message";
const errEvent = eventMap?.error || "error";
const closeEvent = eventMap?.close || "close";
const msgListener = (ev: Event) => {
if (ev instanceof MessageEvent) {
handleMessage(ev.data);
}
};
target.addEventListener(msgEvent, msgListener);
target.addEventListener(errEvent, handleBrowserErrorEvent);
target.addEventListener(closeEvent, function closeListener() {
handleClose();
target.removeEventListener(closeEvent, closeListener);
target.removeEventListener(msgEvent, msgListener);
target.removeEventListener(errEvent, handleBrowserErrorEvent);
});
} else if (typeof source["on"] === "function") { // EventEmitter
const target = source as NodeJS.EventEmitter;
const dataEvent = eventMap?.data || "data";
const errEvent = eventMap?.error || "error";
const endEvent = eventMap?.close || "close";
target.on(dataEvent, handleMessage);
target.once(errEvent, handleError);
target.once(endEvent, () => {
handleClose();
target.off(dataEvent, handleMessage);
target.off(dataEvent, handleError);
});
if (typeof __filename === "string") {
_filename = __filename;
_dirname = __dirname;
} else {
throw new TypeError("the input source cannot be read as an AsyncIterable object");
// This file URL will be replace with `import.meta.url` by Rollup plugin.
_filename = fileURLToPath("file://{__filename}");
_dirname = path.dirname(_filename);
}
return {
[Symbol.asyncIterator]() {
return iterable;
}
};
},
async run(script, args = undefined, options = undefined) {
const msg = {
type: "ffi",
script,
baseUrl: "",
fn: options?.fn || "default",
args: args ?? [],
};
if (typeof Deno === "object") {
msg.baseUrl = "file://" + Deno.cwd() + "/";
} else if (isNode) {
msg.baseUrl = "file://" + process.cwd() + "/";
} else if (typeof location === "object") {
msg.baseUrl = location.href;
if (["cjs", "esm"].includes(path.basename(_dirname))) { // compiled
entry = path.join(path.dirname(_dirname), "worker.mjs");
} else {
entry = path.join(_dirname, "worker.mjs");
}
// `buffer` is used to store data pieces yielded by generator functions before they are
// consumed. `error` and `result` serves similar purposes for function results.
const buffer: any[] = [];
let error: Error | null = null;
let result: { value: any; } | undefined;
let resolver: {
resolve: (data: any) => void;
reject: (err: unknown) => void;
} | undefined;
let iterator: NodeJS.EventEmitter | undefined;
let workerId: number | undefined;
let poolRecord: typeof workerPool[0] | undefined;
let release: () => void;
let terminate = () => Promise.resolve<void>(void 0);
const timeout = options?.timeout ? setTimeout(() => {
const err = new Error(`operation timeout after ${options.timeout}ms`);
if (options?.adapter === "child_process") {
let worker: ChildProcess;
let ok = true;
poolRecord = workerPool.find(item => {
return item.adapter === "child_process" && !item.busy;
});
if (resolver) {
resolver.reject(err);
} else {
error = err;
}
terminate();
}, options.timeout) : null;
const handleMessage = (msg: any) => {
if (msg && typeof msg === "object" && typeof msg.type === "string") {
if (msg.type === "error") {
return handleError(msg.error);
} else if (msg.type === "return") {
if (options?.keepAlive) {
// Release before resolve.
release?.();
if (workerConsumerQueue.length) {
// Queued consumer now has chance to gain the worker.
workerConsumerQueue.shift()?.();
}
} else {
terminate();
}
if (resolver) {
resolver.resolve(msg.value);
} else {
result = { value: msg.value };
}
} else if (msg.type === "yield") {
if (msg.done) {
// The final message of yield event is the return value.
handleMessage({ type: "return", value: msg.value });
} else {
if (iterator) {
iterator.emit("data", msg.value);
} else {
buffer.push(msg.value);
}
}
}
}
};
const handleError = (err: Error | null) => {
if (resolver) {
resolver.reject(err);
} else if (iterator) {
iterator.emit("error", err);
} else {
error = err;
}
};
const handleExit = () => {
if (poolRecord) {
// Clean the pool before resolve.
workerPool = workerPool.filter(record => record !== poolRecord);
if (workerConsumerQueue.length) {
// Queued consumer now has chance to create new worker.
workerConsumerQueue.shift()?.();
}
}
if (resolver) {
resolver.resolve(void 0);
} else if (iterator) {
iterator.emit("close");
} else if (!error && !result) {
result = { value: void 0 };
}
};
if (isNode) {
const path = await import("path");
const { fileURLToPath } = await import("url");
let _filename: string;
let _dirname: string;
let entry: string;
if (typeof __filename === "string") {
_filename = __filename;
_dirname = __dirname;
} else {
// This file URL will be replace with `import.meta.url` by Rollup plugin.
_filename = fileURLToPath("file://{__filename}");
_dirname = path.dirname(_filename);
}
if (["cjs", "esm"].includes(path.basename(_dirname))) { // compiled
entry = path.join(path.dirname(_dirname), "worker.mjs");
} else {
entry = path.join(_dirname, "worker.mjs");
}
if (options?.adapter === "child_process") {
let worker: ChildProcess;
let ok = true;
poolRecord = workerPool.find(item => {
return item.adapter === "child_process" && !item.busy;
worker = poolRecord.worker as ChildProcess;
workerId = poolRecord.workerId;
poolRecord.busy = true;
} else if (workerPool.length < maxWorkerNum) {
const { fork } = await import("child_process");
const isPrior14 = parseInt(process.version.slice(1)) < 14;
worker = fork(entry, {
stdio: "inherit",
serialization: isPrior14 ? "advanced" : "json",
});
if (poolRecord) {
worker = poolRecord.worker as ChildProcess;
workerId = poolRecord.workerId;
poolRecord.busy = true;
} else if (workerPool.length < maxWorkerNum) {
const { fork } = await import("child_process");
const isPrior14 = parseInt(process.version.slice(1)) < 14;
worker = fork(entry, {
stdio: "inherit",
serialization: isPrior14 ? "advanced" : "json",
workerId = worker.pid as number;
ok = await new Promise<boolean>((resolve) => {
worker.once("exit", () => {
if (error) {
// The child process took too long to start and cause timeout error.
resolve(false);
}
});
workerId = worker.pid as number;
ok = await new Promise<boolean>((resolve) => {
worker.once("exit", () => {
if (error) {
// The child process took too long to start and cause timeout error.
resolve(false);
}
});
worker.once("message", () => {
worker.removeAllListeners("exit");
resolve(true);
});
worker.once("message", () => {
worker.removeAllListeners("exit");
resolve(true);
});
});
// Fill the worker pool regardless the current call should keep-alive or not,
// this will make sure that the total number of workers will not exceed the
// maxWorkerNum. If the the call doesn't keep-alive the worker, it will be
// cleaned after the call.
ok && workerPool.push(poolRecord = {
workerId,
worker,
adapter: "child_process",
busy: true,
});
} else {
// Put the current call in the consumer queue if there are no workers available,
// once an existing call finishes, the queue will pop the its head consumer and
// retry.
return new Promise<void>((resolve) => {
workerConsumerQueue.push(resolve);
}).then(() => jsext.run(script, args, options));
}
release = () => {
// Remove the event listener so that later calls will not mess up.
worker.off("message", handleMessage);
poolRecord && (poolRecord.busy = false);
};
terminate = () => Promise.resolve(void worker.kill(1));
if (ok) {
worker.send(msg);
worker.on("message", handleMessage);
worker.once("error", handleError);
worker.once("exit", handleExit);
}
// Fill the worker pool regardless the current call should keep-alive or not,
// this will make sure that the total number of workers will not exceed the
// maxWorkerNum. If the the call doesn't keep-alive the worker, it will be
// cleaned after the call.
ok && workerPool.push(poolRecord = {
workerId,
worker,
adapter: "child_process",
busy: true,
});
} else {
let worker: NodeWorker;
let ok = true;
poolRecord = workerPool.find(item => {
return item.adapter === "worker_threads" && !item.busy;
});
// Put the current call in the consumer queue if there are no workers available,
// once an existing call finishes, the queue will pop the its head consumer and
// retry.
return new Promise<void>((resolve) => {
workerConsumerQueue.push(resolve);
}).then(() => run(script, args, options));
}
if (poolRecord) {
worker = poolRecord.worker as NodeWorker;
workerId = poolRecord.workerId;
poolRecord.busy = true;
} else if (workerPool.length < maxWorkerNum) {
const { Worker } = await import("worker_threads");
worker = new Worker(entry);
// `threadId` may not exist in Bun.
workerId = worker.threadId ?? workerIdCounter.next().value as number;
ok = await new Promise<boolean>((resolve) => {
worker.once("exit", () => {
if (error) {
// The child process took too long to start and cause timeout error.
resolve(false);
}
});
worker.once("online", () => {
worker.removeAllListeners("exit");
resolve(true);
});
});
ok && workerPool.push(poolRecord = {
workerId,
worker,
adapter: "worker_threads",
busy: true,
});
} else {
return new Promise<void>((resolve) => {
workerConsumerQueue.push(resolve);
}).then(() => jsext.run(script, args, options));
}
release = () => {
// Remove the event listener so that later calls will not mess up.
worker.off("message", handleMessage);
poolRecord && (poolRecord.busy = false);
};
terminate = () => Promise.resolve(void worker.kill(1));
release = () => {
worker.off("message", handleMessage);
poolRecord && (poolRecord.busy = false);
};
terminate = async () => void (await worker.terminate());
if (ok) {
worker.postMessage(msg);
worker.on("message", handleMessage);
worker.once("error", handleError);
worker.once("messageerror", handleError);
worker.once("exit", handleExit);
}
if (ok) {
worker.send(msg);
worker.on("message", handleMessage);
worker.once("error", handleError);
worker.once("exit", handleExit);
}
} else {
let worker: Worker;
let worker: NodeWorker;
let ok = true;
poolRecord = workerPool.find(item => {

@@ -1003,35 +980,23 @@ return item.adapter === "worker_threads" && !item.busy;

if (poolRecord) {
worker = poolRecord.worker as Worker;
worker = poolRecord.worker as NodeWorker;
workerId = poolRecord.workerId;
poolRecord.busy = true;
} else if (workerPool.length < maxWorkerNum) {
let url: string;
if (typeof Deno === "object") {
// Deno can load the module regardless of MINE type.
url = [
...("file://{__filename}".split("/").slice(0, -1)),
"worker-web.mjs"
].join("/");
} else {
const _url = options?.webWorkerEntry
|| "https://raw.githubusercontent.com/ayonli/jsext/main/esm/worker-web.mjs";
const res = await fetch(_url);
let blob: Blob;
if (res.headers.get("content-type")?.startsWith("application/javascript")) {
blob = await res.blob();
} else {
const buf = await res.arrayBuffer();
blob = new Blob([new Uint8Array(buf)], {
type: "application/javascript",
});
}
url = URL.createObjectURL(blob);
}
worker = new Worker(url, { type: "module" });
workerId = workerIdCounter.next().value as number;
workerPool.push(poolRecord = {
const { Worker } = await import("worker_threads");
worker = new Worker(entry);
// `threadId` may not exist in Bun.
workerId = worker.threadId ?? workerIdCounter.next().value as number;
ok = await new Promise<boolean>((resolve) => {
worker.once("exit", () => {
if (error) {
// The child process took too long to start and cause timeout error.
resolve(false);
}
});
worker.once("online", () => {
worker.removeAllListeners("exit");
resolve(true);
});
});
ok && workerPool.push(poolRecord = {
workerId,

@@ -1045,68 +1010,142 @@ worker,

workerConsumerQueue.push(resolve);
}).then(() => jsext.run(script, args, options));
}).then(() => run(script, args, options));
}
release = () => {
worker.onmessage = null;
worker.off("message", handleMessage);
poolRecord && (poolRecord.busy = false);
};
terminate = async () => {
await Promise.resolve(worker.terminate());
handleExit();
};
terminate = async () => void (await worker.terminate());
worker.postMessage(msg);
worker.onmessage = (ev) => handleMessage(ev.data);
worker.onerror = (ev) => handleMessage(ev.error || new Error(ev.message));
worker.onmessageerror = () => {
handleError(new Error("unable to deserialize the message"));
};
if (ok) {
worker.postMessage(msg);
worker.on("message", handleMessage);
worker.once("error", handleError);
worker.once("messageerror", handleError);
worker.once("exit", handleExit);
}
}
} else {
let worker: Worker;
poolRecord = workerPool.find(item => {
return item.adapter === "worker_threads" && !item.busy;
});
return {
workerId,
async abort() {
timeout && clearTimeout(timeout);
await terminate();
},
async result() {
return await new Promise<any>((resolve, reject) => {
if (error) {
reject(error);
} else if (result) {
resolve(result.value);
} else {
resolver = { resolve, reject };
}
});
},
async *iterate() {
if (resolver) {
throw new Error("result() has been called");
} else if (result) {
throw new TypeError("the response is not iterable");
if (poolRecord) {
worker = poolRecord.worker as Worker;
workerId = poolRecord.workerId;
poolRecord.busy = true;
} else if (workerPool.length < maxWorkerNum) {
let url: string;
if (typeof Deno === "object") {
// Deno can load the module regardless of MINE type.
url = [
...("file://{__filename}".split("/").slice(0, -1)),
"worker-web.mjs"
].join("/");
} else {
const _url = options?.webWorkerEntry
|| "https://raw.githubusercontent.com/ayonli/jsext/main/esm/worker-web.mjs";
const res = await fetch(_url);
let blob: Blob;
if (res.headers.get("content-type")?.startsWith("application/javascript")) {
blob = await res.blob();
} else {
const buf = await res.arrayBuffer();
blob = new Blob([new Uint8Array(buf)], {
type: "application/javascript",
});
}
const { EventEmitter } = await import("events");
iterator = new EventEmitter();
url = URL.createObjectURL(blob);
}
if (buffer.length) {
(async () => {
await Promise.resolve(null);
let msg: any;
worker = new Worker(url, { type: "module" });
workerId = workerIdCounter.next().value as number;
workerPool.push(poolRecord = {
workerId,
worker,
adapter: "worker_threads",
busy: true,
});
} else {
return new Promise<void>((resolve) => {
workerConsumerQueue.push(resolve);
}).then(() => run(script, args, options));
}
while (msg = buffer.shift()) {
iterator.emit("data", msg);
}
})().catch(console.error);
}
release = () => {
worker.onmessage = null;
poolRecord && (poolRecord.busy = false);
};
terminate = async () => {
await Promise.resolve(worker.terminate());
handleExit();
};
for await (const msg of jsext.read<any>(iterator)) {
yield msg;
}
},
worker.postMessage(msg);
worker.onmessage = (ev) => handleMessage(ev.data);
worker.onerror = (ev) => handleMessage(ev.error || new Error(ev.message));
worker.onmessageerror = () => {
handleError(new Error("unable to deserialize the message"));
};
}
return {
workerId,
async abort() {
timeout && clearTimeout(timeout);
await terminate();
},
async result() {
return await new Promise<any>((resolve, reject) => {
if (error) {
reject(error);
} else if (result) {
resolve(result.value);
} else {
resolver = { resolve, reject };
}
});
},
async *iterate() {
if (resolver) {
throw new Error("result() has been called");
} else if (result) {
throw new TypeError("the response is not iterable");
}
const { EventEmitter } = await import("events");
iterator = new EventEmitter();
if (buffer.length) {
(async () => {
await Promise.resolve(null);
let msg: any;
while (msg = buffer.shift()) {
iterator.emit("data", msg);
}
})().catch(console.error);
}
for await (const msg of read<any>(iterator)) {
yield msg;
}
},
};
}
const jsext = {
try: _try,
func,
wrap,
throttle,
mixins,
isSubclassOf,
read,
run,
};
export default jsext;

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

import { hasOwn, hasOwnMethod, omit, patch, pick, as } from ".";
import { hasOwn, hasOwnMethod, omit, patch, pick, as, isValid } from ".";

@@ -34,13 +34,22 @@ declare global {

/**
* Returns the object if it's an instance of the given type, otherwise returns `null`.
* This function is mainly used for the optional chaining syntax.
* Checks if the value is an instance of the given type, returns the value itself if passed,
* otherwise returns `null`. This function is mainly used for the optional chaining syntax.
* @example
* Object.as(bar, SomeType)?.doSomething();
*/
as(obj: any, type: StringConstructor): string | null;
as(obj: any, type: NumberConstructor): number | null;
as(obj: any, type: BigIntConstructor): bigint | null;
as(obj: any, type: BooleanConstructor): boolean | null;
as(obj: any, type: SymbolConstructor): symbol | null;
as<T>(obj: any, type: Constructor<T>): T | null;
as(value: unknown, type: StringConstructor): string | null;
as(value: unknown, type: NumberConstructor): number | null;
as(value: unknown, type: BigIntConstructor): bigint | null;
as(value: unknown, type: BooleanConstructor): boolean | null;
as(value: unknown, type: SymbolConstructor): symbol | null;
as<T>(value: unknown, type: Constructor<T>): T | null;
/**
* Returns `true` if the given value is valid. Thee following values are considered invalid:
*
* - `undefined`
* - `null`
* - `NaN`
* - `Invalid Date`
*/
isValid(value: unknown): boolean;
}

@@ -61,1 +70,2 @@ }

Object.as = as;
Object.isValid = isValid;

@@ -86,14 +86,14 @@ import type { Constructor } from "../index";

/**
* Returns the object if it's an instance of the given type, otherwise returns `null`.
* This function is mainly used for the optional chaining syntax.
* Checks if the value is an instance of the given type, returns the value itself if passed,
* otherwise returns `null`. This function is mainly used for the optional chaining syntax.
* @example
* as(bar, SomeType)?.doSomething();
* Object.as(bar, SomeType)?.doSomething();
*/
export function as(obj: any, type: StringConstructor): string | null;
export function as(obj: any, type: NumberConstructor): number | null;
export function as(obj: any, type: BigIntConstructor): bigint | null;
export function as(obj: any, type: BooleanConstructor): boolean | null;
export function as(obj: any, type: SymbolConstructor): symbol | null;
export function as<T>(obj: any, type: Constructor<T>): T | null;
export function as(obj: any, type: any): any {
export function as(value: unknown, type: StringConstructor): string | null;
export function as(value: unknown, type: NumberConstructor): number | null;
export function as(value: unknown, type: BigIntConstructor): bigint | null;
export function as(value: unknown, type: BooleanConstructor): boolean | null;
export function as(value: unknown, type: SymbolConstructor): symbol | null;
export function as<T>(value: unknown, type: Constructor<T>): T | null;
export function as(value: any, type: any): any {
if (typeof type !== "function") {

@@ -112,10 +112,10 @@ throw new TypeError("type must be a valid constructor");

if (obj instanceof type) {
if (value instanceof type) {
if ([String, Number, Boolean].includes(type)) {
return obj.valueOf(); // make sure the primitives are returned.
return value.valueOf(); // make sure the primitives are returned.
} else {
return obj;
return value;
}
} else if ((_type = typeof obj) && primitiveMap[_type] === type) {
return obj;
} else if ((_type = typeof value) && primitiveMap[_type] === type) {
return value;
}

@@ -125,1 +125,16 @@

}
/**
* Returns `true` if the given value is valid. Thee following values are considered invalid:
*
* - `undefined`
* - `null`
* - `NaN`
* - `Invalid Date`
*/
export function isValid(value: unknown): boolean {
return value !== undefined
&& value !== null
&& !Object.is(value, NaN)
&& !(value instanceof Date && value.toString() === "Invalid Date");
}
{
"name": "@ayonli/jsext",
"version": "0.4.5",
"version": "0.4.6",
"description": "Additional functions for JavaScript programming in practice.",

@@ -5,0 +5,0 @@ "exports": {

@@ -51,2 +51,14 @@ # JsExt

## Types
- `AsyncFunction`
- `AsyncGeneratorFunction`
- `AsyncFunctionConstructor`
- `Constructor<T>`
- `TypedArray`
- `Optional<T, K extends keyof T>`
- `Ensured<T, K extends keyof T>`
When [augment](./augment.ts)ing, these types will ba attached to the global namespace.
## Sub-packages

@@ -189,8 +201,9 @@

- `omit<T>(obj: T, keys: (string | symbol)[]): Partial<T>`
- `as(obj: any, type: StringConstructor): string | null`
- `as(obj: any, type: NumberConstructor): number | null`
- `as(obj: any, type: BigIntConstructor): bigint | null`
- `as(obj: any, type: BooleanConstructor): boolean | null`
- `as(obj: any, type: SymbolConstructor): symbol | null`
- `as<T>(obj: any, type: Constructor<T>): T | null`
- `as(value: unknown, type: StringConstructor): string | null`
- `as(value: unknown, type: NumberConstructor): number | null`
- `as(value: unknown, type: BigIntConstructor): bigint | null`
- `as(value: unknown, type: BooleanConstructor): boolean | null`
- `as(value: unknown, type: SymbolConstructor): symbol | null`
- `as<T>(value: unknown, type: Constructor<T>): T | null`
- `isValid(value: unknown): boolean`

@@ -197,0 +210,0 @@ *When [augment](./object/augment.ts)ing, these functions will be attached to the `Object` constructor.*