Created
September 21, 2017 04:31
-
-
Save zetekla/e76198d4a4c80b1c815835cb360ca09a to your computer and use it in GitHub Desktop.
Meteor Tracker guard
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Only trigger enclosing computation if the return value of | |
// f is not EJSON.equals to the previuous return value | |
Tracker.guard = function(f) { | |
if (Meteor.isServer || !Tracker.currentComputation) { | |
return f(); | |
} | |
let dep = new Tracker.Dependency(), | |
curView = Blaze.currentView, | |
tplFunc = Template._currentTemplateInstanceFunc; | |
dep.depend(); | |
let value, newValue; | |
Tracker.autorun(comp => { | |
if (curView) { | |
newValue = Blaze._withCurrentView(curView, () => { | |
return tplFunc ? Template._withTemplateInstanceFunc(tplFunc, f) : f(); | |
}); | |
} | |
else { | |
newValue = f(); | |
} | |
if (!comp.firstRun && !EJSON.equals(newValue, value)) { | |
dep.changed(); | |
} | |
value = EJSON.clone(newValue); | |
}); | |
return newValue; | |
}; | |
// Return a function which will always return the same | |
// value as f and changes value whenever f changes value, | |
// but is more efficient because it caches the value of f | |
// in a reactive variable. | |
Tracker.memo = function(f) { | |
if (Meteor.isServer) | |
return f; | |
let value = new ReactiveVar(undefined, EJSON.equals), | |
tracker = Tracker.nonreactive(() => Template.instance()) || Tracker, | |
firstRun = true, | |
comp = tracker.autorun(() => { | |
if (!firstRun) | |
value.set(f()); | |
}); | |
return () => { | |
if (firstRun) { | |
firstRun = false; | |
comp._compute(); | |
} | |
return value.get(); | |
}; | |
}; | |
// Starting work on tracking who triggered an autorun | |
let originalCompute = Tracker.Computation.prototype._compute; | |
Tracker.Computation.prototype._compute = function() { | |
originalCompute.call(this); | |
this.callers = []; | |
}; | |
let originalInvalidate = Tracker.Computation.prototype.invalidate; | |
Tracker.Computation.prototype.invalidate = function() { | |
if (!this._callers) | |
this._callers = []; | |
let e = new Error('dummy'); | |
let stack = e.stack.replace(/^[^\(]+?[\n$]/gm, '') | |
.replace(/^\s+at\s+/gm, '') | |
.replace(/^Object.<anonymous>\s*\(/gm, '{anonymous}()@') | |
.split('\n'); | |
this._callers.push(stack); | |
originalInvalidate.call(this); | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment