ludus/out/goog/promise/promise.js
2023-11-16 13:22:15 -05:00

543 lines
18 KiB
JavaScript

/*TRANSPILED*//*
Copyright The Closure Library Authors.
SPDX-License-Identifier: Apache-2.0
*/
'use strict';
goog.provide("goog.Promise");
goog.require("goog.Thenable");
goog.require("goog.asserts");
goog.require("goog.async.FreeList");
goog.require("goog.async.run");
goog.require("goog.async.throwException");
goog.require("goog.debug.Error");
goog.require("goog.debug.asyncStackTag");
goog.require("goog.functions");
goog.require("goog.promise.Resolver");
goog.Promise = function(resolver, opt_context) {
this.state_ = goog.Promise.State_.PENDING;
this.result_ = undefined;
this.parent_ = null;
this.callbackEntries_ = null;
this.callbackEntriesTail_ = null;
this.executing_ = false;
if (goog.Promise.UNHANDLED_REJECTION_DELAY > 0) {
this.unhandledRejectionId_ = 0;
} else if (goog.Promise.UNHANDLED_REJECTION_DELAY == 0) {
this.hadUnhandledRejection_ = false;
}
if (goog.Promise.LONG_STACK_TRACES) {
this.stack_ = [];
this.addStackTrace_(new Error("created"));
this.currentStep_ = 0;
}
if (resolver != goog.functions.UNDEFINED) {
try {
var self = this;
resolver.call(opt_context, function(value) {
self.resolve_(goog.Promise.State_.FULFILLED, value);
}, function(reason) {
if (goog.DEBUG && !(reason instanceof goog.Promise.CancellationError)) {
try {
if (reason instanceof Error) {
throw reason;
} else {
throw new Error("Promise rejected.");
}
} catch (e) {
}
}
self.resolve_(goog.Promise.State_.REJECTED, reason);
});
} catch (e) {
this.resolve_(goog.Promise.State_.REJECTED, e);
}
}
};
goog.Promise.LONG_STACK_TRACES = goog.define("goog.Promise.LONG_STACK_TRACES", false);
goog.Promise.UNHANDLED_REJECTION_DELAY = goog.define("goog.Promise.UNHANDLED_REJECTION_DELAY", 0);
goog.Promise.State_ = {PENDING:0, BLOCKED:1, FULFILLED:2, REJECTED:3};
goog.Promise.CallbackEntry_ = function() {
this.child = null;
this.onFulfilled = null;
this.onRejected = null;
this.context = null;
this.next = null;
this.always = false;
};
goog.Promise.CallbackEntry_.prototype.reset = function() {
this.child = null;
this.onFulfilled = null;
this.onRejected = null;
this.context = null;
this.always = false;
};
goog.Promise.DEFAULT_MAX_UNUSED = goog.define("goog.Promise.DEFAULT_MAX_UNUSED", 100);
goog.Promise.freelist_ = new goog.async.FreeList(function() {
return new goog.Promise.CallbackEntry_();
}, function(item) {
item.reset();
}, goog.Promise.DEFAULT_MAX_UNUSED);
goog.Promise.getCallbackEntry_ = function(onFulfilled, onRejected, context) {
var entry = goog.Promise.freelist_.get();
entry.onFulfilled = onFulfilled;
entry.onRejected = onRejected;
entry.context = context;
return entry;
};
goog.Promise.returnEntry_ = function(entry) {
goog.Promise.freelist_.put(entry);
};
goog.Promise.resolve = function(opt_value) {
if (opt_value instanceof goog.Promise) {
return opt_value;
}
var promise = new goog.Promise(goog.functions.UNDEFINED);
promise.resolve_(goog.Promise.State_.FULFILLED, opt_value);
return promise;
};
goog.Promise.reject = function(opt_reason) {
return new goog.Promise(function(resolve, reject) {
reject(opt_reason);
});
};
goog.Promise.resolveThen_ = function(value, onFulfilled, onRejected) {
var isThenable = goog.Promise.maybeThen_(value, onFulfilled, onRejected, null);
if (!isThenable) {
goog.async.run(goog.partial(onFulfilled, value));
}
};
goog.Promise.race = function(promises) {
return new goog.Promise(function(resolve, reject) {
if (!promises.length) {
resolve(undefined);
}
for (var i = 0, promise; i < promises.length; i++) {
promise = promises[i];
goog.Promise.resolveThen_(promise, resolve, reject);
}
});
};
goog.Promise.all = function(promises) {
return new goog.Promise(function(resolve, reject) {
var toFulfill = promises.length;
var values = [];
if (!toFulfill) {
resolve(values);
return;
}
var onFulfill = function(index, value) {
toFulfill--;
values[index] = value;
if (toFulfill == 0) {
resolve(values);
}
};
var onReject = function(reason) {
reject(reason);
};
for (var i = 0, promise; i < promises.length; i++) {
promise = promises[i];
goog.Promise.resolveThen_(promise, goog.partial(onFulfill, i), onReject);
}
});
};
goog.Promise.allSettled = function(promises) {
return new goog.Promise(function(resolve, reject) {
var toSettle = promises.length;
var results = [];
if (!toSettle) {
resolve(results);
return;
}
var onSettled = function(index, fulfilled, result) {
toSettle--;
results[index] = fulfilled ? {fulfilled:true, value:result} : {fulfilled:false, reason:result};
if (toSettle == 0) {
resolve(results);
}
};
for (var i = 0, promise; i < promises.length; i++) {
promise = promises[i];
goog.Promise.resolveThen_(promise, goog.partial(onSettled, i, true), goog.partial(onSettled, i, false));
}
});
};
goog.Promise.firstFulfilled = function(promises) {
return new goog.Promise(function(resolve, reject) {
var toReject = promises.length;
var reasons = [];
if (!toReject) {
resolve(undefined);
return;
}
var onFulfill = function(value) {
resolve(value);
};
var onReject = function(index, reason) {
toReject--;
reasons[index] = reason;
if (toReject == 0) {
reject(reasons);
}
};
for (var i = 0, promise; i < promises.length; i++) {
promise = promises[i];
goog.Promise.resolveThen_(promise, onFulfill, goog.partial(onReject, i));
}
});
};
goog.Promise.withResolver = function() {
var resolve, reject;
var promise = new goog.Promise(function(rs, rj) {
resolve = rs;
reject = rj;
});
return new goog.Promise.Resolver_(promise, resolve, reject);
};
goog.Promise.prototype.then = function(opt_onFulfilled, opt_onRejected, opt_context) {
if (opt_onFulfilled != null) {
goog.asserts.assertFunction(opt_onFulfilled, "opt_onFulfilled should be a function.");
}
if (opt_onRejected != null) {
goog.asserts.assertFunction(opt_onRejected, "opt_onRejected should be a function. Did you pass opt_context " + "as the second argument instead of the third?");
}
if (goog.Promise.LONG_STACK_TRACES) {
this.addStackTrace_(new Error("then"));
}
return this.addChildPromise_(typeof opt_onFulfilled === "function" ? opt_onFulfilled : null, typeof opt_onRejected === "function" ? opt_onRejected : null, opt_context);
};
goog.Thenable.addImplementation(goog.Promise);
goog.Promise.prototype.thenVoid = function(opt_onFulfilled, opt_onRejected, opt_context) {
if (opt_onFulfilled != null) {
goog.asserts.assertFunction(opt_onFulfilled, "opt_onFulfilled should be a function.");
}
if (opt_onRejected != null) {
goog.asserts.assertFunction(opt_onRejected, "opt_onRejected should be a function. Did you pass opt_context " + "as the second argument instead of the third?");
}
if (goog.Promise.LONG_STACK_TRACES) {
this.addStackTrace_(new Error("then"));
}
this.addCallbackEntry_(goog.Promise.getCallbackEntry_(opt_onFulfilled || goog.functions.UNDEFINED, opt_onRejected || null, opt_context));
};
goog.Promise.prototype.thenAlways = function(onSettled, opt_context) {
if (goog.Promise.LONG_STACK_TRACES) {
this.addStackTrace_(new Error("thenAlways"));
}
var entry = goog.Promise.getCallbackEntry_(onSettled, onSettled, opt_context);
entry.always = true;
this.addCallbackEntry_(entry);
return this;
};
goog.Promise.prototype.thenCatch = function(onRejected, opt_context) {
if (goog.Promise.LONG_STACK_TRACES) {
this.addStackTrace_(new Error("thenCatch"));
}
return this.addChildPromise_(null, onRejected, opt_context);
};
goog.Promise.prototype["catch"] = goog.Promise.prototype.thenCatch;
goog.Promise.prototype.cancel = function(opt_message) {
if (this.state_ == goog.Promise.State_.PENDING) {
var err = new goog.Promise.CancellationError(opt_message);
goog.async.run(function() {
this.cancelInternal_(err);
}, this);
}
};
goog.Promise.prototype.cancelInternal_ = function(err) {
if (this.state_ == goog.Promise.State_.PENDING) {
if (this.parent_) {
this.parent_.cancelChild_(this, err);
this.parent_ = null;
} else {
this.resolve_(goog.Promise.State_.REJECTED, err);
}
}
};
goog.Promise.prototype.cancelChild_ = function(childPromise, err) {
if (!this.callbackEntries_) {
return;
}
var childCount = 0;
var childEntry = null;
var beforeChildEntry = null;
for (var entry = this.callbackEntries_; entry; entry = entry.next) {
if (!entry.always) {
childCount++;
if (entry.child == childPromise) {
childEntry = entry;
}
if (childEntry && childCount > 1) {
break;
}
}
if (!childEntry) {
beforeChildEntry = entry;
}
}
if (childEntry) {
if (this.state_ == goog.Promise.State_.PENDING && childCount == 1) {
this.cancelInternal_(err);
} else {
if (beforeChildEntry) {
this.removeEntryAfter_(beforeChildEntry);
} else {
this.popEntry_();
}
this.executeCallback_(childEntry, goog.Promise.State_.REJECTED, err);
}
}
};
goog.Promise.prototype.addCallbackEntry_ = function(callbackEntry) {
if (!this.hasEntry_() && (this.state_ == goog.Promise.State_.FULFILLED || this.state_ == goog.Promise.State_.REJECTED)) {
this.scheduleCallbacks_();
}
this.queueEntry_(callbackEntry);
};
goog.Promise.prototype.addChildPromise_ = function(onFulfilled, onRejected, opt_context) {
if (onFulfilled) {
onFulfilled = goog.debug.asyncStackTag.wrap(onFulfilled, "goog.Promise.then");
}
if (onRejected) {
onRejected = goog.debug.asyncStackTag.wrap(onRejected, "goog.Promise.then");
}
var callbackEntry = goog.Promise.getCallbackEntry_(null, null, null);
callbackEntry.child = new goog.Promise(function(resolve, reject) {
callbackEntry.onFulfilled = onFulfilled ? function(value) {
try {
var result = onFulfilled.call(opt_context, value);
resolve(result);
} catch (err) {
reject(err);
}
} : resolve;
callbackEntry.onRejected = onRejected ? function(reason) {
try {
var result = onRejected.call(opt_context, reason);
if (result === undefined && reason instanceof goog.Promise.CancellationError) {
reject(reason);
} else {
resolve(result);
}
} catch (err) {
reject(err);
}
} : reject;
});
callbackEntry.child.parent_ = this;
this.addCallbackEntry_(callbackEntry);
return callbackEntry.child;
};
goog.Promise.prototype.unblockAndFulfill_ = function(value) {
goog.asserts.assert(this.state_ == goog.Promise.State_.BLOCKED);
this.state_ = goog.Promise.State_.PENDING;
this.resolve_(goog.Promise.State_.FULFILLED, value);
};
goog.Promise.prototype.unblockAndReject_ = function(reason) {
goog.asserts.assert(this.state_ == goog.Promise.State_.BLOCKED);
this.state_ = goog.Promise.State_.PENDING;
this.resolve_(goog.Promise.State_.REJECTED, reason);
};
goog.Promise.prototype.resolve_ = function(state, x) {
if (this.state_ != goog.Promise.State_.PENDING) {
return;
}
if (this === x) {
state = goog.Promise.State_.REJECTED;
x = new TypeError("Promise cannot resolve to itself");
}
this.state_ = goog.Promise.State_.BLOCKED;
var isThenable = goog.Promise.maybeThen_(x, this.unblockAndFulfill_, this.unblockAndReject_, this);
if (isThenable) {
return;
}
this.result_ = x;
this.state_ = state;
this.parent_ = null;
this.scheduleCallbacks_();
if (state == goog.Promise.State_.REJECTED && !(x instanceof goog.Promise.CancellationError)) {
goog.Promise.addUnhandledRejection_(this, x);
}
};
goog.Promise.maybeThen_ = function(value, onFulfilled, onRejected, context) {
if (value instanceof goog.Promise) {
value.thenVoid(onFulfilled, onRejected, context);
return true;
} else if (goog.Thenable.isImplementedBy(value)) {
value = value;
value.then(onFulfilled, onRejected, context);
return true;
} else if (goog.isObject(value)) {
const thenable = value;
try {
var then = thenable.then;
if (typeof then === "function") {
goog.Promise.tryThen_(thenable, then, onFulfilled, onRejected, context);
return true;
}
} catch (e) {
onRejected.call(context, e);
return true;
}
}
return false;
};
goog.Promise.tryThen_ = function(thenable, then, onFulfilled, onRejected, context) {
var called = false;
var resolve = function(value) {
if (!called) {
called = true;
onFulfilled.call(context, value);
}
};
var reject = function(reason) {
if (!called) {
called = true;
onRejected.call(context, reason);
}
};
try {
then.call(thenable, resolve, reject);
} catch (e) {
reject(e);
}
};
goog.Promise.prototype.scheduleCallbacks_ = function() {
if (!this.executing_) {
this.executing_ = true;
goog.async.run(this.executeCallbacks_, this);
}
};
goog.Promise.prototype.hasEntry_ = function() {
return !!this.callbackEntries_;
};
goog.Promise.prototype.queueEntry_ = function(entry) {
goog.asserts.assert(entry.onFulfilled != null);
if (this.callbackEntriesTail_) {
this.callbackEntriesTail_.next = entry;
this.callbackEntriesTail_ = entry;
} else {
this.callbackEntries_ = entry;
this.callbackEntriesTail_ = entry;
}
};
goog.Promise.prototype.popEntry_ = function() {
var entry = null;
if (this.callbackEntries_) {
entry = this.callbackEntries_;
this.callbackEntries_ = entry.next;
entry.next = null;
}
if (!this.callbackEntries_) {
this.callbackEntriesTail_ = null;
}
if (entry != null) {
goog.asserts.assert(entry.onFulfilled != null);
}
return entry;
};
goog.Promise.prototype.removeEntryAfter_ = function(previous) {
goog.asserts.assert(this.callbackEntries_);
goog.asserts.assert(previous != null);
if (previous.next == this.callbackEntriesTail_) {
this.callbackEntriesTail_ = previous;
}
previous.next = previous.next.next;
};
goog.Promise.prototype.executeCallbacks_ = function() {
var entry = null;
while (entry = this.popEntry_()) {
if (goog.Promise.LONG_STACK_TRACES) {
this.currentStep_++;
}
this.executeCallback_(entry, this.state_, this.result_);
}
this.executing_ = false;
};
goog.Promise.prototype.executeCallback_ = function(callbackEntry, state, result) {
if (state == goog.Promise.State_.REJECTED && callbackEntry.onRejected && !callbackEntry.always) {
this.removeUnhandledRejection_();
}
if (callbackEntry.child) {
callbackEntry.child.parent_ = null;
goog.Promise.invokeCallback_(callbackEntry, state, result);
} else {
try {
callbackEntry.always ? callbackEntry.onFulfilled.call(callbackEntry.context) : goog.Promise.invokeCallback_(callbackEntry, state, result);
} catch (err) {
goog.Promise.handleRejection_.call(null, err);
}
}
goog.Promise.returnEntry_(callbackEntry);
};
goog.Promise.invokeCallback_ = function(callbackEntry, state, result) {
if (state == goog.Promise.State_.FULFILLED) {
callbackEntry.onFulfilled.call(callbackEntry.context, result);
} else if (callbackEntry.onRejected) {
callbackEntry.onRejected.call(callbackEntry.context, result);
}
};
goog.Promise.prototype.addStackTrace_ = function(err) {
if (goog.Promise.LONG_STACK_TRACES && typeof err.stack === "string") {
var trace = err.stack.split("\n", 4)[3];
var message = err.message;
message += Array(11 - message.length).join(" ");
this.stack_.push(message + trace);
}
};
goog.Promise.prototype.appendLongStack_ = function(err) {
if (goog.Promise.LONG_STACK_TRACES && err && typeof err.stack === "string" && this.stack_.length) {
var longTrace = ["Promise trace:"];
for (var promise = this; promise; promise = promise.parent_) {
for (var i = this.currentStep_; i >= 0; i--) {
longTrace.push(promise.stack_[i]);
}
longTrace.push("Value: " + "[" + (promise.state_ == goog.Promise.State_.REJECTED ? "REJECTED" : "FULFILLED") + "] " + "\x3c" + String(promise.result_) + "\x3e");
}
err.stack += "\n\n" + longTrace.join("\n");
}
};
goog.Promise.prototype.removeUnhandledRejection_ = function() {
if (goog.Promise.UNHANDLED_REJECTION_DELAY > 0) {
for (var p = this; p && p.unhandledRejectionId_; p = p.parent_) {
goog.global.clearTimeout(p.unhandledRejectionId_);
p.unhandledRejectionId_ = 0;
}
} else if (goog.Promise.UNHANDLED_REJECTION_DELAY == 0) {
for (var p = this; p && p.hadUnhandledRejection_; p = p.parent_) {
p.hadUnhandledRejection_ = false;
}
}
};
goog.Promise.addUnhandledRejection_ = function(promise, reason) {
if (goog.Promise.UNHANDLED_REJECTION_DELAY > 0) {
promise.unhandledRejectionId_ = goog.global.setTimeout(function() {
promise.appendLongStack_(reason);
goog.Promise.handleRejection_.call(null, reason);
}, goog.Promise.UNHANDLED_REJECTION_DELAY);
} else if (goog.Promise.UNHANDLED_REJECTION_DELAY == 0) {
promise.hadUnhandledRejection_ = true;
goog.async.run(function() {
if (promise.hadUnhandledRejection_) {
promise.appendLongStack_(reason);
goog.Promise.handleRejection_.call(null, reason);
}
});
}
};
goog.Promise.handleRejection_ = goog.async.throwException;
goog.Promise.setUnhandledRejectionHandler = function(handler) {
goog.Promise.handleRejection_ = handler;
};
goog.Promise.CancellationError = function(opt_message) {
goog.Promise.CancellationError.base(this, "constructor", opt_message);
this.reportErrorToServer = false;
};
goog.inherits(goog.Promise.CancellationError, goog.debug.Error);
goog.Promise.CancellationError.prototype.name = "cancel";
goog.Promise.Resolver_ = function(promise, resolve, reject) {
this.promise = promise;
this.resolve = resolve;
this.reject = reject;
};