Skip to content

Commit

Permalink
implement equals method for equivalent ContextClosure objects (#20)
Browse files Browse the repository at this point in the history
* implement equals method for equivalent ContextClosure objects

* implement DependencyOptions::setIgnoreTemplate() & use ContextClosure source template

The desire of ignoreTemplate is to prevent over-computing bindings for templates. However, wrapping templates in ContextClosures was preventing us from detecting the template that should be ignored. This resolves the issue by ignoring the base template of the ContextClosure

* always wrap templates in ContextClosure when returned from get method and not wrapped already

It could be possible for an object to have an unwrapped Template in it that is returned by looking up segemtns, so this shouldn't be an else.

Also, wrapping a template in two ContextClosures isn't needed, since the inner ContextClosure is going to be the only one that has an effect. Thus, do check for an existing ContextClosure to avoid direct double wrapping.

* more efficient ignore that uses contextClosure.template

* use template.equals to handle possible recursive ContextClosure equality checks
  • Loading branch information
nateps authored Aug 8, 2018
1 parent 8f366f6 commit 5d19968
Show file tree
Hide file tree
Showing 4 changed files with 22 additions and 8 deletions.
11 changes: 6 additions & 5 deletions lib/expressions.js
Original file line number Diff line number Diff line change
Expand Up @@ -174,14 +174,15 @@ Expression.prototype.isUnbound = function(context) {
// Otherwise, inherit from the context
return context.unbound;
};
Expression.prototype._lookupOrContextifyValue = function(value, context) {
Expression.prototype._lookupAndContextifyValue = function(value, context) {
if (this.segments && this.segments.length) {
// If expression has segments, e.g. `bar.baz` in `#foo.bar.baz`, then
// render the base value (e.g. `#foo`) if it's a template and look up the
// value at the indicated path.
value = renderTemplate(value, context);
value = lookup(this.segments, value);
} else if (value instanceof Template) {
}
if (value instanceof Template && !(value instanceof templates.ContextClosure)) {
// If we're not immediately rendering the template, then create a ContextClosure
// so that the value renders with the correct context later.
value = new templates.ContextClosure(value, context);
Expand Down Expand Up @@ -252,7 +253,7 @@ RelativePathExpression.prototype.serialize = function() {
RelativePathExpression.prototype.get = function(context) {
var relativeContext = context.forRelative(this);
var value = relativeContext.get();
return this._lookupOrContextifyValue(value, relativeContext);
return this._lookupAndContextifyValue(value, relativeContext);
};
RelativePathExpression.prototype.resolve = function(context) {
var relativeContext = context.forRelative(this);
Expand Down Expand Up @@ -290,7 +291,7 @@ AliasPathExpression.prototype.get = function(context) {
return aliasContext.item;
}
var value = aliasContext.get();
return this._lookupOrContextifyValue(value, aliasContext);
return this._lookupAndContextifyValue(value, aliasContext);
};
AliasPathExpression.prototype.resolve = function(context) {
var aliasContext = context.forAlias(this.alias);
Expand Down Expand Up @@ -335,7 +336,7 @@ AttributePathExpression.prototype.get = function(context) {
if (value instanceof Expression) {
value = value.get(attributeContext);
}
return this._lookupOrContextifyValue(value, attributeContext);
return this._lookupAndContextifyValue(value, attributeContext);
};
AttributePathExpression.prototype.resolve = function(context) {
var attributeContext = context.forAttribute(this.attribute);
Expand Down
10 changes: 9 additions & 1 deletion lib/options.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,16 @@
var templates = require('./templates');

exports.DependencyOptions = DependencyOptions;

function DependencyOptions(options) {
this.ignoreTemplate = options && options.ignoreTemplate;
this.setIgnoreTemplate(options && options.ignoreTemplate);
}
DependencyOptions.shouldIgnoreTemplate = function(template, options) {
return (options) ? options.ignoreTemplate === template : false;
};
DependencyOptions.prototype.setIgnoreTemplate = function(template) {
while (template instanceof templates.ContextClosure) {
template = template.template;
}
this.ignoreTemplate = template;
};
7 changes: 6 additions & 1 deletion lib/templates.js
Original file line number Diff line number Diff line change
Expand Up @@ -439,10 +439,15 @@ ContextClosure.prototype.attachTo = function(parent, node, context) {
return this.template.attachTo(parent, node, closureContext);
};
ContextClosure.prototype.dependencies = function(context, options) {
if (DependencyOptions.shouldIgnoreTemplate(this, options)) return;
if (DependencyOptions.shouldIgnoreTemplate(this.template, options)) return;
var closureContext = context.closureChild(this.context);
return this.template.dependencies(closureContext, options);
};
ContextClosure.prototype.equals = function(other) {
return (other instanceof ContextClosure) &&
(this.context === other.context) &&
(this.template.equals(other.template));
};

function ViewsMap() {}
function Views() {
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
"author": "Nate Smith",
"license": "MIT",
"dependencies": {
"saddle": "^0.9.1",
"saddle": "^0.9.4",
"serialize-object": "^1.0.0"
},
"bugs": {
Expand Down

0 comments on commit 5d19968

Please sign in to comment.