Skip to content

Commit

Permalink
Opt in to "even lazier" behavior by setting lazyRegister to "max". …
Browse files Browse the repository at this point in the history
…This was done to preserve compatibility with the existing feature. Specifically, when "max" is used, setting `is` in `beforeRegister` and defining `factoryImpl` may only be done on an element's prototype and not its behaviors. In addition, the element's `beforeRegister` is called *before* its behaviors' `beforeRegisters` rather than *after* as in the normal case.
  • Loading branch information
Steven Orvell committed Jul 22, 2016
1 parent fb95dc8 commit b271a88
Show file tree
Hide file tree
Showing 6 changed files with 88 additions and 19 deletions.
29 changes: 24 additions & 5 deletions src/lib/base.html
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,24 @@

// `this` context is a prototype, not an instance
registerCallback: function() {
/*
When lazyRegister is 'max' defer all behavior work until first element
creation.
When set, a behavior cannot setup an element's `is` or
custom constructor via defining `factoryImpl`.
We do call beforeRegister on the prototype to preserve
the ability to use it in ES6. This orders the element
prototype's `beforeRegister` before behaviors' rather than after
as in the normal case.
*/
if (settings.lazyRegister === 'max') {
if (this.beforeRegister) {
this.beforeRegister();
}
} else {
this._desugarBehaviors(); // abstract
this._doBehavior('beforeRegister'); // abstract
}
this._registerFeatures(); // abstract
if (!settings.lazyRegister) {
this.ensureRegisterFinished();
Expand Down Expand Up @@ -59,11 +77,12 @@

_ensureRegisterFinished: function(proto) {
if (proto.__hasRegisterFinished !== proto.is || !proto.is) {
// NOTE: since all behavior is here, this means
// custom constructor and `is` cannot be done in a behavior
// when lazyRegister is true.
proto._desugarBehaviors(); // abstract
proto._doBehavior('beforeRegister'); // abstract
// apply behavior's beforeRegister at first instance time
// IFF `lazyRegister` is 'max'
if (settings.lazyRegister === 'max') {
proto._desugarBehaviors(); // abstract
proto._doBehaviorOnly('beforeRegister'); // abstract
}
proto.__hasRegisterFinished = proto.is;
if (proto._finishRegisterFeatures) {
proto._finishRegisterFeatures();
Expand Down
7 changes: 7 additions & 0 deletions src/micro/behaviors.html
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,13 @@
this._invokeBehavior(this, name, args);
},

// note: repeating logic here to avoid fn call.
_doBehaviorOnly: function(name, args) {
for (var i=0; i < this.behaviors.length; i++) {
this._invokeBehavior(this.behaviors[i], name, args);
}
},

_invokeBehavior: function(b, name, args) {
var fn = b[name];
if (fn) {
Expand Down
2 changes: 2 additions & 0 deletions test/runner.html
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@
'unit/dom-module-inline.html',
'unit/async.html',
'unit/behaviors.html',
'unit/behaviors.html?lazyRegister=true',
'unit/behaviors.html?lazyRegister=max',
'unit/template.html',
'unit/template-whitespace.html',
'unit/ready.html',
Expand Down
31 changes: 31 additions & 0 deletions test/smoke/es6.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<!doctype html>
<html>
<head>
<script src="../../../webcomponentsjs/webcomponents.js"></script>
<script>
Polymer = {lazyRegister: true};
</script>
<link rel="import" href="../../polymer.html">
</head>
<body>
<dom-module id="my-element">
<template>
es6
</template>
</dom-module>

<script>
class MyElement {
beforeRegister() {
this.is = 'my-element';
}
}

Polymer(MyElement);
</script>


<my-element></my-element>

</body>
</html>
17 changes: 11 additions & 6 deletions test/unit/behaviors-elements.html
Original file line number Diff line number Diff line change
Expand Up @@ -249,14 +249,19 @@
}
};

Polymer({
try {

behaviors: [
Polymer.registerBehavior
],
Polymer({

as: 'behavior-as-is'
behaviors: [
Polymer.registerBehavior
],

});
as: 'behavior-as-is'

});
} catch(e) {
window.behaviorAsIsFail = true;
}

</script>
21 changes: 13 additions & 8 deletions test/unit/behaviors.html
Original file line number Diff line number Diff line change
Expand Up @@ -53,13 +53,17 @@
});

test('beforeRegister behavior', function() {
var el = document.createElement('behavior-as-is');
assert.equal(el.is, 'behavior-as-is');
assert.ok(el.$.content);
el.prop = 42;
assert.isTrue(el.propChanged1Called);
assert.isTrue(el.propChanged2Called);
assert.isTrue(el.hasAttribute('attr'));
if (Polymer.Settings.lazyRegister === 'max') {
assert.isTrue(window.behaviorAsIsFail, 'Setting `is` in a behavior did not fail when lazyRegister: `max` set');
} else {
var el = document.createElement('behavior-as-is');
assert.equal(el.is, 'behavior-as-is');
assert.ok(el.$.content);
el.prop = 42;
assert.isTrue(el.propChanged1Called);
assert.isTrue(el.propChanged2Called);
assert.isTrue(el.hasAttribute('attr'));
}
});

});
Expand Down Expand Up @@ -127,7 +131,7 @@
assert.equal(el.attributes.user.value, 'user', 'Behavior hostAttribute overrode user attribute');
});

test('behaviour is null generates warning', function() {
test('behavior is null generates warning', function() {
var warned = false, oldWarn = Polymer.Base._warn;
Polymer.Base._warn = function (message) {
assert.match(message, /behavior is null/);
Expand All @@ -139,6 +143,7 @@
null
]
});
document.createElement('behavior-null');
assert.equal(warned, true, 'Null behaviour should generate warning');
Polymer.Base._warn = oldWarn;
});
Expand Down

0 comments on commit b271a88

Please sign in to comment.