Comparing version 0.8.3 to 0.9.0
@@ -87,28 +87,77 @@ function defaultDispose() { } | ||
var localKey = "_optimism_local"; | ||
var fakeNullFiber = new (/** @class */ (function () { | ||
function Fiber() { | ||
} | ||
return Fiber; | ||
}())); | ||
var getCurrentFiber = function () { return fakeNullFiber; }; | ||
if (typeof module === "object") { | ||
var currentContext = null; | ||
function getParentEntry() { | ||
return currentContext && currentContext.entry; | ||
} | ||
function withEntry(callback, entry) { | ||
var parent = currentContext; | ||
currentContext = { parent: parent, entry: entry }; | ||
try { | ||
var Fiber_1 = module["eriuqer".split("").reverse().join("")]("fibers"); | ||
// If we were able to require fibers, redefine the getCurrentFiber | ||
// function so that it has a chance to return Fiber.current. | ||
getCurrentFiber = function () { return Fiber_1.current || fakeNullFiber; }; | ||
return callback(); | ||
} | ||
catch (e) { } | ||
finally { | ||
currentContext = parent; | ||
} | ||
} | ||
// Returns an object unique to Fiber.current, if fibers are enabled. | ||
// This object is used for Fiber-local storage in ./entry.js. | ||
function get() { | ||
var fiber = getCurrentFiber(); | ||
return fiber[localKey] || (fiber[localKey] = Object.create(null)); | ||
// Immediately run a callback function without any captured context. | ||
function noContext(callback) { | ||
return withEntry(callback, null); | ||
} | ||
// Capture the current context and wrap a callback function so that it | ||
// reestablishes the captured context when called. | ||
function bindContext(callback) { | ||
var context = currentContext; | ||
return function () { | ||
var saved = currentContext; | ||
try { | ||
currentContext = context; | ||
return callback.apply(this, arguments); | ||
} | ||
finally { | ||
currentContext = saved; | ||
} | ||
}; | ||
} | ||
function setTimeoutWithContext(callback, delay) { | ||
return setTimeout(bindContext(callback), delay); | ||
} | ||
function isPromiseLike(value) { | ||
return value && typeof value.then === "function"; | ||
} | ||
// Turn any generator function into an async function (using yield instead | ||
// of await), with context automatically preserved across yields. | ||
function asyncFromGen(genFn) { | ||
return function () { | ||
var context = currentContext; | ||
var gen = genFn.apply(this, arguments); | ||
return new Promise(function (resolve, reject) { | ||
function pump(valueToSend) { | ||
var saved = currentContext; | ||
var result; | ||
try { | ||
currentContext = context; | ||
result = gen.next(valueToSend); | ||
currentContext = saved; | ||
} | ||
catch (error) { | ||
currentContext = saved; | ||
return reject(error); | ||
} | ||
var next = result.done ? resolve : pump; | ||
if (isPromiseLike(result.value)) { | ||
result.value.then(next, reject); | ||
} | ||
else { | ||
next(result.value); | ||
} | ||
} | ||
pump(); | ||
}); | ||
}; | ||
} | ||
var UNKNOWN_VALUE = Object.create(null); | ||
var reusableEmptyArray = []; | ||
var emptySetPool = []; | ||
var reusableEmptyArray = []; | ||
var POOL_TARGET_SIZE = 100; | ||
// Since this package might be used browsers, we should avoid using the | ||
@@ -145,5 +194,2 @@ // Node built-in assert module. | ||
}; | ||
Entry.prototype.isOrphan = function () { | ||
return this.parents.size === 0; | ||
}; | ||
Entry.prototype.setDirty = function () { | ||
@@ -181,8 +227,6 @@ if (this.dirty) | ||
Entry.count = 0; | ||
Entry.POOL_TARGET_SIZE = 100; | ||
return Entry; | ||
}()); | ||
function rememberParent(child) { | ||
var local = get(); | ||
var parent = local.currentParentEntry; | ||
var parent = getParentEntry(); | ||
if (parent) { | ||
@@ -242,8 +286,7 @@ child.parents.add(parent); | ||
var originalChildren = forgetChildren(entry); | ||
var local = get(); | ||
var parent = local.currentParentEntry; | ||
local.currentParentEntry = entry; | ||
var threw = true; | ||
try { | ||
entry.value = entry.fn.apply(null, entry.args); | ||
withEntry(function () { | ||
entry.value = entry.fn.apply(null, entry.args); | ||
}, entry); | ||
threw = false; | ||
@@ -253,4 +296,2 @@ } | ||
entry.recomputing = false; | ||
assert(local.currentParentEntry === entry); | ||
local.currentParentEntry = parent; | ||
if (threw || !maybeSubscribe(entry)) { | ||
@@ -335,3 +376,3 @@ // Mark this Entry dirty if entry.fn threw or we failed to | ||
if (dc.size === 0) { | ||
if (emptySetPool.length < Entry.POOL_TARGET_SIZE) { | ||
if (emptySetPool.length < POOL_TARGET_SIZE) { | ||
emptySetPool.push(dc); | ||
@@ -449,3 +490,3 @@ } | ||
// In those cases, just write your own custom makeCacheKey functions. | ||
var keyTrie = new KeyTrie(true); | ||
var keyTrie = new KeyTrie(typeof WeakMap === "function"); | ||
function defaultMakeCacheKey() { | ||
@@ -464,7 +505,3 @@ var args = []; | ||
function optimistic() { | ||
var args = []; | ||
for (var _i = 0; _i < arguments.length; _i++) { | ||
args[_i] = arguments[_i]; | ||
} | ||
if (disposable && !get().currentParentEntry) { | ||
if (disposable && !getParentEntry()) { | ||
// If there's no current parent computation, and this wrapped | ||
@@ -477,6 +514,7 @@ // function is disposable (meaning we don't care about entry.value, | ||
} | ||
var key = makeCacheKey.apply(null, args); | ||
var key = makeCacheKey.apply(null, arguments); | ||
if (!key) { | ||
return originalFunction.apply(null, args); | ||
return originalFunction.apply(null, arguments); | ||
} | ||
var args = Array.prototype.slice.call(arguments); | ||
var entry = cache.get(key); | ||
@@ -498,6 +536,6 @@ if (entry) { | ||
cache.set(key, entry); | ||
// Clean up any excess entries in the cache, but only if this entry | ||
// has no parents, which means we're not in the middle of a larger | ||
// 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 (entry.isOrphan()) { | ||
if (!getParentEntry()) { | ||
cache.clean(); | ||
@@ -511,7 +549,3 @@ } | ||
optimistic.dirty = function () { | ||
var args = []; | ||
for (var _i = 0; _i < arguments.length; _i++) { | ||
args[_i] = arguments[_i]; | ||
} | ||
var key = makeCacheKey.apply(null, args); | ||
var key = makeCacheKey.apply(null, arguments); | ||
var child = key && cache.get(key); | ||
@@ -525,3 +559,3 @@ if (child) { | ||
export { defaultMakeCacheKey, KeyTrie, wrap }; | ||
export { defaultMakeCacheKey, KeyTrie, wrap, bindContext, noContext, setTimeoutWithContext as setTimeout, asyncFromGen }; | ||
//# sourceMappingURL=bundle.esm.js.map |
@@ -7,3 +7,2 @@ import { OptimisticWrapOptions } from "./index"; | ||
static count: number; | ||
static POOL_TARGET_SIZE: number; | ||
subscribe: OptimisticWrapOptions<TArgs>["subscribe"]; | ||
@@ -20,5 +19,4 @@ unsubscribe?: () => any; | ||
recompute(): TValue; | ||
isOrphan(): boolean; | ||
setDirty(): void; | ||
dispose(): void; | ||
} |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
var local_1 = require("./local"); | ||
var context_1 = require("./context"); | ||
var UNKNOWN_VALUE = Object.create(null); | ||
var reusableEmptyArray = []; | ||
var emptySetPool = []; | ||
var reusableEmptyArray = []; | ||
var POOL_TARGET_SIZE = 100; | ||
// Since this package might be used browsers, we should avoid using the | ||
@@ -38,5 +39,2 @@ // Node built-in assert module. | ||
}; | ||
Entry.prototype.isOrphan = function () { | ||
return this.parents.size === 0; | ||
}; | ||
Entry.prototype.setDirty = function () { | ||
@@ -74,3 +72,2 @@ if (this.dirty) | ||
Entry.count = 0; | ||
Entry.POOL_TARGET_SIZE = 100; | ||
return Entry; | ||
@@ -80,4 +77,3 @@ }()); | ||
function rememberParent(child) { | ||
var local = local_1.get(); | ||
var parent = local.currentParentEntry; | ||
var parent = context_1.getParentEntry(); | ||
if (parent) { | ||
@@ -137,8 +133,7 @@ child.parents.add(parent); | ||
var originalChildren = forgetChildren(entry); | ||
var local = local_1.get(); | ||
var parent = local.currentParentEntry; | ||
local.currentParentEntry = entry; | ||
var threw = true; | ||
try { | ||
entry.value = entry.fn.apply(null, entry.args); | ||
context_1.withEntry(function () { | ||
entry.value = entry.fn.apply(null, entry.args); | ||
}, entry); | ||
threw = false; | ||
@@ -148,4 +143,2 @@ } | ||
entry.recomputing = false; | ||
assert(local.currentParentEntry === entry); | ||
local.currentParentEntry = parent; | ||
if (threw || !maybeSubscribe(entry)) { | ||
@@ -230,3 +223,3 @@ // Mark this Entry dirty if entry.fn threw or we failed to | ||
if (dc.size === 0) { | ||
if (emptySetPool.length < Entry.POOL_TARGET_SIZE) { | ||
if (emptySetPool.length < POOL_TARGET_SIZE) { | ||
emptySetPool.push(dc); | ||
@@ -233,0 +226,0 @@ } |
import { KeyTrie } from "./key-trie"; | ||
export { bindContext, noContext, setTimeout, asyncFromGen, } from "./context"; | ||
export declare type TCacheKey = any; | ||
@@ -3,0 +4,0 @@ export declare function defaultMakeCacheKey(...args: any[]): any; |
@@ -5,5 +5,16 @@ "use strict"; | ||
var entry_1 = require("./entry"); | ||
var local_1 = require("./local"); | ||
var context_1 = require("./context"); | ||
var key_trie_1 = require("./key-trie"); | ||
exports.KeyTrie = key_trie_1.KeyTrie; | ||
// These helper functions are important for making optimism work with | ||
// asynchronous code. In order to register parent-child dependencies, | ||
// optimism needs to know about any currently active parent computations. | ||
// In ordinary synchronous code, the parent context is implicit in the | ||
// execution stack, but asynchronous code requires some extra guidance in | ||
// order to propagate context from one async task segment to the next. | ||
var context_2 = require("./context"); | ||
exports.bindContext = context_2.bindContext; | ||
exports.noContext = context_2.noContext; | ||
exports.setTimeout = context_2.setTimeout; | ||
exports.asyncFromGen = context_2.asyncFromGen; | ||
// The defaultMakeCacheKey function is remarkably powerful, because it gives | ||
@@ -16,3 +27,3 @@ // a unique object for any shallow-identical list of arguments. If you need | ||
// In those cases, just write your own custom makeCacheKey functions. | ||
var keyTrie = new key_trie_1.KeyTrie(true); | ||
var keyTrie = new key_trie_1.KeyTrie(typeof WeakMap === "function"); | ||
function defaultMakeCacheKey() { | ||
@@ -32,7 +43,3 @@ var args = []; | ||
function optimistic() { | ||
var args = []; | ||
for (var _i = 0; _i < arguments.length; _i++) { | ||
args[_i] = arguments[_i]; | ||
} | ||
if (disposable && !local_1.get().currentParentEntry) { | ||
if (disposable && !context_1.getParentEntry()) { | ||
// If there's no current parent computation, and this wrapped | ||
@@ -45,6 +52,7 @@ // function is disposable (meaning we don't care about entry.value, | ||
} | ||
var key = makeCacheKey.apply(null, args); | ||
var key = makeCacheKey.apply(null, arguments); | ||
if (!key) { | ||
return originalFunction.apply(null, args); | ||
return originalFunction.apply(null, arguments); | ||
} | ||
var args = Array.prototype.slice.call(arguments); | ||
var entry = cache.get(key); | ||
@@ -66,6 +74,6 @@ if (entry) { | ||
cache.set(key, entry); | ||
// Clean up any excess entries in the cache, but only if this entry | ||
// has no parents, which means we're not in the middle of a larger | ||
// 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 (entry.isOrphan()) { | ||
if (!context_1.getParentEntry()) { | ||
cache.clean(); | ||
@@ -79,7 +87,3 @@ } | ||
optimistic.dirty = function () { | ||
var args = []; | ||
for (var _i = 0; _i < arguments.length; _i++) { | ||
args[_i] = arguments[_i]; | ||
} | ||
var key = makeCacheKey.apply(null, args); | ||
var key = makeCacheKey.apply(null, arguments); | ||
var child = key && cache.get(key); | ||
@@ -86,0 +90,0 @@ if (child) { |
{ | ||
"name": "optimism", | ||
"version": "0.8.3", | ||
"version": "0.9.0", | ||
"author": "Ben Newman <ben@benjamn.com>", | ||
@@ -5,0 +5,0 @@ "description": "Composable reactive caching with efficient invalidation.", |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
98571
1192