diff --git a/lib/legacy/class.js b/lib/legacy/class.js index bb4326e370..77eb4fb690 100644 --- a/lib/legacy/class.js +++ b/lib/legacy/class.js @@ -155,6 +155,27 @@ 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 value = targetInfo && targetInfo.value; + const sourceInfo = source[p]; + if (sourceInfo.value === undefined && value !== undefined) { + target[p] = Object.assign({value}, sourceInfo); + } else { + target[p] = sourceInfo; + } + } +} + /* Note about construction and extension of legacy classes. [Changed in Q4 2018 to optimize performance.] @@ -227,10 +248,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..993ab0a3db 100644 --- a/test/unit/behaviors.html +++ b/test/unit/behaviors.html @@ -402,15 +402,15 @@ behaviors: [ { properties: { - foo: { value: true }, - bar: { value: true} + foo: { value: 'a' }, + bar: { value: 'a'} } }, { properties: { - foo: { value: true }, + foo: { value: 'b' }, bar: String, - zot: {value: true} + zot: {value: 'b'} } }, @@ -587,9 +587,9 @@ 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'); }); test('readOnly not applied when property was previously observed', function() {