Skip to content

Commit

Permalink
Generalized approach supporting compute and observers
Browse files Browse the repository at this point in the history
  • Loading branch information
kaste committed Feb 12, 2016
1 parent 3c12178 commit f4486a2
Show file tree
Hide file tree
Showing 4 changed files with 115 additions and 16 deletions.
34 changes: 25 additions & 9 deletions src/lib/bind/effects.html
Original file line number Diff line number Diff line change
Expand Up @@ -67,22 +67,31 @@
if (args) {
fn.apply(this, args);
}
} else if (effect.dynamicFn) {
// dynamic functions can be just like every other property `undefined`
// so we MUST ignore an undefined value here. (That's totally the
// same guard we use within `_marshalArgs` and part of the spec.)
} else {
this._warn(this._logf('_complexObserverEffect', 'observer method `' +
effect.method + '` not defined'));
}
},

_computeEffect: function(source, value, effect) {
var args = Polymer.Bind._marshalArgs(this.__data__, effect, source, value);
if (args) {
var fn = this[effect.method];
if (fn) {
this.__setProperty(effect.name, fn.apply(this, args));
} else {
this._warn(this._logf('_computeEffect', 'compute method `' +
effect.method + '` not defined'));
var fn = this[effect.method];
if (fn) {
var args = Polymer.Bind._marshalArgs(this.__data__, effect, source, value);
if (args) {
var computedvalue = fn.apply(this, args);
this.__setProperty(effect.name, computedvalue);
}
} else if (effect.dynamicFn) {
// dynamic functions can be just like every other property `undefined`
// so we MUST ignore an undefined value here. (That's totally the
// same guard we use within `_marshalArgs` and part of the spec.)
} else {
this._warn(this._logf('_computeEffect', 'compute method `' +
effect.method + '` not defined'));
}
},

Expand All @@ -98,6 +107,10 @@
}
this._applyEffectValue(effect, computedvalue);
}
} else if (effect.dynamicFn) {
// dynamic functions can be just like every other property `undefined`
// so we MUST ignore an undefined value here. (That's totally the
// same guard we use within `_marshalArgs` and part of the spec.)
} else {
computedHost._warn(computedHost._logf('_annotatedComputationEffect',
'compute method `' + effect.method + '` not defined'));
Expand All @@ -109,6 +122,9 @@
_marshalArgs: function(model, effect, path, value) {
var values = [];
var args = effect.args;
// Actually we should return early as soon as we see an `undefined`,
// but dom-repeat relies on this behavior.
var bailoutEarly = (args.length > 1 || effect.dynamicFn);
for (var i=0, l=args.length; i<l; i++) {
var arg = args[i];
var name = arg.name;
Expand All @@ -120,7 +136,7 @@
} else {
v = model[name];
}
if (args.length > 1 && v === undefined) {
if (bailoutEarly && v === undefined) {
return;
}
if (arg.wildcard) {
Expand Down
4 changes: 0 additions & 4 deletions src/standard/annotations.html
Original file line number Diff line number Diff line change
Expand Up @@ -147,10 +147,6 @@
if (!p.literal) {
var signature = this._parseMethod(p.value);
if (signature) {
if (this.properties[signature.method]) {
signature.dynamicFn = true;
signature.static = false;
}
p.signature = signature;
} else {
p.model = this._modelForPath(p.value);
Expand Down
35 changes: 32 additions & 3 deletions src/standard/effectBuilder.html
Original file line number Diff line number Diff line change
Expand Up @@ -79,14 +79,27 @@

_addComputedEffect: function(name, expression) {
var sig = this._parseMethod(expression);

var dynamicFn = sig.dynamicFn;

for (var i=0, arg; (i<sig.args.length) && (arg=sig.args[i]); i++) {
this._addPropertyEffect(arg.model, 'compute', {
method: sig.method,
args: sig.args,
trigger: arg,
name: name
name: name,
dynamicFn: dynamicFn
});
}
if (dynamicFn) {
this._addPropertyEffect(sig.method, 'compute', {
method: sig.method,
args: sig.args,
trigger: null,
name: name,
dynamicFn: dynamicFn
})
}
},

_addObserverEffect: function(property, observer) {
Expand All @@ -111,11 +124,22 @@
throw new Error("Malformed observer expression '" + observer + "'");
}

var dynamicFn = sig.dynamicFn;

for (var i=0, arg; (i<sig.args.length) && (arg=sig.args[i]); i++) {
this._addPropertyEffect(arg.model, 'complexObserver', {
method: sig.method,
args: sig.args,
trigger: arg
trigger: arg,
dynamicFn: dynamicFn
});
}
if (dynamicFn) {
this._addPropertyEffect(sig.method, 'complexObserver', {
method: sig.method,
args: sig.args,
trigger: null,
dynamicFn: dynamicFn
});
}
},
Expand Down Expand Up @@ -192,7 +216,8 @@
negate: part.negate,
method: part.signature.method,
args: part.signature.args,
trigger: trigger
trigger: trigger,
dynamicFn: part.signature.dynamicFn
});
},

Expand All @@ -202,6 +227,10 @@
var m = expression.match(/([^\s]+?)\(([\s\S]*)\)/);
if (m) {
var sig = { method: m[1], static: true };
if (this.properties[sig.method]) {
sig.static = false;
sig.dynamicFn = true;
}
if (m[2].trim()) {
// replace escaped commas with comma entity, split on un-escaped commas
var args = m[2].replace(/\\,/g, '&comma;').split(',');
Expand Down
58 changes: 58 additions & 0 deletions test/unit/bind.html
Original file line number Diff line number Diff line change
Expand Up @@ -310,6 +310,64 @@
assert.equal(el.$.check.textContent, 'changed: Hello World.');
});

test('observer with dynamic function', function() {
Polymer({
is: 'x-observer-with-dynamic-function',
properties: {
translate: {
type: Function,
},
message: {
type: String,
value: 'Hello'
},
},

observers: ['translate(message)'],

})

el = document.createElement('x-observer-with-dynamic-function');
document.body.appendChild(el);

var called = 0;
el.translate = function() {
called += 1;
};

assert.equal(called, 1);

});

test('computed property with dynamic function', function() {
Polymer({
is: 'x-computed-property-with-dynamic-function',
properties: {
computedValue: {
computed: "translate('Hello')"
},
translate: {
type: Function
}
}
});

el = document.createElement('x-computed-property-with-dynamic-function');
document.body.appendChild(el);

assert.equal(el.computedValue, undefined);

var called = 0;
el.translate = function(message) {
called += 1;
return 'translated: ' + message;
};

assert.equal(called, 1);
assert.equal(el.computedValue, 'translated: Hello');

});

});

</script>
Expand Down

0 comments on commit f4486a2

Please sign in to comment.