Skip to content

Commit

Permalink
Add static API for creating property fx and minor code refactoring.
Browse files Browse the repository at this point in the history
  • Loading branch information
kevinpschaaf committed May 11, 2017
1 parent eb9c5af commit 7497065
Show file tree
Hide file tree
Showing 2 changed files with 169 additions and 15 deletions.
179 changes: 165 additions & 14 deletions lib/mixins/property-effects.html
Original file line number Diff line number Diff line change
Expand Up @@ -1026,21 +1026,23 @@
* Element class mixin that provides meta-programming for Polymer's template
* binding and data observation (collectively, "property effects") system.
*
* This mixin uses provides the following key methods for adding property effects
* to this element:
* - `_createPropertyObserver`
* - `_createMethodObserver`
* - `_createNotifyingProperty`
* - `_createReadOnlyProperty`
* - `_createReflectedProperty`
* - `_createComputedProperty`
* - `_bindTemplate`
* This mixin uses provides the following key static methods for adding
* property effects to an element class:
* - `createPropertyEffect`
* - `createPropertyObserver`
* - `createMethodObserver`
* - `createNotifyingProperty`
* - `createReadOnlyProperty`
* - `createReflectedProperty`
* - `createComputedProperty`
* - `bindTemplate`
*
* Each method creates one or more property accessors, along with metadata
* used by this mixin's implementation of `_propertiesChanged` to perform
* the property effects. These methods may be called on element instances,
* but are designed to be called on element prototypes such that the work to
* set up accessors and effect metadata are done once per element class.
* the property effects.
*
* Underscored versions of the above methods also exist on the element
* prototype for adding property effects on instances at runtime.
*
* Note that this mixin overrides several `PropertyAccessors` methods, in
* many cases to maintain guarantees provided by the Polymer 1.x features;
Expand Down Expand Up @@ -2004,6 +2006,150 @@
createMethodEffect(this, sig, TYPES.COMPUTE, runComputedEffect, property, dynamicFns);
}

// -- static class methods ------------

/**
* Ensures an accessor exists for the specified property, and adds
* to a list of "property effects" that will run when the accessor for
* the specified property is set. Effects are grouped by "type", which
* roughly corresponds to a phase in effect processing. The effect
* metadata should be in the following form:
*
* {
* fn: effectFunction, // Reference to function to call to perform effect
* info: { ... } // Effect metadata passed to function
* trigger: { // Optional triggering metadata; if not provided
* name: string // the property is treated as a wildcard
* structured: boolean
* wildcard: boolean
* }
* }
*
* Effects are called from `_propertiesChanged` in the following order by
* type:
*
* 1. COMPUTE
* 2. PROPAGATE
* 3. REFLECT
* 4. OBSERVE
* 5. NOTIFY
*
* Effect functions are called with the following signature:
*
* effectFunction(inst, path, props, oldProps, info, hasPaths)
*
* @param {string} property Property that should trigger the effect
* @param {string} type Effect type, from this.PROPERTY_EFFECT_TYPES
* @param {Object=} effect Effect metadata object
* @protected
*/
static addPropertyEffect(property, type, effect) {
this.prototype._addPropertyEffect(property, type, effect);
}

/**
* Creates a single-property observer for the given property.
*
* @param {string} property Property name
* @param {string} methodName Name of observer method to call
* @param {boolean=} dynamicFn Whether the method name should be included as
* a dependency to the effect.
* @protected
*/
static createPropertyObserver(property, methodName, dynamicFn) {
this.prototype._createPropertyObserver(property, methodName, dynamicFn);
}

/**
* Creates a multi-property "method observer" based on the provided
* expression, which should be a string in the form of a normal Javascript
* function signature: `'methodName(arg1, [..., argn])'`. Each argument
* should correspond to a property or path in the context of this
* prototype (or instance), or may be a literal string or number.
*
* @param {string} expression Method expression
* @param {Object=} dynamicFns Map indicating whether method names should
* be included as a dependency to the effect.
* @protected
*/
static createMethodObserver(expression, dynamicFns) {
this.prototype._createMethodObserver(expression, dynamicFns);
}

