Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

optimism

Package Overview
Dependencies
Maintainers
1
Versions
72
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

optimism - npm Package Compare versions

Comparing version 0.1.1 to 0.2.0

261

lib/entry.js
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.Entry = undefined;
var assert = require("assert");
var UNKNOWN_VALUE = Object.create(null);
var emptySetPool = [];
var _toConsumableArray2 = require("babel-runtime/helpers/toConsumableArray");
function Entry(fn, key, args) {
assert(this instanceof Entry);
var _toConsumableArray3 = _interopRequireDefault(_toConsumableArray2);
this.fn = fn;
this.key = key;
this.args = args;
this.value = UNKNOWN_VALUE;
this.dirty = true;
this.parents = new Set;
this.childValues = new Map;
var _map = require("babel-runtime/core-js/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;
}
var _map2 = _interopRequireDefault(_map);
exports.Entry = Entry;
var _set = require("babel-runtime/core-js/set");
var Ep = Entry.prototype;
var _set2 = _interopRequireDefault(_set);
Ep.setDirty = function setDirty() {
this.dirty = true;
this.parents.forEach(function (parent) {
parent.reportDirtyChild(this);
}, this);
};
var _classCallCheck2 = require("babel-runtime/helpers/classCallCheck");
Ep.reportDirtyChild = function reportDirtyChild(child) {
assert(this.childValues.has(child));
var _classCallCheck3 = _interopRequireDefault(_classCallCheck2);
if (! this.dirtyChildren) {
// Initialize this.dirtyChildren with an empty set drawn from the
// emptySetPool if possible.
this.dirtyChildren = emptySetPool.pop() || new Set;
var _createClass2 = require("babel-runtime/helpers/createClass");
} else if (this.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;
}
var _createClass3 = _interopRequireDefault(_createClass2);
this.dirtyChildren.add(child);
var _create = require("babel-runtime/core-js/object/create");
this.parents.forEach(function (parent) {
parent.reportDirtyChild(this);
}, this);
};
var _create2 = _interopRequireDefault(_create);
Ep.reportCleanChild = function reportCleanChild(child) {
assert(! child.dirty);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
this.childValues.set(child, child.value);
var assert = require("assert");
var UNKNOWN_VALUE = (0, _create2.default)(null);
var currentParentEntry = void 0;
var dc = this.dirtyChildren;
if (dc) {
dc.delete(child);
if (dc.size === 0) {
emptySetPool.push(dc);
dc = this.dirtyChildren = null;
}
}
var Entry = exports.Entry = function () {
function Entry(fn, key, args) {
(0, _classCallCheck3.default)(this, Entry);
this.fn = fn;
this.key = key;
this.args = args;
this.value = UNKNOWN_VALUE;
this.dirty = true;
this.parents = new _set2.default();
this.childValues = new _map2.default();
this.dirtyChildren = new _set2.default();
if (this.dirty || dc) {
// This Entry is not clean, either because it's explicitly dirty or
// because it still has dirty children, so we can't report it as
// clean to its parents.
return;
}
(0, _createClass3.default)(Entry, [{
key: "setDirty",
value: function setDirty() {
var _this = this;
this.parents.forEach(function (parent) {
parent.reportCleanChild(this);
}, this);
};
this.dirty = true;
// This is the most important method of the Entry API, because it
// determines whether the cached entry.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) this.value is usally returned very quickly, without recomputation.
Ep.recomputeIfDirty = function recomputeIfDirty() {
if (this.dirty) {
// If this Entry is explicitly dirty because someone called
// entry.setDirty(), recompute.
return this.recompute();
}
this.parents.forEach(function (parent) {
parent.reportDirtyChild(_this);
});
}
}, {
key: "reportDirtyChild",
value: function reportDirtyChild(child) {
var _this2 = this;
assert(this.childValues.has(child));
if (this.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;
if (this.dirtyChildren) {
// Get fresh values for any dirty children, and if those values
// disagree with this.childValues, mark this Entry explicitly dirty.
this.dirtyChildren.forEach(function (child) {
var oldValue = this.childValues.get(child);
if (child.recomputeIfDirty() !== oldValue) {
this.dirty = true;
}
}, this);
}
this.dirtyChildren.add(child);
if (this.dirty) {
// If this Entry has become explicitly dirty after comparing the fresh
// values of its dirty children against this.childValues, recompute.
return this.recompute();
}
this.parents.forEach(function (parent) {
parent.reportDirtyChild(_this2);
});
}
}, {
key: "reportCleanChild",
value: function reportCleanChild(child) {
var _this3 = this;
assert.notStrictEqual(this.value, UNKNOWN_VALUE);
assert(!child.dirty);
return this.value;
};
this.childValues.set(child, child.value);
this.dirtyChildren.delete(child);
var currentParentEntry;
if (this.dirty || this.dirtyChildren.size > 0) {
return;
}
this.parents.forEach(function (parent) {
parent.reportCleanChild(_this3);
});
Ep.recompute = function recompute() {
this.forgetChildren();
this.dirty = true;
var oldParentEntry = currentParentEntry;
currentParentEntry = this;
try {
this.value = this.fn.apply(null, this.args);
this.dirty = false;
} finally {
currentParentEntry = oldParentEntry;
if (! this.dirty) {
this.updateParents();
return this.value;
}
}, {
key: "recomputeIfDirty",
value: function recomputeIfDirty() {
var _this4 = this;
}
};
if (this.dirty) {
return this.recompute();
}
Ep.forgetChildren = function forgetChildren() {
this.childValues.forEach(function (value, child) {
child.parents.delete(this);
}, this);
this.dirtyChildren.forEach(function (child) {
var oldValue = _this4.childValues.get(child);
if (child.recomputeIfDirty() !== oldValue) {
_this4.dirty = true;
}
});
this.childValues.clear();
if (this.dirty) {
return this.recompute();
}
var dc = this.dirtyChildren;
if (dc) {
dc.clear();
emptySetPool.push(dc);
this.dirtyChildren = null;
}
};
return this.value;
}
}, {
key: "recompute",
value: function recompute() {
this.forgetChildren();
this.dirty = true;
var oldParentEntry = currentParentEntry;
currentParentEntry = this;
try {
this.value = this.fn.apply(this, (0, _toConsumableArray3.default)(this.args));
this.dirty = false;
} finally {
currentParentEntry = oldParentEntry;
if (!this.dirty) {
this.updateParents();
return this.value;
}
}
}
}, {
key: "forgetChildren",
value: function forgetChildren() {
var _this5 = this;
Ep.updateParents = function updateParents() {
if (currentParentEntry) {
this.parents.add(currentParentEntry);
}
this.childValues.forEach(function (value, child) {
return child.parents.delete(_this5);
});
this.childValues.clear();
this.dirtyChildren.clear();
}
}, {
key: "updateParents",
value: function updateParents() {
var _this6 = this;
if (currentParentEntry) {
this.parents.add(currentParentEntry);
}
this.parents.forEach(function (parent) {
parent.reportCleanChild(_this6);
});
}
}]);
return Entry;
}();
this.parents.forEach(function (parent) {
parent.reportCleanChild(this);
}, this);
};
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
var LRU = require("lru-cache");
var Entry = require("./entry.js").Entry;
var slice = Array.prototype.slice;
var _create = require("babel-runtime/core-js/object/create");
var _create2 = _interopRequireDefault(_create);
var _stringify = require("babel-runtime/core-js/json/stringify");
var _stringify2 = _interopRequireDefault(_stringify);
exports.makeOptimistic = makeOptimistic;
var _lruCache = require("lru-cache");
var _lruCache2 = _interopRequireDefault(_lruCache);
var _entry = require("./entry.js");
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
function defaultMakeCacheKey() {
for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) {
args[_key] = arguments[_key];
}
return (0, _stringify2.default)(args);
return JSON.stringify(slice.call(arguments));
}
function makeOptimistic(fn, options) {
options = options || (0, _create2.default)(null);
function wrap(fn, options) {
options = options || Object.create(null);
if (typeof options.makeCacheKey !== "function") {

@@ -39,4 +17,4 @@ options.makeCacheKey = defaultMakeCacheKey;

var cache = new _lruCache2.default({
dispose: function dispose(entry, key) {
var cache = new LRU({
dispose: function (entry, key) {
// TODO

@@ -47,13 +25,8 @@ }

function optimistic() {
var _options;
for (var _len2 = arguments.length, args = Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
args[_key2] = arguments[_key2];
var key = options.makeCacheKey.apply(null, arguments);
if (! key) {
return fn.apply(null, arguments);
}
var key = (_options = options).makeCacheKey.apply(_options, args);
if (!key) {
return fn.apply(undefined, args);
}
var args = slice.call(arguments);
var entry = cache.get(key);

@@ -63,3 +36,3 @@ if (entry) {

} else {
cache.set(key, entry = new _entry.Entry(fn, key, args));
cache.set(key, entry = new Entry(fn, key, args));
}

@@ -71,10 +44,8 @@

optimistic.dirty = function () {
var _options2;
var key = (_options2 = options).makeCacheKey.apply(_options2, arguments);
if (!key) {
var key = options.makeCacheKey.apply(null, arguments);
if (! key) {
return;
}
if (!cache.has(key)) {
if (! cache.has(key)) {
return;

@@ -87,2 +58,4 @@ }

return optimistic;
}
}
exports.wrap = wrap;
{
"name": "optimism",
"version": "0.1.1",
"version": "0.2.0",
"author": "Ben Newman <ben@benjamn.com>",

@@ -28,24 +28,10 @@ "description": "Composable reactive caching with efficient invalidation.",

"scripts": {
"prepublish": "babel src/ --out-dir lib/",
"test": "mocha --compilers js:babel-register --reporter spec --full-trace test/tests.js"
"test": "mocha --reporter spec --full-trace test/tests.js"
},
"dependencies": {
"babel-runtime": "^6.11.6",
"lru-cache": "^4.0.1"
},
"devDependencies": {
"babel-cli": "^6.16.0",
"babel-plugin-transform-runtime": "^6.15.0",
"babel-preset-es2015": "^6.16.0",
"babel-register": "^6.16.3",
"mocha": "^3.1.0"
},
"babel": {
"presets": [
"es2015"
],
"plugins": [
"transform-runtime"
]
}
}

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc