Get Polymer compiling clean under closure recommended flags

With these changes we have zero errors and zero warnings with `RECOMMENDED_FLAGS`!

Most of the changes were adding `@override` for methods and properties in mixins. Apparently if you implement an interface you need to say `@override` for each method or property on the interface. This combines with our mixin strategy to the tune of needing to add `@override` on every non-private method and property.

I'm not sure this is intended behavior of the compiler. Filed https://github.com/google/closure-compiler/issues/3137 to see if it is.
This commit is contained in:
Peter Burns
2018-11-04 13:29:04 -08:00
parent 5341dbd298
commit 566dcfaefe
12 changed files with 337 additions and 170 deletions

View File

@@ -48,6 +48,7 @@ PolymerInit.prototype.hostAttributes;
/** @type {(!Object<string, string> | undefined)} */
PolymerInit.prototype.listeners;
/** @record */
let PolymerElementConstructor = function () {};
/** @type {(string | undefined)} */
PolymerElementConstructor.is;
@@ -78,6 +79,26 @@ function Polymer(init){}
*/
Polymer.sanitizeDOMValue;
/**
* @type {boolean}
*/
Polymer.passiveTouchGestures;
/**
* @type {boolean}
*/
Polymer.strictTemplatePolicy;
/**
* @type {boolean}
*/
Polymer.allowTemplateFromDomModule;
/**
* @type {string}
*/
Polymer.rootPath;
/**
* @param {string} string
* @param {Object} obj
@@ -174,7 +195,7 @@ var PolymerDeepPropertyChange;
* @constructor
* @template T
*/
let DomRepeatEvent = function() {};
var DomRepeatEvent = function() {};
/**
* @type {{

View File

@@ -37,7 +37,6 @@ let ArraySelectorMixin = dedupingMixin(superClass => {
/**
* @constructor
* @extends {superClass}
* @implements {Polymer_ElementMixin}
* @private
*/
@@ -52,7 +51,6 @@ let ArraySelectorMixin = dedupingMixin(superClass => {
class ArraySelectorMixin extends elementBase {
static get properties() {
return {
/**
@@ -76,31 +74,22 @@ let ArraySelectorMixin = dedupingMixin(superClass => {
* When `multi` is true, this is an array that contains any selected.
* When `multi` is false, this is the currently selected item, or `null`
* if no item is selected.
* @type {?(Object|Array<!Object>)}
* @type {?Object|?Array<!Object>}
*/
selected: {
type: Object,
notify: true
},
selected: {type: Object, notify: true},
/**
* When `multi` is false, this is the currently selected item, or `null`
* if no item is selected.
* @type {?Object}
*/
selectedItem: {
type: Object,
notify: true
},
selectedItem: {type: Object, notify: true},
/**
* When `true`, calling `select` on an item that is already selected
* will deselect the item.
*/
toggle: {
type: Boolean,
value: false
}
toggle: {type: Boolean, value: false}
};
}
@@ -208,6 +197,7 @@ let ArraySelectorMixin = dedupingMixin(superClass => {
/**
* Clears the selection state.
* @override
* @return {void}
*/
clearSelection() {
@@ -226,6 +216,7 @@ let ArraySelectorMixin = dedupingMixin(superClass => {
/**
* Returns whether the item is currently selected.
*
* @override
* @param {*} item Item from `items` array to test
* @return {boolean} Whether the item is selected
*/
@@ -236,6 +227,7 @@ let ArraySelectorMixin = dedupingMixin(superClass => {
/**
* Returns whether the item is currently selected.
*
* @override
* @param {number} idx Index from `items` array to test
* @return {boolean} Whether the item is selected
*/
@@ -265,6 +257,7 @@ let ArraySelectorMixin = dedupingMixin(superClass => {
/**
* Deselects the given item if it is already selected.
*
* @override
* @param {*} item Item from `items` array to deselect
* @return {void}
*/
@@ -288,6 +281,7 @@ let ArraySelectorMixin = dedupingMixin(superClass => {
/**
* Deselects the given index if it is already selected.
*
* @override
* @param {number} idx Index from `items` array to deselect
* @return {void}
*/
@@ -299,6 +293,7 @@ let ArraySelectorMixin = dedupingMixin(superClass => {
* Selects the given item. When `toggle` is true, this will automatically
* deselect the item if already selected.
*
* @override
* @param {*} item Item from `items` array to select
* @return {void}
*/
@@ -310,6 +305,7 @@ let ArraySelectorMixin = dedupingMixin(superClass => {
* Selects the given index. When `toggle` is true, this will automatically
* deselect the item if already selected.
*
* @override
* @param {number} idx Index from `items` array to select
* @return {void}
*/

View File

@@ -27,10 +27,10 @@ const UndefinedArgumentError = class extends Error {
/**
* Wraps effect functions to catch `UndefinedArgumentError`s and warn.
*
*
* @param {Object=} effect Effect metadata object
* @param {Object=} fnName Name of user function, if known
* @return {?Object} Effect metadata object
* @return {?Object|undefined} Effect metadata object
*/
function wrapEffect(effect, fnName) {
if (effect && effect.fn) {
@@ -54,11 +54,11 @@ function wrapEffect(effect, fnName) {
* Mixin to selectively add back Polymer 1.x's `undefined` rules
* governing when observers & computing functions run based
* on all arguments being defined (reference https://www.polymer-project.org/1.0/docs/devguide/observers#multi-property-observers).
*
*
* When loaded, all legacy elements (defined with `Polymer({...})`)
* will have the mixin applied. The mixin only restores legacy data handling
* if `_legacyUndefinedCheck: true` is set on the element's prototype.
*
*
* This mixin is intended for use to help migration from Polymer 1.x to
* 2.x+ by allowing legacy code to work while identifying observers and
* computing functions that need undefined checks to work without
@@ -72,15 +72,14 @@ function wrapEffect(effect, fnName) {
export const LegacyDataMixin = dedupingMixin(superClass => {
/**
* @constructor
* @extends {superClass}
* @unrestricted
* @private */
* @private
*/
class LegacyDataMixin extends superClass {
/**
* Overrides `Polymer.PropertyEffects` to add `undefined` argument
* checking to match Polymer 1.x style rules
*
*
* @param {!Array<!MethodArg>} args Array of argument metadata
* @param {string} path Property/path name that triggered the method effect
* @param {Object} props Bag of current property changes
@@ -98,7 +97,7 @@ export const LegacyDataMixin = dedupingMixin(superClass => {
// Break out of effect's control flow; will be caught in
// wrapped property effect function below
const name = args[i].name;
throw new UndefinedArgumentError(`Argument '${name}' is undefined. Ensure it has an undefined check.`, name);
throw new UndefinedArgumentError(`Argument '${name}' is undefined.`, name);
}
}
}
@@ -108,7 +107,7 @@ export const LegacyDataMixin = dedupingMixin(superClass => {
/**
* Overrides `Polyer.PropertyEffects` to wrap effect functions to
* catch `UndefinedArgumentError`s and warn.
*
*
* @param {string} property Property that should trigger the effect
* @param {string} type Effect type, from this.PROPERTY_EFFECT_TYPES
* @param {Object=} effect Effect metadata object
@@ -143,9 +142,9 @@ export const LegacyDataMixin = dedupingMixin(superClass => {
// LegacyDataMixin is applied to base class _before_ metaprogramming, to
// ensure override of _addPropertyEffect et.al. are used by metaprogramming
// performed in _finalizeClass
Polymer.Class = (info, mixin) => Class(info,
superClass => mixin ?
mixin(LegacyDataMixin(superClass)) :
Polymer.Class = (info, mixin) => Class(info,
superClass => mixin ?
mixin(LegacyDataMixin(superClass)) :
LegacyDataMixin(superClass)
);

View File

@@ -38,13 +38,12 @@ let styleInterface = window.ShadyCSS;
* @summary Element class mixin that provides Polymer's "legacy" API
*/
export const LegacyElementMixin = dedupingMixin((base) => {
/**
* @constructor
* @extends {base}
* @implements {Polymer_ElementMixin}
* @implements {Polymer_GestureEventListeners}
* @implements {Polymer_DirMixin}
* @extends {HTMLElement}
* @private
*/
const legacyElementBase = DirMixin(GestureEventListeners(ElementMixin(base)));
@@ -73,9 +72,9 @@ export const LegacyElementMixin = dedupingMixin((base) => {
super();
/** @type {boolean} */
this.isAttached;
/** @type {WeakMap<!Element, !Object<string, !Function>>} */
/** @type {?WeakMap<!Element, !Object<string, !Function>>} */
this.__boundListeners;
/** @type {Object<string, Function>} */
/** @type {?Object<string, ?Function>} */
this._debouncers;
// Ensure listeners are applied immediately so that they are
// added before declarative event listeners. This allows an element to
@@ -99,6 +98,7 @@ export const LegacyElementMixin = dedupingMixin((base) => {
/**
* Legacy callback called during the `constructor`, for overriding
* by the user.
* @override
* @return {void}
*/
created() {}
@@ -118,6 +118,7 @@ export const LegacyElementMixin = dedupingMixin((base) => {
/**
* Legacy callback called during `connectedCallback`, for overriding
* by the user.
* @override
* @return {void}
*/
attached() {}
@@ -137,6 +138,7 @@ export const LegacyElementMixin = dedupingMixin((base) => {
/**
* Legacy callback called during `disconnectedCallback`, for overriding
* by the user.
* @override
* @return {void}
*/
detached() {}
@@ -165,6 +167,7 @@ export const LegacyElementMixin = dedupingMixin((base) => {
* @param {?string} old Old value of attribute.
* @param {?string} value Current value of attribute.
* @return {void}
* @override
*/
attributeChanged(name, old, value) {} // eslint-disable-line no-unused-vars
@@ -195,6 +198,7 @@ export const LegacyElementMixin = dedupingMixin((base) => {
* only once for the class.
* @protected
* @return {void}
* @override
*/
_registered() {}
@@ -220,6 +224,7 @@ export const LegacyElementMixin = dedupingMixin((base) => {
* setting aria roles and focusability.
* @protected
* @return {void}
* @override
*/
_ensureAttributes() {}
@@ -233,6 +238,7 @@ export const LegacyElementMixin = dedupingMixin((base) => {
* block render.
* @protected
* @return {void}
* @override
*/
_applyListeners() {}
@@ -247,6 +253,7 @@ export const LegacyElementMixin = dedupingMixin((base) => {
*
* @param {*} value Value to deserialize
* @return {string | undefined} Serialized value
* @override
*/
serialize(value) {
return this._serializeValue(value);
@@ -264,6 +271,7 @@ export const LegacyElementMixin = dedupingMixin((base) => {
* @param {string} value String to deserialize
* @param {*} type Type to deserialize the string to
* @return {*} Returns the deserialized value in the `type` given.
* @override
*/
deserialize(value, type) {
return this._deserializeValue(value, type);
@@ -279,6 +287,7 @@ export const LegacyElementMixin = dedupingMixin((base) => {
* @param {string=} attribute Attribute name to reflect.
* @param {*=} value Property value to reflect.
* @return {void}
* @override
*/
reflectPropertyToAttribute(property, attribute, value) {
this._propertyToAttribute(property, attribute, value);
@@ -294,6 +303,7 @@ export const LegacyElementMixin = dedupingMixin((base) => {
* @param {string} attribute Attribute name to serialize to.
* @param {Element} node Element to set attribute to.
* @return {void}
* @override
*/
serializeValueToAttribute(value, attribute, node) {
this._valueToNodeAttribute(/** @type {Element} */ (node || this), value, attribute);
@@ -306,6 +316,7 @@ export const LegacyElementMixin = dedupingMixin((base) => {
* @param {Object} prototype Target object to copy properties to.
* @param {Object} api Source object to copy properties from.
* @return {Object} prototype object that was passed as first argument.
* @override
*/
extend(prototype, api) {
if (!(prototype && api)) {
@@ -331,6 +342,7 @@ export const LegacyElementMixin = dedupingMixin((base) => {
* @param {!Object} target Target object to copy properties to.
* @param {!Object} source Source object to copy properties from.
* @return {!Object} Target object that was passed as first argument.
* @override
*/
mixin(target, source) {
for (let i in source) {
@@ -349,6 +361,7 @@ export const LegacyElementMixin = dedupingMixin((base) => {
* `object`.
* @return {Object} Returns the given `object` with its prototype set
* to the given `prototype` object.
* @override
*/
chainObject(object, prototype) {
if (object && prototype && object !== prototype) {
@@ -366,7 +379,8 @@ export const LegacyElementMixin = dedupingMixin((base) => {
* @param {HTMLTemplateElement} template HTML template element to instance.
* @return {!DocumentFragment} Document fragment containing the imported
* template content.
*/
* @override
*/
instanceTemplate(template) {
let content = this.constructor._contentForTemplate(template);
let dom = /** @type {!DocumentFragment} */
@@ -384,12 +398,14 @@ export const LegacyElementMixin = dedupingMixin((base) => {
* @param {string} type Name of event type.
* @param {*=} detail Detail value containing event-specific
* payload.
* @param {{ bubbles: (boolean|undefined), cancelable: (boolean|undefined), composed: (boolean|undefined) }=}
* @param {{ bubbles: (boolean|undefined), cancelable: (boolean|undefined),
* composed: (boolean|undefined) }=}
* options Object specifying options. These may include:
* `bubbles` (boolean, defaults to `true`),
* `cancelable` (boolean, defaults to false), and
* `node` on which to fire the event (HTMLElement, defaults to `this`).
* @return {!Event} The new event that was fired.
* @override
*/
fire(type, detail, options) {
options = options || {};
@@ -413,6 +429,7 @@ export const LegacyElementMixin = dedupingMixin((base) => {
* @param {string} eventName Name of event to listen for.
* @param {string} methodName Name of handler method on `this` to call.
* @return {void}
* @override
*/
listen(node, eventName, methodName) {
node = /** @type {!EventTarget} */ (node || this);
@@ -426,7 +443,7 @@ export const LegacyElementMixin = dedupingMixin((base) => {
let key = eventName + methodName;
if (!bl[key]) {
bl[key] = this._addMethodEventListenerToNode(
node, eventName, methodName, this);
/** @type {!Node} */ (node), eventName, methodName, this);
}
}
@@ -439,15 +456,18 @@ export const LegacyElementMixin = dedupingMixin((base) => {
* @param {string} methodName Name of handler method on `this` to not call
anymore.
* @return {void}
* @override
*/
unlisten(node, eventName, methodName) {
node = /** @type {!EventTarget} */ (node || this);
let bl = this.__boundListeners && this.__boundListeners.get(node);
let bl = this.__boundListeners &&
this.__boundListeners.get(/** @type {!Element} */ (node));
let key = eventName + methodName;
let handler = bl && bl[key];
if (handler) {
this._removeEventListenerFromNode(node, eventName, handler);
bl[key] = null;
this._removeEventListenerFromNode(
/** @type {!Node} */ (node), eventName, handler);
bl[key] = /** @type {?} */ (null);
}
}
@@ -465,9 +485,12 @@ export const LegacyElementMixin = dedupingMixin((base) => {
* @param {Element=} node Element to apply scroll direction setting.
* Defaults to `this`.
* @return {void}
* @override
*/
setScrollDirection(direction, node) {
setTouchAction(/** @type {Element} */ (node || this), DIRECTION_MAP[direction] || 'auto');
setTouchAction(
/** @type {!Element} */ (node || this),
DIRECTION_MAP[direction] || 'auto');
}
/* **** End Events **** */
@@ -478,6 +501,7 @@ export const LegacyElementMixin = dedupingMixin((base) => {
*
* @param {string} slctr Selector to run on this local DOM scope
* @return {Element} Element found by the selector, or null if not found.
* @override
*/
$$(slctr) {
return this.root.querySelector(slctr);
@@ -499,6 +523,7 @@ export const LegacyElementMixin = dedupingMixin((base) => {
* This should not be necessary as of Polymer 2.0.2 and is provided only
* for backwards compatibility.
* @return {void}
* @override
*/
distributeContent() {
if (window.ShadyDOM && this.shadowRoot) {
@@ -512,11 +537,13 @@ export const LegacyElementMixin = dedupingMixin((base) => {
* any `<content>` elements are replaced with the list of nodes distributed
* to the `<content>`, the result of its `getDistributedNodes` method.
* @return {!Array<!Node>} List of effective child nodes.
* @suppress {invalidCasts} LegacyElementMixin must be applied to an HTMLElement
* @suppress {invalidCasts} LegacyElementMixin must be applied to an
* HTMLElement
* @override
*/
getEffectiveChildNodes() {
const thisEl = /** @type {Element} */ (this);
const domApi = /** @type {DomApi} */(dom(thisEl));
const domApi = /** @type {PolymerDomApi} */ (dom(thisEl));
return domApi.getEffectiveChildNodes();
}
@@ -526,11 +553,13 @@ export const LegacyElementMixin = dedupingMixin((base) => {
* children that are insertion points.
* @param {string} selector Selector to run.
* @return {!Array<!Node>} List of distributed elements that match selector.
* @suppress {invalidCasts} LegacyElementMixin must be applied to an HTMLElement
* @suppress {invalidCasts} LegacyElementMixin must be applied to an
* HTMLElement
* @override
*/
queryDistributedElements(selector) {
const thisEl = /** @type {Element} */ (this);
const domApi = /** @type {DomApi} */(dom(thisEl));
const domApi = /** @type {PolymerDomApi} */ (dom(thisEl));
return domApi.queryDistributedElements(selector);
}
@@ -541,6 +570,7 @@ export const LegacyElementMixin = dedupingMixin((base) => {
* distributed to the `<content>`.
*
* @return {!Array<!Node>} List of effective children.
* @override
*/
getEffectiveChildren() {
let list = this.getEffectiveChildNodes();
@@ -555,6 +585,7 @@ export const LegacyElementMixin = dedupingMixin((base) => {
* returned by <a href="#getEffectiveChildNodes>getEffectiveChildNodes</a>.
*
* @return {string} List of effective children.
* @override
*/
getEffectiveTextContent() {
let cn = this.getEffectiveChildNodes();
@@ -573,6 +604,7 @@ export const LegacyElementMixin = dedupingMixin((base) => {
* to children that are insertion points.
* @param {string} selector Selector to run.
* @return {Node} First effective child node that matches selector.
* @override
*/
queryEffectiveChildren(selector) {
let e$ = this.queryDistributedElements(selector);
@@ -584,7 +616,9 @@ export const LegacyElementMixin = dedupingMixin((base) => {
* match `selector`. These can be dom child nodes or elements distributed
* to children that are insertion points.
* @param {string} selector Selector to run.
* @return {!Array<!Node>} List of effective child nodes that match selector.
* @return {!Array<!Node>} List of effective child nodes that match
* selector.
* @override
*/
queryAllEffectiveChildren(selector) {
return this.queryDistributedElements(selector);
@@ -599,10 +633,13 @@ export const LegacyElementMixin = dedupingMixin((base) => {
* @param {string=} slctr CSS selector to choose the desired
* `<slot>`. Defaults to `content`.
* @return {!Array<!Node>} List of distributed nodes for the `<slot>`.
* @override
*/
getContentChildNodes(slctr) {
let content = this.root.querySelector(slctr || 'slot');
return content ? /** @type {DomApi} */(dom(content)).getDistributedNodes() : [];
return content ?
/** @type {PolymerDomApi} */ (dom(content)).getDistributedNodes() :
[];
}
/**
@@ -619,6 +656,7 @@ export const LegacyElementMixin = dedupingMixin((base) => {
* @return {!Array<!HTMLElement>} List of distributed nodes for the
* `<slot>`.
* @suppress {invalidCasts}
* @override
*/
getContentChildren(slctr) {
let children = /** @type {!Array<!HTMLElement>} */(this.getContentChildNodes(slctr).filter(function(n) {
@@ -632,7 +670,9 @@ export const LegacyElementMixin = dedupingMixin((base) => {
*
* @param {?Node} node The element to be checked.
* @return {boolean} true if node is in this element's light DOM tree.
* @suppress {invalidCasts} LegacyElementMixin must be applied to an HTMLElement
* @suppress {invalidCasts} LegacyElementMixin must be applied to an
* HTMLElement
* @override
*/
isLightDescendant(node) {
const thisNode = /** @type {Node} */ (this);
@@ -645,6 +685,7 @@ export const LegacyElementMixin = dedupingMixin((base) => {
*
* @param {!Element} node The element to be checked.
* @return {boolean} true if node is in this element's local DOM tree.
* @override
*/
isLocalDescendant(node) {
return this.root === node.getRootNode();
@@ -656,6 +697,7 @@ export const LegacyElementMixin = dedupingMixin((base) => {
* @param {*} container Unused
* @param {*} shouldObserve Unused
* @return {void}
* @override
*/
scopeSubtree(container, shouldObserve) { // eslint-disable-line no-unused-vars
}
@@ -665,7 +707,9 @@ export const LegacyElementMixin = dedupingMixin((base) => {
* @param {string} property The css property name.
* @return {string} Returns the computed css property value for the given
* `property`.
* @suppress {invalidCasts} LegacyElementMixin must be applied to an HTMLElement
* @suppress {invalidCasts} LegacyElementMixin must be applied to an
* HTMLElement
* @override
*/
getComputedStyleValue(property) {
return styleInterface.getComputedStyleValue(/** @type {!Element} */(this), property);
@@ -689,13 +733,14 @@ export const LegacyElementMixin = dedupingMixin((base) => {
* @param {string} jobName String to identify the debounce job.
* @param {function():void} callback Function that is called (with `this`
* context) when the wait time elapses.
* @param {number} wait Optional wait time in milliseconds (ms) after the
* @param {number=} wait Optional wait time in milliseconds (ms) after the
* last signal that must elapse before invoking `callback`
* @return {!Object} Returns a debouncer object on which exists the
* following methods: `isActive()` returns true if the debouncer is
* active; `cancel()` cancels the debouncer if it is active;
* `flush()` immediately invokes the debounced callback if the debouncer
* is active.
* @override
*/
debounce(jobName, callback, wait) {
this._debouncers = this._debouncers || {};
@@ -710,6 +755,7 @@ export const LegacyElementMixin = dedupingMixin((base) => {
*
* @param {string} jobName The name of the debouncer started with `debounce`
* @return {boolean} Whether the debouncer is active (has not yet fired).
* @override
*/
isDebouncerActive(jobName) {
this._debouncers = this._debouncers || {};
@@ -722,6 +768,7 @@ export const LegacyElementMixin = dedupingMixin((base) => {
*
* @param {string} jobName The name of the debouncer started with `debounce`
* @return {void}
* @override
*/
flushDebouncer(jobName) {
this._debouncers = this._debouncers || {};
@@ -736,6 +783,7 @@ export const LegacyElementMixin = dedupingMixin((base) => {
*
* @param {string} jobName The name of the debouncer started with `debounce`
* @return {void}
* @override
*/
cancelDebouncer(jobName) {
this._debouncers = this._debouncers || {};
@@ -751,11 +799,13 @@ export const LegacyElementMixin = dedupingMixin((base) => {
* By default (if no waitTime is specified), async callbacks are run at
* microtask timing, which will occur before paint.
*
* @param {!Function} callback The callback function to run, bound to `this`.
* @param {!Function} callback The callback function to run, bound to
* `this`.
* @param {number=} waitTime Time to wait before calling the
* `callback`. If unspecified or 0, the callback will be run at microtask
* timing (before paint).
* @return {number} Handle that may be used to cancel the async job.
* @override
*/
async(callback, waitTime) {
return waitTime > 0 ? timeOut.run(callback.bind(this), waitTime) :
@@ -768,6 +818,7 @@ export const LegacyElementMixin = dedupingMixin((base) => {
* @param {number} handle Handle returned from original `async` call to
* cancel.
* @return {void}
* @override
*/
cancelAsync(handle) {
handle < 0 ? microTask.cancel(~handle) :
@@ -783,6 +834,7 @@ export const LegacyElementMixin = dedupingMixin((base) => {
* @param {Object=} props Object of properties to configure on the
* instance.
* @return {!Element} Newly created and configured element.
* @override
*/
create(tag, props) {
let elt = document.createElement(tag);
@@ -805,6 +857,7 @@ export const LegacyElementMixin = dedupingMixin((base) => {
* @param {string} selector Selector to test.
* @param {!Element=} node Element to test the selector against.
* @return {boolean} Whether the element matches the selector.
* @override
*/
elementMatches(selector, node) {
return matchesSelector( (node || this), selector);
@@ -816,22 +869,19 @@ export const LegacyElementMixin = dedupingMixin((base) => {
* @param {string} name HTML attribute name
* @param {boolean=} bool Boolean to force the attribute on or off.
* When unspecified, the state of the attribute will be reversed.
* @return {boolean} true if the attribute now exists
* @param {Element=} node Node to target. Defaults to `this`.
* @return {void}
* @override
*/
toggleAttribute(name, bool) {
let node = /** @type {Element} */ this;
if (arguments.length === 3) {
node = /** @type {Element} */ arguments[2];
}
toggleAttribute(name, bool, node) {
node = /** @type {Element} */ (node || this);
if (arguments.length == 1) {
bool = !node.hasAttribute(name);
}
if (bool) {
node.setAttribute(name, '');
return true;
} else {
node.removeAttribute(name);
return false;
}
}
@@ -844,6 +894,7 @@ export const LegacyElementMixin = dedupingMixin((base) => {
* When unspecified, the state of the class will be reversed.
* @param {Element=} node Node to target. Defaults to `this`.
* @return {void}
* @override
*/
toggleClass(name, bool, node) {
node = /** @type {Element} */ (node || this);
@@ -864,6 +915,7 @@ export const LegacyElementMixin = dedupingMixin((base) => {
* @param {Element=} node Element to apply the transform to.
* Defaults to `this`
* @return {void}
* @override
*/
transform(transformText, node) {
node = /** @type {Element} */ (node || this);
@@ -881,6 +933,7 @@ export const LegacyElementMixin = dedupingMixin((base) => {
* @param {Element=} node Element to apply the transform to.
* Defaults to `this`.
* @return {void}
* @override
*/
translate3d(x, y, z, node) {
node = /** @type {Element} */ (node || this);
@@ -897,10 +950,12 @@ export const LegacyElementMixin = dedupingMixin((base) => {
* If the array is passed directly, **no change
* notification is generated**.
*
* @param {string | !Array<number|string>} arrayOrPath Path to array from which to remove the item
* @param {string | !Array<number|string>} arrayOrPath Path to array from
* which to remove the item
* (or the array itself).
* @param {*} item Item to remove.
* @return {Array} Array containing item removed.
* @override
*/
arrayDelete(arrayOrPath, item) {
let index;
@@ -927,6 +982,7 @@ export const LegacyElementMixin = dedupingMixin((base) => {
* @param {string} level One of 'log', 'warn', 'error'
* @param {Array} args Array of strings or objects to log
* @return {void}
* @override
*/
_logger(level, args) {
// accept ['foo', 'bar'] and [['foo', 'bar']]
@@ -946,6 +1002,7 @@ export const LegacyElementMixin = dedupingMixin((base) => {
*
* @param {...*} args Array of strings or objects to log
* @return {void}
* @override
*/
_log(...args) {
this._logger('log', args);
@@ -956,6 +1013,7 @@ export const LegacyElementMixin = dedupingMixin((base) => {
*
* @param {...*} args Array of strings or objects to log
* @return {void}
* @override
*/
_warn(...args) {
this._logger('warn', args);
@@ -966,6 +1024,7 @@ export const LegacyElementMixin = dedupingMixin((base) => {
*
* @param {...*} args Array of strings or objects to log
* @return {void}
* @override
*/
_error(...args) {
this._logger('error', args);
@@ -978,6 +1037,7 @@ export const LegacyElementMixin = dedupingMixin((base) => {
* @param {...*} args Array of strings or objects to log
* @return {Array} Array with formatting information for `console`
* logging.
* @override
*/
_logf(methodName, ...args) {
return ['[%s::%s]', this.is, methodName, ...args];
@@ -988,5 +1048,4 @@ export const LegacyElementMixin = dedupingMixin((base) => {
LegacyElement.prototype.is = '';
return LegacyElement;
});

View File

@@ -22,7 +22,7 @@ const EL_DIR_REPLACMENT = ':host([dir="$2"]) $1';
*/
const DIR_INSTANCES = [];
/** @type {MutationObserver} */
/** @type {?MutationObserver} */
let observer = null;
let DOCUMENT_DIR = '';
@@ -88,7 +88,6 @@ export const DirMixin = dedupingMixin((base) => {
/**
* @constructor
* @extends {base}
* @implements {Polymer_PropertyAccessors}
* @private
*/
@@ -134,7 +133,9 @@ export const DirMixin = dedupingMixin((base) => {
}
/**
* @suppress {invalidCasts} Closure doesn't understand that `this` is an HTMLElement
* @override
* @suppress {invalidCasts} Closure doesn't understand that `this` is an
* HTMLElement
* @return {void}
*/
ready() {
@@ -143,7 +144,9 @@ export const DirMixin = dedupingMixin((base) => {
}
/**
* @suppress {missingProperties} If it exists on elementBase, it can be super'd
* @override
* @suppress {missingProperties} If it exists on elementBase, it can be
* super'd
* @return {void}
*/
connectedCallback() {
@@ -158,7 +161,9 @@ export const DirMixin = dedupingMixin((base) => {
}
/**
* @suppress {missingProperties} If it exists on elementBase, it can be super'd
* @override
* @suppress {missingProperties} If it exists on elementBase, it can be
* super'd
* @return {void}
*/
disconnectedCallback() {

View File

@@ -38,11 +38,10 @@ const DISABLED_ATTR = 'disable-upgrade';
* @appliesMixin ElementMixin
*/
export const DisableUpgradeMixin = dedupingMixin((base) => {
/**
* @constructor
* @extends {base}
* @implements {Polymer_ElementMixin}
* @extends {HTMLElement}
* @private
*/
const superClass = ElementMixin(base);
@@ -59,14 +58,22 @@ export const DisableUpgradeMixin = dedupingMixin((base) => {
return super.observedAttributes.concat(DISABLED_ATTR);
}
/** @override */
/**
* @override
* @param {string} name
* @param {?string} old
* @param {?string} value
* @param {?string=} namespace
* @return {undefined}
*/
attributeChangedCallback(name, old, value, namespace) {
if (name == DISABLED_ATTR) {
if (!this.__dataEnabled && value == null && this.isConnected) {
super.connectedCallback();
}
} else {
super.attributeChangedCallback(name, old, value, namespace);
super.attributeChangedCallback(
name, old, value, /** @type {null|string} */ (namespace));
}
}
@@ -75,7 +82,7 @@ export const DisableUpgradeMixin = dedupingMixin((base) => {
attributes are delivered. Therefore, we stub this out and
call `super._initializeProperties()` manually.
*/
/** @override */
/** @override */
_initializeProperties() {}
// prevent user code in connected from running
@@ -108,5 +115,4 @@ export const DisableUpgradeMixin = dedupingMixin((base) => {
}
return DisableUpgradeClass;
});

View File

@@ -92,12 +92,11 @@ export const version = '3.0.5';
* meta-programming features.
*/
export const ElementMixin = dedupingMixin(base => {
/**
* @constructor
* @extends {base}
* @implements {Polymer_PropertyEffects}
* @implements {Polymer_PropertiesMixin}
* @extends {HTMLElement}
* @private
*/
const polymerElementBase = PropertiesMixin(PropertyEffects(base));
@@ -138,9 +137,11 @@ export const ElementMixin = dedupingMixin(base => {
function ownObservers(constructor) {
if (!constructor.hasOwnProperty(
JSCompiler_renameProperty('__ownObservers', constructor))) {
constructor.__ownObservers =
constructor.hasOwnProperty(JSCompiler_renameProperty('observers', constructor)) ?
/** @type {PolymerElementConstructor} */ (constructor).observers : null;
constructor.__ownObservers =
constructor.hasOwnProperty(
JSCompiler_renameProperty('observers', constructor)) ?
/** @type {PolymerElementConstructor} */ (constructor).observers :
null;
}
return constructor.__ownObservers;
}
@@ -279,8 +280,8 @@ export const ElementMixin = dedupingMixin(base => {
/**
* Look up template from dom-module for element
*
* @param {!string} is Element name to look up
* @return {!HTMLTemplateElement} Template found in dom module, or
* @param {string} is Element name to look up
* @return {?HTMLTemplateElement|undefined} Template found in dom module, or
* undefined if not found
* @protected
*/
@@ -289,7 +290,8 @@ export const ElementMixin = dedupingMixin(base => {
// Under strictTemplatePolicy in 3.x+, dom-module lookup is only allowed
// when opted-in via allowTemplateFromDomModule
if (is && (!strictTemplatePolicy || allowTemplateFromDomModule)) {
template = DomModule.import(is, 'template');
template = /** @type {?HTMLTemplateElement} */ (
DomModule.import(is, 'template'));
// Under strictTemplatePolicy, require any element with an `is`
// specified to have a dom-module
if (strictTemplatePolicy && !template) {
@@ -304,10 +306,11 @@ export const ElementMixin = dedupingMixin(base => {
* @mixinClass
* @unrestricted
* @implements {Polymer_ElementMixin}
* @extends {polymerElementBase}
*/
class PolymerElement extends polymerElementBase {
/**
/**
* Current Polymer version in Semver notation.
* @type {string} Semver notation of the current version of Polymer.
*/
@@ -323,7 +326,7 @@ export const ElementMixin = dedupingMixin(base => {
* @override
* @suppress {missingProperties} Interfaces in closure do not inherit statics, but classes do
*/
static _finalizeClass() {
static _finalizeClass() {
super._finalizeClass();
if (this.hasOwnProperty(
JSCompiler_renameProperty('is', this)) && this.is) {
@@ -354,7 +357,7 @@ export const ElementMixin = dedupingMixin(base => {
* @protected
* @override
*/
static createProperties(props) {
static createProperties(props) {
for (let p in props) {
createPropertyFromConfig(this.prototype, p, props[p], props);
}
@@ -590,7 +593,9 @@ export const ElementMixin = dedupingMixin(base => {
* flushes any pending properties, and updates shimmed CSS properties
* when using the ShadyCSS scoping/custom properties polyfill.
*
* @suppress {missingProperties, invalidCasts} Super may or may not implement the callback
* @override
* @suppress {missingProperties, invalidCasts} Super may or may not
* implement the callback
* @return {void}
*/
connectedCallback() {
@@ -642,6 +647,7 @@ export const ElementMixin = dedupingMixin(base => {
* However, this method may be overridden to allow an element
* to put its dom in another location.
*
* @override
* @throws {Error}
* @suppress {missingReturn}
* @param {StampedTemplate} dom to attach to the element.
@@ -681,6 +687,7 @@ export const ElementMixin = dedupingMixin(base => {
* Note: This function does not support updating CSS mixins.
* You can not dynamically change the value of an `@apply`.
*
* @override
* @param {Object=} properties Bag of custom property key/values to
* apply to this element.
* @return {void}
@@ -702,6 +709,7 @@ export const ElementMixin = dedupingMixin(base => {
* with `/` (absolute URLs) or `#` (hash identifiers). For general purpose
* URL resolution, use `window.URL`.
*
* @override
* @param {string} url URL to resolve.
* @param {string=} base Optional base URL to resolve against, defaults
* to the element's `importPath`
@@ -741,13 +749,12 @@ export let instanceCount = 0;
/**
* Array of Polymer element classes that have been finalized.
* @type {Array<PolymerElement>}
* @type {!Array<!PolymerElementConstructor>}
*/
export const registrations = [];
/**
* @param {!PolymerElementConstructor} prototype Element prototype to log
* @this {this}
* @private
*/
function _regLog(prototype) {
@@ -756,8 +763,7 @@ function _regLog(prototype) {
/**
* Registers a class prototype for telemetry purposes.
* @param {HTMLElement} prototype Element prototype to register
* @this {this}
* @param {!PolymerElementConstructor} prototype Element prototype to register
* @protected
*/
export function register(prototype) {
@@ -767,7 +773,6 @@ export function register(prototype) {
/**
* Logs all elements registered with an `is` to the console.
* @public
* @this {this}
*/
export function dumpRegistrations() {
registrations.forEach(_regLog);

View File

@@ -157,6 +157,7 @@ export const PropertiesChanged = dedupingMixin(
constructor() {
super();
/** @protected {boolean} */
this.__dataEnabled = false;
this.__dataReady = false;
this.__dataInvalid = false;
@@ -421,7 +422,7 @@ export const PropertiesChanged = dedupingMixin(
* @param {string} name Name of attribute that changed
* @param {?string} old Old attribute value
* @param {?string} value New attribute value
* @param {?string} namespace Attribute namespace.
* @param {?string=} namespace Attribute namespace.
* @return {void}
* @suppress {missingProperties} Super may or may not implement the callback
* @override

View File

@@ -69,16 +69,18 @@ function saveAccessorValue(model, property) {
*
* For basic usage of this mixin:
*
* - Declare attributes to observe via the standard `static get observedAttributes()`. Use
* `dash-case` attribute names to represent `camelCase` property names.
* - Declare attributes to observe via the standard `static get
* observedAttributes()`. Use `dash-case` attribute names to represent
* `camelCase` property names.
* - Implement the `_propertiesChanged` callback on the class.
* - Call `MyClass.createPropertiesForAttributes()` **once** on the class to generate
* property accessors for each observed attribute. This must be called before the first
* instance is created, for example, by calling it before calling `customElements.define`.
* It can also be called lazily from the element's `constructor`, as long as it's guarded so
* that the call is only made once, when the first instance is created.
* - Call `this._enableProperties()` in the element's `connectedCallback` to enable
* the accessors.
* - Call `MyClass.createPropertiesForAttributes()` **once** on the class to
* generate property accessors for each observed attribute. This must be
* called before the first instance is created, for example, by calling it
* before calling `customElements.define`. It can also be called lazily from
* the element's `constructor`, as long as it's guarded so that the call is
* only made once, when the first instance is created.
* - Call `this._enableProperties()` in the element's `connectedCallback` to
* enable the accessors.
*
* Any `observedAttributes` will automatically be
* deserialized via `attributeChangedCallback` and set to the associated
@@ -94,7 +96,6 @@ export const PropertyAccessors = dedupingMixin(superClass => {
/**
* @constructor
* @extends {superClass}
* @implements {Polymer_PropertiesChanged}
* @unrestricted
* @private
@@ -145,6 +146,7 @@ export const PropertyAccessors = dedupingMixin(superClass => {
*
* @return {void}
* @protected
* @override
*/
_initializeProperties() {
if (this.__dataProto) {
@@ -162,10 +164,11 @@ export const PropertyAccessors = dedupingMixin(superClass => {
* setter at instance time. This method is provided as an override
* point for customizing or providing more efficient initialization.
*
* @param {Object} props Bag of property values that were overwritten
* @param {!Object} props Bag of property values that were overwritten
* when creating property accessors.
* @return {void}
* @protected
* @override
*/
_initializeProtoProperties(props) {
for (let p in props) {
@@ -177,11 +180,13 @@ export const PropertyAccessors = dedupingMixin(superClass => {
* Ensures the element has the given attribute. If it does not,
* assigns the given value to the attribute.
*
* @suppress {invalidCasts} Closure can't figure out `this` is infact an element
* @suppress {invalidCasts} Closure can't figure out `this` is infact an
* element
*
* @param {string} attribute Name of attribute to ensure is set.
* @param {string} value of the attribute.
* @return {void}
* @override
*/
_ensureAttribute(attribute, value) {
const el = /** @type {!HTMLElement} */(this);
@@ -194,7 +199,9 @@ export const PropertyAccessors = dedupingMixin(superClass => {
* Overrides PropertiesChanged implemention to serialize objects as JSON.
*
* @param {*} value Property value to serialize.
* @return {string | undefined} String serialized from the provided property value.
* @return {string | undefined} String serialized from the provided property
* value.
* @override
*/
_serializeValue(value) {
/* eslint-disable no-fallthrough */
@@ -229,6 +236,7 @@ export const PropertyAccessors = dedupingMixin(superClass => {
* @param {?string} value Attribute value to deserialize.
* @param {*=} type Type to deserialize the string to.
* @return {*} Typed value deserialized from the provided string.
* @override
*/
_deserializeValue(value, type) {
/**
@@ -278,6 +286,7 @@ export const PropertyAccessors = dedupingMixin(superClass => {
* for the values to take effect.
* @protected
* @return {void}
* @override
*/
_definePropertyAccessor(property, readOnly) {
saveAccessorValue(this, property);
@@ -289,6 +298,7 @@ export const PropertyAccessors = dedupingMixin(superClass => {
*
* @param {string} property Property name
* @return {boolean} True if an accessor was created
* @override
*/
_hasAccessor(property) {
return this.__dataHasAccessor && this.__dataHasAccessor[property];
@@ -300,6 +310,7 @@ export const PropertyAccessors = dedupingMixin(superClass => {
* @param {string} prop Property name
* @return {boolean} True if property has a pending change
* @protected
* @override
*/
_isPropertyPending(prop) {
return Boolean(this.__dataPending && (prop in this.__dataPending));

View File

@@ -36,7 +36,7 @@ const TYPES = {
READ_ONLY: '__readOnly'
};
/** @const {RegExp} */
/** @const {!RegExp} */
const capitalAttributeRegex = /[A-Z]/;
/**
@@ -57,8 +57,6 @@ let DataTrigger; //eslint-disable-line no-unused-vars
*/
let DataEffect; //eslint-disable-line no-unused-vars
let PropertyEffectsType; //eslint-disable-line no-unused-vars
/**
* Ensures that the model has an own-property map of effects for the given type.
* The model may be a prototype or an instance.
@@ -104,10 +102,10 @@ function ensureOwnEffectMap(model, type) {
* Runs all effects of a given type for the given set of property changes
* on an instance.
*
* @param {!PropertyEffectsType} inst The instance with effects to run
* @param {Object} effects Object map of property-to-Array of effects
* @param {Object} props Bag of current property changes
* @param {Object=} oldProps Bag of previous values for changed properties
* @param {!Polymer_PropertyEffects} inst The instance with effects to run
* @param {?Object} effects Object map of property-to-Array of effects
* @param {?Object} props Bag of current property changes
* @param {?Object=} oldProps Bag of previous values for changed properties
* @param {boolean=} hasPaths True with `props` contains one or more paths
* @param {*=} extraArgs Additional metadata to pass to effect function
* @return {boolean} True if an effect ran for this property
@@ -118,7 +116,9 @@ function runEffects(inst, effects, props, oldProps, hasPaths, extraArgs) {
let ran = false;
let id = dedupeId++;
for (let prop in props) {
if (runEffectsForProperty(inst, effects, id, prop, props, oldProps, hasPaths, extraArgs)) {
if (runEffectsForProperty(
inst, /** @type {!Object} */ (effects), id, prop, props, oldProps,
hasPaths, extraArgs)) {
ran = true;
}
}
@@ -130,8 +130,8 @@ function runEffects(inst, effects, props, oldProps, hasPaths, extraArgs) {
/**
* Runs a list of effects for a given property.
*
* @param {!PropertyEffectsType} inst The instance with effects to run
* @param {Object} effects Object map of property-to-Array of effects
* @param {!Polymer_PropertyEffects} inst The instance with effects to run
* @param {!Object} effects Object map of property-to-Array of effects
* @param {number} dedupeId Counter used for de-duping effects
* @param {string} prop Name of changed property
* @param {*} props Changed properties
@@ -175,15 +175,15 @@ function runEffectsForProperty(inst, effects, dedupeId, prop, props, oldProps, h
* If no trigger is given, the path is deemed to match.
*
* @param {string} path Path or property that changed
* @param {DataTrigger} trigger Descriptor
* @param {?DataTrigger} trigger Descriptor
* @return {boolean} Whether the path matched the trigger
*/
function pathMatchesTrigger(path, trigger) {
if (trigger) {
let triggerPath = trigger.name;
let triggerPath = /** @type {string} */ (trigger.name);
return (triggerPath == path) ||
(trigger.structured && isAncestor(triggerPath, path)) ||
(trigger.wildcard && isDescendant(triggerPath, path));
!!(trigger.structured && isAncestor(triggerPath, path)) ||
!!(trigger.wildcard && isDescendant(triggerPath, path));
} else {
return true;
}
@@ -195,7 +195,7 @@ function pathMatchesTrigger(path, trigger) {
* Calls the method with `info.methodName` on the instance, passing the
* new and old values.
*
* @param {!PropertyEffectsType} inst The instance the effect will be run on
* @param {!Polymer_PropertyEffects} inst The instance the effect will be run on
* @param {string} property Name of property
* @param {Object} props Bag of current property changes
* @param {Object} oldProps Bag of previous values for changed properties
@@ -223,7 +223,7 @@ function runObserverEffect(inst, property, props, oldProps, info) {
* `notify: true` to ensure object sub-property notifications were
* sent.
*
* @param {!PropertyEffectsType} inst The instance with effects to run
* @param {!Polymer_PropertyEffects} inst The instance with effects to run
* @param {Object} notifyProps Bag of properties to notify
* @param {Object} props Bag of current property changes
* @param {Object} oldProps Bag of previous values for changed properties
@@ -259,7 +259,8 @@ function runNotifyEffects(inst, notifyProps, props, oldProps, hasPaths) {
* Dispatches {property}-changed events with path information in the detail
* object to indicate a sub-path of the property was changed.
*
* @param {!PropertyEffectsType} inst The element from which to fire the event
* @param {!Polymer_PropertyEffects} inst The element from which to fire the
* event
* @param {string} path The path that was changed
* @param {Object} props Bag of current property changes
* @return {boolean} Returns true if the path was notified
@@ -279,11 +280,13 @@ function notifyPath(inst, path, props) {
* Dispatches {property}-changed events to indicate a property (or path)
* changed.
*
* @param {!PropertyEffectsType} inst The element from which to fire the event
* @param {string} eventName The name of the event to send ('{property}-changed')
* @param {!Polymer_PropertyEffects} inst The element from which to fire the
* event
* @param {string} eventName The name of the event to send
* ('{property}-changed')
* @param {*} value The value of the changed property
* @param {string | null | undefined} path If a sub-path of this property changed, the path
* that changed (optional).
* @param {string | null | undefined} path If a sub-path of this property
* changed, the path that changed (optional).
* @return {void}
* @private
* @suppress {invalidCasts}
@@ -305,7 +308,7 @@ function dispatchNotifyEvent(inst, eventName, value, path) {
* Dispatches a non-bubbling event named `info.eventName` on the instance
* with a detail object containing the new `value`.
*
* @param {!PropertyEffectsType} inst The instance the effect will be run on
* @param {!Polymer_PropertyEffects} inst The instance the effect will be run on
* @param {string} property Name of property
* @param {Object} props Bag of current property changes
* @param {Object} oldProps Bag of previous values for changed properties
@@ -334,7 +337,8 @@ function runNotifyEffect(inst, property, props, oldProps, info, hasPaths) {
* scope's name for that path first.
*
* @param {CustomEvent} event Notification event (e.g. '<property>-changed')
* @param {!PropertyEffectsType} inst Host element instance handling the notification event
* @param {!Polymer_PropertyEffects} inst Host element instance handling the
* notification event
* @param {string} fromProp Child element property that was bound
* @param {string} toPath Host property/path that was bound
* @param {boolean} negate Whether the binding was negated
@@ -365,7 +369,7 @@ function handleNotification(event, inst, fromProp, toPath, negate) {
*
* Sets the attribute named `info.attrName` to the given property value.
*
* @param {!PropertyEffectsType} inst The instance the effect will be run on
* @param {!Polymer_PropertyEffects} inst The instance the effect will be run on
* @param {string} property Name of property
* @param {Object} props Bag of current property changes
* @param {Object} oldProps Bag of previous values for changed properties
@@ -391,9 +395,9 @@ function runReflectEffect(inst, property, props, oldProps, info) {
* computed before other effects (binding propagation, observers, and notify)
* run.
*
* @param {!PropertyEffectsType} inst The instance the effect will be run on
* @param {!Object} changedProps Bag of changed properties
* @param {!Object} oldProps Bag of previous values for changed properties
* @param {!Polymer_PropertyEffects} inst The instance the effect will be run on
* @param {?Object} changedProps Bag of changed properties
* @param {?Object} oldProps Bag of previous values for changed properties
* @param {boolean} hasPaths True with `props` contains one or more paths
* @return {void}
* @private
@@ -403,8 +407,8 @@ function runComputedEffects(inst, changedProps, oldProps, hasPaths) {
if (computeEffects) {
let inputProps = changedProps;
while (runEffects(inst, computeEffects, inputProps, oldProps, hasPaths)) {
Object.assign(oldProps, inst.__dataOld);
Object.assign(changedProps, inst.__dataPending);
Object.assign(/** @type {!Object} */ (oldProps), inst.__dataOld);
Object.assign(/** @type {!Object} */ (changedProps), inst.__dataPending);
inputProps = inst.__dataPending;
inst.__dataPending = null;
}
@@ -416,10 +420,10 @@ function runComputedEffects(inst, changedProps, oldProps, hasPaths) {
* values of the arguments specified in the `info` object and setting the
* return value to the computed property specified.
*
* @param {!PropertyEffectsType} inst The instance the effect will be run on
* @param {!Polymer_PropertyEffects} inst The instance the effect will be run on
* @param {string} property Name of property
* @param {Object} props Bag of current property changes
* @param {Object} oldProps Bag of previous values for changed properties
* @param {?Object} props Bag of current property changes
* @param {?Object} oldProps Bag of previous values for changed properties
* @param {?} info Effect metadata
* @return {void}
* @private
@@ -438,8 +442,8 @@ function runComputedEffect(inst, property, props, oldProps, info) {
* Computes path changes based on path links set up using the `linkPaths`
* API.
*
* @param {!PropertyEffectsType} inst The instance whose props are changing
* @param {string | !Array<(string|number)>} path Path that has changed
* @param {!Polymer_PropertyEffects} inst The instance whose props are changing
* @param {string} path Path that has changed
* @param {*} value Value of changed path
* @return {void}
* @private
@@ -544,7 +548,7 @@ function addEffectForBindingPart(constructor, templateInfo, binding, part, index
* there is no support for _path_ bindings via custom binding parts,
* as this is specific to Polymer's path binding syntax.
*
* @param {!PropertyEffectsType} inst The instance the effect will be run on
* @param {!Polymer_PropertyEffects} inst The instance the effect will be run on
* @param {string} path Name of property
* @param {Object} props Bag of current property changes
* @param {Object} oldProps Bag of previous values for changed properties
@@ -581,7 +585,7 @@ function runBindingEffect(inst, path, props, oldProps, info, hasPaths, nodeList)
* Sets the value for an "binding" (binding) effect to a node,
* either as a property or attribute.
*
* @param {!PropertyEffectsType} inst The instance owning the binding effect
* @param {!Polymer_PropertyEffects} inst The instance owning the binding effect
* @param {Node} node Target node for binding
* @param {!Binding} binding Binding metadata
* @param {!BindingPart} part Binding part metadata
@@ -666,7 +670,8 @@ function shouldAddListener(binding) {
* Setup compound binding storage structures, notify listeners, and dataHost
* references onto the bound nodeList.
*
* @param {!PropertyEffectsType} inst Instance that bas been previously bound
* @param {!Polymer_PropertyEffects} inst Instance that bas been previously
* bound
* @param {TemplateInfo} templateInfo Template metadata
* @return {void}
* @private
@@ -729,7 +734,8 @@ function setupCompoundStorage(node, binding) {
* Adds a 2-way binding notification event listener to the node specified
*
* @param {Object} node Child element to add listener to
* @param {!PropertyEffectsType} inst Host element instance to handle notification event
* @param {!Polymer_PropertyEffects} inst Host element instance to handle
* notification event
* @param {Binding} binding Binding metadata
* @return {void}
* @private
@@ -793,7 +799,7 @@ function createMethodEffect(model, sig, type, effectFn, methodInfo, dynamicFn) {
* functions call this function to invoke the method, then use the return
* value accordingly.
*
* @param {!PropertyEffectsType} inst The instance the effect will be run on
* @param {!Polymer_PropertyEffects} inst The instance the effect will be run on
* @param {string} property Name of property
* @param {Object} props Bag of current property changes
* @param {Object} oldProps Bag of previous values for changed properties
@@ -970,7 +976,7 @@ function parseArg(rawArg) {
*
* Note: this implementation only accepts normalized paths
*
* @param {!PropertyEffectsType} inst Instance to send notifications to
* @param {!Polymer_PropertyEffects} inst Instance to send notifications to
* @param {Array} array The array the mutations occurred on
* @param {string} path The path to the array that was mutated
* @param {Array} splices Array of splice records
@@ -991,7 +997,7 @@ function notifySplices(inst, array, path, splices) {
*
* Note: this implementation only accepts normalized paths
*
* @param {!PropertyEffectsType} inst Instance to send notifications to
* @param {!Polymer_PropertyEffects} inst Instance to send notifications to
* @param {Array} array The array the mutations occurred on
* @param {string} path The path to the array that was mutated
* @param {number} index Index at which the array mutation occurred
@@ -1060,7 +1066,6 @@ export const PropertyEffects = dedupingMixin(superClass => {
/**
* @constructor
* @extends {superClass}
* @implements {Polymer_PropertyAccessors}
* @implements {Polymer_TemplateStamp}
* @unrestricted
@@ -1107,7 +1112,7 @@ export const PropertyEffects = dedupingMixin(superClass => {
this.__dataClientsInitialized;
/** @type {!Object} */
this.__data;
/** @type {!Object} */
/** @type {!Object|null} */
this.__dataPending;
/** @type {!Object} */
this.__dataOld;
@@ -1132,6 +1137,7 @@ export const PropertyEffects = dedupingMixin(superClass => {
}
/**
* @override
* @return {void}
*/
_initializeProperties() {
@@ -1190,6 +1196,7 @@ export const PropertyEffects = dedupingMixin(superClass => {
* an instance to add effects at runtime. See that method for
* full API docs.
*
* @override
* @param {string} property Property that should trigger the effect
* @param {string} type Effect type, from this.PROPERTY_EFFECT_TYPES
* @param {Object=} effect Effect metadata object
@@ -1209,6 +1216,7 @@ export const PropertyEffects = dedupingMixin(superClass => {
/**
* Removes the given property effect.
*
* @override
* @param {string} property Property the effect was associated with
* @param {string} type Effect type, from this.PROPERTY_EFFECT_TYPES
* @param {Object=} effect Effect metadata object to remove
@@ -1226,9 +1234,11 @@ export const PropertyEffects = dedupingMixin(superClass => {
* Returns whether the current prototype/instance has a property effect
* of a certain type.
*
* @override
* @param {string} property Property name
* @param {string=} type Effect type, from this.PROPERTY_EFFECT_TYPES
* @return {boolean} True if the prototype/instance has an effect of this type
* @return {boolean} True if the prototype/instance has an effect of this
* type
* @protected
*/
_hasPropertyEffect(property, type) {
@@ -1240,8 +1250,10 @@ export const PropertyEffects = dedupingMixin(superClass => {
* Returns whether the current prototype/instance has a "read only"
* accessor for the given property.
*
* @override
* @param {string} property Property name
* @return {boolean} True if the prototype/instance has an effect of this type
* @return {boolean} True if the prototype/instance has an effect of this
* type
* @protected
*/
_hasReadOnlyEffect(property) {
@@ -1252,8 +1264,10 @@ export const PropertyEffects = dedupingMixin(superClass => {
* Returns whether the current prototype/instance has a "notify"
* property effect for the given property.
*
* @override
* @param {string} property Property name
* @return {boolean} True if the prototype/instance has an effect of this type
* @return {boolean} True if the prototype/instance has an effect of this
* type
* @protected
*/
_hasNotifyEffect(property) {
@@ -1261,11 +1275,13 @@ export const PropertyEffects = dedupingMixin(superClass => {
}
/**
* Returns whether the current prototype/instance has a "reflect to attribute"
* property effect for the given property.
* Returns whether the current prototype/instance has a "reflect to
* attribute" property effect for the given property.
*
* @override
* @param {string} property Property name
* @return {boolean} True if the prototype/instance has an effect of this type
* @return {boolean} True if the prototype/instance has an effect of this
* type
* @protected
*/
_hasReflectEffect(property) {
@@ -1276,8 +1292,10 @@ export const PropertyEffects = dedupingMixin(superClass => {
* Returns whether the current prototype/instance has a "computed"
* property effect for the given property.
*
* @override
* @param {string} property Property name
* @return {boolean} True if the prototype/instance has an effect of this type
* @return {boolean} True if the prototype/instance has an effect of this
* type
* @protected
*/
_hasComputedEffect(property) {
@@ -1301,6 +1319,7 @@ export const PropertyEffects = dedupingMixin(superClass => {
* `path` can be a path string or array of path parts as accepted by the
* public API.
*
* @override
* @param {string | !Array<number|string>} path Path to set
* @param {*} value Value to set
* @param {boolean=} shouldNotify Set to true if this change should
@@ -1335,7 +1354,7 @@ export const PropertyEffects = dedupingMixin(superClass => {
}
this.__dataHasPaths = true;
if (this._setPendingProperty(/**@type{string}*/(path), value, shouldNotify)) {
computeLinkedPaths(this, path, value);
computeLinkedPaths(this, /**@type{string}*/ (path), value);
return true;
}
} else {
@@ -1363,6 +1382,7 @@ export const PropertyEffects = dedupingMixin(superClass => {
*
* Users may override this method to provide alternate approaches.
*
* @override
* @param {!Node} node The node to set a property on
* @param {string} prop The property to set
* @param {*} value The value to set
@@ -1480,6 +1500,7 @@ export const PropertyEffects = dedupingMixin(superClass => {
* pending property changes can later be flushed via a call to
* `_flushClients`.
*
* @override
* @param {Object} client PropertyEffects client to enqueue
* @return {void}
* @protected
@@ -1494,6 +1515,7 @@ export const PropertyEffects = dedupingMixin(superClass => {
/**
* Overrides superclass implementation.
*
* @override
* @return {void}
* @protected
*/
@@ -1507,6 +1529,7 @@ export const PropertyEffects = dedupingMixin(superClass => {
* Flushes any clients previously enqueued via `_enqueueClient`, causing
* their `_flushProperties` method to run.
*
* @override
* @return {void}
* @protected
*/
@@ -1555,6 +1578,7 @@ export const PropertyEffects = dedupingMixin(superClass => {
* `_flushProperties` call on client dom and before any element
* observers are called.
*
* @override
* @return {void}
* @protected
*/
@@ -1569,6 +1593,7 @@ export const PropertyEffects = dedupingMixin(superClass => {
* Property names must be simple properties, not paths. Batched
* path propagation is not supported.
*
* @override
* @param {Object} props Bag of one or more key-value pairs whose key is
* a property and value is the new value to set for that property.
* @param {boolean=} setReadOnly When true, any private values set in
@@ -1623,6 +1648,7 @@ export const PropertyEffects = dedupingMixin(superClass => {
* Runs each class of effects for the batch of changed properties in
* a specific order (compute, propagate, reflect, observe, notify).
*
* @override
* @param {!Object} currentProps Bag of all current accessor values
* @param {?Object} changedProps Bag of properties changed since the last
* call to `_propertiesChanged`
@@ -1669,6 +1695,7 @@ export const PropertyEffects = dedupingMixin(superClass => {
* Called to propagate any property changes to stamped template nodes
* managed by this element.
*
* @override
* @param {Object} changedProps Bag of changed properties
* @param {Object} oldProps Bag of previous values for changed properties
* @param {boolean} hasPaths True with `props` contains one or more paths
@@ -1691,6 +1718,7 @@ export const PropertyEffects = dedupingMixin(superClass => {
* Aliases one data path as another, such that path notifications from one
* are routed to the other.
*
* @override
* @param {string | !Array<string|number>} to Target path to link.
* @param {string | !Array<string|number>} from Source path to link.
* @return {void}
@@ -1709,6 +1737,7 @@ export const PropertyEffects = dedupingMixin(superClass => {
* Note, the path to unlink should be the target (`to`) used when
* linking the paths.
*
* @override
* @param {string | !Array<string|number>} path Target path to unlink.
* @return {void}
* @public
@@ -1730,8 +1759,10 @@ export const PropertyEffects = dedupingMixin(superClass => {
* this.items.splice(1, 1, {name: 'Sam'});
* this.items.push({name: 'Bob'});
* this.notifySplices('items', [
* { index: 1, removed: [{name: 'Todd'}], addedCount: 1, object: this.items, type: 'splice' },
* { index: 3, removed: [], addedCount: 1, object: this.items, type: 'splice'}
* { index: 1, removed: [{name: 'Todd'}], addedCount: 1,
* object: this.items, type: 'splice' },
* { index: 3, removed: [], addedCount: 1,
* object: this.items, type: 'splice'}
* ]);
*
* @param {string} path Path that should be notified.
@@ -1747,9 +1778,11 @@ export const PropertyEffects = dedupingMixin(superClass => {
* Note that splice records _must_ be normalized such that they are
* reported in index order (raw results from `Object.observe` are not
* ordered and must be normalized/merged before notifying).
*
* @override
* @return {void}
* @public
*/
*/
notifySplices(path, splices) {
let info = {path: ''};
let array = /** @type {Array} */(get(this, path, info));
@@ -1763,6 +1796,7 @@ export const PropertyEffects = dedupingMixin(superClass => {
* `undefined` (this method does not throw when dereferencing undefined
* paths).
*
* @override
* @param {(string|!Array<(string|number)>)} path Path to the value
* to read. The path may be specified as a string (e.g. `foo.bar.baz`)
* or an array of path parts (e.g. `['foo.bar', 'baz']`). Note that
@@ -1787,6 +1821,7 @@ export const PropertyEffects = dedupingMixin(superClass => {
* this method does nothing (this method does not throw when
* dereferencing undefined paths).
*
* @override
* @param {(string|!Array<(string|number)>)} path Path to the value
* to write. The path may be specified as a string (e.g. `'foo.bar.baz'`)
* or an array of path parts (e.g. `['foo.bar', 'baz']`). Note that
@@ -1799,7 +1834,7 @@ export const PropertyEffects = dedupingMixin(superClass => {
* When specified, no notification will occur.
* @return {void}
* @public
*/
*/
set(path, value, root) {
if (root) {
set(root, path, value);
@@ -1821,6 +1856,7 @@ export const PropertyEffects = dedupingMixin(superClass => {
* This method notifies other paths to the same array that a
* splice occurred to the array.
*
* @override
* @param {string | !Array<string|number>} path Path to array.
* @param {...*} items Items to push onto array
* @return {number} New length of the array.
@@ -1846,6 +1882,7 @@ export const PropertyEffects = dedupingMixin(superClass => {
* This method notifies other paths to the same array that a
* splice occurred to the array.
*
* @override
* @param {string | !Array<string|number>} path Path to array.
* @return {*} Item that was removed.
* @public
@@ -1871,6 +1908,7 @@ export const PropertyEffects = dedupingMixin(superClass => {
* This method notifies other paths to the same array that a
* splice occurred to the array.
*
* @override
* @param {string | !Array<string|number>} path Path to array.
* @param {number} start Index from which to start removing/inserting.
* @param {number=} deleteCount Number of items to remove.
@@ -1926,6 +1964,7 @@ export const PropertyEffects = dedupingMixin(superClass => {
* This method notifies other paths to the same array that a
* splice occurred to the array.
*
* @override
* @param {string | !Array<string|number>} path Path to array.
* @return {*} Item that was removed.
* @public
@@ -1950,6 +1989,7 @@ export const PropertyEffects = dedupingMixin(superClass => {
* This method notifies other paths to the same array that a
* splice occurred to the array.
*
* @override
* @param {string | !Array<string|number>} path Path to array.
* @param {...*} items Items to insert info array
* @return {number} New length of the array.
@@ -1973,11 +2013,12 @@ export const PropertyEffects = dedupingMixin(superClass => {
* this.item.user.name = 'Bob';
* this.notifyPath('item.user.name');
*
* @override
* @param {string} path Path that should be notified.
* @param {*=} value Value at the path (optional).
* @return {void}
* @public
*/
*/
notifyPath(path, value) {
/** @type {string} */
let propPath;
@@ -2002,6 +2043,7 @@ export const PropertyEffects = dedupingMixin(superClass => {
* an instance to add effects at runtime. See that method for
* full API docs.
*
* @override
* @param {string} property Property name
* @param {boolean=} protectedSetter Creates a custom protected setter
* when `true`.
@@ -2022,8 +2064,10 @@ export const PropertyEffects = dedupingMixin(superClass => {
* an instance to add effects at runtime. See that method for
* full API docs.
*
* @override
* @param {string} property Property name
* @param {string|function(*,*)} method Function or name of observer method to call
* @param {string|function(*,*)} method Function or name of observer method
* to call
* @param {boolean=} dynamicFn Whether the method name should be included as
* a dependency to the effect.
* @return {void}
@@ -2046,6 +2090,7 @@ export const PropertyEffects = dedupingMixin(superClass => {
* an instance to add effects at runtime. See that method for
* full API docs.
*
* @override
* @param {string} expression Method expression
* @param {boolean|Object=} dynamicFn Boolean or object map indicating
* whether method names should be included as a dependency to the effect.
@@ -2065,6 +2110,7 @@ export const PropertyEffects = dedupingMixin(superClass => {
* an instance to add effects at runtime. See that method for
* full API docs.
*
* @override
* @param {string} property Property name
* @return {void}
* @protected
@@ -2084,6 +2130,7 @@ export const PropertyEffects = dedupingMixin(superClass => {
* an instance to add effects at runtime. See that method for
* full API docs.
*
* @override
* @param {string} property Property name
* @return {void}
* @protected
@@ -2108,6 +2155,7 @@ export const PropertyEffects = dedupingMixin(superClass => {
* an instance to add effects at runtime. See that method for
* full API docs.
*
* @override
* @param {string} property Name of computed property to set
* @param {string} expression Method expression
* @param {boolean|Object=} dynamicFn Boolean or object map indicating
@@ -2337,6 +2385,7 @@ export const PropertyEffects = dedupingMixin(superClass => {
* create and link an instance of the template metadata associated with a
* particular stamping.
*
* @override
* @param {!HTMLTemplateElement} template Template containing binding
* bindings
* @param {boolean=} instanceBinding When false (default), performs
@@ -2445,6 +2494,7 @@ export const PropertyEffects = dedupingMixin(superClass => {
* Removes and unbinds the nodes previously contained in the provided
* DocumentFragment returned from `_stampTemplate`.
*
* @override
* @param {!StampedTemplate} dom DocumentFragment previously returned
* from `_stampTemplate` associated with the nodes to be removed
* @return {void}
@@ -2709,8 +2759,8 @@ export const PropertyEffects = dedupingMixin(superClass => {
* Called to evaluate a previously parsed binding part based on a set of
* one or more changed dependencies.
*
* @param {this} inst Element that should be used as scope for
* binding dependencies
* @param {!Polymer_PropertyEffects} inst Element that should be used as
* scope for binding dependencies
* @param {BindingPart} part Binding part metadata
* @param {string} path Property/path that triggered this effect
* @param {Object} props Bag of current property changes
@@ -2740,9 +2790,6 @@ export const PropertyEffects = dedupingMixin(superClass => {
}
// make a typing for closure :P
PropertyEffectsType = PropertyEffects;
return PropertyEffects;
});

View File

@@ -102,7 +102,7 @@ export function stylesFromModule(moduleId) {
* Returns the `<style>` elements within a given template.
*
* @param {!HTMLTemplateElement} template Template to gather styles from
* @param {string} baseURI baseURI for style content
* @param {string=} baseURI baseURI for style content
* @return {!Array<!HTMLStyleElement>} Array of styles
*/
export function stylesFromTemplate(template, baseURI) {
@@ -121,7 +121,8 @@ export function stylesFromTemplate(template, baseURI) {
}));
}
if (baseURI) {
e.textContent = resolveCss(e.textContent, baseURI);
e.textContent =
resolveCss(e.textContent, /** @type {string} */ (baseURI));
}
styles.push(e);
}

View File

@@ -331,15 +331,19 @@ function findMethodHost(template) {
* @suppress {missingProperties} class.prototype is not defined for some reason
*/
function createTemplatizerClass(template, templateInfo, options) {
// Anonymous class created by the templatize
/**
* @constructor
* @extends {TemplateInstanceBase}
*/
let base = options.mutableData ?
MutableTemplateInstanceBase : TemplateInstanceBase;
/**
* Anonymous class created by the templatize
* @constructor
* @extends {base}
* @private
*/
let klass = class extends base { };
/** @override */
klass.prototype.__templatizeOptions = options;
klass.prototype._bindTemplate(template);
addNotifyEffects(klass, template, templateInfo, options);
@@ -355,6 +359,10 @@ function addPropagateEffects(template, templateInfo, options) {
// Provide data API and property effects on memoized template class
let klass = templateInfo.templatizeTemplateClass;
if (!klass) {
/**
* @constructor
* @extends {DataTemplate}
*/
let base = options.mutableData ? MutableDataTemplate : DataTemplate;
/** @private */
klass = templateInfo.templatizeTemplateClass =
@@ -521,6 +529,10 @@ export function templatize(template, owner, options) {
let templateInfo = ctor._parseTemplate(template);
// Get memoized base class for the prototypical template, which
// includes property effects for binding template & forwarding
/**
* @constructor
* @extends {TemplateInstanceBase}
*/
let baseClass = templateInfo.templatizeInstanceClass;
if (!baseClass) {
baseClass = createTemplatizerClass(template, templateInfo, options);
@@ -531,9 +543,13 @@ export function templatize(template, owner, options) {
// Subclass base class and add reference for this specific template
/** @private */
let klass = class TemplateInstance extends baseClass {};
/** @override */
klass.prototype._methodHost = findMethodHost(template);
klass.prototype.__dataHost = template;
klass.prototype.__templatizeOwner = owner;
/** @override */
klass.prototype.__dataHost = /** @type {!DataTemplate} */ (template);
/** @override */
klass.prototype.__templatizeOwner = /** @type {!Object} */ (owner);
/** @override */
klass.prototype.__hostProps = templateInfo.hostProps;
klass = /** @type {function(new:TemplateInstanceBase)} */(klass); //eslint-disable-line no-self-assign
return klass;