UNPKG

relu-core

Version:
96 lines (81 loc) 2.13 kB
var base = require("./base"); var rpConst = require("./const"); module.exports = function rpComputed(fn) { var p = base(); p.constructor = rpComputed; var value; var dependencies var scope; p._get = function() { if(!dependencies) calculateValue(); p.depend(); return value; }; p._getUndependend = function() { if(!dependencies) calculateValue(); return value; }; p._length = function() { if(!Array.isArray(value)) return -1; return value.length; }; p.isConst = function() { return !dependencies || dependencies.every(function(dep) { return dep.isConst(); }); }; p._writable = false; var disposed = false; p.onceDisposed(function() { disposed = true; if(dependencies) disconnect(); }); calculateValue(); function disconnect() { var _scope = scope.slice(); var _deps = dependencies; dependencies = scope = undefined; for(var i = 0; i < _deps.length; i++) { var dep = _deps[i]; dep.removeOnceChangedListener(onDependencyChanged); dep.unref(p); } base.unrefAll(_scope); } function calculateValue() { if(disposed) return; var captured = base.capture(fn); dependencies = captured.dependencies; // if any of the dependencies is disposed, we are in a undefined state for(var i = 0; i < dependencies.length; i++) { if(dependencies[i].isDisposed()) { dependencies.length = 0; captured.value = undefined; } } scope = captured.scope; base.refAll(dependencies, p); for(var i = 0; i < dependencies.length; i++) dependencies[i].onceChanged(onDependencyChanged); var val = captured.value; if(val !== value) { var old = value; value = val; p._updated(value, old); p._changed(); } } function onDependencyChanged() { if(!dependencies) return; var temp = {}; var _deps = base.refAll(dependencies.slice(), temp); var _scope = base.refAll(scope.slice(), temp); disconnect(); base.atAtomicEnd(function() { calculateValue(); base.unrefAll(_deps, temp); base.unrefAll(_scope, temp); }); } return p; };