Skip to content

Commit

Permalink
Closure type fixes.
Browse files Browse the repository at this point in the history
  • Loading branch information
kevinpschaaf committed Jul 1, 2019
1 parent 18c83de commit ff25283
Show file tree
Hide file tree
Showing 6 changed files with 147 additions and 74 deletions.
163 changes: 119 additions & 44 deletions lib/elements/dom-if.js
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,10 @@ class DomIfBase extends PolymerElement {
this.__renderDebouncer = null;
this._lastIf = false;
this.__hideTemplateChildren__ = false;
/** @type {!HTMLTemplateElement|undefined} */
this.__template;
/** @type {!TemplateInfo|undefined} */
this._templateInfo;
}

__debounceRender() {
Expand Down Expand Up @@ -145,19 +149,23 @@ class DomIfBase extends PolymerElement {
/**
* Ensures a template has been assigned to `this.__template`. If it has not
* yet been, it querySelectors for it in its children and if it does not yet
* exist (e.g. in parser-generated case), opens a mutation observer and
* exist (e.g. in parser-generated case), opens a mutation observer and
* waits for it to appear (returns false if it has not yet been found,
* otherwise true). In the `removeNestedTemplates` case, the "template" will
* be the `dom-if` element itself.
*
*
* @return {boolean} True when a template has been found, false otherwise
*/
__ensureTemplate() {
if (!this.__template) {
// When `removeNestedTemplates` is true, the "template" is the element
// itself, which has been given a `_templateInfo` property
let template = this._templateInfo ? this :
/** @type {HTMLTemplateElement} */(wrap(this).querySelector('template'));
const thisAsTemplate = /** @type {!HTMLTemplateElement} */ (
/** @type {!HTMLElement} */ (this));
let template = thisAsTemplate._templateInfo ?
thisAsTemplate :
/** @type {!HTMLTemplateElement} */
(wrap(thisAsTemplate).querySelector('template'));
if (!template) {
// Wait until childList changes and template should be there by then
let observer = new MutationObserver(() => {
Expand All @@ -183,12 +191,12 @@ class DomIfBase extends PolymerElement {
* connection or the template-finding mutation observer firing will queue
* another render, causing this method to be called again at a more
* appropriate time).
*
*
* Subclasses should implement the following methods called here:
* - `__hasInstance`
* - `__createAndInsertInstance`
* - `__getInstanceNodes`
*
*
* @return {boolean} True if the instance was created, false otherwise.
*/
__ensureInstance() {
Expand Down Expand Up @@ -225,7 +233,7 @@ class DomIfBase extends PolymerElement {
* that multiple changes trigger only a single render. The render method
* should be called if, for example, template rendering is required to
* validate application state.
*
*
* @return {void}
*/
render() {
Expand All @@ -238,7 +246,7 @@ class DomIfBase extends PolymerElement {
* 2. Remove the template instance (when false and restamp:true)
* 3. Sync the hidden state of the instance nodes with the if/restamp state
* 4. Fires the `dom-change` event when necessary
*
*
* @return {void}
*/
__render() {
Expand All @@ -259,6 +267,54 @@ class DomIfBase extends PolymerElement {
this._lastIf = this.if;
}
}

/**
* Abstract API to be implemented by subclass: Returns true if a template
* instance has been created and inserted.
*
* @protected
* @return {boolean} True when an instance has been created.
*/
__hasInstance() { }

/**
* Abstract API to be implemented by subclass: Returns the child nodes stamped
* from a template instance.
*
* @protected
* @return {Array<Node>} Array of child nodes stamped from the template
* instance.
*/
__getInstanceNodes() { }

/**
* Abstract API to be implemented by subclass: Creates an instance of the
* template and inserts it into the given parent node.
*
* @protected
* @param {Node} parentNode The parent node to insert the instance into
* @return {void}
*/
__createAndInsertInstance(parentNode) { }

/**
* Abstract API to be implemented by subclass: Removes nodes created by an
* instance of a template and any associated cleanup.
*
* @protected
* @return {void}
*/
__teardownInstance() { }

/**
* Abstract API to be implemented by subclass: Shows or hides any template
* instance childNodes based on the `if` state of the element and its
* `__hideTemplateChildren__` property.
*
* @protected
* @return {void}
*/
_showHideChildren() { }
}

/**
Expand Down Expand Up @@ -291,7 +347,8 @@ class DomIfFast extends DomIfBase {

/**
* Implementation of abstract API needed by DomIfBase.
*
*
* @override
* @return {boolean} True when an instance has been created.
*/
__hasInstance() {
Expand All @@ -301,6 +358,7 @@ class DomIfFast extends DomIfBase {
/**
* Implementation of abstract API needed by DomIfBase.
*
* @override
* @return {Array<Node>} Array of child nodes stamped from the template
* instance.
*/
Expand All @@ -314,6 +372,7 @@ class DomIfFast extends DomIfBase {
* Stamps the template by calling `_stampTemplate` on the `__dataHost` of this
* element and then inserts the resulting nodes into the given `parentNode`.
*
* @override
* @param {Node} parentNode The parent node to insert the instance into
* @return {void}
*/
Expand All @@ -325,7 +384,8 @@ class DomIfFast extends DomIfBase {
}
}
// Pre-bind and link the template into the effects system
const templateInfo = host._bindTemplate(this.__template, true);
const templateInfo = host._bindTemplate(
/** @type {!HTMLTemplateElement} */ (this.__template), true);
// Install runEffects hook that prevents running property effects
// (and any nested template effects) when the `if` is false
templateInfo.runEffects = (runEffects, changedProps) => {
Expand Down Expand Up @@ -354,13 +414,14 @@ class DomIfFast extends DomIfBase {
}
};
// Stamp the template, and set its DocumentFragment to the "instance"
this.__instance = host._stampTemplate(this.__template, templateInfo);
this.__instance = host._stampTemplate(
/** @type {!HTMLTemplateElement} */ (this.__template), templateInfo);
wrap(parentNode).insertBefore(this.__instance, this);
}

/**
* Run effects for any properties that changed while the `if` was false.
*
*
* @return {void}
*/
__syncHostProperties() {
Expand All @@ -373,25 +434,29 @@ class DomIfFast extends DomIfBase {

/**
* Implementation of abstract API needed by DomIfBase.
*
*
* Remove the instance and any nodes it created. Uses the `__dataHost`'s
* runtime `_removeBoundDom` method.
*
*
* @override
* @return {void}
*/
__teardownInstance() {
const host = this.__dataHost || this;
if (this.__instance) {
host._removeBoundDom(this.__instance);
this.__syncProps = null;
this.__instance = null;
}
}

/**
* Implementation of abstract API needed by DomIfBase.
*
* Shows or hides the template instance top level child nodes. For
* text nodes, `textContent` is removed while "hidden" and replaced when
* "shown."
*
* @override
* @return {void}
* @protected
* @suppress {visibility}
Expand All @@ -410,7 +475,7 @@ class DomIfFast extends DomIfBase {

/**
* The "legacy" implementation of `dom-if`, implemented using `Templatizer`.
*
*
* In this version, `this.__instance` is the `TemplateInstance` returned
* from the templatized constructor.
*/
Expand All @@ -425,7 +490,8 @@ class DomIfLegacy extends DomIfBase {

/**
* Implementation of abstract API needed by DomIfBase.
*
*
* @override
* @return {boolean} True when an instance has been created.
*/
__hasInstance() {
Expand All @@ -435,6 +501,7 @@ class DomIfLegacy extends DomIfBase {
/**
* Implementation of abstract API needed by DomIfBase.
*
* @override
* @return {Array<Node>} Array of child nodes stamped from the template
* instance.
*/
Expand All @@ -449,36 +516,39 @@ class DomIfLegacy extends DomIfBase {
* constructor (which is created lazily if it does not yet exist), and then
* inserts its resulting `root` doc fragment into the given `parentNode`.
*
* @override
* @param {Node} parentNode The parent node to insert the instance into
* @return {void}
*/
__createAndInsertInstance(parentNode) {
// Ensure we have an instance constructor
if (!this.__ctor) {
this.__ctor = templatize(this.__template, this, {
// dom-if templatizer instances require `mutable: true`, as
// `__syncHostProperties` relies on that behavior to sync objects
mutableData: true,
/**
* @param {string} prop Property to forward
* @param {*} value Value of property
* @this {DomIf}
*/
forwardHostProp: function(prop, value) {
if (this.__instance) {
if (this.if) {
this.__instance.forwardHostProp(prop, value);
} else {
// If we have an instance but are squelching host property
// forwarding due to if being false, note the invalidated
// properties so `__syncHostProperties` can sync them the next
// time `if` becomes true
this.__invalidProps = this.__invalidProps || Object.create(null);
this.__invalidProps[root(prop)] = true;
this.__ctor = templatize(
/** @type {!HTMLTemplateElement} */ (this.__template), this, {
// dom-if templatizer instances require `mutable: true`, as
// `__syncHostProperties` relies on that behavior to sync objects
mutableData: true,
/**
* @param {string} prop Property to forward
* @param {*} value Value of property
* @this {DomIfLegacy}
*/
forwardHostProp: function(prop, value) {
if (this.__instance) {
if (this.if) {
this.__instance.forwardHostProp(prop, value);
} else {
// If we have an instance but are squelching host property
// forwarding due to if being false, note the invalidated
// properties so `__syncHostProperties` can sync them the next
// time `if` becomes true
this.__invalidProps =
this.__invalidProps || Object.create(null);
this.__invalidProps[root(prop)] = true;
}
}
}
}
}
});
});
}
// Create and insert the instance
this.__instance = new this.__ctor();
Expand All @@ -487,9 +557,10 @@ class DomIfLegacy extends DomIfBase {

/**
* Implementation of abstract API needed by DomIfBase.
*
*
* Removes the instance and any nodes it created.
*
*
* @override
* @return {void}
*/
__teardownInstance() {
Expand All @@ -515,7 +586,7 @@ class DomIfLegacy extends DomIfBase {
/**
* Forwards any properties that changed while the `if` was false into the
* template instance and flushes it.
*
*
* @return {void}
*/
__syncHostProperties() {
Expand All @@ -530,11 +601,15 @@ class DomIfLegacy extends DomIfBase {
}

/**
* Implementation of abstract API needed by DomIfBase.
*
* Shows or hides the template instance top level child elements. For
* text nodes, `textContent` is removed while "hidden" and replaced when
* "shown."
* @return {void}
*
* @override
* @protected
* @return {void}
* @suppress {visibility}
*/
_showHideChildren() {
Expand Down
11 changes: 8 additions & 3 deletions lib/elements/dom-repeat.js
Original file line number Diff line number Diff line change
Expand Up @@ -301,6 +301,8 @@ export class DomRepeat extends domRepeatBase {
this.__ctor = null;
this.__isDetached = true;
this.template = null;
/** @type {TemplateInfo} */
this._templateInfo;
}

/**
Expand Down Expand Up @@ -341,10 +343,13 @@ export class DomRepeat extends domRepeatBase {
if (!this.__ctor) {
// When `removeNestedTemplates` is true, the "template" is the element
// itself, which has been given a `_templateInfo` property
let template = this.template = this._templateInfo ? this :
/** @type {HTMLTemplateElement} */(this.querySelector('template'));
const thisAsTemplate = /** @type {!HTMLTemplateElement} */ (
/** @type {!HTMLElement} */ (this));
let template = this.template = thisAsTemplate._templateInfo ?
thisAsTemplate :
/** @type {!HTMLTemplateElement} */ (this.querySelector('template'));
if (!template) {
// // Wait until childList changes and template should be there by then
// Wait until childList changes and template should be there by then
let observer = new MutationObserver(() => {
if (this.querySelector('template')) {
observer.disconnect();
Expand Down
8 changes: 1 addition & 7 deletions lib/mixins/property-effects.js
Original file line number Diff line number Diff line change
Expand Up @@ -1274,9 +1274,6 @@ function upper(name) {
* @appliesMixin PropertyAccessors
* @summary Element class mixin that provides meta-programming for Polymer's
* template binding and data observation system.
* @template T
* @param {function(new:T)} superClass Class to apply mixin to.
* @return {function(new:T)} superClass with mixin applied.
*/
export const PropertyEffects = dedupingMixin(superClass => {

Expand Down Expand Up @@ -1350,9 +1347,6 @@ export const PropertyEffects = dedupingMixin(superClass => {
this.__templateInfo;
}

/**
* @return {!Object<string, string>} Effect prototype property name map.
*/
get PROPERTY_EFFECT_TYPES() {
return TYPES;
}
Expand Down Expand Up @@ -2762,7 +2756,7 @@ export const PropertyEffects = dedupingMixin(superClass => {
* in the main element template.
*
* @param {!HTMLTemplateElement} template Template to stamp
* @param {Object=} templateInfo Optional bound template info associated
* @param {TemplateInfo=} templateInfo Optional bound template info associated
* with the template to be stamped; if omitted the template will be
* automatically bound.
* @return {!StampedTemplate} Cloned template content
Expand Down
Loading

0 comments on commit ff25283

Please sign in to comment.