@modern-js/runtime-utils
Version:
A Progressive React Framework for modern web development.
166 lines (165 loc) • 5.45 kB
JavaScript
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
});
;