From 2efccb95f44eb48b5cc850ce6c0a46f4eb680076 Mon Sep 17 00:00:00 2001 From: Daniel Freedman Date: Tue, 20 Jun 2017 17:30:57 -0700 Subject: [PATCH] Remove @suppress {missingProperties} It may break stuff in closure to use this much, so try to shape classes for closure directly. Use polymer pass v2 to remove warnings for properties defined in `properties` block --- closure.log | 314 +++++++++++++++++++-------- externs/polymer-externs.js | 27 ++- externs/webcomponents-externs.js | 1 + gulpfile.js | 10 +- lib/elements/array-selector.html | 2 +- lib/elements/dom-bind.html | 1 - lib/elements/dom-if.html | 1 - lib/elements/dom-repeat.html | 7 +- lib/legacy/class.html | 3 +- lib/legacy/legacy-element-mixin.html | 1 - lib/mixins/element-mixin.html | 10 +- lib/mixins/mutable-data.html | 3 +- lib/mixins/property-accessors.html | 28 ++- lib/mixins/property-effects.html | 113 +++++----- lib/utils/templatize.html | 12 - 15 files changed, 342 insertions(+), 191 deletions(-) diff --git a/closure.log b/closure.log index 03bcf4cd11..bd9bdcfe0b 100644 --- a/closure.log +++ b/closure.log @@ -1,4 +1,6 @@ -gulp-google-closure-compiler: externs/closure-types.js:1053: WARNING - property connectedCallback not defined on any supertype of Polymer_ElementMixin +gulp-google-closure-compiler: WARNING - Type annotation references non-existent type Polymer.ElementProperties. + +externs/closure-types.js:1053: WARNING - property connectedCallback not defined on any supertype of Polymer_ElementMixin Polymer_ElementMixin.prototype.connectedCallback = function(){}; ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -6,128 +8,258 @@ externs/closure-types.js:1057: WARNING - property disconnectedCallback not defin Polymer_ElementMixin.prototype.disconnectedCallback = function(){}; ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -externs/closure-types.js:2036: WARNING - property mutableData on interface Polymer_OptionalMutableData is not implemented by type OptionalMutableData -Polymer_OptionalMutableData.prototype.mutableData; -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +polymer.html_script_11.js:464: WARNING - Property negate never defined on $jscomp$destructuring$var0 of type {event: ?} + let {event, negate} = binding.parts[0]; + ^^^^^^ + +polymer.html_script_11.js:490: WARNING - Property target never defined on binding of type {kind: string} + if (binding.kind === 'attribute' && binding.target[0] === '-') { + ^^^^^^^^^^^^^^ + +polymer.html_script_11.js:491: WARNING - Property target never defined on binding of type {kind: string} + console.warn('Cannot set attribute ' + binding.target + + ^^^^^^^^^^^^^^ + +polymer.html_script_11.js:494: WARNING - Property dependencies never defined on part of type Object + let dependencies = part.dependencies; + ^^^^^^^^^^^^^^^^^ + +polymer.html_script_11.js:565: WARNING - Property kind never defined on binding of type {target: string} + value = Polymer.sanitizeDOMValue(value, binding.target, binding.kind, node); + ^^^^^^^^^^^^ + +polymer.html_script_11.js:569: WARNING - Property target never defined on binding of type {kind: ?} + inst._valueToNodeAttribute(/** @type {Element} */(node), value, binding.target); + ^^^^^^^^^^^^^^ + +polymer.html_script_11.js:572: WARNING - Property target never defined on binding of type {kind: ?} + let prop = binding.target; + ^^^^^^^^^^^^^^ + +polymer.html_script_11.js:602: WARNING - Property kind never defined on binding of type Object + if (binding.kind !== 'attribute') { + ^^^^^^^^^^^^ + +polymer.html_script_11.js:604: WARNING - Property target never defined on binding of type Object + if (binding.target === 'textContent' || + ^^^^^^^^^^^^^^ + +polymer.html_script_11.js:605: WARNING - Property target never defined on binding of type Object + (node.localName == 'input' && binding.target == 'value')) { + ^^^^^^^^^^^^^^ + +polymer.html_script_11.js:643: WARNING - Property nodeInfoList never defined on $jscomp$destructuring$var1 of type {nodeList: ?} + let {nodeList, nodeInfoList} = templateInfo; + ^^^^^^^^^^^^ + +polymer.html_script_11.js:731: WARNING - Property methodName never defined on sig of type Object + (typeof dynamicFn !== 'object' || dynamicFn[sig.methodName])); + ^^^^^^^^^^^^^^ + +polymer.html_script_11.js:733: WARNING - Property methodName never defined on sig of type Object + methodName: sig.methodName, + ^^^^^^^^^^^^^^ + +polymer.html_script_11.js:734: WARNING - Property args never defined on sig of type Object + args: sig.args, + ^^^^^^^^ + +polymer.html_script_11.js:738: WARNING - Property args never defined on sig of type Object + for (let i=0, arg; (i=, nodeList: ?, wasPreBound: truthy=} + runEffects(this, templateInfo.propertyEffects, this.__data, null, + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -polymer.html_script_31.js:532: WARNING - Property indexAs never defined on this of type DomRepeat{__instances: Object, __itemsIdxToInstIdx: Object{}, __limit: number, items: ?=} - inst._setPendingProperty(this.indexAs, instIdx); - ^^^^^^^^^^^^ +polymer.html_script_11.js:2323: WARNING - Property templateInfo never defined on dom of type DocumentFragment + let templateInfo = dom.templateInfo; + ^^^^^^^^^^^^^^^^ -polymer.html_script_31.js:533: WARNING - Property itemsIndexAs never defined on this of type DomRepeat{__instances: Object, __itemsIdxToInstIdx: Object{}, __limit: number, items: ?=} - inst._setPendingProperty(this.itemsIndexAs, itemIdx); - ^^^^^^^^^^^^^^^^^ +polymer.html_script_11.js:2361: WARNING - Property _parseTemplateNode never defined on propertyEffectsBase of type propertyEffectsBase<|function(new:propertyEffectsBase):?|> + let noted = super._parseTemplateNode(node, templateInfo, nodeInfo); + ^^^^^^^^^^^^^^^^^^^^^^^^ -polymer.html_script_31.js:569: WARNING - Property as never defined on this of type DomRepeat - model[this.as] = item; - ^^^^^^^ +polymer.html_script_11.js:2426: WARNING - Property _parseTemplateNodeAttribute never defined on propertyEffectsBase of type propertyEffectsBase<|function(new:propertyEffectsBase):?|> + return super._parseTemplateNodeAttribute(node, templateInfo, nodeInfo, name, value); + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -polymer.html_script_31.js:570: WARNING - Property indexAs never defined on this of type DomRepeat - model[this.indexAs] = instIdx; - ^^^^^^^^^^^^ +polymer.html_script_11.js:2444: WARNING - Property _parseTemplateNestedTemplate never defined on propertyEffectsBase of type propertyEffectsBase<|function(new:propertyEffectsBase):?|> + let noted = super._parseTemplateNestedTemplate(node, templateInfo, nodeInfo); + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -polymer.html_script_31.js:571: WARNING - Property itemsIndexAs never defined on this of type DomRepeat - model[this.itemsIndexAs] = itemIdx; - ^^^^^^^^^^^^^^^^^ +polymer.html_script_11.js:2517: WARNING - Property args never defined on $jscomp$destructuring$var2 of type Object + let {args, methodName} = signature; + ^^^^ -polymer.html_script_31.js:580: WARNING - Property as never defined on this of type DomRepeat{__pool: {pop: LOOSE_TOP_FUNCTION} (loose)} - inst._setPendingProperty(this.as, item); - ^^^^^^^ +polymer.html_script_11.js:2517: WARNING - Property methodName never defined on $jscomp$destructuring$var2 of type Object + let {args, methodName} = signature; + ^^^^^^^^^^ -polymer.html_script_31.js:581: WARNING - Property indexAs never defined on this of type DomRepeat{__pool: {pop: LOOSE_TOP_FUNCTION} (loose)} - inst._setPendingProperty(this.indexAs, instIdx); - ^^^^^^^^^^^^ +polymer.html_script_11.js:2573: WARNING - Property source never defined on part of type Object + } else if (path != part.source) { + ^^^^^^^^^^^ -polymer.html_script_31.js:582: WARNING - Property itemsIndexAs never defined on this of type DomRepeat{__pool: {pop: LOOSE_TOP_FUNCTION} (loose)} - inst._setPendingProperty(this.itemsIndexAs, itemIdx); - ^^^^^^^^^^^^^^^^^ +polymer.html_script_11.js:2574: WARNING - Property source never defined on part of type Object + value = Polymer.Path.get(inst, part.source); + ^^^^^^^^^^^ -polymer.html_script_31.js:619: WARNING - Property as never defined on this of type DomRepeat{__instances: Object, __itemsIdxToInstIdx: Object} - let itemPath = this.as + (itemSubPath ? '.' + itemSubPath : ''); - ^^^^^^^ +polymer.html_script_12.js:158: WARNING - Property prototype never defined on klass of type HTMLElement{__classProperties: Object|null} + let superCtor = Object.getPrototypeOf(klass.prototype).constructor; + ^^^^^^^^^^^^^^^ -polymer.html_script_31.js:642: WARNING - Property as never defined on this of type DomRepeat - return instance && instance[this.as]; - ^^^^^^^ +polymer.html_script_12.js:613: WARNING - Property $ never defined on this.root of type DocumentFragment + this.$ = this.root.$; + ^^^^^^^^^^^ -polymer.html_script_31.js:656: WARNING - Property indexAs never defined on this of type DomRepeat - return instance && instance[this.indexAs]; - ^^^^^^^^^^^^ +polymer.html_script_12.js:743: WARNING - Property _parseTemplateContent never defined on polymerElementBase of type polymerElementBase<|function(new:polymerElementBase):?|> + return super._parseTemplateContent(template, templateInfo, nodeInfo); + ^^^^^^^^^^^^^^^^^^^^^^^^^^^ -polymer.html_script_32.js:245: WARNING - Property if never defined on this of type DomIf - let hidden = this.__hideTemplateChildren__ || !this.if; - ^^^^^^^ +polymer.html_script_23.js:446: WARNING - Property forceRender never defined on any type in the program + this.shadowRoot.forceRender(); + ^^^^^^^^^^^^^^^^^^^^^^^^^^^ -polymer.html_script_33.js:154: WARNING - Property items never defined on this of type ArraySelectorMixin - if (selected.has(this.items[idx])) { - ^^^^^^^^^^ +polymer.html_script_27.js:118: WARNING - Property __dataHost never defined on this.__dataHost of type DataTemplate + let templateHost = this.__dataHost.__dataHost; + ^^^^^^^^^^^^^^^^^^^^^^^^^^ -polymer.html_script_33.js:155: WARNING - Property items never defined on this of type ArraySelectorMixin - selected.set(this.items[idx], idx); - ^^^^^^^^^^ +polymer.html_script_27.js:190: WARNING - Property __dataHost never defined on model.__dataHost of type DataTemplate + model = model.__dataHost.__dataHost; + ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +polymer.html_script_27.js:232: WARNING - Property _bindTemplate never defined on klass.prototype of type klass.prototype + klass.prototype._bindTemplate(template); + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +polymer.html_script_27.js:250: WARNING - Property _addPropertyEffect never defined on klass.prototype of type polymer_html_script_27$classdecl$var1.prototype + klass.prototype._addPropertyEffect('_host_' + prop, + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +polymer.html_script_27.js:251: WARNING - Property PROPERTY_EFFECT_TYPES never defined on klass.prototype of type polymer_html_script_27$classdecl$var1.prototype + klass.prototype.PROPERTY_EFFECT_TYPES.PROPAGATE, + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +polymer.html_script_27.js:253: WARNING - Property _createNotifyingProperty never defined on klass.prototype of type polymer_html_script_27$classdecl$var1.prototype + klass.prototype._createNotifyingProperty('_host_' + prop); + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +polymer.html_script_29.js:95: WARNING - Property $ never defined on this.root of type DocumentFragment + this.$ = this.root.$; + ^^^^^^^^^^^ + +polymer.html_script_31.js:218: WARNING - property _setRenderedItemCount not defined on any supertype of DomRepeat + renderedItemCount: { + ^^^^^^^^^^^^^^^^^ + +polymer.html_script_31.js:365: WARNING - Property __dataHost never defined on this of type DomRepeat + return this.__dataHost._methodHost || this.__dataHost; + ^^^^^^^^^^^^^^^ + +polymer.html_script_32.js:222: WARNING - Property __dataHost never defined on this of type DomIf{__instance: {_setPendingProperty: LOOSE_TOP_FUNCTION} (loose)} + this.__instance._setPendingProperty(prop, this.__dataHost[prop]); + ^^^^^^^^^^^^^^^ + +polymer.html_script_33.js:169: WARNING - The right side in the assignment is not a subtype of the left side. +Expected : Object +Found : null + + this.selected = this.selectedItem = null; + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +polymer.html_script_33.js:169: WARNING - The right side in the assignment is not a subtype of the left side. +Expected : Object +Found : null + + this.selected = this.selectedItem = null; + ^^^^^^^^^^^^^^^^^^^^^^^^ + +polymer.html_script_33.js:208: WARNING - The right side in the assignment is not a subtype of the left side. +Expected : Object +Found : Array|null +More details: +The found type is a union that includes an unexpected type: null + this.selected = this.multi ? [] : null + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +polymer.html_script_33.js:209: WARNING - The right side in the assignment is not a subtype of the left side. +Expected : Object +Found : null + + this.selectedItem = null; + ^^^^^^^^^^^^^^^^^^^^^^^^ + +polymer.html_script_33.js:229: WARNING - Invalid type for index. +Expected : number +Found : * -polymer.html_script_33.js:228: WARNING - Property items never defined on this of type ArraySelectorMixin return this.isSelected(this.items[idx]); - ^^^^^^^^^^ + ^^^ + +polymer.html_script_33.js:268: WARNING - The right side in the assignment is not a subtype of the left side. +Expected : Object +Found : null -polymer.html_script_33.js:278: WARNING - Property items never defined on this of type ArraySelectorMixin - this.deselect(this.items[idx]); - ^^^^^^^^^^ + this.selected = this.selectedItem = null; + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -polymer.html_script_33.js:288: WARNING - Property items never defined on this of type ArraySelectorMixin - this.selectIndex(this.items.indexOf(item)); - ^^^^^^^^^^ +polymer.html_script_33.js:268: WARNING - The right side in the assignment is not a subtype of the left side. +Expected : Object +Found : null -polymer.html_script_33.js:298: WARNING - Property items never defined on this of type ArraySelectorMixin - let item = this.items[idx]; - ^^^^^^^^^^ + this.selected = this.selectedItem = null; + ^^^^^^^^^^^^^^^^^^^^^^^^ polymer.html_script_35.js:5: WARNING - Property _mutablePropertyChange never defined on Polymer.MutableData of type function(?):? let mutablePropertyChange = Polymer.MutableData._mutablePropertyChange; ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -0 error(s), 33 warning(s), 75.7% typed +0 error(s), 61 warning(s), 75.7% typed diff --git a/externs/polymer-externs.js b/externs/polymer-externs.js index e6b636de07..d6daa9fa50 100644 --- a/externs/polymer-externs.js +++ b/externs/polymer-externs.js @@ -61,15 +61,18 @@ Polymer.sanitizeDOMValue; */ function JSCompiler_renameProperty(string, obj) {} -/** @record */ -function PolymerTelemetry(){} -/** @type {number} */ -PolymerTelemetry.prototype.instanceCount; -/** @type {Array} */ -PolymerTelemetry.prototype.registrations; -/** @type {function(HTMLElement)} */ -PolymerTelemetry.prototype._regLog; -/** @type {function(HTMLElement)} */ -PolymerTelemetry.prototype.register; -/** @type {function(HTMLElement)} */ -PolymerTelemetry.prototype.dumpRegistrations; \ No newline at end of file +/** @type {Object} */ +Polymer.telemetry; + +/** @type {Object} */ +Polymer_PropertyEffects.prototype.__computeEffects; +/** @type {Object} */ +Polymer_PropertyEffects.prototype.__reflectEffects; +/** @type {Object} */ +Polymer_PropertyEffects.prototype.__notifyEffects; +/** @type {Object} */ +Polymer_PropertyEffects.prototype.__propagateEffects; +/** @type {Object} */ +Polymer_PropertyEffects.prototype.__observeEffects; +/** @type {Object} */ +Polymer_PropertyEffects.prototype.__readOnly; \ No newline at end of file diff --git a/externs/webcomponents-externs.js b/externs/webcomponents-externs.js index c43ef4348a..d06dc892ee 100644 --- a/externs/webcomponents-externs.js +++ b/externs/webcomponents-externs.js @@ -2,6 +2,7 @@ * @fileoverview Externs for webcomponents polyfills * @externs */ +/* eslint-disable */ let HTMLImports = { /** diff --git a/gulpfile.js b/gulpfile.js index 574e551290..c34ddade42 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -107,6 +107,7 @@ gulp.task('closure', ['clean'], () => { } config('polymer.html'); + // config('lib/mixins/property-effects.html'); const project = new PolymerProject({ shell: `./${entry}`, @@ -146,6 +147,7 @@ gulp.task('closure', ['clean'], () => { rewrite_polyfills: false, new_type_inf: true, checks_only: CLOSURE_LINT_ONLY, + polymer_version: 2, externs: [ 'bower_components/shadycss/externs/shadycss-externs.js', 'externs/webcomponents-externs.js', @@ -153,9 +155,11 @@ gulp.task('closure', ['clean'], () => { 'externs/polymer-externs.js', ], extra_annotation_name: [ - 'polymerMixin', - 'polymerMixinClass', - 'polymerElement' + 'appliesMixin', + 'mixinClass', + 'mixinFunction', + 'polymer', + 'customElement' ] }, closurePluginOptions); diff --git a/lib/elements/array-selector.html b/lib/elements/array-selector.html index a57c1738c5..ea78f6dc1e 100644 --- a/lib/elements/array-selector.html +++ b/lib/elements/array-selector.html @@ -32,7 +32,6 @@ * * @mixinFunction * @polymer - * @appliesMixin Polymer.ElementMixin * @memberof Polymer * @summary Element mixin for recording dynamic associations between item paths in a * master `items` array and a `selected` array @@ -48,6 +47,7 @@ /** * @mixinClass + * @polymer * @implements {Polymer_ArraySelectorMixin} * @unrestricted */ diff --git a/lib/elements/dom-bind.html b/lib/elements/dom-bind.html index cc39300524..028fe86031 100644 --- a/lib/elements/dom-bind.html +++ b/lib/elements/dom-bind.html @@ -87,7 +87,6 @@ /** * Forces the element to render its content. This is typically only * necessary to call if HTMLImports with the async attribute are used. - * @suppress {missingProperties} */ render() { let template; diff --git a/lib/elements/dom-if.html b/lib/elements/dom-if.html index fad92cadcd..902b5626ae 100644 --- a/lib/elements/dom-if.html +++ b/lib/elements/dom-if.html @@ -230,7 +230,6 @@ return true; } - /** @suppress {missingProperties} */ __syncHostProperties() { let props = this.__invalidProps; if (props) { diff --git a/lib/elements/dom-repeat.html b/lib/elements/dom-repeat.html index 149b747416..17a1401588 100644 --- a/lib/elements/dom-repeat.html +++ b/lib/elements/dom-repeat.html @@ -118,7 +118,7 @@ * @polymer * @memberof Polymer * @extends {domRepeatBase} - * @appliesMixin Polymer.MutableData + * @appliesMixin Polymer.OptionalMutableData * @summary Custom element for stamping instance of a template bound to * items in an array. */ @@ -372,10 +372,6 @@ return true; } - /* eslint-disable valid-jsdoc */ - /** - * @suppress {missingProperties} - */ __getMethodHost() { // Technically this should be the owner of the outermost template. // In shadow dom, this is always getRootNode().host, but we can @@ -384,7 +380,6 @@ // instance causing it to get a dataHost. return this.__dataHost._methodHost || this.__dataHost; } - /* eslint-enable valid-jsdoc */ __sortChanged(sort) { let methodHost = this.__getMethodHost(); diff --git a/lib/legacy/class.html b/lib/legacy/class.html index a09859124d..ea6f92956f 100644 --- a/lib/legacy/class.html +++ b/lib/legacy/class.html @@ -135,7 +135,7 @@ * @param {!PolymerInit} info Polymer info object * @param {!HTMLElement} Base base class to extend with info object * @return {!HTMLElement} Generated class - * @suppress {missingProperties, checkTypes} + * @suppress {checkTypes} * @private */ function GenerateClassFromInfo(info, Base) { @@ -151,7 +151,6 @@ } /** - * @suppress {missingProperties} * @return {HTMLTemplateElement} template for this class */ static get template() { diff --git a/lib/legacy/legacy-element-mixin.html b/lib/legacy/legacy-element-mixin.html index 6bf1eecfb8..41a3448c0c 100644 --- a/lib/legacy/legacy-element-mixin.html +++ b/lib/legacy/legacy-element-mixin.html @@ -459,7 +459,6 @@ * a user should call `distributeContent` if distribution has been * invalidated due to an element being added or removed from the shadowRoot * that contains an insertion point (``) inside its subtree. - * @suppress {missingProperties} */ distributeContent() { if (window.ShadyDOM && this.shadowRoot) { diff --git a/lib/mixins/element-mixin.html b/lib/mixins/element-mixin.html index 46efa7c251..2a7c821213 100644 --- a/lib/mixins/element-mixin.html +++ b/lib/mixins/element-mixin.html @@ -167,7 +167,6 @@ * * @param {PolymerElementConstructor} klass Element class * @return {PolymerElementProperties} Flattened properties for this class - * @suppress {missingProperties} * @private */ function propertiesForClass(klass) { @@ -626,7 +625,6 @@ * Stamps the element template. * * @override - * @suppress {missingProperties} */ ready() { if (this._template) { @@ -758,7 +756,6 @@ * created for them. * * @override - * @suppress {missingProperties} */ static _parseTemplateContent(template, templateInfo, nodeInfo) { templateInfo.dynamicFns = templateInfo.dynamicFns || propertiesForClass(this); @@ -790,9 +787,8 @@ */ registrations: [], /** - * @param {HTMLElement} prototype Element prototype to log + * @param {!PolymerElementConstructor} prototype Element prototype to log * @private - * @suppress {missingProperties} */ _regLog: function(prototype) { console.log('[' + prototype.is + ']: registered') @@ -801,7 +797,7 @@ * Registers a class prototype for telemetry purposes. * @param {HTMLElement} prototype Element prototype to register * @protected - * @this {PolymerTelemetry} + * @this {this} */ register: function(prototype) { this.registrations.push(prototype); @@ -810,7 +806,7 @@ /** * Logs all elements registered with an `is` to the console. * @public - * @this {PolymerTelemetry} + * @this {this} */ dumpRegistrations: function() { this.registrations.forEach(this._regLog); diff --git a/lib/mixins/mutable-data.html b/lib/mixins/mutable-data.html index 9297f80a4d..618aa3e008 100644 --- a/lib/mixins/mutable-data.html +++ b/lib/mixins/mutable-data.html @@ -100,7 +100,7 @@ } } - /** @type boolean */ + /** @type {boolean} */ MutableData.prototype.mutableData = false; return MutableData; @@ -150,6 +150,7 @@ /** * @mixinClass + * @polymer * @implements {Polymer_OptionalMutableData} */ class OptionalMutableData extends superClass { diff --git a/lib/mixins/property-accessors.html b/lib/mixins/property-accessors.html index 71efa266ce..4e73571510 100644 --- a/lib/mixins/property-accessors.html +++ b/lib/mixins/property-accessors.html @@ -119,6 +119,28 @@ constructor() { super(); + /** @type {boolean} */ + this.__serializing; + /** @type {number} */ + this.__dataCounter; + /** @type {boolean} */ + this.__dataEnabled; + /** @type {boolean} */ + this.__dataReady; + /** @type {boolean} */ + this.__dataInvalid; + /** @type {!Object} */ + this.__data; + /** @type {Object} */ + this.__dataPending; + /** @type {Object} */ + this.__dataOld; + /** @type {Object} */ + this.__dataProto; + /** @type {Object} */ + this.__dataHasAccessor; + /** @type {Object} */ + this.__dataInstanceProps; this._initializeProperties(); } @@ -452,7 +474,7 @@ this.__dataOld = {}; } // Ensure old is captured from the last turn - if (!(property in this.__dataOld)) { + if (this.__dataOld && !(property in this.__dataOld)) { this.__dataOld[property] = old; } this.__data[property] = value; @@ -469,7 +491,7 @@ * @protected */ _isPropertyPending(prop) { - return this.__dataPending && (prop in this.__dataPending); + return Boolean(this.__dataPending && (prop in this.__dataPending)); } /** @@ -519,7 +541,7 @@ * @protected */ _flushProperties() { - if (this.__dataPending) { + if (this.__dataPending && this.__dataOld) { let changedProps = this.__dataPending; this.__dataPending = null; this.__dataCounter++; diff --git a/lib/mixins/property-effects.html b/lib/mixins/property-effects.html index b2660637ee..de22972b42 100644 --- a/lib/mixins/property-effects.html +++ b/lib/mixins/property-effects.html @@ -62,6 +62,8 @@ */ 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. @@ -107,7 +109,7 @@ * Runs all effects of a given type for the given set of property changes * on an instance. * - * @param {!Polymer_PropertyEffects} inst The instance with effects to run + * @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 @@ -133,7 +135,7 @@ /** * Runs a list of effects for a given property. * - * @param {!Polymer_PropertyEffects} inst The instance with effects to run + * @param {!PropertyEffectsType} 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 @@ -198,12 +200,11 @@ * Calls the method with `info.methodName` on the instance, passing the * new and old values. * - * @param {!Polymer_PropertyEffects} inst The instance the effect will be run on + * @param {!PropertyEffectsType} 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 {?} info Effect metadata - * @suppress {missingProperties} * @private */ function runObserverEffect(inst, property, props, oldProps, info) { @@ -226,12 +227,11 @@ * `notify: true` to ensure object sub-property notifications were * sent. * - * @param {!Polymer_PropertyEffects} inst The instance with effects to run + * @param {!PropertyEffectsType} 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 * @param {boolean} hasPaths True with `props` contains one or more paths - * @suppress {missingProperties} * @private */ function runNotifyEffects(inst, notifyProps, props, oldProps, hasPaths) { @@ -262,7 +262,7 @@ * Dispatches {property}-changed events with path information in the detail * object to indicate a sub-path of the property was changed. * - * @param {!Polymer_PropertyEffects} inst The element from which to fire the event + * @param {!PropertyEffectsType} 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 @@ -282,7 +282,7 @@ * Dispatches {property}-changed events to indicate a property (or path) * changed. * - * @param {!Polymer_PropertyEffects} inst The element from which to fire the event + * @param {!PropertyEffectsType} 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 @@ -307,13 +307,12 @@ * Dispatches a non-bubbling event named `info.eventName` on the instance * with a detail object containing the new `value`. * - * @param {!Polymer_PropertyEffects} inst The instance the effect will be run on + * @param {!PropertyEffectsType} 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 {?} info Effect metadata * @param {boolean} hasPaths True with `props` contains one or more paths - * @suppress {missingProperties} * @private */ function runNotifyEffect(inst, property, props, oldProps, info, hasPaths) { @@ -336,7 +335,7 @@ * scope's name for that path first. * * @param {CustomEvent} event Notification event (e.g. '-changed') - * @param {!Polymer_PropertyEffects} inst Host element instance handling the notification event + * @param {!PropertyEffectsType} 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 @@ -366,12 +365,11 @@ * * Sets the attribute named `info.attrName` to the given property value. * - * @param {!Polymer_PropertyEffects} inst The instance the effect will be run on + * @param {!PropertyEffectsType} 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 {?} info Effect metadata - * @suppress {missingProperties} * @private */ function runReflectEffect(inst, property, props, oldProps, info) { @@ -392,12 +390,11 @@ * computed before other effects (binding propagation, observers, and notify) * run. * - * @param {!Polymer_PropertyEffects} inst The instance the effect will be run on + * @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 {boolean} hasPaths True with `props` contains one or more paths * @private - * @suppress {missingProperties} */ function runComputedEffects(inst, changedProps, oldProps, hasPaths) { let computeEffects = inst.__computeEffects; @@ -417,7 +414,7 @@ * values of the arguments specified in the `info` object and setting the * return value to the computed property specified. * - * @param {!Polymer_PropertyEffects} inst The instance the effect will be run on + * @param {!PropertyEffectsType} 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 @@ -438,11 +435,10 @@ * Computes path changes based on path links set up using the `linkPaths` * API. * - * @param {!Polymer_PropertyEffects} inst The instance whose props are changing + * @param {!PropertyEffectsType} inst The instance whose props are changing * @param {string | !Array<(string|number)>} path Path that has changed * @param {*} value Value of changed path * @private - * @suppress {missingProperties} */ function computeLinkedPaths(inst, path, value) { let links = inst.__dataLinkedPaths; @@ -478,7 +474,6 @@ * only for 'property' bindings, since these must be initialized as part * of boot-up) * @private - * @suppress {missingProperties} */ function addBinding(constructor, templateInfo, nodeInfo, kind, target, parts, literal) { // Create binding metadata and add to nodeInfo @@ -510,7 +505,6 @@ * @param {Object} binding Binding metadata * @param {Object} part Binding part metadata * @param {number} index Index into `nodeInfoList` for this node - * @suppress {missingProperties} */ function addEffectForBindingPart(constructor, templateInfo, binding, part, index) { if (!part.literal) { @@ -544,7 +538,7 @@ * there is no support for _path_ bindings via custom binding parts, * as this is specific to Polymer's path binding syntax. * - * @param {!Polymer_PropertyEffects} inst The instance the effect will be run on + * @param {!PropertyEffectsType} 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 @@ -579,12 +573,11 @@ * Sets the value for an "binding" (binding) effect to a node, * either as a property or attribute. * - * @param {!Polymer_PropertyEffects} inst The instance owning the binding effect + * @param {!PropertyEffectsType} inst The instance owning the binding effect * @param {Node} node Target node for binding * @param {Object} binding Binding metadata * @param {Object} part Binding part metadata * @param {*} value Value to set - * @suppress {missingProperties} * @private */ function applyBindingValue(inst, node, binding, part, value) { @@ -620,7 +613,6 @@ * @param {Object} part Binding part metadata * @return {*} Transformed value to set * @private - * @suppress {missingProperties} */ function computeBindingValue(node, value, binding, part) { if (binding.isCompound) { @@ -663,10 +655,9 @@ * Setup compound binding storage structures, notify listeners, and dataHost * references onto the bound nodeList. * - * @param {!Polymer_PropertyEffects} inst Instance that bas been previously bound + * @param {!PropertyEffectsType} inst Instance that bas been previously bound * @param {Object} templateInfo Template metadata * @private - * @suppress {missingProperties} */ function setupBindings(inst, templateInfo) { // Setup compound storage, dataHost, and notify listeners @@ -725,7 +716,7 @@ * Adds a 2-way binding notification event listener to the node specified * * @param {Object} node Child element to add listener to - * @param {!Polymer_PropertyEffects} inst Host element instance to handle notification event + * @param {!PropertyEffectsType} inst Host element instance to handle notification event * @param {Object} binding Binding metadata * @private */ @@ -755,7 +746,6 @@ * method names should be included as a dependency to the effect. Note, * defaults to true if the signature is static (sig.static is true). * @private - * @suppress {missingProperties} */ function createMethodEffect(model, sig, type, effectFn, methodInfo, dynamicFn) { dynamicFn = sig.static || (dynamicFn && @@ -788,13 +778,12 @@ * functions call this function to invoke the method, then use the return * value accordingly. * - * @param {!Polymer_PropertyEffects} inst The instance the effect will be run on + * @param {!PropertyEffectsType} 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 {?} info Effect metadata * @return {*} Returns the return value from the method invocation - * @suppress {missingProperties} * @private */ function runMethodEffect(inst, property, props, oldProps, info) { @@ -965,7 +954,6 @@ * @param {Object} props Bag of current property changes * @return {Array<*>} Array of argument values * @private - * @suppress {missingProperties} */ function marshalArgs(data, args, path, props) { let values = []; @@ -1010,12 +998,11 @@ * * Note: this implementation only accepts normalized paths * - * @param {!Polymer_PropertyEffects} inst Instance to send notifications to + * @param {!PropertyEffectsType} 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 * @private - * @suppress {missingProperties} */ function notifySplices(inst, array, path, splices) { let splicesPath = path + '.splices'; @@ -1031,7 +1018,7 @@ * * Note: this implementation only accepts normalized paths * - * @param {!Polymer_PropertyEffects} inst Instance to send notifications to + * @param {!PropertyEffectsType} 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 @@ -1115,6 +1102,46 @@ */ class PropertyEffects extends propertyEffectsBase { + constructor() { + super(); + /** @type {boolean} */ + this.__dataClientsReady; + /** @type {Array} */ + this.__dataPendingClients; + /** @type {Object} */ + this.__dataToNotify; + /** @type {Object} */ + this.__dataLinkedPaths; + /** @type {boolean} */ + this.__dataHasPaths; + /** @type {Object} */ + this.__dataCompoundStorage; + /** @type {Object} */ + this.__dataHost; + /** @type {!Object} */ + this.__dataTemp; + /** @type {boolean} */ + this.__dataClientsInitialized; + /** @type {!Object} */ + this.__data; + /** @type {!Object} */ + this.__dataPending; + /** @type {!Object} */ + this.__dataOld; + /** @type {Object} */ + this.__computeEffects; + /** @type {Object} */ + this.__reflectEffects; + /** @type {Object} */ + this.__notifyEffects; + /** @type {Object} */ + this.__propagateEffects; + /** @type {Object} */ + this.__observeEffects; + /** @type {Object} */ + this.__readOnly; + } + get PROPERTY_EFFECT_TYPES() { return TYPES; } @@ -1154,7 +1181,6 @@ * * @override * @param {Object} props Properties to initialize on the instance - * @suppress {missingProperties} */ _initializeInstanceProperties(props) { let readOnly = this.__readOnly; @@ -1584,7 +1610,6 @@ * a specific order (compute, propagate, reflect, observe, notify). * * @override - * @suppress {missingProperties} */ _propertiesChanged(currentProps, changedProps, oldProps) { // ---------------------------- @@ -1701,7 +1726,6 @@ * reported in index order (raw results from `Object.observe` are not * ordered and must be normalized/merged before notifying). * @public - * @suppress {missingProperties} */ notifySplices(path, splices) { let info = {}; @@ -1777,7 +1801,6 @@ * @param {...*} items Items to push onto array * @return {number} New length of the array. * @public - * @suppress {missingProperties} */ push(path, ...items) { let info = {}; @@ -1802,7 +1825,6 @@ * @param {string} path Path to array. * @return {*} Item that was removed. * @public - * @suppress {missingProperties} */ pop(path) { let info = {}; @@ -1831,7 +1853,6 @@ * @param {...*} items Items to insert into array. * @return {Array} Array of removed items. * @public - * @suppress {missingProperties} */ splice(path, start, deleteCount, ...items) { let info = {}; @@ -1864,7 +1885,6 @@ * @param {string} path Path to array. * @return {*} Item that was removed. * @public - * @suppress {missingProperties} */ shift(path) { let info = {}; @@ -1890,7 +1910,6 @@ * @param {...*} items Items to insert info array * @return {number} New length of the array. * @public - * @suppress {missingProperties} */ unshift(path, ...items) { let info = {}; @@ -1913,7 +1932,6 @@ * @param {string} path Path that should be notified. * @param {*=} value Value at the path (optional). * @public - * @suppress {missingProperties} */ notifyPath(path, value) { /** @type {string} */ @@ -2284,7 +2302,6 @@ * * @param {HTMLTemplateElement} template Template to stamp * @return {DocumentFragment} Cloned template content - * @suppress {missingProperties} * @protected */ _stampTemplate(template) { @@ -2320,7 +2337,6 @@ * * @param {DocumentFragment} dom DocumentFragment previously returned * from `_stampTemplate` associated with the nodes to be removed - * @suppress {missingProperties} * @protected */ _removeBoundDom(dom) { @@ -2361,7 +2377,6 @@ * @return {boolean} `true` if the visited node added node-specific * metadata to `nodeInfo` * @protected - * @suppress {missingProperties} */ static _parseTemplateNode(node, templateInfo, nodeInfo) { let noted = super._parseTemplateNode(node, templateInfo, nodeInfo); @@ -2394,7 +2409,6 @@ * @return {boolean} `true` if the visited node added node-specific * metadata to `nodeInfo` * @protected - * @suppress {missingProperties} */ static _parseTemplateNodeAttribute(node, templateInfo, nodeInfo, name, value) { let parts = this._parseBindings(value, templateInfo); @@ -2446,7 +2460,6 @@ * @return {boolean} `true` if the visited node added node-specific * metadata to `nodeInfo` * @protected - * @suppress {missingProperties} */ static _parseTemplateNestedTemplate(node, templateInfo, nodeInfo) { let noted = super._parseTemplateNestedTemplate(node, templateInfo, nodeInfo); @@ -2492,7 +2505,6 @@ * @param {Object} templateInfo Current template metadata * @return {Array} Array of binding part metadata * @protected - * @suppress {missingProperties} */ static _parseBindings(text, templateInfo) { let parts = []; @@ -2574,7 +2586,6 @@ * @param {boolean} hasPaths True with `props` contains one or more paths * @return {*} Value the binding part evaluated to * @protected - * @suppress {missingProperties} */ static _evaluateBinding(inst, part, path, props, oldProps, hasPaths) { let value; @@ -2597,6 +2608,8 @@ } + PropertyEffectsType = PropertyEffects; + return PropertyEffects; }); diff --git a/lib/utils/templatize.html b/lib/utils/templatize.html index 81286f751b..184466da3a 100644 --- a/lib/utils/templatize.html +++ b/lib/utils/templatize.html @@ -117,7 +117,6 @@ } /** * @override - * @suppress {missingProperties} */ _addEventListenerToNode(node, eventName, handler) { if (this._methodHost && this.__templatizeOptions.parentModel) { @@ -193,7 +192,6 @@ * or else the host element. * * @return {Polymer_PropertyEffects} The parent model of this instance - * @suppress {missingProperties} */ get parentModel() { let model = this.__parentModel; @@ -238,10 +236,6 @@ return templateHost && templateHost._methodHost || templateHost; } - /* eslint-disable valid-jsdoc */ - /** - * @suppress {missingProperties} - */ function createTemplatizerClass(template, templateInfo, options) { // Anonymous class created by the templatize let base = options.mutableData ? @@ -253,12 +247,7 @@ addNotifyEffects(klass, template, templateInfo, options); return klass; } - /* eslint-enable valid-jsdoc */ - /* eslint-disable valid-jsdoc */ - /** - * @suppress {missingProperties} - */ function addPropagateEffects(template, templateInfo, options) { let userForwardHostProp = options.forwardHostProp; if (userForwardHostProp) { @@ -293,7 +282,6 @@ template._enableProperties(); } } - /* eslint-enable valid-jsdoc */ function createForwardHostPropEffect(hostProp, userForwardHostProp) { return function forwardHostProp(template, prop, props) {