@ayonli/jsext
Advanced tools
+23
-0
@@ -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; |
+5
-0
@@ -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 +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
@@ -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"} |
+22
-7
| "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":";;;AAEA,SAAgB,MAAM,CAAC,GAAQ,EAAE,GAA6B;IAC1D,OAAO,MAAM,CAAC,SAAS,CAAC,cAAc,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;AAC1D,CAAC;AAFD,wBAEC;AAAA,CAAC;AAEF;;;;GAIG;AACH,SAAgB,YAAY,CAAC,GAAQ,EAAE,MAAuB;;IAC1D,MAAM,KAAK,GAAG,MAAM,CAAC,cAAc,CAAC,GAAG,CAAC,CAAC;IAEzC,IAAI,CAAC,KAAK,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,EAAE;QAClC,OAAO,KAAK,CAAC;KAChB;IAED,OAAO,OAAO,CAAA,MAAA,MAAM,CAAC,wBAAwB,CAAC,KAAK,EAAE,MAAM,CAAC,0CAAE,KAAK,CAAA,KAAK,UAAU,CAAC;AACvF,CAAC;AARD,oCAQC;AAYD,SAAgB,KAAK,CAAC,MAAW,EAAE,GAAG,OAAc;IAChD,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE;QAC1B,KAAK,MAAM,GAAG,IAAI,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE;YACvC,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,IAAI,MAAM,CAAC,GAAG,CAAC,KAAK,SAAS,EAAE;gBACnD,MAAM,CAAC,GAAG,CAAC,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC;aAC7B;SACJ;KACJ;IAED,OAAO,MAAM,CAAC;AAClB,CAAC;AAVD,sBAUC;AAAA,CAAC;AAKF,SAAgB,IAAI,CAAC,GAAQ,EAAE,IAAyB;IACpD,OAAO,IAAI,CAAC,MAAM,CAAC,CAAC,MAAW,EAAE,GAAoB,EAAE,EAAE;QACrD,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,KAAK,SAAS,EAAE;YACtC,MAAM,CAAC,GAAG,CAAC,GAAG,GAAG,CAAC,GAAG,CAAC,CAAC;SAC1B;QAED,OAAO,MAAM,CAAC;IAClB,CAAC,EAAE,EAAE,CAAC,CAAC;AACX,CAAC;AARD,oBAQC;AAUD,SAAgB,IAAI,CAAC,GAAQ,EAAE,IAAyB;IACpD,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IACrC,MAAM,QAAQ,GAAG,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC;IAC5D,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC;IAEnC,oCAAoC;IACpC,IAAI,GAAG,YAAY,KAAK,EAAE;QACtB,CAAC,MAAM,EAAE,SAAS,EAAE,OAAO,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE;YACvC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC;gBAClB,GAAW,CAAC,GAAG,CAAC,KAAK,SAAS;gBAC/B,CAAC,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EACtB;gBACE,MAAM,CAAC,GAAG,CAAC,GAAI,GAAW,CAAC,GAAG,CAAC,CAAC;aACnC;QACL,CAAC,CAAC,CAAC;KACN;IAED,OAAO,MAAM,CAAC;AAClB,CAAC;AAlBD,oBAkBC;AAcD,SAAgB,EAAE,CAAC,KAAU,EAAE,IAAS;IACpC,IAAI,OAAO,IAAI,KAAK,UAAU,EAAE;QAC5B,MAAM,IAAI,SAAS,CAAC,kCAAkC,CAAC,CAAC;KAC3D;IAED,IAAI,KAAU,CAAC;IACf,MAAM,YAAY,GAA6B;QAC3C,QAAQ,EAAE,MAAM;QAChB,QAAQ,EAAE,MAAM;QAChB,QAAQ,EAAE,MAAM;QAChB,SAAS,EAAE,OAAO;QAClB,QAAQ,EAAE,MAAM;KACnB,CAAC;IAEF,IAAI,KAAK,YAAY,IAAI,EAAE;QACvB,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE;YAC1C,OAAO,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC,yCAAyC;SACpE;aAAM;YACH,OAAO,KAAK,CAAC;SAChB;KACJ;SAAM,IAAI,CAAC,KAAK,GAAG,OAAO,KAAK,CAAC,IAAI,YAAY,CAAC,KAAK,CAAC,KAAK,IAAI,EAAE;QAC/D,OAAO,KAAK,CAAC;KAChB;IAED,OAAO,IAAI,CAAC;AAChB,CAAC;AAzBD,gBAyBC;AAED;;;;;;;GAOG;AACH,SAAgB,OAAO,CAAC,KAAc;IAClC,OAAO,KAAK,KAAK,SAAS;WACnB,KAAK,KAAK,IAAI;WACd,CAAC,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,GAAG,CAAC;WACtB,CAAC,CAAC,KAAK,YAAY,IAAI,IAAI,KAAK,CAAC,QAAQ,EAAE,KAAK,cAAc,CAAC,CAAC;AAC3E,CAAC;AALD,0BAKC"} |
+6
-0
@@ -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
@@ -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"} |
+21
-7
@@ -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; |
+19
-9
@@ -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; |
+30
-15
@@ -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"); | ||
| } |
+1
-1
| { | ||
| "name": "@ayonli/jsext", | ||
| "version": "0.4.5", | ||
| "version": "0.4.6", | ||
| "description": "Additional functions for JavaScript programming in practice.", | ||
@@ -5,0 +5,0 @@ "exports": { |
+19
-6
@@ -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.* |
Network access
Supply chain riskThis module accesses the network.
Found 1 instance in 1 package
Shell access
Supply chain riskThis module accesses the system shell. Accessing the system shell increases the risk of executing arbitrary code.
Found 1 instance in 1 package
AI-detected potential code anomaly
Supply chain riskAI has identified unusual behaviors that may pose a security risk.
Found 2 instances in 1 package
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
Found 1 instance in 1 package
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
Found 1 instance in 1 package
Network access
Supply chain riskThis module accesses the network.
Found 1 instance in 1 package
Shell access
Supply chain riskThis module accesses the system shell. Accessing the system shell increases the risk of executing arbitrary code.
Found 1 instance in 1 package
AI-detected potential code anomaly
Supply chain riskAI has identified unusual behaviors that may pose a security risk.
Found 1 instance in 1 package
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
Found 1 instance in 1 package
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
Found 1 instance in 1 package
5984
3.74%343
3.94%383751
-0.31%12
33.33%