Skip to content

Commit

Permalink
Factoring improvements around attribute serialize/deserialize
Browse files Browse the repository at this point in the history
  • Loading branch information
Steven Orvell committed Nov 16, 2017
1 parent fb0f90b commit a7b46b1
Show file tree
Hide file tree
Showing 4 changed files with 28 additions and 54 deletions.
4 changes: 2 additions & 2 deletions lib/mixins/element-mixin.html
Original file line number Diff line number Diff line change
Expand Up @@ -283,7 +283,7 @@
* @param {Object} dynamicFns Object containing keys for any properties
* that are functions and should trigger the effect when the function
* reference is changed
* @private
* @protected
*/
static createObservers(observers, dynamicFns) {
const proto = this.prototype;
Expand Down Expand Up @@ -564,7 +564,7 @@
*/
attributeChangedCallback(name, old, value) {
if (old !== value) {
let property = caseMap.dashToCamelCase(name);
let property = this._attributeForProperty(name);
if (!this._hasReadOnlyEffect(property)) {
super.attributeChangedCallback(name, old, value);
}
Expand Down
18 changes: 13 additions & 5 deletions lib/mixins/properties-changed.html
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@
/**
* Creates property accessors for the given property names.
* @param {Object} props Object whose keys are names of accessors.
* @protected
*/
static createProperties(props) {
const proto = this.prototype;
Expand Down Expand Up @@ -88,16 +89,16 @@
}
if (!this.__dataHasAccessor[property]) {
this.__dataHasAccessor[property] = true;
this._generatePropertyAccessor(property, readOnly);
this._definePropertyAccessor(property, readOnly);
}
}

/**
* Generates a property accessor for the given property.
* Defines a property accessor for the given property.
* @param {string} property Name of the property
* @param {boolean=} readOnly When true, no setter is created
*/
_generatePropertyAccessor(property, readOnly) {
_definePropertyAccessor(property, readOnly) {
Object.defineProperty(this, property, {
/* eslint-disable valid-jsdoc */
/** @this {PropertiesChanged} */
Expand Down Expand Up @@ -416,14 +417,21 @@
*
* This method is called when reading HTML attribute values to
* JS properties. Users may override this method to provide
* deserialization for custom `type`s.
* deserialization for custom `type`s. The given `type` is executed
* as a function with the value as an argument. The `Boolean` `type`
* is specially handled such that an empty string returns true.
*
* @param {?string} value Value to deserialize.
* @param {*=} type Type to deserialize the string to.
* @return {*} Typed value deserialized from the provided string.
*/
_deserializeValue(value, type) {
return typeof type == 'function' ? type(value) : value;
switch (type) {
case Boolean:
return (value !== null);
default:
return typeof type == 'function' ? type(value) : value;
}
}

/**
Expand Down
23 changes: 10 additions & 13 deletions lib/mixins/properties-mixin.html
Original file line number Diff line number Diff line change
Expand Up @@ -42,28 +42,25 @@
*/
const base = Polymer.PropertiesChanged(superClass);

function BooleanAttribute(value) {
return value !== null;
}

/**
* Mixes `moreProps` into `props` but upgrades shorthand type
* syntax to { type: Type}.
*
* @param {Object} props Bag to collect flattened properties into
* @param {Object} moreProps Bag of properties to add to `props`
* @return {Object} The input `props` bag
* @param {Object} props Properties to normalize
* @return {Object} Copy of input `props` with normalized properties that
* are in the form {type: Type}
* @private
*/
function mixProperties(props, moreProps) {
for (let p in moreProps) {
let o = moreProps[p];
function normalizeProperties(props) {
const output = {};
for (let p in props) {
let o = props[p];
if (typeof o == 'function') {
o = { type: o };
}
props[p] = o;
output[p] = o;
}
return props;
return output;
}

/**
Expand Down Expand Up @@ -93,7 +90,7 @@
if (!ctor.hasOwnProperty(
JSCompiler_renameProperty('__ownProperties', ctor))) {
const props = ctor.properties;
ctor.__ownProperties = props ? mixProperties({}, props) : null;
ctor.__ownProperties = props ? normalizeProperties(props) : null;
}
return ctor.__ownProperties;
}
Expand Down
37 changes: 3 additions & 34 deletions lib/mixins/property-accessors.html
Original file line number Diff line number Diff line change
Expand Up @@ -204,21 +204,6 @@
}
}

/**
* Overrides PropertiesChanged implementation to calls the
* `_serializeValue` method to convert the typed value to a string.
* If the `_serializeValue` method returns `undefined`,
* the attribute will be removed (this is the default for boolean
* type `false`).
*
* @param {Element} node Element to set attribute to.
* @param {*} value Value to serialize.
* @param {string} attribute Attribute name to serialize to.
*/
_valueToNodeAttribute(node, value, attribute) {
super._valueToNodeAttribute(node, this._serializeValue(value), attribute);
}

/**
* Overrides PropertiesChanged implemention to serialize objects as JSON.
*
Expand Down Expand Up @@ -265,22 +250,13 @@
*/
let outValue;
switch (type) {
case Number:
outValue = Number(value);
break;

case Boolean:
outValue = (value !== null);
break;

case Object:
try {
outValue = JSON.parse(/** @type {string} */(value));
} catch(x) {
// allow non-JSON literals like Strings and Numbers
}
break;

case Array:
try {
outValue = JSON.parse(/** @type {string} */(value));
Expand All @@ -289,17 +265,10 @@
console.warn(`Polymer::Attributes: couldn't decode Array as JSON: ${value}`);
}
break;

case Date:
outValue = new Date(value);
break;

case String:
default:
outValue = value;
outValue = super._deserializeValue(value, type);
break;
}

return outValue;
}
/* eslint-enable no-fallthrough */
Expand All @@ -318,9 +287,9 @@
* for the values to take effect.
* @protected
*/
_generatePropertyAccessor(property, readOnly) {
_definePropertyAccessor(property, readOnly) {
saveAccessorValue(this, property);
super._generatePropertyAccessor(property, readOnly);
super._definePropertyAccessor(property, readOnly);
}

/**
Expand Down

0 comments on commit a7b46b1

Please sign in to comment.