|
62 | 62 | * @suppress {invalidCasts, checkTypes} |
63 | 63 | */ |
64 | 64 | function mixinBehaviors(behaviors, klass) { |
65 | | - if (behaviors) { |
66 | | - klass = applyBehaviors(behaviors, klass); |
67 | | - } |
68 | | - // provides behaviors functionality |
69 | | - return GenerateClassFromInfo({}, klass); |
70 | | - } |
71 | | - |
72 | | - function applyBehaviors(behaviors, klass) { |
73 | | - if (!behaviors) { |
74 | | - klass = /** @type {HTMLElement} */(klass); // eslint-disable-line no-self-assign |
75 | | - return klass; |
76 | | - } |
77 | | - // NOTE: ensure the behavior is extending a class with |
78 | | - // legacy element api. This is necessary since behaviors expect to be able |
79 | | - // to access 1.x legacy api. |
80 | | - klass = class extends Polymer.LegacyElementMixin(klass) { }; |
81 | | - if (!Array.isArray(behaviors)) { |
82 | | - behaviors = [behaviors]; |
83 | | - } |
84 | | - let superBehaviors = klass.prototype.behaviors; |
85 | | - // get flattened, deduped list of behaviors *not* already on super class |
86 | | - behaviors = flattenBehaviors(behaviors, null, superBehaviors); |
87 | | - if (superBehaviors) { |
88 | | - behaviors = superBehaviors.concat(behaviors); |
89 | | - } |
90 | | - // Set behaviors on prototype |
91 | | - klass.prototype.behaviors = behaviors; |
92 | | - return klass; |
| 65 | + return GenerateClassFromInfo({}, Polymer.LegacyElementMixin(klass), behaviors); |
93 | 66 | } |
94 | 67 |
|
95 | 68 | // NOTE: |
|
124 | 97 | // (again same as 1.x) |
125 | 98 | function copyBehaviorProperties(behaviors, klass) { |
126 | 99 | const meta = {}; |
| 100 | + const superMeta = klass.prototype.__behaviorMetaProps; |
127 | 101 | if (behaviors) { |
128 | 102 | klass.prototype.__behaviorMetaProps = meta; |
129 | 103 | for (let i=0; i<behaviors.length; i++) { |
130 | 104 | copyProperties(behaviors[i], klass.prototype); |
131 | | - memoizeBehaviorMetaProps(meta, behaviors[i]); |
| 105 | + memoizeBehaviorMetaProps(meta, behaviors[i], superMeta); |
132 | 106 | } |
133 | 107 | } |
134 | 108 | klass.prototype.__behaviorMetaProps = meta; |
135 | 109 | } |
136 | 110 |
|
137 | | - function memoizeBehaviorMetaProps(meta, behavior) { |
| 111 | + function memoizeBehaviorMetaProps(meta, behavior, superMeta) { |
138 | 112 | for (let p in memoizedProps) { |
139 | 113 | if (behavior[p]) { |
140 | | - meta[p] = meta[p] || []; |
| 114 | + meta[p] = meta[p] || (superMeta && superMeta[p] ? superMeta[p].slice() : []); |
141 | 115 | meta[p].push(behavior[p]); |
142 | 116 | } |
143 | 117 | } |
|
222 | 196 | * @suppress {checkTypes} |
223 | 197 | * @private |
224 | 198 | */ |
225 | | - function GenerateClassFromInfo(info, Base) { |
| 199 | + function GenerateClassFromInfo(info, Base, behaviors) { |
226 | 200 |
|
227 | 201 | /** @private */ |
228 | 202 | class PolymerGenerated extends Base { |
|
289 | 263 | /** |
290 | 264 | * @return {void} |
291 | 265 | */ |
| 266 | + // Called on element prototype |
292 | 267 | _registered() { |
293 | 268 | /* NOTE: `beforeRegister` is called here for bc, but the behavior |
294 | 269 | is different than in 1.x. In 1.0, the method was called *after* |
|
297 | 272 | in `beforeRegister` or `registered`. It is no longer possible to set |
298 | 273 | `is` in `beforeRegister` as you could in 1.x. |
299 | 274 | */ |
300 | | - const proto = Object.getPrototypeOf(this); |
301 | | - copyBehaviorProperties(proto.behaviors, proto.constructor); |
| 275 | + const proto = this; |
| 276 | + if (proto.hasOwnProperty('behaviors')) { |
| 277 | + copyBehaviorProperties(proto.behaviors, proto.constructor); |
| 278 | + } |
| 279 | + proto.__behaviorMetaProps = proto.__behaviorMetaProps || {}; |
302 | 280 | copyProperties(info, proto); |
303 | 281 | // Note, previously these were interleaved. |
304 | | - let list = this.__behaviorMetaProps.beforeRegister; |
| 282 | + let list = proto.__behaviorMetaProps.beforeRegister; |
305 | 283 | if (list) { |
306 | 284 | for (let i=0; i < list.length; i++) { |
307 | 285 | list[i].call(proto); |
308 | 286 | } |
309 | 287 | } |
310 | | - list = this.__behaviorMetaProps.registered; |
| 288 | + list = proto.__behaviorMetaProps.registered; |
311 | 289 | if (list) { |
312 | 290 | for (let i=0; i < list.length; i++) { |
313 | 291 | list[i].call(proto); |
|
431 | 409 | if (info.attributeChanged) { |
432 | 410 | info.attributeChanged.call(this, name, old, value); |
433 | 411 | } |
434 | | - } |
| 412 | + } |
| 413 | + } |
| 414 | + |
| 415 | + // apply behaviors |
| 416 | + if (behaviors) { |
| 417 | + // NOTE: ensure the behavior is extending a class with |
| 418 | + // legacy element api. This is necessary since behaviors expect to be able |
| 419 | + // to access 1.x legacy api. |
| 420 | + if (!Array.isArray(behaviors)) { |
| 421 | + behaviors = [behaviors]; |
| 422 | + } |
| 423 | + let superBehaviors = PolymerGenerated.prototype.__allBehaviors; |
| 424 | + // get flattened, deduped list of behaviors *not* already on super class |
| 425 | + behaviors = flattenBehaviors(behaviors, null, superBehaviors); |
| 426 | + PolymerGenerated.prototype.__allBehaviors = superBehaviors ? |
| 427 | + superBehaviors.concat(behaviors) : behaviors; |
| 428 | + PolymerGenerated.prototype.behaviors = behaviors; |
435 | 429 | } |
436 | 430 |
|
437 | 431 | PolymerGenerated.generatedFrom = info; |
|
513 | 507 | } |
514 | 508 | let klass = mixin ? mixin(Polymer.LegacyElementMixin(HTMLElement)) : |
515 | 509 | Polymer.LegacyElementMixin(HTMLElement); |
516 | | - if (info.behaviors) { |
517 | | - klass = applyBehaviors(info.behaviors, klass); |
518 | | - } |
519 | | - klass = GenerateClassFromInfo(info, klass); |
| 510 | + klass = GenerateClassFromInfo(info, klass, info.behaviors); |
520 | 511 | // decorate klass with registration info |
521 | 512 | klass.is = info.is; |
522 | 513 | return klass; |
|
0 commit comments