UNPKG

@socketsupply/socket

Version:

A Cross-Platform, Native Runtime for Desktop and Mobile Apps — Create apps using HTML, CSS, and JavaScript. Written from the ground up to be small and maintainable.

170 lines (144 loc) 4.3 kB
// @ts-nocheck import * as asyncHooks from './async/hooks.js' const resourceSymbol = Symbol('PromiseResource') export const NativePromise = globalThis.Promise export const NativePromisePrototype = { then: globalThis.Promise.prototype.then, catch: globalThis.Promise.prototype.catch, finally: globalThis.Promise.prototype.finally } export const NativePromiseAll = globalThis.Promise.all.bind(globalThis.Promise) export const NativePromiseAny = globalThis.Promise.any.bind(globalThis.Promise) /** * @typedef {function(any): void} ResolveFunction */ /** * @typedef {function(Error|string|null): void} RejectFunction */ /** * @typedef {function(ResolveFunction, RejectFunction): void} ResolverFunction */ /** * @typedef {{ * promise: Promise, * resolve: ResolveFunction, * reject: RejectFunction * }} PromiseResolvers */ // @ts-ignore export class Promise extends NativePromise { /** * Creates a new `Promise` with resolver functions. * @see {https://github.com/tc39/proposal-promise-with-resolvers} * @return {PromiseResolvers} */ static withResolvers () { if (typeof super.withResolvers === 'function') { return super.withResolvers() } const resolvers = { promise: null, resolve: null, reject: null } resolvers.promise = new Promise((resolve, reject) => { resolvers.resolve = resolve resolvers.reject = reject }) return resolvers } /** * `Promise` class constructor. * @ignore * @param {ResolverFunction} resolver */ constructor (resolver) { super(resolver) // eslint-disable-next-line this[resourceSymbol] = new class Promise extends asyncHooks.CoreAsyncResource { constructor () { super('Promise') } } } } Promise.all = function (iterable) { return NativePromiseAll.call(NativePromise, Array.from(iterable).map((promise, index) => { if (!promise || typeof promise.catch !== 'function') { return promise } return promise.catch((err) => { return Promise.reject(Object.defineProperties(err, { [Symbol.for('socket.runtime.CallSite.PromiseElementIndex')]: { configurable: true, enumerable: false, writable: false, value: index }, [Symbol.for('socket.runtime.CallSite.PromiseAll')]: { configurable: true, enumerable: false, writable: false, value: true } })) }) })) } Promise.any = function (iterable) { return NativePromiseAny.call(NativePromise, Array.from(iterable).map((promise, index) => { if (!promise || typeof promise.catch !== 'function') { return promise } return promise.catch((err) => { return Promise.reject(Object.defineProperties(err, { [Symbol.for('socket.runtime.CallSite.PromiseElementIndex')]: { configurable: true, enumerable: false, writable: false, value: index }, [Symbol.for('socket.runtime.CallSite.PromiseAny')]: { configurable: true, enumerable: false, writable: false, value: true } })) }) })) } function wrapNativePromiseFunction (name) { const prototype = Promise.prototype if (prototype[name].__async_wrapped__) { return } const nativeFunction = prototype[name] prototype[name] = function (...args) { if (asyncHooks.executionAsyncResource().type === 'RuntimeExecution') { return nativeFunction.call(this, ...args) } const resource = this[resourceSymbol] return nativeFunction.call( this, ...args.map((arg) => { if (typeof arg === 'function') { return asyncHooks.wrap( arg, 'Promise', resource?.asyncId?.() ?? asyncHooks.getNextAsyncResourceId(), resource?.triggerAsyncId?.() ?? asyncHooks.getDefaultExecutionAsyncId(), resource ?? undefined ) } return arg }) ) } Object.defineProperty(prototype[name], '__async_wrapped__', { configurable: false, enumerable: false, writable: false, value: true }) } wrapNativePromiseFunction('then') wrapNativePromiseFunction('catch') wrapNativePromiseFunction('finally') export default Promise