Skip to content

Commit

Permalink
Fixes #74. The finalize technique used in Polymer.Element is not am…
Browse files Browse the repository at this point in the history
…enable to subclassing and may need to be rethought. To work around this issue for now, classes generated from Polymer 1 style objects use a separate mechanism to call `registered`.
  • Loading branch information
Steven Orvell committed Aug 19, 2016
1 parent 7f11f5f commit a0878fb
Show file tree
Hide file tree
Showing 3 changed files with 96 additions and 64 deletions.
31 changes: 16 additions & 15 deletions src/compat/class.html
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@
for (var i=0; i<behaviors.length; i++) {
var b = behaviors[i];
if (b) {
klass = Array.isArray(b) ? mixinBehaviors(b, klass) :
klass = Array.isArray(b) ? mixinBehaviors(b, klass) :
MixinBehavior(b, klass);
}
}
Expand Down Expand Up @@ -72,29 +72,30 @@
properties: behavior.properties,
observers: behavior.observers
};

class PolymerGenerated extends Base {

static get config() {
return config;
}

static finalize() {
if (!this.finalized) {
super.finalize();
if (behavior.registered) {
behavior.registered.call(this.prototype);
}
this.finalized = true;
}
}

_invokeFunction(fn, args) {
if (fn) {
fn.apply(this, args);
}
}

constructor() {
super();
// call `registereed` only if it was not called for *this* constructor
if (!PolymerGenerated.hasOwnProperty('__registered')) {
PolymerGenerated.__registered = true;
if (behavior.registered) {
behavior.registered.call(Object.getPrototypeOf(this));
}
}
}

created() {
super.created();
this._invokeFunction(behavior.created);
Expand Down Expand Up @@ -128,7 +129,7 @@
}

for (var p in behavior) {
if (!(p in metaProps))
if (!(p in metaProps))
utils.copyOwnProperty(p, behavior, PolymerGenerated.prototype);
}

Expand Down Expand Up @@ -176,12 +177,12 @@
// behaviors on prototype for BC...
behaviors.reverse();
klass.prototype.behaviors = behaviors;
// NOTE: while we could call `beforeRegister` here to maintain
// NOTE: while we could call `beforeRegister` here to maintain
// some BC, the state of the element at this point is not as it was in 1.0
// In 1.0, the method was called *after* mixing prototypes together
// but before processing of meta-objects. Since this is now done
// in 1 step via `MixinBehavior`, this is no longer possible.
// However, *most* work (not setting `is`) that was previously done in
// However, *most* work (not setting `is`) that was previously done in
// `beforeRegister` should be possible in `registered`.
return klass;
}
Expand Down
45 changes: 45 additions & 0 deletions test/smoke/behaviors-registered.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
<!doctype html>
<!--
@license
Copyright (c) 2014 The Polymer Project Authors. All rights reserved.
This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
Code distributed by Google as part of the polymer project is also
subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
-->
<html>
<head>
<title>Polymer - behaviors</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script src="../../../webcomponentsjs/webcomponents-lite.js"></script>
<link rel="import" href="../../polymer.html">
</head>
<body>
<dom-module id="my-element">
<template>
Check console output
</template>
<script>
let count = 0;
let TestBehavior = {
// Invoked once in Polymer 1.0, twice in alacarte.
registered: function() {
console.log(++count);
console.log(this.behaviors);
}
};
Polymer({
is: 'my-element',
behaviors: [TestBehavior]
});
</script>
</dom-module>

</head>
<body>
<my-element></my-element>
</body>
</body>
</html>
84 changes: 35 additions & 49 deletions test/unit/behaviors.html
Original file line number Diff line number Diff line change
Expand Up @@ -210,7 +210,7 @@
<div id="content"></div>
</template>
<script>
Polymer.registerBehavior ={
Polymer.registerBehavior1 ={
registered: function() {
this.constructor.createProperties({
prop: {
Expand All @@ -220,6 +220,8 @@
this.constructor.createMethodObservers([
'propChanged2(prop)'
]);
this.registeredCount++;
this.registeredThis = this;
},
ready: function() {
this.ensureAttributes({
Expand All @@ -234,61 +236,37 @@
}
};

Polymer({
behaviors: [
Polymer.registerBehavior
],

is: 'behavior-registered'
});
</script>
</dom-module>

<!--
<dom-module id="behavior-as-is">
<template><div id="content"></div></template>
<script>
Polymer.registerBehavior ={
beforeRegister: function() {
this.is = this.as;
this.properties = {
prop: {
observer: 'propChanged1'
}
};
this.hostAttributes = {
attr: true
};
this.observers = [
'propChanged2(prop)'
];
},
propChanged1: function() {
this.propChanged1Called = true;
},
propChanged2: function() {
this.propChanged2Called = true;
Polymer.registerBehavior2 ={
registered: function() {
this.registeredCount++;
}
};

try {
Polymer.registerBehavior3 ={
registered: function() {
this.registeredCount++;
}
};

Polymer({
Polymer({
behaviors: [
Polymer.registerBehavior1,
Polymer.registerBehavior2,
Polymer.registerBehavior3
],

behaviors: [
Polymer.registerBehavior
],
registered: function() {
this.registeredCount++;
},

as: 'behavior-as-is'
registeredCount: 0,

});
} catch(e) {
window.behaviorAsIsFail = true;
}
is: 'behavior-registered'
});
</script>
</dom-module>
-->
</script>

</script>

<test-fixture id="single">
<template>
Expand Down Expand Up @@ -357,17 +335,25 @@
});
});

suite('registered behavior', function() {
test('registered behavior', function() {
suite('behavior.registered', function() {
test('can install dynamic properties', function() {
var el = fixture('registered');
assert.ok(el.$.content);
el.prop = 42;
assert.isTrue(el.propChanged1Called);
assert.isTrue(el.propChanged2Called);
assert.isTrue(el.hasAttribute('attr'));
});

test('called once for each behavior with access to element prototype', function() {
var el = fixture('registered');
assert.equal(el.registeredCount, 4);
assert.equal(el.registeredThis, Object.getPrototypeOf(el));
});

});


suite('multi-behaviors element', function() {
var el;

Expand Down

0 comments on commit a0878fb

Please sign in to comment.