UNPKG

@modern-js/runtime-utils

Version:

A Progressive React Framework for modern web development.

166 lines (165 loc) • 5.45 kB
"use strict"; var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __hasOwnProp = Object.prototype.hasOwnProperty; var __export = (target, all) => { for (var name in all) __defProp(target, name, { get: all[name], enumerable: true }); }; var __copyProps = (to, from, except, desc) => { if (from && typeof from === "object" || typeof from === "function") { for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); } return to; }; var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); var deferreds_exports = {}; __export(deferreds_exports, { AbortedDeferredError: () => AbortedDeferredError, DeferredData: () => DeferredData, activeDeferreds: () => activeDeferreds, invariant: () => invariant }); module.exports = __toCommonJS(deferreds_exports); function invariant(value, message) { if (value === false || value === null || typeof value === "undefined") { throw new Error(message); } } class AbortedDeferredError extends Error { } function isTrackedPromise(value) { return value instanceof Promise && value._tracked === true; } function unwrapTrackedPromise(value) { if (!isTrackedPromise(value)) { return value; } if (value._error) { throw value._error; } return value._data; } class DeferredData { trackPromise(key, value) { if (!(value instanceof Promise)) { return value; } this.deferredKeys.push(key); this.pendingKeysSet.add(key); const promise = Promise.race([ value, this.abortPromise ]).then((data) => this.onSettle(promise, key, void 0, data), (error) => this.onSettle(promise, key, error)); promise.catch(() => { }); Object.defineProperty(promise, "_tracked", { get: () => true }); return promise; } onSettle(promise, key, error, data) { if (this.controller.signal.aborted && error instanceof AbortedDeferredError) { this.unlistenAbortSignal(); Object.defineProperty(promise, "_error", { get: () => error }); return Promise.reject(error); } this.pendingKeysSet.delete(key); if (this.done) { this.unlistenAbortSignal(); } if (error === void 0 && data === void 0) { const undefinedError = new Error(`Deferred data for key "${key}" resolved/rejected with \`undefined\`, you must resolve/reject with a value or \`null\`.`); Object.defineProperty(promise, "_error", { get: () => undefinedError }); this.emit(false, key); return Promise.reject(undefinedError); } if (data === void 0) { Object.defineProperty(promise, "_error", { get: () => error }); this.emit(false, key); return Promise.reject(error); } Object.defineProperty(promise, "_data", { get: () => data }); this.emit(false, key); return data; } emit(aborted, settledKey) { this.subscribers.forEach((subscriber) => subscriber(aborted, settledKey)); } subscribe(fn) { this.subscribers.add(fn); return () => this.subscribers.delete(fn); } cancel() { this.controller.abort(); this.pendingKeysSet.forEach((v, k) => this.pendingKeysSet.delete(k)); this.emit(true); } async resolveData(signal) { let aborted = false; if (!this.done) { const onAbort = () => this.cancel(); signal.addEventListener("abort", onAbort); aborted = await new Promise((resolve) => { this.subscribe((aborted2) => { signal.removeEventListener("abort", onAbort); if (aborted2 || this.done) { resolve(aborted2); } }); }); } return aborted; } get done() { return this.pendingKeysSet.size === 0; } get unwrappedData() { invariant(this.data !== null && this.done, "Can only unwrap data on initialized and settled deferreds"); return Object.entries(this.data).reduce((acc, [key, value]) => Object.assign(acc, { [key]: unwrapTrackedPromise(value) }), {}); } get pendingKeys() { return Array.from(this.pendingKeysSet); } constructor(data, responseInit) { this.pendingKeysSet = /* @__PURE__ */ new Set(); this.subscribers = /* @__PURE__ */ new Set(); this.__modern_deferred = true; this.deferredKeys = []; invariant(data && typeof data === "object" && !Array.isArray(data), "defer() only accepts plain objects"); let reject; this.abortPromise = new Promise((_, r) => reject = r); this.controller = new AbortController(); const onAbort = () => reject(new AbortedDeferredError("Deferred data aborted")); this.unlistenAbortSignal = () => this.controller.signal.removeEventListener("abort", onAbort); this.controller.signal.addEventListener("abort", onAbort); this.data = Object.entries(data).reduce((acc, [key, value]) => Object.assign(acc, { [key]: this.trackPromise(key, value) }), {}); if (this.done) { this.unlistenAbortSignal(); } this.init = responseInit; } } const activeDeferreds = /* @__PURE__ */ new Map(); // Annotate the CommonJS export names for ESM import in node: 0 && (module.exports = { AbortedDeferredError, DeferredData, activeDeferreds, invariant });