mirror of
https://github.com/Polymer/polymer.git
synced 2025-02-25 18:55:30 -06:00
Perform property effect binning in property-effects
This commit is contained in:
@@ -21,9 +21,6 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
|
||||
|
||||
constructor(templateStamp, attributes, annotations) {
|
||||
super(attributes, annotations);
|
||||
this._currentEffects = null;
|
||||
// Not a correct assign polyfill-- only use where proto's don't matter!
|
||||
// _mixin: Object.assign ? Object.assign : Polymer.Utils.mixin,
|
||||
this._mixin = Polymer.Utils.mixin;
|
||||
this._effectUid = 0;
|
||||
this.templateStamp = templateStamp ||
|
||||
@@ -34,82 +31,6 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
|
||||
}
|
||||
}
|
||||
|
||||
addPropertyEffect(model, property, effect) {
|
||||
model = this.getModel(model);
|
||||
if (!model.setProperties) {
|
||||
var lib = this;
|
||||
model.setProperties = function(props, fromAbove) {
|
||||
lib.setProperties(this, props, fromAbove);
|
||||
};
|
||||
model.set = model.notifyPath = function(prop, value) {
|
||||
lib.set(this, prop, value);
|
||||
};
|
||||
}
|
||||
super.addPropertyEffect.apply(this, arguments);
|
||||
if (this._currentEffects) {
|
||||
var effects = this._currentEffects[property] ||
|
||||
(this._currentEffects[property] = []);
|
||||
effects.push(effect);
|
||||
}
|
||||
}
|
||||
|
||||
_accumulateEffects(model, name, fn, args) {
|
||||
model = this.getModel(model);
|
||||
this._currentEffects = this._ensureEffects(model, name);
|
||||
fn.apply(this, args);
|
||||
this._currentEffects = null;
|
||||
}
|
||||
|
||||
// -- read only ----------------------------------------------
|
||||
|
||||
createReadOnlyProperty(model, property) {
|
||||
model = this.getModel(model);
|
||||
super.createReadOnlyProperty.apply(this, arguments);
|
||||
this._ensureEffects(model, '_isReadOnly')[property] = true;
|
||||
}
|
||||
|
||||
// -- observer ----------------------------------------------
|
||||
|
||||
createObserver(model) {
|
||||
this._accumulateEffects(model, '_observerEffects',
|
||||
super.createObserver, arguments);
|
||||
}
|
||||
|
||||
// -- notify ----------------------------------------------
|
||||
|
||||
createNotifyingProperty(model) {
|
||||
this._accumulateEffects(model, '_notifyEffects',
|
||||
super.createNotifyingProperty, arguments);
|
||||
}
|
||||
|
||||
// -- reflect ----------------------------------------------
|
||||
|
||||
createReflectedProperty(model) {
|
||||
this._accumulateEffects(model, '_annotationEffects',
|
||||
super.createReflectedProperty, arguments);
|
||||
}
|
||||
|
||||
// -- complexObserver ----------------------------------------------
|
||||
|
||||
createMultiObserver(model) {
|
||||
this._accumulateEffects(model, '_observerEffects',
|
||||
super.createMultiObserver, arguments);
|
||||
}
|
||||
|
||||
// -- computed ----------------------------------------------
|
||||
|
||||
createComputedProperty(model) {
|
||||
this._accumulateEffects(model, '_computedEffects',
|
||||
super.createComputedProperty, arguments);
|
||||
}
|
||||
|
||||
// -- annotation ----------------------------------------------
|
||||
|
||||
bindTemplate(model, template) {
|
||||
this._accumulateEffects(model, '_annotationEffects',
|
||||
super.bindTemplate, [model, template]);
|
||||
}
|
||||
|
||||
// -- set properties machinery
|
||||
|
||||
setProperties(inst, props, fromAbove) {
|
||||
@@ -158,7 +79,7 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
|
||||
// Run computed effects
|
||||
var inputProps = changedProps;
|
||||
var computedProps;
|
||||
while (this._runEffects(inst, inst._computedEffects, inputProps)) {
|
||||
while (this._runEffects(inst, Types.COMPUTE, inputProps)) {
|
||||
this._mixin(oldProps, inst.__dataOld);
|
||||
this._mixin(changedProps, inst.__dataPending);
|
||||
computedProps = this._mixin(computedProps || {}, inst.__dataPending);
|
||||
@@ -177,9 +98,9 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
|
||||
if (runId == inst._runId) {
|
||||
changedProps = inst.__interimData;
|
||||
// Run annotation effects
|
||||
this._runEffects(inst, inst._annotationEffects, changedProps);
|
||||
this._runEffects(inst, Types.PROPAGATE, changedProps);
|
||||
if (!inst._propertyEffectsActive) {
|
||||
this._runEffects(inst, inst._annotationEffects, {__static__: true});
|
||||
this._runEffects(inst, Types.PROPAGATE, {__static__: true});
|
||||
}
|
||||
// Recurse to clients
|
||||
this._flushPropClients(inst);
|
||||
@@ -187,7 +108,7 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
|
||||
if (inst._propertyEffectsActive) {
|
||||
inst.__interimData = null;
|
||||
// Run observer effects
|
||||
this._runEffects(inst, inst._observerEffects, changedProps, oldProps);
|
||||
this._runEffects(inst, Types.OBSERVE, changedProps, oldProps);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -268,8 +189,9 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
|
||||
}
|
||||
}
|
||||
|
||||
_runEffects(inst, effects, props, oldProps) {
|
||||
_runEffects(inst, type, props, oldProps) {
|
||||
var ran;
|
||||
var effects = inst[type];
|
||||
if (effects) {
|
||||
var id = this._effectUid++;
|
||||
for (var prop in props) {
|
||||
@@ -332,6 +254,8 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
|
||||
|
||||
}
|
||||
|
||||
var Types = BatchedEffects.Types;
|
||||
|
||||
// export
|
||||
Polymer.BatchedEffects = BatchedEffects;
|
||||
|
||||
|
||||
@@ -85,6 +85,17 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
|
||||
}
|
||||
}
|
||||
|
||||
_addObservedAttribute(model, name) {
|
||||
var attrName = Polymer.CaseMap.camelToDashCase(name);
|
||||
var ctor = model.constructor;
|
||||
if (!ctor.hasOwnProperty('observedAttributes')) {
|
||||
ctor.observedAttributes =
|
||||
ctor.observedAttributes ?
|
||||
ctor.observedAttributes.slice() : [];
|
||||
}
|
||||
ctor.observedAttributes.push(attrName);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// export
|
||||
|
||||
@@ -46,34 +46,33 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
|
||||
|
||||
// Prototype setup ----------------------------------------
|
||||
|
||||
addPropertyEffect(model, path, effect, readOnly) {
|
||||
addPropertyEffect(model, path, type, effect) {
|
||||
model = this.getModel(model);
|
||||
var property = this._rootForPath(path);
|
||||
var effects = this._ensureEffects(model, '_propertyEffects')[property];
|
||||
// _propertyEffects only used to track whether an accessor has been created or not
|
||||
var effects = this._ensureOwnMappedArray(model, '_propertyEffects')[property];
|
||||
if (!effects) {
|
||||
effects = model._propertyEffects[property] = [];
|
||||
// TODO(sorvell): kosher to bail here if an accessor already exists?
|
||||
if (!readOnly && model.hasOwnProperty(property)) {
|
||||
console.warn('Accessor already exists for', property, 'on', model);
|
||||
} else {
|
||||
this.createAccessor(model, property, readOnly);
|
||||
}
|
||||
if (!readOnly) {
|
||||
this._addObservedAttribute(model, property);
|
||||
}
|
||||
this.createAccessor(model, property, type == Types.READ_ONLY);
|
||||
}
|
||||
if (effect && !readOnly) {
|
||||
// effects are accumulated into arrays per property based on type
|
||||
if (effect) {
|
||||
effect.path = path;
|
||||
effects.push(effect);
|
||||
effects = this._ensureOwnMappedArray(model, type)[property];
|
||||
if (!effects) {
|
||||
effects = model[type][property] = [];
|
||||
}
|
||||
effects.push(effect);
|
||||
}
|
||||
}
|
||||
|
||||
_ensureEffects(model, name) {
|
||||
var effects = model[name];
|
||||
_ensureOwnMappedArray(model, type) {
|
||||
var effects = model[type];
|
||||
if (!effects) {
|
||||
effects = model[name] = {};
|
||||
} else if (!model.hasOwnProperty(name)) {
|
||||
effects = model[name] = Object.create(model[name]);
|
||||
effects = model[type] = {};
|
||||
} else if (!model.hasOwnProperty(type)) {
|
||||
effects = model[type] = Object.create(model[type]);
|
||||
for (var p in effects) {
|
||||
// TODO(kschaaf): replace with fast array copy #!%&$!
|
||||
effects[p] = effects[p].slice();
|
||||
@@ -87,17 +86,6 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
|
||||
return (dot < 0) ? path : path.slice(0, dot);
|
||||
}
|
||||
|
||||
_addObservedAttribute(model, name) {
|
||||
var attrName = Polymer.CaseMap.camelToDashCase(name);
|
||||
var ctor = model.constructor;
|
||||
if (!ctor.hasOwnProperty('observedAttributes')) {
|
||||
ctor.observedAttributes =
|
||||
ctor.observedAttributes ?
|
||||
ctor.observedAttributes.slice() : [];
|
||||
}
|
||||
ctor.observedAttributes.push(attrName);
|
||||
}
|
||||
|
||||
// Runtime ----------------------------------------
|
||||
|
||||
setProperty(inst, property, value) {
|
||||
@@ -133,15 +121,11 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
|
||||
}
|
||||
}
|
||||
|
||||
// TODO(kschaaf): rather than create+run, consider closing over
|
||||
// run in create to avoid extra info object creation, otoh maybe
|
||||
// its good for debugging?
|
||||
|
||||
// -- readOnly ----------------------------------------------
|
||||
|
||||
createReadOnlyProperty(model, property, privateSetter) {
|
||||
model = this.getModel(model);
|
||||
this.addPropertyEffect(model, property, null, true);
|
||||
this.addPropertyEffect(model, property, Types.READ_ONLY);
|
||||
var lib = this;
|
||||
if (privateSetter) {
|
||||
model['_set' + this._upper(property)] = function(value) {
|
||||
@@ -157,7 +141,7 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
|
||||
// -- observer ----------------------------------------------
|
||||
|
||||
createObserver(model, property, methodName, context) {
|
||||
this.addPropertyEffect(model, property, {
|
||||
this.addPropertyEffect(model, property, Types.OBSERVE, {
|
||||
fn: this._runObserverEffect,
|
||||
info: {
|
||||
methodName: methodName,
|
||||
@@ -178,7 +162,7 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
|
||||
// -- notify ----------------------------------------------
|
||||
|
||||
createNotifyingProperty(model, property) {
|
||||
this.addPropertyEffect(model, property, {
|
||||
this.addPropertyEffect(model, property, Types.NOTIFY, {
|
||||
fn: this._runNotifyEffect,
|
||||
info: {
|
||||
lib: this,
|
||||
@@ -197,7 +181,7 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
|
||||
// -- reflect ----------------------------------------------
|
||||
|
||||
createReflectedProperty(model, property) {
|
||||
this.addPropertyEffect(model, property, {
|
||||
this.addPropertyEffect(model, property, Types.PROPAGATE, {
|
||||
fn: this._runReflectEffect,
|
||||
info: {
|
||||
lib: this,
|
||||
@@ -214,7 +198,8 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
|
||||
|
||||
createMultiObserver(model, expression) {
|
||||
var sig = this._parseMethod(expression);
|
||||
this._createMethodEffect(model, sig, this._runMultiObserverEffect);
|
||||
this._createMethodEffect(model, sig, Types.OBSERVE,
|
||||
this._runMultiObserverEffect);
|
||||
}
|
||||
|
||||
_runMultiObserverEffect(property, value, old, info) {
|
||||
@@ -225,7 +210,8 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
|
||||
|
||||
createComputedProperty(model, property, expression) {
|
||||
var sig = this._parseMethod(expression);
|
||||
this._createMethodEffect(model, sig, this._runComputedEffect, property);
|
||||
this._createMethodEffect(model, sig, Types.COMPUTE,
|
||||
this._runComputedEffect, property);
|
||||
}
|
||||
|
||||
_runComputedEffect(property, value, old, info) {
|
||||
@@ -257,7 +243,7 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
|
||||
if (part.signature) {
|
||||
this._addAnnotatedComputationEffect(model, note, part, index);
|
||||
} else if (!part.literal) {
|
||||
this.addPropertyEffect(model, part.rootProperty, {
|
||||
this.addPropertyEffect(model, part.rootProperty, Types.PROPAGATE, {
|
||||
fn: this._runAnnotationEffect,
|
||||
info: {
|
||||
lib: this,
|
||||
@@ -345,7 +331,7 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
|
||||
}
|
||||
|
||||
_addAnnotatedComputationEffect(model, note, part, index) {
|
||||
this._createMethodEffect(model, part.signature,
|
||||
this._createMethodEffect(model, part.signature, Types.PROPAGATE,
|
||||
this._runAnnotationComputationEffect, {
|
||||
index: index,
|
||||
isCompound: note.isCompound,
|
||||
@@ -492,6 +478,13 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
|
||||
}
|
||||
}
|
||||
|
||||
_pathMatchesEffect(path, effect) {
|
||||
var effectArg = effect.path;
|
||||
return (effectArg == path) ||
|
||||
(effectArg.indexOf(path + '.') === 0) ||
|
||||
(/* effect.trigger.wildcard && */ path.indexOf(effectArg) === 0);
|
||||
}
|
||||
|
||||
_fixPath(property, root, path) {
|
||||
return property + path.slice(root.length);
|
||||
}
|
||||
@@ -502,7 +495,7 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
|
||||
|
||||
// -- for method-based effects (complexObserver & computed) --------------
|
||||
|
||||
_createMethodEffect(model, sig, effectFn, methodInfo) {
|
||||
_createMethodEffect(model, sig, type, effectFn, methodInfo) {
|
||||
var dynamicFn = sig.dynamicFn;
|
||||
var info = {
|
||||
lib: this,
|
||||
@@ -512,20 +505,20 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
|
||||
dynamicFn: dynamicFn
|
||||
};
|
||||
if (sig.static) {
|
||||
this.addPropertyEffect(model, '__static__', {
|
||||
this.addPropertyEffect(model, '__static__', type, {
|
||||
fn: effectFn, info: info
|
||||
});
|
||||
} else {
|
||||
for (var i=0, arg; (i<sig.args.length) && (arg=sig.args[i]); i++) {
|
||||
if (!arg.literal) {
|
||||
this.addPropertyEffect(model, arg.rootProperty, {
|
||||
this.addPropertyEffect(model, arg.rootProperty, type, {
|
||||
fn: effectFn, info: info
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
if (dynamicFn) {
|
||||
this._addPropertyEffect(model, sig.methodName, {
|
||||
this._addPropertyEffect(model, sig.methodName, type, {
|
||||
fn: effectFn, info: info
|
||||
});
|
||||
}
|
||||
@@ -701,6 +694,14 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
|
||||
|
||||
}
|
||||
|
||||
var Types = PropertyEffects.Types = {
|
||||
COMPUTE: '_computeEffects',
|
||||
NOTIFY: '_notifyEffects',
|
||||
PROPAGATE: '_propagateEffects',
|
||||
OBSERVE: '_observeEffects',
|
||||
READ_ONLY: '_readOnly'
|
||||
}
|
||||
|
||||
// export
|
||||
Polymer.PropertyEffects = PropertyEffects;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user