diff --git a/lib/legacy/class.js b/lib/legacy/class.js index bb4326e370..a35c0c5c84 100644 --- a/lib/legacy/class.js +++ b/lib/legacy/class.js @@ -155,6 +155,26 @@ function flattenBehaviors(behaviors, list, exclude) { return list; } +/** + * Copies property descriptors from source to target, overwriting all fields + * of any previous descriptor for a property *except* for `value`, which is + * merged in from the target if it does not exist on the source. + * + * @param {*} target Target properties object + * @param {*} source Source properties object + */ +function mergeProperties(target, source) { + for (const p in source) { + const targetInfo = target[p]; + const sourceInfo = source[p]; + if (!('value' in sourceInfo) && targetInfo && ('value' in targetInfo)) { + target[p] = Object.assign({value: targetInfo.value}, sourceInfo); + } else { + target[p] = sourceInfo; + } + } +} + /* Note about construction and extension of legacy classes. [Changed in Q4 2018 to optimize performance.] @@ -227,10 +247,10 @@ function GenerateClassFromInfo(info, Base, behaviors) { const properties = {}; if (behaviorList) { for (let i=0; i < behaviorList.length; i++) { - Object.assign(properties, behaviorList[i].properties); + mergeProperties(properties, behaviorList[i].properties); } } - Object.assign(properties, info.properties); + mergeProperties(properties, info.properties); return properties; } diff --git a/test/unit/behaviors.html b/test/unit/behaviors.html index 33bdc92497..6af4b6512b 100644 --- a/test/unit/behaviors.html +++ b/test/unit/behaviors.html @@ -402,15 +402,17 @@ behaviors: [ { properties: { - foo: { value: true }, - bar: { value: true} + foo: { value: 'a' }, + bar: { value: 'a' }, + ziz: { value: 'a' } } }, { properties: { - foo: { value: true }, + foo: { value: 'b' }, bar: String, - zot: {value: true} + zot: { value: 'b' }, + ziz: { value: 'b' } } }, @@ -418,7 +420,8 @@ properties: { foo: String, - zot: String + zot: String, + ziz: { value: 'c' } } }); @@ -587,9 +590,10 @@ test('behavior default values can be overridden', function() { const el = fixture('override-default-value'); - assert.notOk(el.foo); - assert.notOk(el.bar); - assert.notOk(el.zot); + assert.equal(el.foo, 'b'); + assert.equal(el.bar, 'a'); + assert.equal(el.zot, 'b'); + assert.equal(el.ziz, 'c'); }); test('readOnly not applied when property was previously observed', function() {