/**
* Causes the setter for the given property to dispatch `<property>-changed`
* events to notify of changes to the property.
*
* @param {string} property Property name
* @protected
*/
static createNotifyingProperty(property) {
this.prototype._createNotifyingProperty(property);
}

/**
* Creates a read-only accessor for the given property.
*
* To set the property, use the protected `_setProperty` API.
* To create a custom protected setter (e.g. `_setMyProp()` for
* property `myProp`), pass `true` for `protectedSetter`.
*
* Note, if the property will have other property effects, this method
* should be called first, before adding other effects.
*
* @param {string} property Property name
* @param {boolean=} protectedSetter Creates a custom protected setter
* when `true`.
* @protected
*/
static createReadOnlyProperty(property, protectedSetter) {
this.prototype._createReadOnlyProperty(property, protectedSetter);
}

/**
* Causes the setter for the given property to reflect the property value
* to a (dash-cased) attribute of the same name.
*
* @param {string} property Property name
* @protected
*/
static createReflectedProperty(property) {
this.prototype._createReflectedProperty(property);
}

/**
* Creates a computed property whose value is set to the result of the
* method described by the given `expression` each time one or more
* arguments to the method changes. The expression should be a string
* in the form of a normal Javascript function signature:
* `'methodName(arg1, [..., argn])'`
*
* @param {string} property Name of computed property to set
* @param {string} expression Method expression
* @param {Object=} dynamicFns Map indicating whether method names should
* be included as a dependency to the effect.
* @protected
*/
static createComputedProperty(property, expression, dynamicFns) {
this.prototype._createComputedProperty(property, expression, dynamicFns);
}

/**
* Parses the provided template to ensure binding effects are created
* for them, and then ensures property accessors are created for any
* dependent properties in the template. Binding effects for bound
* templates are stored in a linked list on the instance so that
* templates can be efficiently stamped and unstamped.
*
* @param {HTMLTemplateElement} template Template containing binding
* bindings
* @return {Object} Template metadata object
* @protected
*/
static bindTemplate(template) {
return this.prototype._bindTemplate(template);
}

// -- binding ----------------------------------------------

/**
Expand Down Expand Up @@ -2046,8 +2192,10 @@
templateInfo = Object.create(templateInfo);
templateInfo.wasPreBound = wasPreBound;
if (!wasPreBound && this.__templateInfo) {
templateInfo.nextTemplateInfo = this.__templateInfo;
this.__templateInfo.previousTemplateInfo = templateInfo;
let last = this.__templateInfoLast || this.__templateInfo;
this.__templateInfoLast = last.nextTemplateInfo = templateInfo;
templateInfo.previousTemplateInfo = last;
return templateInfo;
}
}
return this.__templateInfo = templateInfo;
Expand Down Expand Up @@ -2134,6 +2282,9 @@
templateInfo.nextTemplateInfo.previousTemplateInfo =
templateInfo.previousTemplateInfo;
}
if (this.__templateInfoLast == templateInfo) {
this.__templateInfoLast = templateInfo.previousTemplateInfo;
}
// Remove stamped nodes
let nodes = templateInfo.childNodes;
for (let i=0; i<nodes.length; i++) {
Expand Down
5 changes: 4 additions & 1 deletion lib/mixins/template-stamp.html
Original file line number Diff line number Diff line change
Expand Up @@ -281,7 +281,10 @@
if (this._parseTemplateNode(node, templateInfo, childInfo)) {
childInfo.infoIndex = templateInfo.nodeInfoList.push(childInfo) - 1;
}
parentIndex++;
// Increment if not removed
if (node.parentNode) {
parentIndex++;
}
}
}

Expand Down

0 comments on commit 7497065

Please sign in to comment.