From ae1b4173b0a303c4d16e82c88c1c8757cb594217 Mon Sep 17 00:00:00 2001 From: Kevin Schaaf Date: Fri, 24 Aug 2018 11:45:33 -0700 Subject: [PATCH] Updates based on code review. Add computed tests. --- lib/legacy/legacy-data-mixin.js | 73 ++++++++++---- test/unit/legacy-data.html | 164 +++++++++++++++++++++++++++++++- 2 files changed, 212 insertions(+), 25 deletions(-) diff --git a/lib/legacy/legacy-data-mixin.js b/lib/legacy/legacy-data-mixin.js index cc9aa2b55b..018ccd31f9 100644 --- a/lib/legacy/legacy-data-mixin.js +++ b/lib/legacy/legacy-data-mixin.js @@ -13,15 +13,43 @@ import { Polymer } from '../../polymer-legacy.js'; import { dedupingMixin } from '../utils/mixin.js'; const UndefinedArgumentError = class extends Error { - constructor(message) { + constructor(message, arg) { super(message); + this.arg = arg; this.name = this.constructor.name; // Affordances for ensuring instanceof works after babel ES5 compilation + // TODO(kschaaf): Remove after polymer CLI updates to newer Babel that + // sets the constructor/prototype correctly for subclassed builtins this.constructor = UndefinedArgumentError; this.__proto__ = UndefinedArgumentError.prototype; } }; +/** + * 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 + */ +function wrapEffect(effect, fnName) { + if (effect && effect.fn) { + const fn = effect.fn; + effect.fn = function() { + try { + fn.apply(this, arguments); + } catch (e) { + if (e instanceof UndefinedArgumentError) { + console.warn(`Argument '${e.arg}'${fnName ?` for method '${fnName}'` : ''} was undefined. Ensure it has an undefined check.`); + } else { + throw e; + } + } + }; + } + return effect; +} + /** * Mixin to selectively add back Polymer 1.x's `undefined` rules * governing when observers & computing functions run based @@ -50,7 +78,7 @@ export const LegacyDataMixin = dedupingMixin(superClass => { * @private */ class LegacyDataMixin extends superClass { /** - * Overrides `Polyer.PropertyEffects` to add `undefined` argument + * Overrides `Polymer.PropertyEffects` to add `undefined` argument * checking to match Polymer 1.x style rules * * @param {!Array} args Array of argument metadata @@ -61,12 +89,16 @@ export const LegacyDataMixin = dedupingMixin(superClass => { */ _marshalArgs(args, path, props) { const vals = super._marshalArgs(args, path, props); - if (this._legacyUndefinedCheck && args.length > 1) { - for (let i=0; i 1) { + for (let i=0; i { * @protected */ _addPropertyEffect(property, type, effect) { - if (effect && effect.fn) { - const fn = effect.fn; - effect.fn = function() { - try { - fn.apply(this, arguments); - } catch (e) { - if (e instanceof UndefinedArgumentError) { - console.warn(e.message); - } else { - throw e; - } - } - }; - } - return super._addPropertyEffect(property, type, effect); + return super._addPropertyEffect(property, type, + wrapEffect(effect, effect && effect.info && effect.info.methodName)); + } + + /** + * Overrides `Polyer.PropertyEffects` to wrap effect functions to + * catch `UndefinedArgumentError`s and warn. + * + * @param {Object} templateInfo Template metadata to add effect to + * @param {string} prop Property that should trigger the effect + * @param {Object=} effect Effect metadata object + * @return {void} + * @protected + */ + static _addTemplatePropertyEffect(templateInfo, prop, effect) { + return super._addTemplatePropertyEffect(templateInfo, prop, wrapEffect(effect)); } } diff --git a/test/unit/legacy-data.html b/test/unit/legacy-data.html index be01f95109..3747c9f561 100644 --- a/test/unit/legacy-data.html +++ b/test/unit/legacy-data.html @@ -20,16 +20,34 @@ +