This commit is contained in:
479
node_modules/optimism/lib/bundle.esm.js
generated
vendored
Normal file
479
node_modules/optimism/lib/bundle.esm.js
generated
vendored
Normal file
@@ -0,0 +1,479 @@
|
||||
import { Slot } from '@wry/context';
|
||||
export { asyncFromGen, bind as bindContext, noContext, setTimeout } from '@wry/context';
|
||||
|
||||
function defaultDispose() { }
|
||||
var Cache = /** @class */ (function () {
|
||||
function Cache(max, dispose) {
|
||||
if (max === void 0) { max = Infinity; }
|
||||
if (dispose === void 0) { dispose = defaultDispose; }
|
||||
this.max = max;
|
||||
this.dispose = dispose;
|
||||
this.map = new Map();
|
||||
this.newest = null;
|
||||
this.oldest = null;
|
||||
}
|
||||
Cache.prototype.has = function (key) {
|
||||
return this.map.has(key);
|
||||
};
|
||||
Cache.prototype.get = function (key) {
|
||||
var entry = this.getEntry(key);
|
||||
return entry && entry.value;
|
||||
};
|
||||
Cache.prototype.getEntry = function (key) {
|
||||
var entry = this.map.get(key);
|
||||
if (entry && entry !== this.newest) {
|
||||
var older = entry.older, newer = entry.newer;
|
||||
if (newer) {
|
||||
newer.older = older;
|
||||
}
|
||||
if (older) {
|
||||
older.newer = newer;
|
||||
}
|
||||
entry.older = this.newest;
|
||||
entry.older.newer = entry;
|
||||
entry.newer = null;
|
||||
this.newest = entry;
|
||||
if (entry === this.oldest) {
|
||||
this.oldest = newer;
|
||||
}
|
||||
}
|
||||
return entry;
|
||||
};
|
||||
Cache.prototype.set = function (key, value) {
|
||||
var entry = this.getEntry(key);
|
||||
if (entry) {
|
||||
return entry.value = value;
|
||||
}
|
||||
entry = {
|
||||
key: key,
|
||||
value: value,
|
||||
newer: null,
|
||||
older: this.newest
|
||||
};
|
||||
if (this.newest) {
|
||||
this.newest.newer = entry;
|
||||
}
|
||||
this.newest = entry;
|
||||
this.oldest = this.oldest || entry;
|
||||
this.map.set(key, entry);
|
||||
return entry.value;
|
||||
};
|
||||
Cache.prototype.clean = function () {
|
||||
while (this.oldest && this.map.size > this.max) {
|
||||
this.delete(this.oldest.key);
|
||||
}
|
||||
};
|
||||
Cache.prototype.delete = function (key) {
|
||||
var entry = this.map.get(key);
|
||||
if (entry) {
|
||||
if (entry === this.newest) {
|
||||
this.newest = entry.older;
|
||||
}
|
||||
if (entry === this.oldest) {
|
||||
this.oldest = entry.newer;
|
||||
}
|
||||
if (entry.newer) {
|
||||
entry.newer.older = entry.older;
|
||||
}
|
||||
if (entry.older) {
|
||||
entry.older.newer = entry.newer;
|
||||
}
|
||||
this.map.delete(key);
|
||||
this.dispose(entry.value, key);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
return Cache;
|
||||
}());
|
||||
|
||||
var parentEntrySlot = new Slot();
|
||||
|
||||
var reusableEmptyArray = [];
|
||||
var emptySetPool = [];
|
||||
var POOL_TARGET_SIZE = 100;
|
||||
// Since this package might be used browsers, we should avoid using the
|
||||
// Node built-in assert module.
|
||||
function assert(condition, optionalMessage) {
|
||||
if (!condition) {
|
||||
throw new Error(optionalMessage || "assertion failure");
|
||||
}
|
||||
}
|
||||
function valueIs(a, b) {
|
||||
var len = a.length;
|
||||
return (
|
||||
// Unknown values are not equal to each other.
|
||||
len > 0 &&
|
||||
// Both values must be ordinary (or both exceptional) to be equal.
|
||||
len === b.length &&
|
||||
// The underlying value or exception must be the same.
|
||||
a[len - 1] === b[len - 1]);
|
||||
}
|
||||
function valueGet(value) {
|
||||
switch (value.length) {
|
||||
case 0: throw new Error("unknown value");
|
||||
case 1: return value[0];
|
||||
case 2: throw value[1];
|
||||
}
|
||||
}
|
||||
function valueCopy(value) {
|
||||
return value.slice(0);
|
||||
}
|
||||
var Entry = /** @class */ (function () {
|
||||
function Entry(fn, args) {
|
||||
this.fn = fn;
|
||||
this.args = args;
|
||||
this.parents = new Set();
|
||||
this.childValues = new Map();
|
||||
// When this Entry has children that are dirty, this property becomes
|
||||
// a Set containing other Entry objects, borrowed from emptySetPool.
|
||||
// When the set becomes empty, it gets recycled back to emptySetPool.
|
||||
this.dirtyChildren = null;
|
||||
this.dirty = true;
|
||||
this.recomputing = false;
|
||||
this.value = [];
|
||||
++Entry.count;
|
||||
}
|
||||
// This is the most important method of the Entry API, because it
|
||||
// determines whether the cached this.value can be returned immediately,
|
||||
// or must be recomputed. The overall performance of the caching system
|
||||
// depends on the truth of the following observations: (1) this.dirty is
|
||||
// usually false, (2) this.dirtyChildren is usually null/empty, and thus
|
||||
// (3) valueGet(this.value) is usually returned without recomputation.
|
||||
Entry.prototype.recompute = function () {
|
||||
assert(!this.recomputing, "already recomputing");
|
||||
if (!rememberParent(this) && maybeReportOrphan(this)) {
|
||||
// The recipient of the entry.reportOrphan callback decided to dispose
|
||||
// of this orphan entry by calling entry.dispose(), so we don't need to
|
||||
// (and should not) proceed with the recomputation.
|
||||
return void 0;
|
||||
}
|
||||
return mightBeDirty(this)
|
||||
? reallyRecompute(this)
|
||||
: valueGet(this.value);
|
||||
};
|
||||
Entry.prototype.setDirty = function () {
|
||||
if (this.dirty)
|
||||
return;
|
||||
this.dirty = true;
|
||||
this.value.length = 0;
|
||||
reportDirty(this);
|
||||
// We can go ahead and unsubscribe here, since any further dirty
|
||||
// notifications we receive will be redundant, and unsubscribing may
|
||||
// free up some resources, e.g. file watchers.
|
||||
maybeUnsubscribe(this);
|
||||
};
|
||||
Entry.prototype.dispose = function () {
|
||||
var _this = this;
|
||||
forgetChildren(this).forEach(maybeReportOrphan);
|
||||
maybeUnsubscribe(this);
|
||||
// Because this entry has been kicked out of the cache (in index.js),
|
||||
// we've lost the ability to find out if/when this entry becomes dirty,
|
||||
// whether that happens through a subscription, because of a direct call
|
||||
// to entry.setDirty(), or because one of its children becomes dirty.
|
||||
// Because of this loss of future information, we have to assume the
|
||||
// worst (that this entry might have become dirty very soon), so we must
|
||||
// immediately mark this entry's parents as dirty. Normally we could
|
||||
// just call entry.setDirty() rather than calling parent.setDirty() for
|
||||
// each parent, but that would leave this entry in parent.childValues
|
||||
// and parent.dirtyChildren, which would prevent the child from being
|
||||
// truly forgotten.
|
||||
this.parents.forEach(function (parent) {
|
||||
parent.setDirty();
|
||||
forgetChild(parent, _this);
|
||||
});
|
||||
};
|
||||
Entry.count = 0;
|
||||
return Entry;
|
||||
}());
|
||||
function rememberParent(child) {
|
||||
var parent = parentEntrySlot.getValue();
|
||||
if (parent) {
|
||||
child.parents.add(parent);
|
||||
if (!parent.childValues.has(child)) {
|
||||
parent.childValues.set(child, []);
|
||||
}
|
||||
if (mightBeDirty(child)) {
|
||||
reportDirtyChild(parent, child);
|
||||
}
|
||||
else {
|
||||
reportCleanChild(parent, child);
|
||||
}
|
||||
return parent;
|
||||
}
|
||||
}
|
||||
function reallyRecompute(entry) {
|
||||
// Since this recomputation is likely to re-remember some of this
|
||||
// entry's children, we forget our children here but do not call
|
||||
// maybeReportOrphan until after the recomputation finishes.
|
||||
var originalChildren = forgetChildren(entry);
|
||||
// Set entry as the parent entry while calling recomputeNewValue(entry).
|
||||
parentEntrySlot.withValue(entry, recomputeNewValue, [entry]);
|
||||
if (maybeSubscribe(entry)) {
|
||||
// If we successfully recomputed entry.value and did not fail to
|
||||
// (re)subscribe, then this Entry is no longer explicitly dirty.
|
||||
setClean(entry);
|
||||
}
|
||||
// Now that we've had a chance to re-remember any children that were
|
||||
// involved in the recomputation, we can safely report any orphan
|
||||
// children that remain.
|
||||
originalChildren.forEach(maybeReportOrphan);
|
||||
return valueGet(entry.value);
|
||||
}
|
||||
function recomputeNewValue(entry) {
|
||||
entry.recomputing = true;
|
||||
// Set entry.value as unknown.
|
||||
entry.value.length = 0;
|
||||
try {
|
||||
// If entry.fn succeeds, entry.value will become a normal Value.
|
||||
entry.value[0] = entry.fn.apply(null, entry.args);
|
||||
}
|
||||
catch (e) {
|
||||
// If entry.fn throws, entry.value will become exceptional.
|
||||
entry.value[1] = e;
|
||||
}
|
||||
// Either way, this line is always reached.
|
||||
entry.recomputing = false;
|
||||
}
|
||||
function mightBeDirty(entry) {
|
||||
return entry.dirty || !!(entry.dirtyChildren && entry.dirtyChildren.size);
|
||||
}
|
||||
function setClean(entry) {
|
||||
entry.dirty = false;
|
||||
if (mightBeDirty(entry)) {
|
||||
// This Entry may still have dirty children, in which case we can't
|
||||
// let our parents know we're clean just yet.
|
||||
return;
|
||||
}
|
||||
reportClean(entry);
|
||||
}
|
||||
function reportDirty(child) {
|
||||
child.parents.forEach(function (parent) { return reportDirtyChild(parent, child); });
|
||||
}
|
||||
function reportClean(child) {
|
||||
child.parents.forEach(function (parent) { return reportCleanChild(parent, child); });
|
||||
}
|
||||
// Let a parent Entry know that one of its children may be dirty.
|
||||
function reportDirtyChild(parent, child) {
|
||||
// Must have called rememberParent(child) before calling
|
||||
// reportDirtyChild(parent, child).
|
||||
assert(parent.childValues.has(child));
|
||||
assert(mightBeDirty(child));
|
||||
if (!parent.dirtyChildren) {
|
||||
parent.dirtyChildren = emptySetPool.pop() || new Set;
|
||||
}
|
||||
else if (parent.dirtyChildren.has(child)) {
|
||||
// If we already know this child is dirty, then we must have already
|
||||
// informed our own parents that we are dirty, so we can terminate
|
||||
// the recursion early.
|
||||
return;
|
||||
}
|
||||
parent.dirtyChildren.add(child);
|
||||
reportDirty(parent);
|
||||
}
|
||||
// Let a parent Entry know that one of its children is no longer dirty.
|
||||
function reportCleanChild(parent, child) {
|
||||
// Must have called rememberChild(child) before calling
|
||||
// reportCleanChild(parent, child).
|
||||
assert(parent.childValues.has(child));
|
||||
assert(!mightBeDirty(child));
|
||||
var childValue = parent.childValues.get(child);
|
||||
if (childValue.length === 0) {
|
||||
parent.childValues.set(child, valueCopy(child.value));
|
||||
}
|
||||
else if (!valueIs(childValue, child.value)) {
|
||||
parent.setDirty();
|
||||
}
|
||||
removeDirtyChild(parent, child);
|
||||
if (mightBeDirty(parent)) {
|
||||
return;
|
||||
}
|
||||
reportClean(parent);
|
||||
}
|
||||
function removeDirtyChild(parent, child) {
|
||||
var dc = parent.dirtyChildren;
|
||||
if (dc) {
|
||||
dc.delete(child);
|
||||
if (dc.size === 0) {
|
||||
if (emptySetPool.length < POOL_TARGET_SIZE) {
|
||||
emptySetPool.push(dc);
|
||||
}
|
||||
parent.dirtyChildren = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
// If the given entry has a reportOrphan method, and no remaining parents,
|
||||
// call entry.reportOrphan and return true iff it returns true. The
|
||||
// reportOrphan function should return true to indicate entry.dispose()
|
||||
// has been called, and the entry has been removed from any other caches
|
||||
// (see index.js for the only current example).
|
||||
function maybeReportOrphan(entry) {
|
||||
return entry.parents.size === 0 &&
|
||||
typeof entry.reportOrphan === "function" &&
|
||||
entry.reportOrphan() === true;
|
||||
}
|
||||
// Removes all children from this entry and returns an array of the
|
||||
// removed children.
|
||||
function forgetChildren(parent) {
|
||||
var children = reusableEmptyArray;
|
||||
if (parent.childValues.size > 0) {
|
||||
children = [];
|
||||
parent.childValues.forEach(function (_value, child) {
|
||||
forgetChild(parent, child);
|
||||
children.push(child);
|
||||
});
|
||||
}
|
||||
// After we forget all our children, this.dirtyChildren must be empty
|
||||
// and therefore must have been reset to null.
|
||||
assert(parent.dirtyChildren === null);
|
||||
return children;
|
||||
}
|
||||
function forgetChild(parent, child) {
|
||||
child.parents.delete(parent);
|
||||
parent.childValues.delete(child);
|
||||
removeDirtyChild(parent, child);
|
||||
}
|
||||
function maybeSubscribe(entry) {
|
||||
if (typeof entry.subscribe === "function") {
|
||||
try {
|
||||
maybeUnsubscribe(entry); // Prevent double subscriptions.
|
||||
entry.unsubscribe = entry.subscribe.apply(null, entry.args);
|
||||
}
|
||||
catch (e) {
|
||||
// If this Entry has a subscribe function and it threw an exception
|
||||
// (or an unsubscribe function it previously returned now throws),
|
||||
// return false to indicate that we were not able to subscribe (or
|
||||
// unsubscribe), and this Entry should remain dirty.
|
||||
entry.setDirty();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
// Returning true indicates either that there was no entry.subscribe
|
||||
// function or that it succeeded.
|
||||
return true;
|
||||
}
|
||||
function maybeUnsubscribe(entry) {
|
||||
var unsubscribe = entry.unsubscribe;
|
||||
if (typeof unsubscribe === "function") {
|
||||
entry.unsubscribe = void 0;
|
||||
unsubscribe();
|
||||
}
|
||||
}
|
||||
|
||||
// A trie data structure that holds object keys weakly, yet can also hold
|
||||
// non-object keys, unlike the native `WeakMap`.
|
||||
var KeyTrie = /** @class */ (function () {
|
||||
function KeyTrie(weakness) {
|
||||
this.weakness = weakness;
|
||||
}
|
||||
KeyTrie.prototype.lookup = function () {
|
||||
var array = [];
|
||||
for (var _i = 0; _i < arguments.length; _i++) {
|
||||
array[_i] = arguments[_i];
|
||||
}
|
||||
return this.lookupArray(array);
|
||||
};
|
||||
KeyTrie.prototype.lookupArray = function (array) {
|
||||
var node = this;
|
||||
array.forEach(function (key) { return node = node.getChildTrie(key); });
|
||||
return node.data || (node.data = Object.create(null));
|
||||
};
|
||||
KeyTrie.prototype.getChildTrie = function (key) {
|
||||
var map = this.weakness && isObjRef(key)
|
||||
? this.weak || (this.weak = new WeakMap())
|
||||
: this.strong || (this.strong = new Map());
|
||||
var child = map.get(key);
|
||||
if (!child)
|
||||
map.set(key, child = new KeyTrie(this.weakness));
|
||||
return child;
|
||||
};
|
||||
return KeyTrie;
|
||||
}());
|
||||
function isObjRef(value) {
|
||||
switch (typeof value) {
|
||||
case "object":
|
||||
if (value === null)
|
||||
break;
|
||||
// Fall through to return true...
|
||||
case "function":
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// The defaultMakeCacheKey function is remarkably powerful, because it gives
|
||||
// a unique object for any shallow-identical list of arguments. If you need
|
||||
// to implement a custom makeCacheKey function, you may find it helpful to
|
||||
// delegate the final work to defaultMakeCacheKey, which is why we export it
|
||||
// here. However, you may want to avoid defaultMakeCacheKey if your runtime
|
||||
// does not support WeakMap, or you have the ability to return a string key.
|
||||
// In those cases, just write your own custom makeCacheKey functions.
|
||||
var keyTrie = new KeyTrie(typeof WeakMap === "function");
|
||||
function defaultMakeCacheKey() {
|
||||
var args = [];
|
||||
for (var _i = 0; _i < arguments.length; _i++) {
|
||||
args[_i] = arguments[_i];
|
||||
}
|
||||
return keyTrie.lookupArray(args);
|
||||
}
|
||||
var caches = new Set();
|
||||
function wrap(originalFunction, options) {
|
||||
if (options === void 0) { options = Object.create(null); }
|
||||
var cache = new Cache(options.max || Math.pow(2, 16), function (entry) { return entry.dispose(); });
|
||||
var disposable = !!options.disposable;
|
||||
var makeCacheKey = options.makeCacheKey || defaultMakeCacheKey;
|
||||
function optimistic() {
|
||||
if (disposable && !parentEntrySlot.hasValue()) {
|
||||
// If there's no current parent computation, and this wrapped
|
||||
// function is disposable (meaning we don't care about entry.value,
|
||||
// just dependency tracking), then we can short-cut everything else
|
||||
// in this function, because entry.recompute() is going to recycle
|
||||
// the entry object without recomputing anything, anyway.
|
||||
return void 0;
|
||||
}
|
||||
var key = makeCacheKey.apply(null, arguments);
|
||||
if (key === void 0) {
|
||||
return originalFunction.apply(null, arguments);
|
||||
}
|
||||
var args = Array.prototype.slice.call(arguments);
|
||||
var entry = cache.get(key);
|
||||
if (entry) {
|
||||
entry.args = args;
|
||||
}
|
||||
else {
|
||||
entry = new Entry(originalFunction, args);
|
||||
cache.set(key, entry);
|
||||
entry.subscribe = options.subscribe;
|
||||
if (disposable) {
|
||||
entry.reportOrphan = function () { return cache.delete(key); };
|
||||
}
|
||||
}
|
||||
var value = entry.recompute();
|
||||
// Move this entry to the front of the least-recently used queue,
|
||||
// since we just finished computing its value.
|
||||
cache.set(key, entry);
|
||||
caches.add(cache);
|
||||
// Clean up any excess entries in the cache, but only if there is no
|
||||
// active parent entry, meaning we're not in the middle of a larger
|
||||
// computation that might be flummoxed by the cleaning.
|
||||
if (!parentEntrySlot.hasValue()) {
|
||||
caches.forEach(function (cache) { return cache.clean(); });
|
||||
caches.clear();
|
||||
}
|
||||
// If options.disposable is truthy, the caller of wrap is telling us
|
||||
// they don't care about the result of entry.recompute(), so we should
|
||||
// avoid returning the value, so it won't be accidentally used.
|
||||
return disposable ? void 0 : value;
|
||||
}
|
||||
optimistic.dirty = function () {
|
||||
var key = makeCacheKey.apply(null, arguments);
|
||||
var child = key !== void 0 && cache.get(key);
|
||||
if (child) {
|
||||
child.setDirty();
|
||||
}
|
||||
};
|
||||
return optimistic;
|
||||
}
|
||||
|
||||
export { KeyTrie, defaultMakeCacheKey, wrap };
|
||||
//# sourceMappingURL=bundle.esm.js.map
|
||||
Reference in New Issue
Block a user