mirror of
https://github.com/Polymer/polymer.git
synced 2026-08-19 01:14:44 -05:00
Merge branch '2.x' into perf-opt
This commit is contained in:
@@ -1416,4 +1416,22 @@ Polymer_DisableUpgradeMixin.prototype.connectedCallback = function(){};
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
Polymer_DisableUpgradeMixin.prototype.disconnectedCallback = function(){};
|
||||
Polymer_DisableUpgradeMixin.prototype.disconnectedCallback = function(){};
|
||||
/**
|
||||
* @interface
|
||||
*/
|
||||
function Polymer_LegacyDataMixin(){}
|
||||
/**
|
||||
* @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
|
||||
* @return {void}
|
||||
*/
|
||||
Polymer_LegacyDataMixin.prototype._addPropertyEffect = function(property, type, effect){};
|
||||
/**
|
||||
* @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}
|
||||
*/
|
||||
Polymer_LegacyDataMixin._addTemplatePropertyEffect = function(templateInfo, prop, effect){};
|
||||
@@ -57,6 +57,9 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
if (Polymer.strictTemplatePolicy) {
|
||||
throw new Error(`strictTemplatePolicy: dom-bind not allowed`);
|
||||
}
|
||||
this.root = null;
|
||||
this.$ = null;
|
||||
this.__children = null;
|
||||
|
||||
@@ -255,8 +255,12 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
|
||||
if (c$ && c$.length) {
|
||||
// use first child parent, for case when dom-if may have been detached
|
||||
let parent = c$[0].parentNode;
|
||||
for (let i=0, n; (i<c$.length) && (n=c$[i]); i++) {
|
||||
parent.removeChild(n);
|
||||
// Instance children may be disconnected from parents when dom-if
|
||||
// detaches if a tree was innerHTML'ed
|
||||
if (parent) {
|
||||
for (let i=0, n; (i<c$.length) && (n=c$[i]); i++) {
|
||||
parent.removeChild(n);
|
||||
}
|
||||
}
|
||||
}
|
||||
this.__instance = null;
|
||||
|
||||
@@ -15,6 +15,12 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
|
||||
|
||||
let modules = {};
|
||||
let lcModules = {};
|
||||
function setModule(id, module) {
|
||||
// store id separate from lowercased id so that
|
||||
// in all cases mixedCase id will stored distinctly
|
||||
// and lowercase version is a fallback
|
||||
modules[id] = lcModules[id.toLowerCase()] = module;
|
||||
}
|
||||
function findModule(id) {
|
||||
return modules[id] || lcModules[id.toLowerCase()];
|
||||
}
|
||||
@@ -124,12 +130,14 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
|
||||
register(id) {
|
||||
id = id || this.id;
|
||||
if (id) {
|
||||
// Under strictTemplatePolicy, reject and null out any re-registered
|
||||
// dom-module since it is ambiguous whether first-in or last-in is trusted
|
||||
if (Polymer.strictTemplatePolicy && findModule(id) !== undefined) {
|
||||
setModule(id, null);
|
||||
throw new Error(`strictTemplatePolicy: dom-module ${id} re-registered`);
|
||||
}
|
||||
this.id = id;
|
||||
// store id separate from lowercased id so that
|
||||
// in all cases mixedCase id will stored distinctly
|
||||
// and lowercase version is a fallback
|
||||
modules[id] = this;
|
||||
lcModules[id.toLowerCase()] = this;
|
||||
setModule(id, this);
|
||||
styleOutsideTemplateCheck(this);
|
||||
}
|
||||
}
|
||||
|
||||
+10
-16
@@ -230,22 +230,6 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
|
||||
return observers;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {HTMLTemplateElement} template for this class
|
||||
*/
|
||||
static get template() {
|
||||
// get template first from any imperative set in `info._template`
|
||||
return info._template ||
|
||||
// next look in dom-module associated with this element's is.
|
||||
Polymer.DomModule && Polymer.DomModule.import(this.is, 'template') ||
|
||||
// next look for superclass template (note: use superclass symbol
|
||||
// to ensure correct `this.is`)
|
||||
Base.template ||
|
||||
// finally fall back to `_template` in element's prototype.
|
||||
this.prototype._template ||
|
||||
null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {void}
|
||||
*/
|
||||
@@ -499,6 +483,7 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
|
||||
*
|
||||
* @param {!PolymerInit} info Object containing Polymer metadata and functions
|
||||
* to become class methods.
|
||||
* @template T
|
||||
* @param {function(T):T} mixin Optional mixin to apply to legacy base class
|
||||
* before extending with Polymer metaprogramming.
|
||||
* @return {function(new:HTMLElement)} Generated class
|
||||
@@ -513,6 +498,15 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
|
||||
klass = GenerateClassFromInfo(info, klass, info.behaviors);
|
||||
// decorate klass with registration info
|
||||
klass.is = info.is;
|
||||
// To match 1.x behavior, `_template` supplied on a behavior should take
|
||||
// precedence over dom-module lookup for `is`; this also prevents
|
||||
// dom-module injection under strictTemplatePolicy for an element that
|
||||
// would normally get its template from a behavior.
|
||||
// TODO(sorvell): Remove once "flattened behaviors" lands, since both
|
||||
// `_template` and `is` will be on the same class after that change
|
||||
if (klass.prototype._template !== undefined) {
|
||||
klass.prototype._template = klass.prototype._template;
|
||||
}
|
||||
return klass;
|
||||
};
|
||||
|
||||
|
||||
@@ -0,0 +1,171 @@
|
||||
<!--
|
||||
@license
|
||||
Copyright (c) 2017 The Polymer Project Authors. All rights reserved.
|
||||
This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
|
||||
The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
|
||||
The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
|
||||
Code distributed by Google as part of the polymer project is also
|
||||
subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
|
||||
-->
|
||||
|
||||
<link rel="import" href="class.html">
|
||||
<link rel="import" href="../../polymer.html">
|
||||
<link rel="import" href="../utils/mixin.html">
|
||||
<link rel="import" href="../utils/templatize.html">
|
||||
|
||||
<script>
|
||||
(function() {
|
||||
'use strict';
|
||||
|
||||
const UndefinedArgumentError = class extends Error {
|
||||
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
|
||||
* 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
|
||||
* the mixin in Polymer 2.
|
||||
*
|
||||
* @mixinFunction
|
||||
* @polymer
|
||||
* @summary Mixin to selectively add back Polymer 1.x's `undefined` rules
|
||||
* governing when observers & computing functions run.
|
||||
*/
|
||||
Polymer.LegacyDataMixin = Polymer.dedupingMixin(superClass => {
|
||||
|
||||
/**
|
||||
* @polymer
|
||||
* @mixinClass
|
||||
* @implements {Polymer_LegacyDataMixin}
|
||||
*/
|
||||
class LegacyDataMixin extends superClass {
|
||||
/**
|
||||
* Overrides `Polyer.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
|
||||
* @return {Array<*>} Array of argument values
|
||||
* @private
|
||||
*/
|
||||
_marshalArgs(args, path, props) {
|
||||
const vals = super._marshalArgs(args, path, props);
|
||||
// Per legacy data rules, single-property observers (whether in `properties`
|
||||
// and in `observers`) are called regardless of whether their argument is
|
||||
// undefined or not. Multi-property observers must have all arguments defined
|
||||
if (this._legacyUndefinedCheck && vals.length > 1) {
|
||||
for (let i=0; i<vals.length; i++) {
|
||||
if (vals[i] === undefined) {
|
||||
// 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
return vals;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
* @return {void}
|
||||
* @protected
|
||||
*/
|
||||
_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));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return LegacyDataMixin;
|
||||
|
||||
});
|
||||
|
||||
// LegacyDataMixin is applied to base class _before_ metaprogramming, to
|
||||
// ensure override of _addPropertyEffect et.al. are used by metaprogramming
|
||||
// performed in _finalizeClass
|
||||
const Class = Polymer.Class;
|
||||
Polymer.Class = (info, mixin) => Class(info,
|
||||
superClass => mixin ?
|
||||
mixin(Polymer.LegacyDataMixin(superClass)) :
|
||||
Polymer.LegacyDataMixin(superClass)
|
||||
);
|
||||
|
||||
// Apply LegacyDataMixin to Templatizer instances as well, and defer
|
||||
// runtime switch to the root's host (_methodHost)
|
||||
Polymer.Templatize.mixin =
|
||||
Polymer.dedupingMixin(superClass => class extends Polymer.LegacyDataMixin(superClass) {
|
||||
get _legacyUndefinedCheck() {
|
||||
return this._methodHost && this._methodHost._legacyUndefinedCheck;
|
||||
}
|
||||
});
|
||||
|
||||
console.info('LegacyDataMixin will be applied to all legacy elements.\n' +
|
||||
'Set `_legacyUndefinedCheck: true` to enable.');
|
||||
|
||||
})();
|
||||
</script>
|
||||
@@ -132,7 +132,7 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a memoized version of the the `observers` array.
|
||||
* Returns a memoized version of the `observers` array.
|
||||
* @param {PolymerElementConstructor} constructor Element class
|
||||
* @return {Array} Array containing own observers for the given class
|
||||
* @protected
|
||||
@@ -156,7 +156,7 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
|
||||
* alter these settings. However, additional `observers` may be added
|
||||
* by subclasses.
|
||||
*
|
||||
* The info object should may contain property metadata as follows:
|
||||
* The info object should contain property metadata as follows:
|
||||
*
|
||||
* * `type`: {function} type to which an attribute matching the property
|
||||
* is deserialized. Note the property is camel-cased from a dash-cased
|
||||
@@ -168,7 +168,7 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
|
||||
* property 'foo',
|
||||
*
|
||||
* * `computed`: {string} creates a computed property. A computed property
|
||||
* also automatically is set to `readOnly: true`. The value is calculated
|
||||
* is also automatically set to `readOnly: true`. The value is calculated
|
||||
* by running a method and arguments parsed from the given string. For
|
||||
* example 'compute(foo)' will compute a given property when the
|
||||
* 'foo' property changes by executing the 'compute' method. This method
|
||||
@@ -288,6 +288,27 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
|
||||
}
|
||||
|
||||
/**
|
||||
* Look up template from dom-module for element
|
||||
*
|
||||
* @param {!string} is Element name to look up
|
||||
* @return {!HTMLTemplateElement} Template found in dom module, or
|
||||
* undefined if not found
|
||||
* @protected
|
||||
*/
|
||||
function getTemplateFromDomModule(is) {
|
||||
let template = null;
|
||||
if (is && Polymer.DomModule) {
|
||||
template = Polymer.DomModule.import(is, 'template');
|
||||
// Under strictTemplatePolicy, require any element with an `is`
|
||||
// specified to have a dom-module
|
||||
if (Polymer.strictTemplatePolicy && !template) {
|
||||
throw new Error(`strictTemplatePolicy: expecting dom-module or null template for ${is}`);
|
||||
}
|
||||
}
|
||||
return template;
|
||||
}
|
||||
|
||||
/**
|
||||
* @polymer
|
||||
* @mixinClass
|
||||
* @unrestricted
|
||||
@@ -381,7 +402,7 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
|
||||
* class MySubClass extends MySuperClass {
|
||||
* static get template() {
|
||||
* if (!memoizedTemplate) {
|
||||
* memoizedTemplate = super.template.cloneNode(true);
|
||||
* memoizedTemplate = MySuperClass.template.cloneNode(true);
|
||||
* let subContent = document.createElement('div');
|
||||
* subContent.textContent = 'This came from MySubClass';
|
||||
* memoizedTemplate.content.appendChild(subContent);
|
||||
@@ -393,17 +414,43 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
|
||||
* @return {HTMLTemplateElement|string} Template to be stamped
|
||||
*/
|
||||
static get template() {
|
||||
// Explanation of template-related properties:
|
||||
// - constructor.template (this getter): the template for the class.
|
||||
// This can come from the prototype (for legacy elements), from a
|
||||
// dom-module, or from the super class's template (or can be overridden
|
||||
// altogether by the user)
|
||||
// - constructor._template: memoized version of constructor.template
|
||||
// - prototype._template: working template for the element, which will be
|
||||
// parsed and modified in place. It is a cloned version of
|
||||
// constructor.template, saved in _finalizeClass(). Note that before
|
||||
// this getter is called, for legacy elements this could be from a
|
||||
// _template field on the info object passed to Polymer(), a behavior,
|
||||
// or set in registered(); once the static getter runs, a clone of it
|
||||
// will overwrite it on the prototype as the working template.
|
||||
if (!this.hasOwnProperty(JSCompiler_renameProperty('_template', this))) {
|
||||
this._template = Polymer.DomModule && Polymer.DomModule.import(
|
||||
/** @type {PolymerElementConstructor}*/ (this).is, 'template') ||
|
||||
// note: implemented so a subclass can retrieve the super
|
||||
// template; call the super impl this way so that `this` points
|
||||
// to the superclass.
|
||||
Object.getPrototypeOf(/** @type {PolymerElementConstructor}*/ (this).prototype).constructor.template;
|
||||
this._template =
|
||||
// If user has put template on prototype (e.g. in legacy via registered
|
||||
// callback or info object), prefer that first
|
||||
this.prototype.hasOwnProperty(JSCompiler_renameProperty('_template', this.prototype)) ?
|
||||
this.prototype._template :
|
||||
// Look in dom-module associated with this element's is
|
||||
(getTemplateFromDomModule(/** @type {PolymerElementConstructor}*/ (this).is) ||
|
||||
// Next look for superclass template (call the super impl this
|
||||
// way so that `this` points to the superclass)
|
||||
Object.getPrototypeOf(/** @type {PolymerElementConstructor}*/ (this).prototype).constructor.template);
|
||||
}
|
||||
return this._template;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the template.
|
||||
*
|
||||
* @param {!HTMLTemplateElement|string} value Template to set.
|
||||
*/
|
||||
static set template(value) {
|
||||
this._template = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Path matching the url from which the element was imported.
|
||||
*
|
||||
|
||||
@@ -814,7 +814,7 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
|
||||
let context = inst._methodHost || inst;
|
||||
let fn = context[info.methodName];
|
||||
if (fn) {
|
||||
let args = marshalArgs(inst.__data, info.args, property, props);
|
||||
let args = inst._marshalArgs(info.args, property, props);
|
||||
return fn.apply(context, args);
|
||||
} else if (!info.dynamicFn) {
|
||||
console.warn('method `' + info.methodName + '` not defined');
|
||||
@@ -970,56 +970,6 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
|
||||
return a;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gather the argument values for a method specified in the provided array
|
||||
* of argument metadata.
|
||||
*
|
||||
* The `path` and `value` arguments are used to fill in wildcard descriptor
|
||||
* when the method is being called as a result of a path notification.
|
||||
*
|
||||
* @param {Object} data Instance data storage object to read properties from
|
||||
* @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
|
||||
* @return {Array<*>} Array of argument values
|
||||
* @private
|
||||
*/
|
||||
function marshalArgs(data, args, path, props) {
|
||||
let values = [];
|
||||
for (let i=0, l=args.length; i<l; i++) {
|
||||
let arg = args[i];
|
||||
let name = arg.name;
|
||||
let v;
|
||||
if (arg.literal) {
|
||||
v = arg.value;
|
||||
} else {
|
||||
if (arg.structured) {
|
||||
v = Polymer.Path.get(data, name);
|
||||
// when data is not stored e.g. `splices`
|
||||
if (v === undefined) {
|
||||
v = props[name];
|
||||
}
|
||||
} else {
|
||||
v = data[name];
|
||||
}
|
||||
}
|
||||
if (arg.wildcard) {
|
||||
// Only send the actual path changed info if the change that
|
||||
// caused the observer to run matched the wildcard
|
||||
let baseChanged = (name.indexOf(path + '.') === 0);
|
||||
let matches = (path.indexOf(name) === 0 && !baseChanged);
|
||||
values[i] = {
|
||||
path: matches ? path : name,
|
||||
value: matches ? props[path] : v,
|
||||
base: v
|
||||
};
|
||||
} else {
|
||||
values[i] = v;
|
||||
}
|
||||
}
|
||||
return values;
|
||||
}
|
||||
|
||||
// data api
|
||||
|
||||
/**
|
||||
@@ -2181,6 +2131,56 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
|
||||
createMethodEffect(this, sig, TYPES.COMPUTE, runComputedEffect, property, dynamicFn);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gather the argument values for a method specified in the provided array
|
||||
* of argument metadata.
|
||||
*
|
||||
* The `path` and `value` arguments are used to fill in wildcard descriptor
|
||||
* when the method is being called as a result of a path notification.
|
||||
*
|
||||
* @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
|
||||
* @return {Array<*>} Array of argument values
|
||||
* @private
|
||||
*/
|
||||
_marshalArgs(args, path, props) {
|
||||
const data = this.__data;
|
||||
let values = [];
|
||||
for (let i=0, l=args.length; i<l; i++) {
|
||||
let arg = args[i];
|
||||
let name = arg.name;
|
||||
let v;
|
||||
if (arg.literal) {
|
||||
v = arg.value;
|
||||
} else {
|
||||
if (arg.structured) {
|
||||
v = Polymer.Path.get(data, name);
|
||||
// when data is not stored e.g. `splices`
|
||||
if (v === undefined) {
|
||||
v = props[name];
|
||||
}
|
||||
} else {
|
||||
v = data[name];
|
||||
}
|
||||
}
|
||||
if (arg.wildcard) {
|
||||
// Only send the actual path changed info if the change that
|
||||
// caused the observer to run matched the wildcard
|
||||
let baseChanged = (name.indexOf(path + '.') === 0);
|
||||
let matches = (path.indexOf(name) === 0 && !baseChanged);
|
||||
values[i] = {
|
||||
path: matches ? path : name,
|
||||
value: matches ? props[path] : v,
|
||||
base: v
|
||||
};
|
||||
} else {
|
||||
values[i] = v;
|
||||
}
|
||||
}
|
||||
return values;
|
||||
}
|
||||
|
||||
// -- static class methods ------------
|
||||
|
||||
/**
|
||||
|
||||
@@ -297,6 +297,10 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
|
||||
// Anonymous class created by the templatize
|
||||
let base = options.mutableData ?
|
||||
MutableTemplateInstanceBase : TemplateInstanceBase;
|
||||
// Affordance for global mixins onto TemplatizeInstance
|
||||
if (Polymer.Templatize.mixin) {
|
||||
base = Polymer.Templatize.mixin(base);
|
||||
}
|
||||
/**
|
||||
* @constructor
|
||||
* @extends {base}
|
||||
@@ -509,6 +513,12 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
|
||||
* @suppress {invalidCasts}
|
||||
*/
|
||||
templatize(template, owner, options) {
|
||||
// Under strictTemplatePolicy, the templatized element must be owned
|
||||
// by a (trusted) Polymer element, indicated by existence of _methodHost;
|
||||
// e.g. for dom-if & dom-repeat in main document, _methodHost is null
|
||||
if (Polymer.strictTemplatePolicy && !findMethodHost(template)) {
|
||||
throw new Error('strictTemplatePolicy: template owner not trusted');
|
||||
}
|
||||
options = /** @type {!TemplatizeOptions} */(options || {});
|
||||
if (template.__templatizeOwner) {
|
||||
throw new Error('A <template> can only be templatized once');
|
||||
|
||||
Generated
+15
-15
@@ -4471,9 +4471,9 @@
|
||||
}
|
||||
},
|
||||
"blob": {
|
||||
"version": "0.0.5",
|
||||
"resolved": "https://registry.npmjs.org/blob/-/blob-0.0.5.tgz",
|
||||
"integrity": "sha512-gaqbzQPqOoamawKg0LGVd7SzLgXS+JH61oWprSLH+P+abTczqJbhTR8CmJ2u9/bUYNmHTGJx/UEmn6doAvvuig==",
|
||||
"version": "0.0.4",
|
||||
"resolved": "http://registry.npmjs.org/blob/-/blob-0.0.4.tgz",
|
||||
"integrity": "sha1-vPEwUspURj8w+fx+lbmkdjCpSSE=",
|
||||
"dev": true
|
||||
},
|
||||
"body-parser": {
|
||||
@@ -5836,15 +5836,15 @@
|
||||
}
|
||||
},
|
||||
"engine.io-parser": {
|
||||
"version": "2.1.3",
|
||||
"resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-2.1.3.tgz",
|
||||
"integrity": "sha512-6HXPre2O4Houl7c4g7Ic/XzPnHBvaEmN90vtRO9uLmwtRqQmTOw0QMevL1TOfL2Cpu1VzsaTmMotQgMdkzGkVA==",
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-2.1.2.tgz",
|
||||
"integrity": "sha512-dInLFzr80RijZ1rGpx1+56/uFoH7/7InhH3kZt+Ms6hT8tNx3NGW/WNSA/f8As1WkOfkuyb3tnRyuXGxusclMw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"after": "0.8.2",
|
||||
"arraybuffer.slice": "~0.0.7",
|
||||
"base64-arraybuffer": "0.1.5",
|
||||
"blob": "0.0.5",
|
||||
"blob": "0.0.4",
|
||||
"has-binary2": "~1.0.2"
|
||||
}
|
||||
},
|
||||
@@ -6470,7 +6470,7 @@
|
||||
},
|
||||
"fecha": {
|
||||
"version": "2.3.3",
|
||||
"resolved": "http://registry.npmjs.org/fecha/-/fecha-2.3.3.tgz",
|
||||
"resolved": "https://registry.npmjs.org/fecha/-/fecha-2.3.3.tgz",
|
||||
"integrity": "sha512-lUGBnIamTAwk4znq5BcqsDaxSmZ9nDVJaij6NvRt/Tg4R69gERA+otPKbS86ROw9nxVMw2/mp1fnaiWqbs6Sdg==",
|
||||
"dev": true
|
||||
},
|
||||
@@ -7646,7 +7646,7 @@
|
||||
},
|
||||
"hoek": {
|
||||
"version": "4.2.1",
|
||||
"resolved": "http://registry.npmjs.org/hoek/-/hoek-4.2.1.tgz",
|
||||
"resolved": "https://registry.npmjs.org/hoek/-/hoek-4.2.1.tgz",
|
||||
"integrity": "sha512-QLg82fGkfnJ/4iy1xZ81/9SIJiq1NGFUMGs6ParyjBZr6jW2Ufj/snDqTHixNlHdPNwN2RLVD0Pi3igeK9+JfA==",
|
||||
"dev": true
|
||||
},
|
||||
@@ -11511,9 +11511,9 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@types/node": {
|
||||
"version": "9.6.36",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-9.6.36.tgz",
|
||||
"integrity": "sha512-Fbw+AdRLL01vv7Rk7bYaNPecqmKoinJHGbpKnDpbUZmUj/0vj3nLqPQ4CNBzr3q2zso6Cq/4jHoCAdH78fvJrw==",
|
||||
"version": "9.6.35",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-9.6.35.tgz",
|
||||
"integrity": "sha512-h5zvHS8wXHGa+Gcqs9K8vqCgOtqjr0+NqG/DDJmQIX1wpR9HivAfgV8bjcD3mGM4bPfQw5Aneb2Pn8355L83jA==",
|
||||
"dev": true
|
||||
},
|
||||
"async": {
|
||||
@@ -11534,9 +11534,9 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@types/node": {
|
||||
"version": "4.9.1",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-4.9.1.tgz",
|
||||
"integrity": "sha512-+LRWWDiB4SGY3FG8Cb8R8n9GJQ/rsoZr17zz+v95f7fdiQitk3bvZnjxhcl9T+DBuQ3exfW/3uvEHmLylYDWaw==",
|
||||
"version": "4.9.0",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-4.9.0.tgz",
|
||||
"integrity": "sha512-xUFkZ+er9gUGw0x9qyfmr/Th0LuX6IB0m7HrRMB6sO6vcBVRFZ/3YV1EeiOC2fG50RX09avDfKwGBHOnPVxFeg==",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
|
||||
+3
-1
@@ -45,6 +45,7 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
|
||||
'unit/custom-style-async.html',
|
||||
'unit/custom-style-scope-cache.html',
|
||||
'unit/events.html',
|
||||
'unit/strict-template-policy.html',
|
||||
'unit/template-whitespace.html',
|
||||
'unit/resolveurl.html',
|
||||
'unit/case-map.html',
|
||||
@@ -79,7 +80,8 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
|
||||
'unit/dir.html',
|
||||
'unit/disable-upgrade.html',
|
||||
'unit/shady-unscoped-style.html',
|
||||
'unit/html-tag.html'
|
||||
'unit/html-tag.html',
|
||||
'unit/legacy-data.html'
|
||||
// 'unit/multi-style.html'
|
||||
];
|
||||
|
||||
|
||||
@@ -22,6 +22,12 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
|
||||
</template>
|
||||
</dom-module>
|
||||
|
||||
<dom-module id="template-from-base">
|
||||
<template>
|
||||
<div id="from-base">should not be used</div>
|
||||
</template>
|
||||
</dom-module>
|
||||
|
||||
<script>
|
||||
HTMLImports.whenReady(function() {
|
||||
window.BehaviorA = {
|
||||
@@ -283,6 +289,57 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
|
||||
|
||||
is: 'behavior-registered'
|
||||
});
|
||||
|
||||
window.templateBehavior1 = {
|
||||
_template: Polymer.html`<div id="from-behavior1"></div>`
|
||||
};
|
||||
|
||||
window.templateBehavior2 = {
|
||||
_template: Polymer.html`<div id="from-behavior2"></div>`
|
||||
};
|
||||
|
||||
window.templateBehaviorFromRegistered = {
|
||||
registered: function() {
|
||||
this._template = Polymer.html`<div id="behavior-from-registered"></div>`;
|
||||
}
|
||||
};
|
||||
|
||||
Polymer({
|
||||
is: 'template-from-registered',
|
||||
registered: function() {
|
||||
this._template = Polymer.html`<div id="from-registered"></div>`;
|
||||
}
|
||||
});
|
||||
|
||||
Polymer({
|
||||
is: 'template-from-base',
|
||||
behaviors: [
|
||||
window.templateBehavior1
|
||||
]
|
||||
});
|
||||
|
||||
Polymer({
|
||||
is: 'template-from-behavior',
|
||||
behaviors: [
|
||||
window.templateBehavior1
|
||||
]
|
||||
});
|
||||
|
||||
Polymer({
|
||||
is: 'template-from-behavior-overridden',
|
||||
behaviors: [
|
||||
window.templateBehavior1,
|
||||
window.templateBehavior2
|
||||
]
|
||||
});
|
||||
|
||||
Polymer({
|
||||
is: 'template-from-behavior-registered',
|
||||
behaviors: [
|
||||
window.templateBehaviorFromRegistered
|
||||
]
|
||||
});
|
||||
|
||||
});
|
||||
</script>
|
||||
|
||||
@@ -309,6 +366,37 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
|
||||
<behavior-registered></behavior-registered>
|
||||
</template>
|
||||
</test-fixture>
|
||||
|
||||
<test-fixture id="from-registered">
|
||||
<template>
|
||||
<template-from-registered></template-from-registered>
|
||||
</template>
|
||||
</test-fixture>
|
||||
|
||||
<test-fixture id="from-base">
|
||||
<template>
|
||||
<template-from-base></template-from-base>
|
||||
</template>
|
||||
</test-fixture>
|
||||
|
||||
<test-fixture id="from-behavior">
|
||||
<template>
|
||||
<template-from-behavior></template-from-behavior>
|
||||
</template>
|
||||
</test-fixture>
|
||||
|
||||
<test-fixture id="from-behavior-overridden">
|
||||
<template>
|
||||
<template-from-behavior-overridden></template-from-behavior-overridden>
|
||||
</template>
|
||||
</test-fixture>
|
||||
|
||||
<test-fixture id="from-behavior-registered">
|
||||
<template>
|
||||
<template-from-behavior-registered></template-from-behavior-registered>
|
||||
</template>
|
||||
</test-fixture>
|
||||
|
||||
<script>
|
||||
|
||||
suite('single behavior element', function() {
|
||||
@@ -505,6 +593,37 @@ suite('nested-behaviors element', function() {
|
||||
|
||||
});
|
||||
|
||||
suite('templates from behaviors', function() {
|
||||
|
||||
test('template from registered callback', function() {
|
||||
var el = fixture('from-registered');
|
||||
assert.ok(el.shadowRoot.querySelector('#from-registered'));
|
||||
});
|
||||
|
||||
test('template from base', function() {
|
||||
var el = fixture('from-base');
|
||||
assert.notOk(el.shadowRoot.querySelector('#from-base'));
|
||||
assert.ok(el.shadowRoot.querySelector('#from-behavior1'));
|
||||
});
|
||||
|
||||
test('template from behavior', function() {
|
||||
var el = fixture('from-behavior');
|
||||
assert.ok(el.shadowRoot.querySelector('#from-behavior1'));
|
||||
});
|
||||
|
||||
test('template from overriding behavior', function() {
|
||||
var el = fixture('from-behavior-overridden');
|
||||
assert.notOk(el.shadowRoot.querySelector('#from-behavior1'));
|
||||
assert.ok(el.shadowRoot.querySelector('#from-behavior2'));
|
||||
});
|
||||
|
||||
test('template from behavior registered callback', function() {
|
||||
var el = fixture('from-behavior-registered');
|
||||
assert.ok(el.shadowRoot.querySelector('#behavior-from-registered'));
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
</script>
|
||||
|
||||
</body>
|
||||
|
||||
@@ -0,0 +1,436 @@
|
||||
<!doctype html>
|
||||
<!--
|
||||
@license
|
||||
Copyright (c) 2017 The Polymer Project Authors. All rights reserved.
|
||||
This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
|
||||
The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
|
||||
The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
|
||||
Code distributed by Google as part of the polymer project is also
|
||||
subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
|
||||
-->
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<script src="../../../webcomponentsjs/webcomponents-lite.js"></script>
|
||||
<script src="../../../web-component-tester/browser.js"></script>
|
||||
<link rel="import" href="../../polymer.html">
|
||||
<link rel="import" href="../../lib/legacy/legacy-data-mixin.html">
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<dom-module id="x-data">
|
||||
<template>
|
||||
<div id="child"
|
||||
computed-single="[[computeSingle(inlineSingleDep)]]"
|
||||
computed-multi="[[computeMulti(inlineMultiDep1, inlineMultiDep2)]]">
|
||||
<dom-if if>
|
||||
<template><div id="ifChild" computed-multi="[[computeMulti(inlineMultiIfDep1, inlineMultiIfDep2)]]"></div></template>
|
||||
</dom-if>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
HTMLImports.whenReady(() => {
|
||||
Polymer({
|
||||
is: 'x-data',
|
||||
_legacyUndefinedCheck: true,
|
||||
properties: {
|
||||
singleProp: String,
|
||||
multiProp1: String,
|
||||
multiProp2: String,
|
||||
computedSingleDep: String,
|
||||
computedMultiDep1: String,
|
||||
computedMultiDep2: String,
|
||||
inlineSingleDep: String,
|
||||
inlineMultiDep1: String,
|
||||
inlineMultiDep2: String,
|
||||
inlineMultiIfDep1: String,
|
||||
inlineMultiIfDep2: String,
|
||||
computedSingle: {
|
||||
computed: 'computeSingle(computedSingleDep)'
|
||||
},
|
||||
computedMulti: {
|
||||
computed: 'computeMulti(computedMultiDep1, computedMultiDep2)'
|
||||
}
|
||||
},
|
||||
observers: [
|
||||
'staticObserver("staticObserver")',
|
||||
'singlePropObserver(singleProp)',
|
||||
'multiPropObserver(multiProp1, multiProp2)',
|
||||
'throws(throwProp)'
|
||||
],
|
||||
created() {
|
||||
this.singlePropObserver = sinon.spy();
|
||||
this.multiPropObserver = sinon.spy();
|
||||
this.staticObserver = sinon.spy();
|
||||
this.computeSingle = sinon.spy((inlineSingleDep) => `[${inlineSingleDep}]`);
|
||||
this.computeMulti = sinon.spy((inlineMultiDep1, inlineMultiDep2) => `[${inlineMultiDep1},${inlineMultiDep2}]`);
|
||||
},
|
||||
throws() {
|
||||
throw new Error('real error');
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
</dom-module>
|
||||
|
||||
<test-fixture id="declarative-none">
|
||||
<template>
|
||||
<x-data></x-data>
|
||||
</template>
|
||||
</test-fixture>
|
||||
|
||||
<test-fixture id="declarative-single">
|
||||
<template>
|
||||
<x-data single-prop="a"></x-data>
|
||||
</template>
|
||||
</test-fixture>
|
||||
|
||||
<test-fixture id="declarative-multi-one">
|
||||
<template>
|
||||
<x-data multi-prop1="b"></x-data>
|
||||
</template>
|
||||
</test-fixture>
|
||||
|
||||
<test-fixture id="declarative-multi-all">
|
||||
<template>
|
||||
<x-data multi-prop1="b" multi-prop2="c"></x-data>
|
||||
</template>
|
||||
</test-fixture>
|
||||
|
||||
<test-fixture id="declarative-single-computed">
|
||||
<template>
|
||||
<x-data computed-single-dep="a"></x-data>
|
||||
</template>
|
||||
</test-fixture>
|
||||
|
||||
<test-fixture id="declarative-multi-one-computed">
|
||||
<template>
|
||||
<x-data computed-multi-dep1="b"></x-data>
|
||||
</template>
|
||||
</test-fixture>
|
||||
|
||||
<test-fixture id="declarative-multi-all-computed">
|
||||
<template>
|
||||
<x-data computed-multi-dep1="b" computed-multi-dep2="c"></x-data>
|
||||
</template>
|
||||
</test-fixture>
|
||||
|
||||
<test-fixture id="declarative-single-computed-inline">
|
||||
<template>
|
||||
<x-data inline-single-dep="a"></x-data>
|
||||
</template>
|
||||
</test-fixture>
|
||||
|
||||
<test-fixture id="declarative-multi-one-computed-inline">
|
||||
<template>
|
||||
<x-data inline-multi-dep1="b"></x-data>
|
||||
</template>
|
||||
</test-fixture>
|
||||
|
||||
<test-fixture id="declarative-multi-all-computed-inline">
|
||||
<template>
|
||||
<x-data inline-multi-dep1="b" inline-multi-dep2="c"></x-data>
|
||||
</template>
|
||||
</test-fixture>
|
||||
|
||||
<test-fixture id="declarative-multi-if-one-computed-inline">
|
||||
<template>
|
||||
<x-data inline-multi-if-dep1="b"></x-data>
|
||||
</template>
|
||||
</test-fixture>
|
||||
|
||||
<test-fixture id="declarative-multi-if-all-computed-inline">
|
||||
<template>
|
||||
<x-data inline-multi-if-dep1="b" inline-multi-if-dep2="c"></x-data>
|
||||
</template>
|
||||
</test-fixture>
|
||||
|
||||
<script>
|
||||
(function() {
|
||||
|
||||
let el;
|
||||
|
||||
function assertEffects(callCounts) {
|
||||
assert.equal(el.staticObserver.callCount, 1, 'staticObserver call count wrong');
|
||||
assert.equal(el.singlePropObserver.callCount,
|
||||
callCounts.singlePropObserver || 0, 'singlePropObserver call count wrong');
|
||||
assert.equal(el.multiPropObserver.callCount,
|
||||
callCounts.multiPropObserver || 0, 'multiPropObserver call count wrong');
|
||||
assert.equal(el.computeSingle.callCount,
|
||||
callCounts.computeSingle || 0, 'computeSingle call count wrong');
|
||||
assert.equal(el.computeMulti.callCount,
|
||||
callCounts.computeMulti || 0, 'computeMulti call count wrong');
|
||||
assert.equal(console.warn.callCount, callCounts.warn || 0,
|
||||
'console.warn call count wrong');
|
||||
}
|
||||
|
||||
suite('imperative', () => {
|
||||
|
||||
setup(() => sinon.spy(console, 'warn'));
|
||||
|
||||
function setupElement(check, props) {
|
||||
el = document.createElement('x-data');
|
||||
el._legacyUndefinedCheck = check;
|
||||
Object.assign(el, props);
|
||||
document.body.appendChild(el);
|
||||
Polymer.flush();
|
||||
}
|
||||
|
||||
teardown(() => {
|
||||
console.warn.restore();
|
||||
el.parentNode.removeChild(el);
|
||||
});
|
||||
|
||||
const singleProp = 'singleProp';
|
||||
const multiProp1 = 'multiProp1';
|
||||
const multiProp2 = 'multiProp2';
|
||||
const computedSingleDep = 'computedSingleDep';
|
||||
const computedMultiDep1 = 'computedMultiDep1';
|
||||
const computedMultiDep2 = 'computedMultiDep2';
|
||||
const inlineSingleDep = 'inlineSingleDep';
|
||||
const inlineMultiDep1 = 'inlineMultiDep1';
|
||||
const inlineMultiDep2 = 'inlineMultiDep2';
|
||||
const inlineMultiIfDep1 = 'inlineMultiIfDep1';
|
||||
const inlineMultiIfDep2 = 'inlineMultiIfDep2';
|
||||
|
||||
suite('check disabled', () => {
|
||||
test('no arguments defined', () => {
|
||||
setupElement(false, {});
|
||||
assertEffects({});
|
||||
});
|
||||
test('singlePropObserver argument defined', () => {
|
||||
setupElement(false, {singleProp});
|
||||
assertEffects({singlePropObserver: 1});
|
||||
});
|
||||
test('one multiPropObserver arguments defined', () => {
|
||||
setupElement(false, {multiProp1});
|
||||
assertEffects({multiPropObserver: 1});
|
||||
});
|
||||
test('all multiPropObserver defined', () => {
|
||||
setupElement(false, {multiProp1, multiProp2});
|
||||
assertEffects({multiPropObserver: 1});
|
||||
});
|
||||
test('singlePropObserver argument undefined', () => {
|
||||
setupElement(false, {singleProp});
|
||||
assertEffects({singlePropObserver: 1});
|
||||
el.singleProp = undefined;
|
||||
assertEffects({singlePropObserver: 2});
|
||||
});
|
||||
test('one multiPropObserver arguments undefined', () => {
|
||||
setupElement(false, {multiProp1, multiProp2});
|
||||
assertEffects({multiPropObserver: 1});
|
||||
el.multiProp1 = undefined;
|
||||
assertEffects({multiPropObserver: 2});
|
||||
});
|
||||
test('all multiPropObserver undefined', () => {
|
||||
setupElement(false, {multiProp1, multiProp2});
|
||||
assertEffects({multiPropObserver: 1});
|
||||
el.multiProp1 = undefined;
|
||||
assertEffects({multiPropObserver: 2});
|
||||
el.multiProp2 = undefined;
|
||||
assertEffects({multiPropObserver: 3});
|
||||
});
|
||||
test('computeSingle argument defined', () => {
|
||||
setupElement(false, {computedSingleDep});
|
||||
assertEffects({computeSingle: 1});
|
||||
assert.equal(el.computedSingle, '[computedSingleDep]');
|
||||
});
|
||||
test('one computeMulti argument defined', () => {
|
||||
setupElement(false, {computedMultiDep1});
|
||||
assertEffects({computeMulti: 1});
|
||||
assert.equal(el.computedMulti, '[computedMultiDep1,undefined]');
|
||||
});
|
||||
test('all computeMulti argument defined', () => {
|
||||
setupElement(false, {computedMultiDep1, computedMultiDep2});
|
||||
assertEffects({computeMulti: 1});
|
||||
assert.equal(el.computedMulti, '[computedMultiDep1,computedMultiDep2]');
|
||||
});
|
||||
test('inline computeSingle argument defined', () => {
|
||||
setupElement(false, {inlineSingleDep});
|
||||
assertEffects({computeSingle: 1});
|
||||
assert.equal(el.$.child.computedSingle, '[inlineSingleDep]');
|
||||
});
|
||||
test('one inline computeMulti argument defined', () => {
|
||||
setupElement(false, {inlineMultiDep1});
|
||||
assertEffects({computeMulti: 1});
|
||||
assert.equal(el.$.child.computedMulti, '[inlineMultiDep1,undefined]');
|
||||
});
|
||||
test('all inline computeMulti argument defined', () => {
|
||||
setupElement(false, {inlineMultiDep1, inlineMultiDep2});
|
||||
assertEffects({computeMulti: 1});
|
||||
assert.equal(el.$.child.computedMulti, '[inlineMultiDep1,inlineMultiDep2]');
|
||||
});
|
||||
test('one inline computeMulti argument defined in dom-if', () => {
|
||||
setupElement(false, {inlineMultiIfDep1});
|
||||
assertEffects({computeMulti: 1});
|
||||
assert.equal(el.$$('#ifChild').computedMulti, '[inlineMultiIfDep1,undefined]');
|
||||
});
|
||||
test('all inline computeMulti argument defined in dom-if', () => {
|
||||
setupElement(false, {inlineMultiIfDep1, inlineMultiIfDep2});
|
||||
assertEffects({computeMulti: 1});
|
||||
assert.equal(el.$$('#ifChild').computedMulti, '[inlineMultiIfDep1,inlineMultiIfDep2]');
|
||||
});
|
||||
});
|
||||
|
||||
suite('warn', () => {
|
||||
test('no arguments defined', () => {
|
||||
setupElement(true, {});
|
||||
assertEffects({});
|
||||
});
|
||||
test('singlePropObserver argument defined', () => {
|
||||
setupElement(true, {singleProp});
|
||||
assertEffects({singlePropObserver: 1});
|
||||
});
|
||||
test('one multiPropObserver arguments defined', () => {
|
||||
setupElement(true, {multiProp1});
|
||||
assertEffects({multiPropObserver: 0, warn: 1});
|
||||
});
|
||||
test('all multiPropObserver defined', () => {
|
||||
setupElement(true, {multiProp1, multiProp2});
|
||||
assertEffects({multiPropObserver: 1});
|
||||
});
|
||||
test('singlePropObserver argument undefined', () => {
|
||||
setupElement(true, {singleProp});
|
||||
assertEffects({singlePropObserver: 1});
|
||||
el.singleProp = undefined;
|
||||
assertEffects({singlePropObserver: 2});
|
||||
});
|
||||
test('one multiPropObserver arguments undefined', () => {
|
||||
setupElement(true, {multiProp1, multiProp2});
|
||||
assertEffects({multiPropObserver: 1});
|
||||
el.multiProp1 = undefined;
|
||||
assertEffects({multiPropObserver: 1, warn: 1});
|
||||
});
|
||||
test('all multiPropObserver undefined', () => {
|
||||
setupElement(true, {multiProp1, multiProp2});
|
||||
assertEffects({multiPropObserver: 1});
|
||||
el.multiProp1 = undefined;
|
||||
assertEffects({multiPropObserver: 1, warn: 1});
|
||||
el.multiProp2 = undefined;
|
||||
assertEffects({multiPropObserver: 1, warn: 2});
|
||||
});
|
||||
test('computeSingle argument defined', () => {
|
||||
setupElement(true, {computedSingleDep});
|
||||
assertEffects({computeSingle: 1});
|
||||
assert.equal(el.computedSingle, '[computedSingleDep]');
|
||||
});
|
||||
test('one computeMulti argument defined', () => {
|
||||
setupElement(true, {computedMultiDep1});
|
||||
assertEffects({warn: 1});
|
||||
assert.equal(el.computedMulti, undefined);
|
||||
});
|
||||
test('all computeMulti argument defined', () => {
|
||||
setupElement(true, {computedMultiDep1, computedMultiDep2});
|
||||
assertEffects({computeMulti: 1});
|
||||
assert.equal(el.computedMulti, '[computedMultiDep1,computedMultiDep2]');
|
||||
});
|
||||
test('inline computeSingle argument defined', () => {
|
||||
setupElement(true, {inlineSingleDep});
|
||||
assertEffects({computeSingle: 1});
|
||||
assert.equal(el.$.child.computedSingle, '[inlineSingleDep]');
|
||||
});
|
||||
test('one inline computeMulti argument defined', () => {
|
||||
setupElement(true, {inlineMultiDep1});
|
||||
assertEffects({warn: 1});
|
||||
assert.equal(el.$.child.computedMulti, undefined);
|
||||
});
|
||||
test('all inline computeMulti argument defined', () => {
|
||||
setupElement(true, {inlineMultiDep1, inlineMultiDep2});
|
||||
assertEffects({computeMulti: 1});
|
||||
assert.equal(el.$.child.computedMulti, '[inlineMultiDep1,inlineMultiDep2]');
|
||||
});
|
||||
test('one inline computeMulti argument defined in dom-if', () => {
|
||||
setupElement(true, {inlineMultiIfDep1});
|
||||
assertEffects({warn: 1});
|
||||
assert.equal(el.$$('#ifChild').computedMulti, undefined);
|
||||
});
|
||||
test('all inline computeMulti argument defined in dom-if', () => {
|
||||
setupElement(true, {inlineMultiIfDep1, inlineMultiIfDep2});
|
||||
assertEffects({computeMulti: 1});
|
||||
assert.equal(el.$$('#ifChild').computedMulti, '[inlineMultiIfDep1,inlineMultiIfDep2]');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
suite('declarative', () => {
|
||||
|
||||
setup(() => sinon.spy(console, 'warn'));
|
||||
|
||||
teardown(() => console.warn.restore());
|
||||
|
||||
suite('warn', () => {
|
||||
test('no arguments defined', () => {
|
||||
el = fixture('declarative-none');
|
||||
assertEffects({});
|
||||
});
|
||||
test('singlePropObserver argument defined', () => {
|
||||
el = fixture('declarative-single');
|
||||
assertEffects({singlePropObserver: 1});
|
||||
});
|
||||
test('one multiPropObserver arguments defined', () => {
|
||||
el = fixture('declarative-multi-one');
|
||||
assertEffects({multiPropObserver: 0, warn: 1});
|
||||
});
|
||||
test('all multiPropObserver defined', () => {
|
||||
el = fixture('declarative-multi-all');
|
||||
assertEffects({multiPropObserver: 1});
|
||||
});
|
||||
test('computeSingle argument defined', () => {
|
||||
el = fixture('declarative-single-computed');
|
||||
assertEffects({computeSingle: 1});
|
||||
assert.equal(el.computedSingle, '[a]');
|
||||
});
|
||||
test('one computeMulti arguments defined', () => {
|
||||
el = fixture('declarative-multi-one-computed');
|
||||
assertEffects({computeMulti: 0, warn: 1});
|
||||
assert.equal(el.computedMulti, undefined);
|
||||
});
|
||||
test('all computeMulti defined', () => {
|
||||
el = fixture('declarative-multi-all-computed');
|
||||
assert.equal(el.computedMulti, '[b,c]');
|
||||
});
|
||||
test('inline computeSingle argument defined', () => {
|
||||
el = fixture('declarative-single-computed-inline');
|
||||
assertEffects({computeSingle: 1});
|
||||
assert.equal(el.$.child.computedSingle, '[a]');
|
||||
});
|
||||
test('inline one computeMulti arguments defined', () => {
|
||||
el = fixture('declarative-multi-one-computed-inline');
|
||||
assertEffects({computeMulti: 0, warn: 1});
|
||||
assert.equal(el.$.child.computedMulti, undefined);
|
||||
});
|
||||
test('inline all computeMulti defined', () => {
|
||||
el = fixture('declarative-multi-all-computed-inline');
|
||||
assertEffects({computeMulti: 1});
|
||||
assert.equal(el.$.child.computedMulti, '[b,c]');
|
||||
});
|
||||
test('one inline computeMulti argument defined in dom-if', () => {
|
||||
el = fixture('declarative-multi-if-one-computed-inline');
|
||||
Polymer.flush();
|
||||
assertEffects({computeMulti: 0, warn: 1});
|
||||
assert.equal(el.$$('#ifChild').computedMulti, undefined);
|
||||
});
|
||||
test('all inline computeMulti argument defined in dom-if', () => {
|
||||
el = fixture('declarative-multi-if-all-computed-inline');
|
||||
Polymer.flush();
|
||||
assertEffects({computeMulti: 1});
|
||||
assert.equal(el.$$('#ifChild').computedMulti, '[b,c]');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
suite('other', () => {
|
||||
test('real errors still throw', () => {
|
||||
const el = document.createElement('x-data');
|
||||
document.body.appendChild(el);
|
||||
assert.throws(() => {
|
||||
el.throwProp = true;
|
||||
}, /real error/);
|
||||
document.body.removeChild(el);
|
||||
});
|
||||
});
|
||||
|
||||
})();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,359 @@
|
||||
<!doctype html>
|
||||
<!--
|
||||
@license
|
||||
Copyright (c) 2017 The Polymer Project Authors. All rights reserved.
|
||||
This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
|
||||
The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
|
||||
The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
|
||||
Code distributed by Google as part of the polymer project is also
|
||||
subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
|
||||
-->
|
||||
<html>
|
||||
<head>
|
||||
<script src="../../../webcomponentsjs/webcomponents-lite.js"></script>
|
||||
<script>
|
||||
Polymer = {
|
||||
strictTemplatePolicy: true
|
||||
};
|
||||
// Errors thrown in custom element reactions are not thrown up
|
||||
// the call stack to the dom methods that provoked them, so need
|
||||
// to catch them here and prevent mocha from complaining about them
|
||||
window.addEventListener('error', event => {
|
||||
if (window.uncaughtErrorFilter && window.uncaughtErrorFilter(event)) {
|
||||
event.preventDefault();
|
||||
event.stopImmediatePropagation();
|
||||
}
|
||||
});
|
||||
</script>
|
||||
<script src="../../../web-component-tester/browser.js"></script>
|
||||
<link rel="import" href="../../polymer.html">
|
||||
<script>
|
||||
HTMLImports.whenReady(() => {
|
||||
// Errors thrown in Polymer's debouncer queue get re-thrown
|
||||
// via setTimeout, making them particulary difficult to verify;
|
||||
// Wrap debouncer callbacks and store on the globalError to test later
|
||||
const debounce = Polymer.Debouncer.debounce;
|
||||
Polymer.Debouncer.debounce = function(debouncer, asyncModule, callback) {
|
||||
return debounce(debouncer, asyncModule, function() {
|
||||
try {
|
||||
callback();
|
||||
} catch(error) {
|
||||
if (!window.uncaughtErrorFilter || !window.uncaughtErrorFilter(error)) {
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
});
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<dom-module id="trusted-element">
|
||||
<template>Trusted</template>
|
||||
<script>
|
||||
HTMLImports.whenReady(function() {
|
||||
class TrustedElement extends Polymer.Element {
|
||||
static get is() { return 'trusted-element'; }
|
||||
}
|
||||
customElements.define(TrustedElement.is, TrustedElement);
|
||||
});
|
||||
</script>
|
||||
</dom-module>
|
||||
|
||||
<dom-module id="trusted-element-legacy">
|
||||
<template>Trusted</template>
|
||||
<script>
|
||||
HTMLImports.whenReady(function() {
|
||||
Polymer({is: 'trusted-element-legacy'});
|
||||
});
|
||||
</script>
|
||||
</dom-module>
|
||||
|
||||
<dom-module id="trusted-templates">
|
||||
<template>
|
||||
<dom-repeat items="[0]">
|
||||
<template>
|
||||
<div id="dom-repeat-ok"></div>
|
||||
<dom-if if>
|
||||
<template><div id="nested-dom-if-ok"></div></template>
|
||||
</dom-if>
|
||||
</template>
|
||||
</dom-repeat>
|
||||
<dom-if if>
|
||||
<template>
|
||||
<div id="dom-if-ok"></div>
|
||||
<dom-repeat items="[0]">
|
||||
<template>
|
||||
<div id="nested-dom-repeat-ok"></div>
|
||||
</template>
|
||||
</dom-repeat>
|
||||
</template>
|
||||
</dom-if>
|
||||
</template>
|
||||
<script>
|
||||
HTMLImports.whenReady(function() {
|
||||
class TrustedTemplates extends Polymer.Element {
|
||||
static get is() { return 'trusted-templates'; }
|
||||
}
|
||||
customElements.define(TrustedTemplates.is, TrustedTemplates);
|
||||
});
|
||||
</script>
|
||||
</dom-module>
|
||||
|
||||
<dom-module id="trusted-templates-legacy">
|
||||
<template>
|
||||
<template is="dom-repeat" items="[0]">
|
||||
<div id="dom-repeat-ok"></div>
|
||||
<template is="dom-if" if><div id="nested-dom-if-ok"></div></template>
|
||||
</template>
|
||||
<template is="dom-if" if>
|
||||
<div id="dom-if-ok"></div>
|
||||
<template is="dom-repeat" items="[0]"><div id="nested-dom-repeat-ok"></div></template>
|
||||
</template>
|
||||
</template>
|
||||
<script>
|
||||
HTMLImports.whenReady(function() {
|
||||
Polymer({is: 'trusted-templates-legacy'});
|
||||
});
|
||||
</script>
|
||||
</dom-module>
|
||||
|
||||
<div id="target"></div>
|
||||
|
||||
<script>
|
||||
suite('strictTemplatePolicy', function() {
|
||||
|
||||
// Capture mocha's default onerror
|
||||
const onerror = window.onerror;
|
||||
const topOnerror = window.top.topOnerror;
|
||||
|
||||
function restoreOnError() {
|
||||
window.onerror = onerror;
|
||||
window.top.onerror = topOnerror;
|
||||
window.uncaughtErrorFilter = window.top.uncaughtErrorFilter = null;
|
||||
}
|
||||
|
||||
teardown(function() {
|
||||
// Restore mocha's onerror
|
||||
restoreOnError();
|
||||
document.getElementById('target').textContent = '';
|
||||
});
|
||||
|
||||
// Errors thrown in custom element reactions are not thrown up
|
||||
// the call stack to the dom methods that provoked them, so this
|
||||
// wraps Chai's assert.throws to re-throw uncaught errors
|
||||
function assertThrows(fn, re) {
|
||||
// Safari does not forward error messages
|
||||
re = new RegExp('(' + re.toString().slice(1,-1) + ')|(Script error\\.)', re.flags);
|
||||
// Catch uncaught errors; note when running in iframe sometimes
|
||||
// Safari errors are thrown on the top window, sometimes not, so
|
||||
// catch in both places
|
||||
let uncaughtError = null;
|
||||
window.onerror = window.top.onerror = window.uncaughtErrorFilter =
|
||||
window.top.uncaughtErrorFilter = function(err) {
|
||||
if (!uncaughtError) {
|
||||
uncaughtError = err instanceof Error ? err : new Error(err.message || err);
|
||||
}
|
||||
return true;
|
||||
};
|
||||
assert.throws(function() {
|
||||
fn();
|
||||
// Re-throw any uncaughtErrors
|
||||
if (uncaughtError) {
|
||||
throw uncaughtError;
|
||||
}
|
||||
// Force polyfill reactions and/or async template stamping
|
||||
Polymer.flush();
|
||||
// Re-throw any uncaughtErrors
|
||||
if (uncaughtError) {
|
||||
throw uncaughtError;
|
||||
}
|
||||
}, re);
|
||||
restoreOnError();
|
||||
}
|
||||
|
||||
test('dom-bind', function() {
|
||||
assertThrows(function() {
|
||||
document.getElementById('target').innerHTML =
|
||||
'<dom-bind>' +
|
||||
' <template>' +
|
||||
' <div id="injected"></div>'+
|
||||
' </template>`' +
|
||||
'</dom-bind>';
|
||||
}, /dom-bind not allowed/);
|
||||
assert.notOk(document.getElementById('injected'));
|
||||
});
|
||||
|
||||
test('dom-if', function() {
|
||||
assertThrows(function() {
|
||||
document.getElementById('target').innerHTML =
|
||||
'<dom-if if>' +
|
||||
' <template>' +
|
||||
' <div id="injected"></div>'+
|
||||
' </template>' +
|
||||
'</dom-if>';
|
||||
}, /template owner not trusted/);
|
||||
assert.notOk(document.getElementById('injected'));
|
||||
});
|
||||
|
||||
test('dom-repeat', function() {
|
||||
assertThrows(function() {
|
||||
document.getElementById('target').innerHTML =
|
||||
'<dom-repeat items="[0]">' +
|
||||
' <template>' +
|
||||
' <div id="injected"></div>'+
|
||||
' </template>`' +
|
||||
'</dom-repeat>';
|
||||
}, /template owner not trusted/);
|
||||
assert.notOk(document.getElementById('injected'));
|
||||
});
|
||||
|
||||
test('dom-module after registration', function() {
|
||||
assertThrows(function() {
|
||||
document.getElementById('target').innerHTML =
|
||||
'<dom-module id="trusted-element">' +
|
||||
' <template>' +
|
||||
' <div id="injected"></div>'+
|
||||
' </template>`' +
|
||||
'</dom-module>';
|
||||
}, /trusted-element re-registered/);
|
||||
let el;
|
||||
assertThrows(function() {
|
||||
el = document.createElement('trusted-element');
|
||||
document.getElementById('target').appendChild(el);
|
||||
}, /expecting dom-module or null template for trusted-element/);
|
||||
assert.notOk(el && el.shadowRoot);
|
||||
assert.notOk(document.getElementById('injected'));
|
||||
});
|
||||
|
||||
test('dom-module after registration, again', function() {
|
||||
assertThrows(function() {
|
||||
document.getElementById('target').innerHTML =
|
||||
'<dom-module id="trusted-element">' +
|
||||
' <template>' +
|
||||
' <div id="injected"></div>'+
|
||||
' </template>`' +
|
||||
'</dom-module>';
|
||||
}, /trusted-element re-registered/);
|
||||
const el = document.createElement('trusted-element');
|
||||
document.getElementById('target').appendChild(el);
|
||||
assert.notOk(el.shadowRoot);
|
||||
assert.notOk(document.getElementById('injected'));
|
||||
});
|
||||
|
||||
test('dom-module before registration', function() {
|
||||
document.getElementById('target').innerHTML =
|
||||
'<dom-module id="has-no-template">' +
|
||||
' <template>' +
|
||||
' <div id="injected"></div>'+
|
||||
' </template>`' +
|
||||
'</dom-module>';
|
||||
class HasNoTemplate extends Polymer.Element {
|
||||
static get is() { return 'has-no-template'; }
|
||||
static get template() { return null; }
|
||||
}
|
||||
customElements.define(HasNoTemplate.is, HasNoTemplate);
|
||||
let el = document.createElement('has-no-template');
|
||||
document.getElementById('target').appendChild(el);
|
||||
assert.notOk(el.shadowRoot);
|
||||
assert.notOk(document.getElementById('injected'));
|
||||
});
|
||||
|
||||
test('dom-module after registration (legacy)', function() {
|
||||
assertThrows(function() {
|
||||
document.getElementById('target').innerHTML =
|
||||
'<dom-module id="trusted-element-legacy">' +
|
||||
' <template>' +
|
||||
' <div id="injected"></div>'+
|
||||
' </template>`' +
|
||||
'</dom-module>';
|
||||
}, /trusted-element-legacy re-registered/);
|
||||
let el;
|
||||
assertThrows(function() {
|
||||
el = document.createElement('trusted-element-legacy');
|
||||
document.getElementById('target').appendChild(el);
|
||||
}, /expecting dom-module or null template for trusted-element-legacy/);
|
||||
assert.notOk(el && el.shadowRoot);
|
||||
assert.notOk(document.getElementById('injected'));
|
||||
});
|
||||
|
||||
test('dom-module after registration, again (legacy)', function() {
|
||||
assertThrows(function() {
|
||||
document.getElementById('target').innerHTML =
|
||||
'<dom-module id="trusted-element-legacy">' +
|
||||
' <template>' +
|
||||
' <div id="injected"></div>'+
|
||||
' </template>`' +
|
||||
'</dom-module>';
|
||||
}, /trusted-element-legacy re-registered/);
|
||||
const el = document.createElement('trusted-element-legacy');
|
||||
document.getElementById('target').appendChild(el);
|
||||
assert.notOk(el.shadowRoot);
|
||||
assert.notOk(document.getElementById('injected'));
|
||||
});
|
||||
|
||||
test('dom-module before registration (legacy)', function() {
|
||||
document.getElementById('target').innerHTML =
|
||||
'<dom-module id="has-no-template-legacy">' +
|
||||
' <template>' +
|
||||
' <div id="injected"></div>'+
|
||||
' </template>`' +
|
||||
'</dom-module>';
|
||||
Polymer({
|
||||
is: 'has-no-template-legacy',
|
||||
_template: null
|
||||
});
|
||||
let el = document.createElement('has-no-template-legacy');
|
||||
document.getElementById('target').appendChild(el);
|
||||
assert.notOk(el.shadowRoot);
|
||||
assert.notOk(document.getElementById('injected'));
|
||||
});
|
||||
|
||||
test('element without explicit template throws', function() {
|
||||
assertThrows(function() {
|
||||
class HasNoTemplateThrows extends Polymer.Element {
|
||||
static get is() { return 'has-no-template-throws'; }
|
||||
}
|
||||
customElements.define(HasNoTemplateThrows.is, HasNoTemplateThrows);
|
||||
var el = document.createElement('has-no-template-throws');
|
||||
document.getElementById('target').appendChild(el);
|
||||
}, /expecting dom-module or null template/);
|
||||
});
|
||||
|
||||
test('element without explicit template throws (legacy)', function() {
|
||||
assertThrows(function() {
|
||||
Polymer({
|
||||
is: 'has-no-template-throws-legacy'
|
||||
});
|
||||
var el = document.createElement('has-no-template-throws-legacy');
|
||||
document.getElementById('target').appendChild(el);
|
||||
}, /expecting dom-module or null template/);
|
||||
});
|
||||
|
||||
test('template helpers in trusted templates work', function() {
|
||||
var el = document.createElement('trusted-templates');
|
||||
document.getElementById('target').appendChild(el);
|
||||
Polymer.flush();
|
||||
assert.ok(el.shadowRoot.querySelector('#dom-repeat-ok'));
|
||||
assert.ok(el.shadowRoot.querySelector('#dom-if-ok'));
|
||||
assert.ok(el.shadowRoot.querySelector('#nested-dom-repeat-ok'));
|
||||
assert.ok(el.shadowRoot.querySelector('#nested-dom-if-ok'));
|
||||
});
|
||||
|
||||
test('template helpers in trusted templates work (legacy)', function() {
|
||||
var el = document.createElement('trusted-templates-legacy');
|
||||
document.getElementById('target').appendChild(el);
|
||||
Polymer.flush();
|
||||
assert.ok(el.shadowRoot.querySelector('#dom-repeat-ok'));
|
||||
assert.ok(el.shadowRoot.querySelector('#dom-if-ok'));
|
||||
assert.ok(el.shadowRoot.querySelector('#nested-dom-repeat-ok'));
|
||||
assert.ok(el.shadowRoot.querySelector('#nested-dom-if-ok'));
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
Vendored
+1
-1
@@ -91,5 +91,5 @@ declare namespace Polymer {
|
||||
*
|
||||
* @returns Generated class
|
||||
*/
|
||||
function Class(info: PolymerInit, mixin: (p0: T|null) => T|null): {new(): HTMLElement};
|
||||
function Class<T>(info: PolymerInit, mixin: (p0: T) => T): {new(): HTMLElement};
|
||||
}
|
||||
|
||||
+89
@@ -0,0 +1,89 @@
|
||||
/**
|
||||
* DO NOT EDIT
|
||||
*
|
||||
* This file was automatically generated by
|
||||
* https://github.com/Polymer/gen-typescript-declarations
|
||||
*
|
||||
* To modify these typings, edit the source file(s):
|
||||
* lib/legacy/legacy-data-mixin.html
|
||||
*/
|
||||
|
||||
/// <reference path="class.d.ts" />
|
||||
/// <reference path="../../polymer.d.ts" />
|
||||
/// <reference path="../utils/mixin.d.ts" />
|
||||
/// <reference path="../utils/templatize.d.ts" />
|
||||
|
||||
declare class UndefinedArgumentError extends Error {
|
||||
constructor(message: any, arg: any);
|
||||
}
|
||||
|
||||
declare namespace Polymer {
|
||||
|
||||
|
||||
/**
|
||||
* 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
|
||||
* the mixin in Polymer 2.
|
||||
*/
|
||||
function LegacyDataMixin<T extends new (...args: any[]) => {}>(base: T): T & LegacyDataMixinConstructor;
|
||||
|
||||
interface LegacyDataMixinConstructor {
|
||||
new(...args: any[]): LegacyDataMixin;
|
||||
|
||||
/**
|
||||
* Overrides `Polyer.PropertyEffects` to wrap effect functions to
|
||||
* catch `UndefinedArgumentError`s and warn.
|
||||
*
|
||||
* @param templateInfo Template metadata to add effect to
|
||||
* @param prop Property that should trigger the effect
|
||||
* @param effect Effect metadata object
|
||||
*/
|
||||
_addTemplatePropertyEffect(templateInfo: object|null, prop: string, effect?: object|null): void;
|
||||
}
|
||||
|
||||
interface LegacyDataMixin {
|
||||
readonly _legacyUndefinedCheck: any;
|
||||
|
||||
/**
|
||||
* Overrides `Polyer.PropertyEffects` to wrap effect functions to
|
||||
* catch `UndefinedArgumentError`s and warn.
|
||||
*
|
||||
* @param property Property that should trigger the effect
|
||||
* @param type Effect type, from this.PROPERTY_EFFECT_TYPES
|
||||
* @param effect Effect metadata object
|
||||
*/
|
||||
_addPropertyEffect(property: string, type: string, effect?: object|null): void;
|
||||
}
|
||||
}
|
||||
|
||||
declare class LegacyDataMixin extends superClass {
|
||||
|
||||
/**
|
||||
* Overrides `Polyer.PropertyEffects` to wrap effect functions to
|
||||
* catch `UndefinedArgumentError`s and warn.
|
||||
*
|
||||
* @param templateInfo Template metadata to add effect to
|
||||
* @param prop Property that should trigger the effect
|
||||
* @param effect Effect metadata object
|
||||
*/
|
||||
static _addTemplatePropertyEffect(templateInfo: object|null, prop: string, effect?: object|null): void;
|
||||
|
||||
/**
|
||||
* Overrides `Polyer.PropertyEffects` to wrap effect functions to
|
||||
* catch `UndefinedArgumentError`s and warn.
|
||||
*
|
||||
* @param property Property that should trigger the effect
|
||||
* @param type Effect type, from this.PROPERTY_EFFECT_TYPES
|
||||
* @param effect Effect metadata object
|
||||
*/
|
||||
_addPropertyEffect(property: string, type: string, effect?: object|null): void;
|
||||
}
|
||||
Reference in New Issue
Block a user