diff --git a/src/declaration/properties.js b/src/declaration/properties.js index 3e40ac7..b0494b1 100644 --- a/src/declaration/properties.js +++ b/src/declaration/properties.js @@ -64,27 +64,39 @@ prototype._publishLC = this.lowerCaseMap(publish); } }, - requireProperties: function(properties, prototype, base) { + // sync prototype to property descriptors; + // desriptor format contains default value and optionally a + // hint for reflecting the property to an attribute. + // e.g. {foo: 5, bar: {value: true, reflect: true}} + // reflect: {foo: true} is also supported + // + requireProperties: function(propertyDescriptors, prototype, base) { // reflected properties prototype.reflect = prototype.reflect || {}; // ensure a prototype value for each property - for (var n in properties) { - if (this.valueReflects(properties[n])) { - prototype.reflect[n] = true; + // and update the property's reflect to attribute status + for (var n in propertyDescriptors) { + var propertyDescriptor = propertyDescriptors[n]; + var reflects = this.reflectHintForDescriptor(propertyDescriptor); + if (prototype.reflect[n] === undefined && reflects !== undefined) { + prototype.reflect[n] = reflects; } - if (prototype[n] === undefined && base[n] === undefined) { - prototype[n] = this.valueForProperty(properties[n]); + if (prototype[n] === undefined) { + prototype[n] = this.valueForDescriptor(propertyDescriptor); } } }, - valueForProperty: function(propertyValue) { - return (typeof propertyValue === 'object' && propertyValue !== null) ? - (propertyValue.value !== undefined ? propertyValue.value : null) : - propertyValue; + valueForDescriptor: function(propertyDescriptor) { + var value = typeof propertyDescriptor === 'object' && + propertyDescriptor ? propertyDescriptor.value : propertyDescriptor; + return value !== undefined ? value : null; }, - valueReflects: function(propertyValue) { - return (typeof propertyValue === 'object' && propertyValue !== null && - propertyValue.reflect); + // returns the value of the descriptor's 'reflect' property or undefined + reflectHintForDescriptor: function(propertyDescriptor) { + if (typeof propertyDescriptor === 'object' && + propertyDescriptor && propertyDescriptor.reflect !== undefined) { + return propertyDescriptor.reflect; + } }, lowerCaseMap: function(properties) { var map = {}; diff --git a/test/html/prop-attr-reflection.html b/test/html/prop-attr-reflection.html index dc3533c..08173fa 100644 --- a/test/html/prop-attr-reflection.html +++ b/test/html/prop-attr-reflection.html @@ -36,6 +36,18 @@ }); + + + + + @@ -109,6 +121,16 @@ //assert.isFalse(xbar.hasAttribute('obj'), 'property with default type of object does not serialize'); done(); }); + + var xzot = document.querySelector('x-zot'); + assert.equal(xzot.str, 'str2'); + xzot.str = 'hello'; + assert.equal(xzot.getAttribute('str'), xzot.str); + + assert.equal(xzot.zot, 2); + xzot.zot = 5; + assert.isFalse(xzot.hasAttribute('zot'), 'extendee reflect false not honored'); + xbar.obj = 'hi'; Platform.flush(); // trigger a mutation to watch diff --git a/test/html/publish-attributes.html b/test/html/publish-attributes.html index c82be6d..dadb22f 100644 --- a/test/html/publish-attributes.html +++ b/test/html/publish-attributes.html @@ -53,6 +53,18 @@ assert.deepEqual( XBar.prototype.publish, {Foo: null, baz: null, Bar: null}); + assert.deepEqual( + XZot.prototype.publish, + {Foo: null, baz: null, Bar: null, zot: 3}); + assert.deepEqual( + XSquid.prototype.publish, + {Foo: null, baz: 13, Bar: null, zot: 5, squid: 7}); + assert.equal(XSquid.prototype.Foo, XSquid.prototype.publish.Foo); + assert.equal(XSquid.prototype.baz, XSquid.prototype.publish.baz); + assert.equal(XSquid.prototype.Bar, XSquid.prototype.publish.Bar); + assert.equal(XSquid.prototype.zot, XSquid.prototype.publish.zot); + assert.equal(XSquid.prototype.squid, XSquid.prototype.publish.squid); + done(); });