@avs/go-react 0.12.71731 → 0.13.71740
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/demo/node_modules/.vite/deps/@polymer_iron-resizable-behavior_iron-resizable-behavior__js.js +2321 -0
- package/demo/node_modules/.vite/deps/@polymer_iron-resizable-behavior_iron-resizable-behavior__js.js.map +7 -0
- package/demo/node_modules/.vite/deps/@polymer_polymer_lib_legacy_class__js.js +13 -0
- package/demo/node_modules/.vite/deps/@polymer_polymer_lib_legacy_class__js.js.map +7 -0
- package/demo/node_modules/.vite/deps/@polymer_polymer_lib_utils_mixin__js.js +8 -0
- package/demo/node_modules/.vite/deps/@polymer_polymer_lib_utils_mixin__js.js.map +7 -0
- package/demo/node_modules/.vite/deps/@polymer_polymer_lib_utils_render-status__js.js +12 -0
- package/demo/node_modules/.vite/deps/@polymer_polymer_lib_utils_render-status__js.js.map +7 -0
- package/demo/node_modules/.vite/deps/@polymer_polymer_polymer-element__js.js +15 -0
- package/demo/node_modules/.vite/deps/@polymer_polymer_polymer-element__js.js.map +7 -0
- package/demo/node_modules/.vite/deps/_metadata.json +103 -0
- package/demo/node_modules/.vite/deps/chunk-6HI7N2AN.js +267 -0
- package/demo/node_modules/.vite/deps/chunk-6HI7N2AN.js.map +7 -0
- package/demo/node_modules/.vite/deps/chunk-BHAOVVTR.js +4597 -0
- package/demo/node_modules/.vite/deps/chunk-BHAOVVTR.js.map +7 -0
- package/demo/node_modules/.vite/deps/chunk-BSA4YZO6.js +83 -0
- package/demo/node_modules/.vite/deps/chunk-BSA4YZO6.js.map +7 -0
- package/demo/node_modules/.vite/deps/chunk-BUSYA2B4.js +8 -0
- package/demo/node_modules/.vite/deps/chunk-BUSYA2B4.js.map +7 -0
- package/demo/node_modules/.vite/deps/chunk-CWUEONQP.js +991 -0
- package/demo/node_modules/.vite/deps/chunk-CWUEONQP.js.map +7 -0
- package/demo/node_modules/.vite/deps/chunk-I2HDYNON.js +46 -0
- package/demo/node_modules/.vite/deps/chunk-I2HDYNON.js.map +7 -0
- package/demo/node_modules/.vite/deps/chunk-MXBCLPIN.js +5 -0
- package/demo/node_modules/.vite/deps/chunk-MXBCLPIN.js.map +7 -0
- package/demo/node_modules/.vite/deps/chunk-PRUGAEYJ.js +4871 -0
- package/demo/node_modules/.vite/deps/chunk-PRUGAEYJ.js.map +7 -0
- package/demo/node_modules/.vite/deps/chunk-QQPVW2K2.js +62 -0
- package/demo/node_modules/.vite/deps/chunk-QQPVW2K2.js.map +7 -0
- package/demo/node_modules/.vite/deps/package.json +3 -0
- package/demo/node_modules/.vite/deps/react-dom.js +6 -0
- package/demo/node_modules/.vite/deps/react-dom.js.map +7 -0
- package/demo/node_modules/.vite/deps/react-dom_client.js +20193 -0
- package/demo/node_modules/.vite/deps/react-dom_client.js.map +7 -0
- package/demo/node_modules/.vite/deps/react.js +5 -0
- package/demo/node_modules/.vite/deps/react.js.map +7 -0
- package/demo/node_modules/.vite/deps/react_jsx-dev-runtime.js +265 -0
- package/demo/node_modules/.vite/deps/react_jsx-dev-runtime.js.map +7 -0
- package/demo/node_modules/.vite/deps/react_jsx-runtime.js +276 -0
- package/demo/node_modules/.vite/deps/react_jsx-runtime.js.map +7 -0
- package/demo/node_modules/.vite/deps/three.js +41878 -0
- package/demo/node_modules/.vite/deps/three.js.map +7 -0
- package/demo/public/hydrogen.json +1 -1
- package/demo/src/App.tsx +17 -17
- package/package.json +3 -3
- package/src/AvsGoDataViz.jsx +2 -0
|
@@ -0,0 +1,4871 @@
|
|
|
1
|
+
import {
|
|
2
|
+
dedupingMixin
|
|
3
|
+
} from "./chunk-I2HDYNON.js";
|
|
4
|
+
|
|
5
|
+
// ../../../node_modules/@polymer/polymer/lib/utils/resolve-url.js
|
|
6
|
+
var CSS_URL_RX = /(url\()([^)]*)(\))/g;
|
|
7
|
+
var ABS_URL = /(^\/[^\/])|(^#)|(^[\w-\d]*:)/;
|
|
8
|
+
var workingURL;
|
|
9
|
+
var resolveDoc;
|
|
10
|
+
function resolveUrl(url, baseURI) {
|
|
11
|
+
if (url && ABS_URL.test(url)) {
|
|
12
|
+
return url;
|
|
13
|
+
}
|
|
14
|
+
if (url === "//") {
|
|
15
|
+
return url;
|
|
16
|
+
}
|
|
17
|
+
if (workingURL === void 0) {
|
|
18
|
+
workingURL = false;
|
|
19
|
+
try {
|
|
20
|
+
const u = new URL("b", "http://a");
|
|
21
|
+
u.pathname = "c%20d";
|
|
22
|
+
workingURL = u.href === "http://a/c%20d";
|
|
23
|
+
} catch (e) {
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
if (!baseURI) {
|
|
27
|
+
baseURI = document.baseURI || window.location.href;
|
|
28
|
+
}
|
|
29
|
+
if (workingURL) {
|
|
30
|
+
try {
|
|
31
|
+
return new URL(url, baseURI).href;
|
|
32
|
+
} catch (e) {
|
|
33
|
+
return url;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
if (!resolveDoc) {
|
|
37
|
+
resolveDoc = document.implementation.createHTMLDocument("temp");
|
|
38
|
+
resolveDoc.base = resolveDoc.createElement("base");
|
|
39
|
+
resolveDoc.head.appendChild(resolveDoc.base);
|
|
40
|
+
resolveDoc.anchor = resolveDoc.createElement("a");
|
|
41
|
+
resolveDoc.body.appendChild(resolveDoc.anchor);
|
|
42
|
+
}
|
|
43
|
+
resolveDoc.base.href = baseURI;
|
|
44
|
+
resolveDoc.anchor.href = url;
|
|
45
|
+
return resolveDoc.anchor.href || url;
|
|
46
|
+
}
|
|
47
|
+
function resolveCss(cssText, baseURI) {
|
|
48
|
+
return cssText.replace(CSS_URL_RX, function(m, pre, url, post) {
|
|
49
|
+
return pre + "'" + resolveUrl(url.replace(/["']/g, ""), baseURI) + "'" + post;
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
function pathFromUrl(url) {
|
|
53
|
+
return url.substring(0, url.lastIndexOf("/") + 1);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// ../../../node_modules/@polymer/polymer/lib/utils/settings.js
|
|
57
|
+
var useShadow = !window.ShadyDOM || !window.ShadyDOM.inUse;
|
|
58
|
+
var useNativeCSSProperties = Boolean(!window.ShadyCSS || window.ShadyCSS.nativeCss);
|
|
59
|
+
var useNativeCustomElements = !window.customElements.polyfillWrapFlushCallback;
|
|
60
|
+
var supportsAdoptingStyleSheets = useShadow && "adoptedStyleSheets" in Document.prototype && "replaceSync" in CSSStyleSheet.prototype && // Since spec may change, feature detect exact API we need
|
|
61
|
+
(() => {
|
|
62
|
+
try {
|
|
63
|
+
const sheet = new CSSStyleSheet();
|
|
64
|
+
sheet.replaceSync("");
|
|
65
|
+
const host = document.createElement("div");
|
|
66
|
+
host.attachShadow({ mode: "open" });
|
|
67
|
+
host.shadowRoot.adoptedStyleSheets = [sheet];
|
|
68
|
+
return host.shadowRoot.adoptedStyleSheets[0] === sheet;
|
|
69
|
+
} catch (e) {
|
|
70
|
+
return false;
|
|
71
|
+
}
|
|
72
|
+
})();
|
|
73
|
+
var rootPath = window.Polymer && window.Polymer.rootPath || pathFromUrl(document.baseURI || window.location.href);
|
|
74
|
+
var sanitizeDOMValue = window.Polymer && window.Polymer.sanitizeDOMValue || void 0;
|
|
75
|
+
var passiveTouchGestures = window.Polymer && window.Polymer.setPassiveTouchGestures || false;
|
|
76
|
+
var strictTemplatePolicy = window.Polymer && window.Polymer.strictTemplatePolicy || false;
|
|
77
|
+
var allowTemplateFromDomModule = window.Polymer && window.Polymer.allowTemplateFromDomModule || false;
|
|
78
|
+
var legacyOptimizations = window.Polymer && window.Polymer.legacyOptimizations || false;
|
|
79
|
+
var legacyWarnings = window.Polymer && window.Polymer.legacyWarnings || false;
|
|
80
|
+
var syncInitialRender = window.Polymer && window.Polymer.syncInitialRender || false;
|
|
81
|
+
var legacyUndefined = window.Polymer && window.Polymer.legacyUndefined || false;
|
|
82
|
+
var orderedComputed = window.Polymer && window.Polymer.orderedComputed || false;
|
|
83
|
+
var cancelSyntheticClickEvents = true;
|
|
84
|
+
var removeNestedTemplates = window.Polymer && window.Polymer.removeNestedTemplates || false;
|
|
85
|
+
var fastDomIf = window.Polymer && window.Polymer.fastDomIf || false;
|
|
86
|
+
var suppressTemplateNotifications = window.Polymer && window.Polymer.suppressTemplateNotifications || false;
|
|
87
|
+
var legacyNoObservedAttributes = window.Polymer && window.Polymer.legacyNoObservedAttributes || false;
|
|
88
|
+
var useAdoptedStyleSheetsWithBuiltCSS = window.Polymer && window.Polymer.useAdoptedStyleSheetsWithBuiltCSS || false;
|
|
89
|
+
|
|
90
|
+
// ../../../node_modules/@polymer/polymer/lib/elements/dom-module.js
|
|
91
|
+
var modules = {};
|
|
92
|
+
var lcModules = {};
|
|
93
|
+
function setModule(id, module) {
|
|
94
|
+
modules[id] = lcModules[id.toLowerCase()] = module;
|
|
95
|
+
}
|
|
96
|
+
function findModule(id) {
|
|
97
|
+
return modules[id] || lcModules[id.toLowerCase()];
|
|
98
|
+
}
|
|
99
|
+
function styleOutsideTemplateCheck(inst) {
|
|
100
|
+
if (inst.querySelector("style")) {
|
|
101
|
+
console.warn("dom-module %s has style outside template", inst.id);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
var DomModule = class extends HTMLElement {
|
|
105
|
+
/** @override */
|
|
106
|
+
static get observedAttributes() {
|
|
107
|
+
return ["id"];
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Retrieves the element specified by the css `selector` in the module
|
|
111
|
+
* registered by `id`. For example, this.import('foo', 'img');
|
|
112
|
+
* @param {string} id The id of the dom-module in which to search.
|
|
113
|
+
* @param {string=} selector The css selector by which to find the element.
|
|
114
|
+
* @return {Element} Returns the element which matches `selector` in the
|
|
115
|
+
* module registered at the specified `id`.
|
|
116
|
+
*
|
|
117
|
+
* @export
|
|
118
|
+
* @nocollapse Referred to indirectly in style-gather.js
|
|
119
|
+
*/
|
|
120
|
+
static import(id, selector) {
|
|
121
|
+
if (id) {
|
|
122
|
+
let m = findModule(id);
|
|
123
|
+
if (m && selector) {
|
|
124
|
+
return m.querySelector(selector);
|
|
125
|
+
}
|
|
126
|
+
return m;
|
|
127
|
+
}
|
|
128
|
+
return null;
|
|
129
|
+
}
|
|
130
|
+
/* eslint-disable no-unused-vars */
|
|
131
|
+
/**
|
|
132
|
+
* @param {string} name Name of attribute.
|
|
133
|
+
* @param {?string} old Old value of attribute.
|
|
134
|
+
* @param {?string} value Current value of attribute.
|
|
135
|
+
* @param {?string} namespace Attribute namespace.
|
|
136
|
+
* @return {void}
|
|
137
|
+
* @override
|
|
138
|
+
*/
|
|
139
|
+
attributeChangedCallback(name, old, value, namespace) {
|
|
140
|
+
if (old !== value) {
|
|
141
|
+
this.register();
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
/* eslint-enable no-unused-args */
|
|
145
|
+
/**
|
|
146
|
+
* The absolute URL of the original location of this `dom-module`.
|
|
147
|
+
*
|
|
148
|
+
* This value will differ from this element's `ownerDocument` in the
|
|
149
|
+
* following ways:
|
|
150
|
+
* - Takes into account any `assetpath` attribute added during bundling
|
|
151
|
+
* to indicate the original location relative to the bundled location
|
|
152
|
+
* - Uses the HTMLImports polyfill's `importForElement` API to ensure
|
|
153
|
+
* the path is relative to the import document's location since
|
|
154
|
+
* `ownerDocument` is not currently polyfilled
|
|
155
|
+
*/
|
|
156
|
+
get assetpath() {
|
|
157
|
+
if (!this.__assetpath) {
|
|
158
|
+
const owner = window.HTMLImports && HTMLImports.importForElement ? HTMLImports.importForElement(this) || document : this.ownerDocument;
|
|
159
|
+
const url = resolveUrl(
|
|
160
|
+
this.getAttribute("assetpath") || "",
|
|
161
|
+
owner.baseURI
|
|
162
|
+
);
|
|
163
|
+
this.__assetpath = pathFromUrl(url);
|
|
164
|
+
}
|
|
165
|
+
return this.__assetpath;
|
|
166
|
+
}
|
|
167
|
+
/**
|
|
168
|
+
* Registers the dom-module at a given id. This method should only be called
|
|
169
|
+
* when a dom-module is imperatively created. For
|
|
170
|
+
* example, `document.createElement('dom-module').register('foo')`.
|
|
171
|
+
* @param {string=} id The id at which to register the dom-module.
|
|
172
|
+
* @return {void}
|
|
173
|
+
*/
|
|
174
|
+
register(id) {
|
|
175
|
+
id = id || this.id;
|
|
176
|
+
if (id) {
|
|
177
|
+
if (strictTemplatePolicy && findModule(id) !== void 0) {
|
|
178
|
+
setModule(id, null);
|
|
179
|
+
throw new Error(`strictTemplatePolicy: dom-module ${id} re-registered`);
|
|
180
|
+
}
|
|
181
|
+
this.id = id;
|
|
182
|
+
setModule(id, this);
|
|
183
|
+
styleOutsideTemplateCheck(this);
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
};
|
|
187
|
+
DomModule.prototype["modules"] = modules;
|
|
188
|
+
customElements.define("dom-module", DomModule);
|
|
189
|
+
|
|
190
|
+
// ../../../node_modules/@polymer/polymer/lib/utils/style-gather.js
|
|
191
|
+
var MODULE_STYLE_LINK_SELECTOR = "link[rel=import][type~=css]";
|
|
192
|
+
var INCLUDE_ATTR = "include";
|
|
193
|
+
var SHADY_UNSCOPED_ATTR = "shady-unscoped";
|
|
194
|
+
function importModule(moduleId) {
|
|
195
|
+
return (
|
|
196
|
+
/** @type {?DomModule} */
|
|
197
|
+
DomModule.import(moduleId)
|
|
198
|
+
);
|
|
199
|
+
}
|
|
200
|
+
function styleForImport(importDoc) {
|
|
201
|
+
let container = importDoc.body ? importDoc.body : importDoc;
|
|
202
|
+
const importCss = resolveCss(
|
|
203
|
+
container.textContent,
|
|
204
|
+
importDoc.baseURI
|
|
205
|
+
);
|
|
206
|
+
const style = document.createElement("style");
|
|
207
|
+
style.textContent = importCss;
|
|
208
|
+
return style;
|
|
209
|
+
}
|
|
210
|
+
function stylesFromModules(moduleIds) {
|
|
211
|
+
const modules2 = moduleIds.trim().split(/\s+/);
|
|
212
|
+
const styles = [];
|
|
213
|
+
for (let i = 0; i < modules2.length; i++) {
|
|
214
|
+
styles.push(...stylesFromModule(modules2[i]));
|
|
215
|
+
}
|
|
216
|
+
return styles;
|
|
217
|
+
}
|
|
218
|
+
function stylesFromModule(moduleId) {
|
|
219
|
+
const m = importModule(moduleId);
|
|
220
|
+
if (!m) {
|
|
221
|
+
console.warn("Could not find style data in module named", moduleId);
|
|
222
|
+
return [];
|
|
223
|
+
}
|
|
224
|
+
if (m._styles === void 0) {
|
|
225
|
+
const styles = [];
|
|
226
|
+
styles.push(..._stylesFromModuleImports(m));
|
|
227
|
+
const template = (
|
|
228
|
+
/** @type {?HTMLTemplateElement} */
|
|
229
|
+
m.querySelector("template")
|
|
230
|
+
);
|
|
231
|
+
if (template) {
|
|
232
|
+
styles.push(...stylesFromTemplate(
|
|
233
|
+
template,
|
|
234
|
+
/** @type {templateWithAssetPath} */
|
|
235
|
+
m.assetpath
|
|
236
|
+
));
|
|
237
|
+
}
|
|
238
|
+
m._styles = styles;
|
|
239
|
+
}
|
|
240
|
+
return m._styles;
|
|
241
|
+
}
|
|
242
|
+
function stylesFromTemplate(template, baseURI) {
|
|
243
|
+
if (!template._styles) {
|
|
244
|
+
const styles = [];
|
|
245
|
+
const e$ = template.content.querySelectorAll("style");
|
|
246
|
+
for (let i = 0; i < e$.length; i++) {
|
|
247
|
+
let e = e$[i];
|
|
248
|
+
let include = e.getAttribute(INCLUDE_ATTR);
|
|
249
|
+
if (include) {
|
|
250
|
+
styles.push(...stylesFromModules(include).filter(function(item, index, self) {
|
|
251
|
+
return self.indexOf(item) === index;
|
|
252
|
+
}));
|
|
253
|
+
}
|
|
254
|
+
if (baseURI) {
|
|
255
|
+
e.textContent = resolveCss(
|
|
256
|
+
e.textContent,
|
|
257
|
+
/** @type {string} */
|
|
258
|
+
baseURI
|
|
259
|
+
);
|
|
260
|
+
}
|
|
261
|
+
styles.push(e);
|
|
262
|
+
}
|
|
263
|
+
template._styles = styles;
|
|
264
|
+
}
|
|
265
|
+
return template._styles;
|
|
266
|
+
}
|
|
267
|
+
function stylesFromModuleImports(moduleId) {
|
|
268
|
+
let m = importModule(moduleId);
|
|
269
|
+
return m ? _stylesFromModuleImports(m) : [];
|
|
270
|
+
}
|
|
271
|
+
function _stylesFromModuleImports(module) {
|
|
272
|
+
const styles = [];
|
|
273
|
+
const p$ = module.querySelectorAll(MODULE_STYLE_LINK_SELECTOR);
|
|
274
|
+
for (let i = 0; i < p$.length; i++) {
|
|
275
|
+
let p = p$[i];
|
|
276
|
+
if (p.import) {
|
|
277
|
+
const importDoc = p.import;
|
|
278
|
+
const unscoped = p.hasAttribute(SHADY_UNSCOPED_ATTR);
|
|
279
|
+
if (unscoped && !importDoc._unscopedStyle) {
|
|
280
|
+
const style = styleForImport(importDoc);
|
|
281
|
+
style.setAttribute(SHADY_UNSCOPED_ATTR, "");
|
|
282
|
+
importDoc._unscopedStyle = style;
|
|
283
|
+
} else if (!importDoc._style) {
|
|
284
|
+
importDoc._style = styleForImport(importDoc);
|
|
285
|
+
}
|
|
286
|
+
styles.push(unscoped ? importDoc._unscopedStyle : importDoc._style);
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
return styles;
|
|
290
|
+
}
|
|
291
|
+
function cssFromModules(moduleIds) {
|
|
292
|
+
let modules2 = moduleIds.trim().split(/\s+/);
|
|
293
|
+
let cssText = "";
|
|
294
|
+
for (let i = 0; i < modules2.length; i++) {
|
|
295
|
+
cssText += cssFromModule(modules2[i]);
|
|
296
|
+
}
|
|
297
|
+
return cssText;
|
|
298
|
+
}
|
|
299
|
+
function cssFromModule(moduleId) {
|
|
300
|
+
let m = importModule(moduleId);
|
|
301
|
+
if (m && m._cssText === void 0) {
|
|
302
|
+
let cssText = _cssFromModuleImports(m);
|
|
303
|
+
let t = (
|
|
304
|
+
/** @type {?HTMLTemplateElement} */
|
|
305
|
+
m.querySelector("template")
|
|
306
|
+
);
|
|
307
|
+
if (t) {
|
|
308
|
+
cssText += cssFromTemplate(
|
|
309
|
+
t,
|
|
310
|
+
/** @type {templateWithAssetPath} */
|
|
311
|
+
m.assetpath
|
|
312
|
+
);
|
|
313
|
+
}
|
|
314
|
+
m._cssText = cssText || null;
|
|
315
|
+
}
|
|
316
|
+
if (!m) {
|
|
317
|
+
console.warn("Could not find style data in module named", moduleId);
|
|
318
|
+
}
|
|
319
|
+
return m && m._cssText || "";
|
|
320
|
+
}
|
|
321
|
+
function cssFromTemplate(template, baseURI) {
|
|
322
|
+
let cssText = "";
|
|
323
|
+
const e$ = stylesFromTemplate(template, baseURI);
|
|
324
|
+
for (let i = 0; i < e$.length; i++) {
|
|
325
|
+
let e = e$[i];
|
|
326
|
+
if (e.parentNode) {
|
|
327
|
+
e.parentNode.removeChild(e);
|
|
328
|
+
}
|
|
329
|
+
cssText += e.textContent;
|
|
330
|
+
}
|
|
331
|
+
return cssText;
|
|
332
|
+
}
|
|
333
|
+
function _cssFromModuleImports(module) {
|
|
334
|
+
let cssText = "";
|
|
335
|
+
let styles = _stylesFromModuleImports(module);
|
|
336
|
+
for (let i = 0; i < styles.length; i++) {
|
|
337
|
+
cssText += styles[i].textContent;
|
|
338
|
+
}
|
|
339
|
+
return cssText;
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
// ../../../node_modules/@polymer/polymer/lib/utils/wrap.js
|
|
343
|
+
var wrap = window["ShadyDOM"] && window["ShadyDOM"]["noPatch"] && window["ShadyDOM"]["wrap"] ? window["ShadyDOM"]["wrap"] : window["ShadyDOM"] ? (n) => ShadyDOM["patch"](n) : (n) => n;
|
|
344
|
+
|
|
345
|
+
// ../../../node_modules/@polymer/polymer/lib/utils/path.js
|
|
346
|
+
function isPath(path) {
|
|
347
|
+
return path.indexOf(".") >= 0;
|
|
348
|
+
}
|
|
349
|
+
function root(path) {
|
|
350
|
+
let dotIndex = path.indexOf(".");
|
|
351
|
+
if (dotIndex === -1) {
|
|
352
|
+
return path;
|
|
353
|
+
}
|
|
354
|
+
return path.slice(0, dotIndex);
|
|
355
|
+
}
|
|
356
|
+
function isAncestor(base, path) {
|
|
357
|
+
return base.indexOf(path + ".") === 0;
|
|
358
|
+
}
|
|
359
|
+
function isDescendant(base, path) {
|
|
360
|
+
return path.indexOf(base + ".") === 0;
|
|
361
|
+
}
|
|
362
|
+
function translate(base, newBase, path) {
|
|
363
|
+
return newBase + path.slice(base.length);
|
|
364
|
+
}
|
|
365
|
+
function matches(base, path) {
|
|
366
|
+
return base === path || isAncestor(base, path) || isDescendant(base, path);
|
|
367
|
+
}
|
|
368
|
+
function normalize(path) {
|
|
369
|
+
if (Array.isArray(path)) {
|
|
370
|
+
let parts = [];
|
|
371
|
+
for (let i = 0; i < path.length; i++) {
|
|
372
|
+
let args = path[i].toString().split(".");
|
|
373
|
+
for (let j = 0; j < args.length; j++) {
|
|
374
|
+
parts.push(args[j]);
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
return parts.join(".");
|
|
378
|
+
} else {
|
|
379
|
+
return path;
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
function split(path) {
|
|
383
|
+
if (Array.isArray(path)) {
|
|
384
|
+
return normalize(path).split(".");
|
|
385
|
+
}
|
|
386
|
+
return path.toString().split(".");
|
|
387
|
+
}
|
|
388
|
+
function get(root2, path, info) {
|
|
389
|
+
let prop = root2;
|
|
390
|
+
let parts = split(path);
|
|
391
|
+
for (let i = 0; i < parts.length; i++) {
|
|
392
|
+
if (!prop) {
|
|
393
|
+
return;
|
|
394
|
+
}
|
|
395
|
+
let part = parts[i];
|
|
396
|
+
prop = prop[part];
|
|
397
|
+
}
|
|
398
|
+
if (info) {
|
|
399
|
+
info.path = parts.join(".");
|
|
400
|
+
}
|
|
401
|
+
return prop;
|
|
402
|
+
}
|
|
403
|
+
function set(root2, path, value) {
|
|
404
|
+
let prop = root2;
|
|
405
|
+
let parts = split(path);
|
|
406
|
+
let last = parts[parts.length - 1];
|
|
407
|
+
if (parts.length > 1) {
|
|
408
|
+
for (let i = 0; i < parts.length - 1; i++) {
|
|
409
|
+
let part = parts[i];
|
|
410
|
+
prop = prop[part];
|
|
411
|
+
if (!prop) {
|
|
412
|
+
return;
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
prop[last] = value;
|
|
416
|
+
} else {
|
|
417
|
+
prop[path] = value;
|
|
418
|
+
}
|
|
419
|
+
return parts.join(".");
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
// ../../../node_modules/@polymer/polymer/lib/utils/case-map.js
|
|
423
|
+
var caseMap = {};
|
|
424
|
+
var DASH_TO_CAMEL = /-[a-z]/g;
|
|
425
|
+
var CAMEL_TO_DASH = /([A-Z])/g;
|
|
426
|
+
function dashToCamelCase(dash) {
|
|
427
|
+
return caseMap[dash] || (caseMap[dash] = dash.indexOf("-") < 0 ? dash : dash.replace(
|
|
428
|
+
DASH_TO_CAMEL,
|
|
429
|
+
(m) => m[1].toUpperCase()
|
|
430
|
+
));
|
|
431
|
+
}
|
|
432
|
+
function camelToDashCase(camel) {
|
|
433
|
+
return caseMap[camel] || (caseMap[camel] = camel.replace(CAMEL_TO_DASH, "-$1").toLowerCase());
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
// ../../../node_modules/@polymer/polymer/lib/utils/async.js
|
|
437
|
+
var microtaskCurrHandle = 0;
|
|
438
|
+
var microtaskLastHandle = 0;
|
|
439
|
+
var microtaskCallbacks = [];
|
|
440
|
+
var microtaskNodeContent = 0;
|
|
441
|
+
var microtaskScheduled = false;
|
|
442
|
+
var microtaskNode = document.createTextNode("");
|
|
443
|
+
new window.MutationObserver(microtaskFlush).observe(microtaskNode, { characterData: true });
|
|
444
|
+
function microtaskFlush() {
|
|
445
|
+
microtaskScheduled = false;
|
|
446
|
+
const len = microtaskCallbacks.length;
|
|
447
|
+
for (let i = 0; i < len; i++) {
|
|
448
|
+
let cb = microtaskCallbacks[i];
|
|
449
|
+
if (cb) {
|
|
450
|
+
try {
|
|
451
|
+
cb();
|
|
452
|
+
} catch (e) {
|
|
453
|
+
setTimeout(() => {
|
|
454
|
+
throw e;
|
|
455
|
+
});
|
|
456
|
+
}
|
|
457
|
+
}
|
|
458
|
+
}
|
|
459
|
+
microtaskCallbacks.splice(0, len);
|
|
460
|
+
microtaskLastHandle += len;
|
|
461
|
+
}
|
|
462
|
+
var timeOut = {
|
|
463
|
+
/**
|
|
464
|
+
* Returns a sub-module with the async interface providing the provided
|
|
465
|
+
* delay.
|
|
466
|
+
*
|
|
467
|
+
* @memberof timeOut
|
|
468
|
+
* @param {number=} delay Time to wait before calling callbacks in ms
|
|
469
|
+
* @return {!AsyncInterface} An async timeout interface
|
|
470
|
+
*/
|
|
471
|
+
after(delay) {
|
|
472
|
+
return {
|
|
473
|
+
run(fn) {
|
|
474
|
+
return window.setTimeout(fn, delay);
|
|
475
|
+
},
|
|
476
|
+
cancel(handle) {
|
|
477
|
+
window.clearTimeout(handle);
|
|
478
|
+
}
|
|
479
|
+
};
|
|
480
|
+
},
|
|
481
|
+
/**
|
|
482
|
+
* Enqueues a function called in the next task.
|
|
483
|
+
*
|
|
484
|
+
* @memberof timeOut
|
|
485
|
+
* @param {!Function} fn Callback to run
|
|
486
|
+
* @param {number=} delay Delay in milliseconds
|
|
487
|
+
* @return {number} Handle used for canceling task
|
|
488
|
+
*/
|
|
489
|
+
run(fn, delay) {
|
|
490
|
+
return window.setTimeout(fn, delay);
|
|
491
|
+
},
|
|
492
|
+
/**
|
|
493
|
+
* Cancels a previously enqueued `timeOut` callback.
|
|
494
|
+
*
|
|
495
|
+
* @memberof timeOut
|
|
496
|
+
* @param {number} handle Handle returned from `run` of callback to cancel
|
|
497
|
+
* @return {void}
|
|
498
|
+
*/
|
|
499
|
+
cancel(handle) {
|
|
500
|
+
window.clearTimeout(handle);
|
|
501
|
+
}
|
|
502
|
+
};
|
|
503
|
+
var microTask = {
|
|
504
|
+
/**
|
|
505
|
+
* Enqueues a function called at microtask timing.
|
|
506
|
+
*
|
|
507
|
+
* @memberof microTask
|
|
508
|
+
* @param {!Function=} callback Callback to run
|
|
509
|
+
* @return {number} Handle used for canceling task
|
|
510
|
+
*/
|
|
511
|
+
run(callback) {
|
|
512
|
+
if (!microtaskScheduled) {
|
|
513
|
+
microtaskScheduled = true;
|
|
514
|
+
microtaskNode.textContent = microtaskNodeContent++;
|
|
515
|
+
}
|
|
516
|
+
microtaskCallbacks.push(callback);
|
|
517
|
+
return microtaskCurrHandle++;
|
|
518
|
+
},
|
|
519
|
+
/**
|
|
520
|
+
* Cancels a previously enqueued `microTask` callback.
|
|
521
|
+
*
|
|
522
|
+
* @memberof microTask
|
|
523
|
+
* @param {number} handle Handle returned from `run` of callback to cancel
|
|
524
|
+
* @return {void}
|
|
525
|
+
*/
|
|
526
|
+
cancel(handle) {
|
|
527
|
+
const idx = handle - microtaskLastHandle;
|
|
528
|
+
if (idx >= 0) {
|
|
529
|
+
if (!microtaskCallbacks[idx]) {
|
|
530
|
+
throw new Error("invalid async handle: " + handle);
|
|
531
|
+
}
|
|
532
|
+
microtaskCallbacks[idx] = null;
|
|
533
|
+
}
|
|
534
|
+
}
|
|
535
|
+
};
|
|
536
|
+
|
|
537
|
+
// ../../../node_modules/@polymer/polymer/lib/mixins/properties-changed.js
|
|
538
|
+
var microtask = microTask;
|
|
539
|
+
var PropertiesChanged = dedupingMixin(
|
|
540
|
+
/**
|
|
541
|
+
* @template T
|
|
542
|
+
* @param {function(new:T)} superClass Class to apply mixin to.
|
|
543
|
+
* @return {function(new:T)} superClass with mixin applied.
|
|
544
|
+
*/
|
|
545
|
+
(superClass) => {
|
|
546
|
+
class PropertiesChanged2 extends superClass {
|
|
547
|
+
/**
|
|
548
|
+
* Creates property accessors for the given property names.
|
|
549
|
+
* @param {!Object} props Object whose keys are names of accessors.
|
|
550
|
+
* @return {void}
|
|
551
|
+
* @protected
|
|
552
|
+
* @nocollapse
|
|
553
|
+
*/
|
|
554
|
+
static createProperties(props) {
|
|
555
|
+
const proto2 = this.prototype;
|
|
556
|
+
for (let prop in props) {
|
|
557
|
+
if (!(prop in proto2)) {
|
|
558
|
+
proto2._createPropertyAccessor(prop);
|
|
559
|
+
}
|
|
560
|
+
}
|
|
561
|
+
}
|
|
562
|
+
/**
|
|
563
|
+
* Returns an attribute name that corresponds to the given property.
|
|
564
|
+
* The attribute name is the lowercased property name. Override to
|
|
565
|
+
* customize this mapping.
|
|
566
|
+
* @param {string} property Property to convert
|
|
567
|
+
* @return {string} Attribute name corresponding to the given property.
|
|
568
|
+
*
|
|
569
|
+
* @protected
|
|
570
|
+
* @nocollapse
|
|
571
|
+
*/
|
|
572
|
+
static attributeNameForProperty(property) {
|
|
573
|
+
return property.toLowerCase();
|
|
574
|
+
}
|
|
575
|
+
/**
|
|
576
|
+
* Override point to provide a type to which to deserialize a value to
|
|
577
|
+
* a given property.
|
|
578
|
+
* @param {string} name Name of property
|
|
579
|
+
*
|
|
580
|
+
* @protected
|
|
581
|
+
* @nocollapse
|
|
582
|
+
*/
|
|
583
|
+
static typeForProperty(name) {
|
|
584
|
+
}
|
|
585
|
+
//eslint-disable-line no-unused-vars
|
|
586
|
+
/**
|
|
587
|
+
* Creates a setter/getter pair for the named property with its own
|
|
588
|
+
* local storage. The getter returns the value in the local storage,
|
|
589
|
+
* and the setter calls `_setProperty`, which updates the local storage
|
|
590
|
+
* for the property and enqueues a `_propertiesChanged` callback.
|
|
591
|
+
*
|
|
592
|
+
* This method may be called on a prototype or an instance. Calling
|
|
593
|
+
* this method may overwrite a property value that already exists on
|
|
594
|
+
* the prototype/instance by creating the accessor.
|
|
595
|
+
*
|
|
596
|
+
* @param {string} property Name of the property
|
|
597
|
+
* @param {boolean=} readOnly When true, no setter is created; the
|
|
598
|
+
* protected `_setProperty` function must be used to set the property
|
|
599
|
+
* @return {void}
|
|
600
|
+
* @protected
|
|
601
|
+
* @override
|
|
602
|
+
*/
|
|
603
|
+
_createPropertyAccessor(property, readOnly) {
|
|
604
|
+
this._addPropertyToAttributeMap(property);
|
|
605
|
+
if (!this.hasOwnProperty(JSCompiler_renameProperty("__dataHasAccessor", this))) {
|
|
606
|
+
this.__dataHasAccessor = Object.assign({}, this.__dataHasAccessor);
|
|
607
|
+
}
|
|
608
|
+
if (!this.__dataHasAccessor[property]) {
|
|
609
|
+
this.__dataHasAccessor[property] = true;
|
|
610
|
+
this._definePropertyAccessor(property, readOnly);
|
|
611
|
+
}
|
|
612
|
+
}
|
|
613
|
+
/**
|
|
614
|
+
* Adds the given `property` to a map matching attribute names
|
|
615
|
+
* to property names, using `attributeNameForProperty`. This map is
|
|
616
|
+
* used when deserializing attribute values to properties.
|
|
617
|
+
*
|
|
618
|
+
* @param {string} property Name of the property
|
|
619
|
+
* @override
|
|
620
|
+
*/
|
|
621
|
+
_addPropertyToAttributeMap(property) {
|
|
622
|
+
if (!this.hasOwnProperty(JSCompiler_renameProperty("__dataAttributes", this))) {
|
|
623
|
+
this.__dataAttributes = Object.assign({}, this.__dataAttributes);
|
|
624
|
+
}
|
|
625
|
+
let attr = this.__dataAttributes[property];
|
|
626
|
+
if (!attr) {
|
|
627
|
+
attr = this.constructor.attributeNameForProperty(property);
|
|
628
|
+
this.__dataAttributes[attr] = property;
|
|
629
|
+
}
|
|
630
|
+
return attr;
|
|
631
|
+
}
|
|
632
|
+
/**
|
|
633
|
+
* Defines a property accessor for the given property.
|
|
634
|
+
* @param {string} property Name of the property
|
|
635
|
+
* @param {boolean=} readOnly When true, no setter is created
|
|
636
|
+
* @return {void}
|
|
637
|
+
* @override
|
|
638
|
+
*/
|
|
639
|
+
_definePropertyAccessor(property, readOnly) {
|
|
640
|
+
Object.defineProperty(this, property, {
|
|
641
|
+
/* eslint-disable valid-jsdoc */
|
|
642
|
+
/** @this {PropertiesChanged} */
|
|
643
|
+
get() {
|
|
644
|
+
return this.__data[property];
|
|
645
|
+
},
|
|
646
|
+
/** @this {PropertiesChanged} */
|
|
647
|
+
set: readOnly ? function() {
|
|
648
|
+
} : function(value) {
|
|
649
|
+
if (this._setPendingProperty(property, value, true)) {
|
|
650
|
+
this._invalidateProperties();
|
|
651
|
+
}
|
|
652
|
+
}
|
|
653
|
+
/* eslint-enable */
|
|
654
|
+
});
|
|
655
|
+
}
|
|
656
|
+
constructor() {
|
|
657
|
+
super();
|
|
658
|
+
this.__dataEnabled = false;
|
|
659
|
+
this.__dataReady = false;
|
|
660
|
+
this.__dataInvalid = false;
|
|
661
|
+
this.__data = {};
|
|
662
|
+
this.__dataPending = null;
|
|
663
|
+
this.__dataOld = null;
|
|
664
|
+
this.__dataInstanceProps = null;
|
|
665
|
+
this.__dataCounter = 0;
|
|
666
|
+
this.__serializing = false;
|
|
667
|
+
this._initializeProperties();
|
|
668
|
+
}
|
|
669
|
+
/**
|
|
670
|
+
* Lifecycle callback called when properties are enabled via
|
|
671
|
+
* `_enableProperties`.
|
|
672
|
+
*
|
|
673
|
+
* Users may override this function to implement behavior that is
|
|
674
|
+
* dependent on the element having its property data initialized, e.g.
|
|
675
|
+
* from defaults (initialized from `constructor`, `_initializeProperties`),
|
|
676
|
+
* `attributeChangedCallback`, or values propagated from host e.g. via
|
|
677
|
+
* bindings. `super.ready()` must be called to ensure the data system
|
|
678
|
+
* becomes enabled.
|
|
679
|
+
*
|
|
680
|
+
* @return {void}
|
|
681
|
+
* @public
|
|
682
|
+
* @override
|
|
683
|
+
*/
|
|
684
|
+
ready() {
|
|
685
|
+
this.__dataReady = true;
|
|
686
|
+
this._flushProperties();
|
|
687
|
+
}
|
|
688
|
+
/**
|
|
689
|
+
* Initializes the local storage for property accessors.
|
|
690
|
+
*
|
|
691
|
+
* Provided as an override point for performing any setup work prior
|
|
692
|
+
* to initializing the property accessor system.
|
|
693
|
+
*
|
|
694
|
+
* @return {void}
|
|
695
|
+
* @protected
|
|
696
|
+
* @override
|
|
697
|
+
*/
|
|
698
|
+
_initializeProperties() {
|
|
699
|
+
for (let p in this.__dataHasAccessor) {
|
|
700
|
+
if (this.hasOwnProperty(p)) {
|
|
701
|
+
this.__dataInstanceProps = this.__dataInstanceProps || {};
|
|
702
|
+
this.__dataInstanceProps[p] = this[p];
|
|
703
|
+
delete this[p];
|
|
704
|
+
}
|
|
705
|
+
}
|
|
706
|
+
}
|
|
707
|
+
/**
|
|
708
|
+
* Called at ready time with bag of instance properties that overwrote
|
|
709
|
+
* accessors when the element upgraded.
|
|
710
|
+
*
|
|
711
|
+
* The default implementation sets these properties back into the
|
|
712
|
+
* setter at ready time. This method is provided as an override
|
|
713
|
+
* point for customizing or providing more efficient initialization.
|
|
714
|
+
*
|
|
715
|
+
* @param {Object} props Bag of property values that were overwritten
|
|
716
|
+
* when creating property accessors.
|
|
717
|
+
* @return {void}
|
|
718
|
+
* @protected
|
|
719
|
+
* @override
|
|
720
|
+
*/
|
|
721
|
+
_initializeInstanceProperties(props) {
|
|
722
|
+
Object.assign(this, props);
|
|
723
|
+
}
|
|
724
|
+
/**
|
|
725
|
+
* Updates the local storage for a property (via `_setPendingProperty`)
|
|
726
|
+
* and enqueues a `_proeprtiesChanged` callback.
|
|
727
|
+
*
|
|
728
|
+
* @param {string} property Name of the property
|
|
729
|
+
* @param {*} value Value to set
|
|
730
|
+
* @return {void}
|
|
731
|
+
* @protected
|
|
732
|
+
* @override
|
|
733
|
+
*/
|
|
734
|
+
_setProperty(property, value) {
|
|
735
|
+
if (this._setPendingProperty(property, value)) {
|
|
736
|
+
this._invalidateProperties();
|
|
737
|
+
}
|
|
738
|
+
}
|
|
739
|
+
/**
|
|
740
|
+
* Returns the value for the given property.
|
|
741
|
+
* @param {string} property Name of property
|
|
742
|
+
* @return {*} Value for the given property
|
|
743
|
+
* @protected
|
|
744
|
+
* @override
|
|
745
|
+
*/
|
|
746
|
+
_getProperty(property) {
|
|
747
|
+
return this.__data[property];
|
|
748
|
+
}
|
|
749
|
+
/* eslint-disable no-unused-vars */
|
|
750
|
+
/**
|
|
751
|
+
* Updates the local storage for a property, records the previous value,
|
|
752
|
+
* and adds it to the set of "pending changes" that will be passed to the
|
|
753
|
+
* `_propertiesChanged` callback. This method does not enqueue the
|
|
754
|
+
* `_propertiesChanged` callback.
|
|
755
|
+
*
|
|
756
|
+
* @param {string} property Name of the property
|
|
757
|
+
* @param {*} value Value to set
|
|
758
|
+
* @param {boolean=} ext Not used here; affordance for closure
|
|
759
|
+
* @return {boolean} Returns true if the property changed
|
|
760
|
+
* @protected
|
|
761
|
+
* @override
|
|
762
|
+
*/
|
|
763
|
+
_setPendingProperty(property, value, ext) {
|
|
764
|
+
let old = this.__data[property];
|
|
765
|
+
let changed = this._shouldPropertyChange(property, value, old);
|
|
766
|
+
if (changed) {
|
|
767
|
+
if (!this.__dataPending) {
|
|
768
|
+
this.__dataPending = {};
|
|
769
|
+
this.__dataOld = {};
|
|
770
|
+
}
|
|
771
|
+
if (this.__dataOld && !(property in this.__dataOld)) {
|
|
772
|
+
this.__dataOld[property] = old;
|
|
773
|
+
}
|
|
774
|
+
this.__data[property] = value;
|
|
775
|
+
this.__dataPending[property] = value;
|
|
776
|
+
}
|
|
777
|
+
return changed;
|
|
778
|
+
}
|
|
779
|
+
/* eslint-enable */
|
|
780
|
+
/**
|
|
781
|
+
* @param {string} property Name of the property
|
|
782
|
+
* @return {boolean} Returns true if the property is pending.
|
|
783
|
+
*/
|
|
784
|
+
_isPropertyPending(property) {
|
|
785
|
+
return !!(this.__dataPending && this.__dataPending.hasOwnProperty(property));
|
|
786
|
+
}
|
|
787
|
+
/**
|
|
788
|
+
* Marks the properties as invalid, and enqueues an async
|
|
789
|
+
* `_propertiesChanged` callback.
|
|
790
|
+
*
|
|
791
|
+
* @return {void}
|
|
792
|
+
* @protected
|
|
793
|
+
* @override
|
|
794
|
+
*/
|
|
795
|
+
_invalidateProperties() {
|
|
796
|
+
if (!this.__dataInvalid && this.__dataReady) {
|
|
797
|
+
this.__dataInvalid = true;
|
|
798
|
+
microtask.run(() => {
|
|
799
|
+
if (this.__dataInvalid) {
|
|
800
|
+
this.__dataInvalid = false;
|
|
801
|
+
this._flushProperties();
|
|
802
|
+
}
|
|
803
|
+
});
|
|
804
|
+
}
|
|
805
|
+
}
|
|
806
|
+
/**
|
|
807
|
+
* Call to enable property accessor processing. Before this method is
|
|
808
|
+
* called accessor values will be set but side effects are
|
|
809
|
+
* queued. When called, any pending side effects occur immediately.
|
|
810
|
+
* For elements, generally `connectedCallback` is a normal spot to do so.
|
|
811
|
+
* It is safe to call this method multiple times as it only turns on
|
|
812
|
+
* property accessors once.
|
|
813
|
+
*
|
|
814
|
+
* @return {void}
|
|
815
|
+
* @protected
|
|
816
|
+
* @override
|
|
817
|
+
*/
|
|
818
|
+
_enableProperties() {
|
|
819
|
+
if (!this.__dataEnabled) {
|
|
820
|
+
this.__dataEnabled = true;
|
|
821
|
+
if (this.__dataInstanceProps) {
|
|
822
|
+
this._initializeInstanceProperties(this.__dataInstanceProps);
|
|
823
|
+
this.__dataInstanceProps = null;
|
|
824
|
+
}
|
|
825
|
+
this.ready();
|
|
826
|
+
}
|
|
827
|
+
}
|
|
828
|
+
/**
|
|
829
|
+
* Calls the `_propertiesChanged` callback with the current set of
|
|
830
|
+
* pending changes (and old values recorded when pending changes were
|
|
831
|
+
* set), and resets the pending set of changes. Generally, this method
|
|
832
|
+
* should not be called in user code.
|
|
833
|
+
*
|
|
834
|
+
* @return {void}
|
|
835
|
+
* @protected
|
|
836
|
+
* @override
|
|
837
|
+
*/
|
|
838
|
+
_flushProperties() {
|
|
839
|
+
this.__dataCounter++;
|
|
840
|
+
const props = this.__data;
|
|
841
|
+
const changedProps = this.__dataPending;
|
|
842
|
+
const old = this.__dataOld;
|
|
843
|
+
if (this._shouldPropertiesChange(props, changedProps, old)) {
|
|
844
|
+
this.__dataPending = null;
|
|
845
|
+
this.__dataOld = null;
|
|
846
|
+
this._propertiesChanged(props, changedProps, old);
|
|
847
|
+
}
|
|
848
|
+
this.__dataCounter--;
|
|
849
|
+
}
|
|
850
|
+
/**
|
|
851
|
+
* Called in `_flushProperties` to determine if `_propertiesChanged`
|
|
852
|
+
* should be called. The default implementation returns true if
|
|
853
|
+
* properties are pending. Override to customize when
|
|
854
|
+
* `_propertiesChanged` is called.
|
|
855
|
+
* @param {!Object} currentProps Bag of all current accessor values
|
|
856
|
+
* @param {?Object} changedProps Bag of properties changed since the last
|
|
857
|
+
* call to `_propertiesChanged`
|
|
858
|
+
* @param {?Object} oldProps Bag of previous values for each property
|
|
859
|
+
* in `changedProps`
|
|
860
|
+
* @return {boolean} true if changedProps is truthy
|
|
861
|
+
* @override
|
|
862
|
+
*/
|
|
863
|
+
_shouldPropertiesChange(currentProps, changedProps, oldProps) {
|
|
864
|
+
return Boolean(changedProps);
|
|
865
|
+
}
|
|
866
|
+
/**
|
|
867
|
+
* Callback called when any properties with accessors created via
|
|
868
|
+
* `_createPropertyAccessor` have been set.
|
|
869
|
+
*
|
|
870
|
+
* @param {!Object} currentProps Bag of all current accessor values
|
|
871
|
+
* @param {?Object} changedProps Bag of properties changed since the last
|
|
872
|
+
* call to `_propertiesChanged`
|
|
873
|
+
* @param {?Object} oldProps Bag of previous values for each property
|
|
874
|
+
* in `changedProps`
|
|
875
|
+
* @return {void}
|
|
876
|
+
* @protected
|
|
877
|
+
* @override
|
|
878
|
+
*/
|
|
879
|
+
_propertiesChanged(currentProps, changedProps, oldProps) {
|
|
880
|
+
}
|
|
881
|
+
/**
|
|
882
|
+
* Method called to determine whether a property value should be
|
|
883
|
+
* considered as a change and cause the `_propertiesChanged` callback
|
|
884
|
+
* to be enqueued.
|
|
885
|
+
*
|
|
886
|
+
* The default implementation returns `true` if a strict equality
|
|
887
|
+
* check fails. The method always returns false for `NaN`.
|
|
888
|
+
*
|
|
889
|
+
* Override this method to e.g. provide stricter checking for
|
|
890
|
+
* Objects/Arrays when using immutable patterns.
|
|
891
|
+
*
|
|
892
|
+
* @param {string} property Property name
|
|
893
|
+
* @param {*} value New property value
|
|
894
|
+
* @param {*} old Previous property value
|
|
895
|
+
* @return {boolean} Whether the property should be considered a change
|
|
896
|
+
* and enqueue a `_proeprtiesChanged` callback
|
|
897
|
+
* @protected
|
|
898
|
+
* @override
|
|
899
|
+
*/
|
|
900
|
+
_shouldPropertyChange(property, value, old) {
|
|
901
|
+
return (
|
|
902
|
+
// Strict equality check
|
|
903
|
+
old !== value && // This ensures (old==NaN, value==NaN) always returns false
|
|
904
|
+
(old === old || value === value)
|
|
905
|
+
);
|
|
906
|
+
}
|
|
907
|
+
/**
|
|
908
|
+
* Implements native Custom Elements `attributeChangedCallback` to
|
|
909
|
+
* set an attribute value to a property via `_attributeToProperty`.
|
|
910
|
+
*
|
|
911
|
+
* @param {string} name Name of attribute that changed
|
|
912
|
+
* @param {?string} old Old attribute value
|
|
913
|
+
* @param {?string} value New attribute value
|
|
914
|
+
* @param {?string} namespace Attribute namespace.
|
|
915
|
+
* @return {void}
|
|
916
|
+
* @suppress {missingProperties} Super may or may not implement the callback
|
|
917
|
+
* @override
|
|
918
|
+
*/
|
|
919
|
+
attributeChangedCallback(name, old, value, namespace) {
|
|
920
|
+
if (old !== value) {
|
|
921
|
+
this._attributeToProperty(name, value);
|
|
922
|
+
}
|
|
923
|
+
if (super.attributeChangedCallback) {
|
|
924
|
+
super.attributeChangedCallback(name, old, value, namespace);
|
|
925
|
+
}
|
|
926
|
+
}
|
|
927
|
+
/**
|
|
928
|
+
* Deserializes an attribute to its associated property.
|
|
929
|
+
*
|
|
930
|
+
* This method calls the `_deserializeValue` method to convert the string to
|
|
931
|
+
* a typed value.
|
|
932
|
+
*
|
|
933
|
+
* @param {string} attribute Name of attribute to deserialize.
|
|
934
|
+
* @param {?string} value of the attribute.
|
|
935
|
+
* @param {*=} type type to deserialize to, defaults to the value
|
|
936
|
+
* returned from `typeForProperty`
|
|
937
|
+
* @return {void}
|
|
938
|
+
* @override
|
|
939
|
+
*/
|
|
940
|
+
_attributeToProperty(attribute, value, type) {
|
|
941
|
+
if (!this.__serializing) {
|
|
942
|
+
const map = this.__dataAttributes;
|
|
943
|
+
const property = map && map[attribute] || attribute;
|
|
944
|
+
this[property] = this._deserializeValue(value, type || this.constructor.typeForProperty(property));
|
|
945
|
+
}
|
|
946
|
+
}
|
|
947
|
+
/**
|
|
948
|
+
* Serializes a property to its associated attribute.
|
|
949
|
+
*
|
|
950
|
+
* @suppress {invalidCasts} Closure can't figure out `this` is an element.
|
|
951
|
+
*
|
|
952
|
+
* @param {string} property Property name to reflect.
|
|
953
|
+
* @param {string=} attribute Attribute name to reflect to.
|
|
954
|
+
* @param {*=} value Property value to refect.
|
|
955
|
+
* @return {void}
|
|
956
|
+
* @override
|
|
957
|
+
*/
|
|
958
|
+
_propertyToAttribute(property, attribute, value) {
|
|
959
|
+
this.__serializing = true;
|
|
960
|
+
value = arguments.length < 3 ? this[property] : value;
|
|
961
|
+
this._valueToNodeAttribute(
|
|
962
|
+
/** @type {!HTMLElement} */
|
|
963
|
+
this,
|
|
964
|
+
value,
|
|
965
|
+
attribute || this.constructor.attributeNameForProperty(property)
|
|
966
|
+
);
|
|
967
|
+
this.__serializing = false;
|
|
968
|
+
}
|
|
969
|
+
/**
|
|
970
|
+
* Sets a typed value to an HTML attribute on a node.
|
|
971
|
+
*
|
|
972
|
+
* This method calls the `_serializeValue` method to convert the typed
|
|
973
|
+
* value to a string. If the `_serializeValue` method returns `undefined`,
|
|
974
|
+
* the attribute will be removed (this is the default for boolean
|
|
975
|
+
* type `false`).
|
|
976
|
+
*
|
|
977
|
+
* @param {Element} node Element to set attribute to.
|
|
978
|
+
* @param {*} value Value to serialize.
|
|
979
|
+
* @param {string} attribute Attribute name to serialize to.
|
|
980
|
+
* @return {void}
|
|
981
|
+
* @override
|
|
982
|
+
*/
|
|
983
|
+
_valueToNodeAttribute(node, value, attribute) {
|
|
984
|
+
const str = this._serializeValue(value);
|
|
985
|
+
if (attribute === "class" || attribute === "name" || attribute === "slot") {
|
|
986
|
+
node = /** @type {?Element} */
|
|
987
|
+
wrap(node);
|
|
988
|
+
}
|
|
989
|
+
if (str === void 0) {
|
|
990
|
+
node.removeAttribute(attribute);
|
|
991
|
+
} else {
|
|
992
|
+
node.setAttribute(
|
|
993
|
+
attribute,
|
|
994
|
+
// Closure's type for `setAttribute`'s second parameter incorrectly
|
|
995
|
+
// excludes `TrustedScript`.
|
|
996
|
+
str === "" && window.trustedTypes ? (
|
|
997
|
+
/** @type {?} */
|
|
998
|
+
window.trustedTypes.emptyScript
|
|
999
|
+
) : str
|
|
1000
|
+
);
|
|
1001
|
+
}
|
|
1002
|
+
}
|
|
1003
|
+
/**
|
|
1004
|
+
* Converts a typed JavaScript value to a string.
|
|
1005
|
+
*
|
|
1006
|
+
* This method is called when setting JS property values to
|
|
1007
|
+
* HTML attributes. Users may override this method to provide
|
|
1008
|
+
* serialization for custom types.
|
|
1009
|
+
*
|
|
1010
|
+
* @param {*} value Property value to serialize.
|
|
1011
|
+
* @return {string | undefined} String serialized from the provided
|
|
1012
|
+
* property value.
|
|
1013
|
+
* @override
|
|
1014
|
+
*/
|
|
1015
|
+
_serializeValue(value) {
|
|
1016
|
+
switch (typeof value) {
|
|
1017
|
+
case "boolean":
|
|
1018
|
+
return value ? "" : void 0;
|
|
1019
|
+
default:
|
|
1020
|
+
return value != null ? value.toString() : void 0;
|
|
1021
|
+
}
|
|
1022
|
+
}
|
|
1023
|
+
/**
|
|
1024
|
+
* Converts a string to a typed JavaScript value.
|
|
1025
|
+
*
|
|
1026
|
+
* This method is called when reading HTML attribute values to
|
|
1027
|
+
* JS properties. Users may override this method to provide
|
|
1028
|
+
* deserialization for custom `type`s. Types for `Boolean`, `String`,
|
|
1029
|
+
* and `Number` convert attributes to the expected types.
|
|
1030
|
+
*
|
|
1031
|
+
* @param {?string} value Value to deserialize.
|
|
1032
|
+
* @param {*=} type Type to deserialize the string to.
|
|
1033
|
+
* @return {*} Typed value deserialized from the provided string.
|
|
1034
|
+
* @override
|
|
1035
|
+
*/
|
|
1036
|
+
_deserializeValue(value, type) {
|
|
1037
|
+
switch (type) {
|
|
1038
|
+
case Boolean:
|
|
1039
|
+
return value !== null;
|
|
1040
|
+
case Number:
|
|
1041
|
+
return Number(value);
|
|
1042
|
+
default:
|
|
1043
|
+
return value;
|
|
1044
|
+
}
|
|
1045
|
+
}
|
|
1046
|
+
}
|
|
1047
|
+
return PropertiesChanged2;
|
|
1048
|
+
}
|
|
1049
|
+
);
|
|
1050
|
+
|
|
1051
|
+
// ../../../node_modules/@polymer/polymer/lib/mixins/property-accessors.js
|
|
1052
|
+
var nativeProperties = {};
|
|
1053
|
+
var proto = HTMLElement.prototype;
|
|
1054
|
+
while (proto) {
|
|
1055
|
+
let props = Object.getOwnPropertyNames(proto);
|
|
1056
|
+
for (let i = 0; i < props.length; i++) {
|
|
1057
|
+
nativeProperties[props[i]] = true;
|
|
1058
|
+
}
|
|
1059
|
+
proto = Object.getPrototypeOf(proto);
|
|
1060
|
+
}
|
|
1061
|
+
var isTrustedType = (() => {
|
|
1062
|
+
if (!window.trustedTypes) {
|
|
1063
|
+
return () => false;
|
|
1064
|
+
}
|
|
1065
|
+
return (val) => trustedTypes.isHTML(val) || trustedTypes.isScript(val) || trustedTypes.isScriptURL(val);
|
|
1066
|
+
})();
|
|
1067
|
+
function saveAccessorValue(model, property) {
|
|
1068
|
+
if (!nativeProperties[property]) {
|
|
1069
|
+
let value = model[property];
|
|
1070
|
+
if (value !== void 0) {
|
|
1071
|
+
if (model.__data) {
|
|
1072
|
+
model._setPendingProperty(property, value);
|
|
1073
|
+
} else {
|
|
1074
|
+
if (!model.__dataProto) {
|
|
1075
|
+
model.__dataProto = {};
|
|
1076
|
+
} else if (!model.hasOwnProperty(JSCompiler_renameProperty("__dataProto", model))) {
|
|
1077
|
+
model.__dataProto = Object.create(model.__dataProto);
|
|
1078
|
+
}
|
|
1079
|
+
model.__dataProto[property] = value;
|
|
1080
|
+
}
|
|
1081
|
+
}
|
|
1082
|
+
}
|
|
1083
|
+
}
|
|
1084
|
+
var PropertyAccessors = dedupingMixin((superClass) => {
|
|
1085
|
+
const base = PropertiesChanged(superClass);
|
|
1086
|
+
class PropertyAccessors2 extends base {
|
|
1087
|
+
/**
|
|
1088
|
+
* Generates property accessors for all attributes in the standard
|
|
1089
|
+
* static `observedAttributes` array.
|
|
1090
|
+
*
|
|
1091
|
+
* Attribute names are mapped to property names using the `dash-case` to
|
|
1092
|
+
* `camelCase` convention
|
|
1093
|
+
*
|
|
1094
|
+
* @return {void}
|
|
1095
|
+
* @nocollapse
|
|
1096
|
+
*/
|
|
1097
|
+
static createPropertiesForAttributes() {
|
|
1098
|
+
let a$ = (
|
|
1099
|
+
/** @type {?} */
|
|
1100
|
+
this.observedAttributes
|
|
1101
|
+
);
|
|
1102
|
+
for (let i = 0; i < a$.length; i++) {
|
|
1103
|
+
this.prototype._createPropertyAccessor(dashToCamelCase(a$[i]));
|
|
1104
|
+
}
|
|
1105
|
+
}
|
|
1106
|
+
/**
|
|
1107
|
+
* Returns an attribute name that corresponds to the given property.
|
|
1108
|
+
* By default, converts camel to dash case, e.g. `fooBar` to `foo-bar`.
|
|
1109
|
+
* @param {string} property Property to convert
|
|
1110
|
+
* @return {string} Attribute name corresponding to the given property.
|
|
1111
|
+
*
|
|
1112
|
+
* @protected
|
|
1113
|
+
* @nocollapse
|
|
1114
|
+
*/
|
|
1115
|
+
static attributeNameForProperty(property) {
|
|
1116
|
+
return camelToDashCase(property);
|
|
1117
|
+
}
|
|
1118
|
+
/**
|
|
1119
|
+
* Overrides PropertiesChanged implementation to initialize values for
|
|
1120
|
+
* accessors created for values that already existed on the element
|
|
1121
|
+
* prototype.
|
|
1122
|
+
*
|
|
1123
|
+
* @return {void}
|
|
1124
|
+
* @protected
|
|
1125
|
+
* @override
|
|
1126
|
+
*/
|
|
1127
|
+
_initializeProperties() {
|
|
1128
|
+
if (this.__dataProto) {
|
|
1129
|
+
this._initializeProtoProperties(this.__dataProto);
|
|
1130
|
+
this.__dataProto = null;
|
|
1131
|
+
}
|
|
1132
|
+
super._initializeProperties();
|
|
1133
|
+
}
|
|
1134
|
+
/**
|
|
1135
|
+
* Called at instance time with bag of properties that were overwritten
|
|
1136
|
+
* by accessors on the prototype when accessors were created.
|
|
1137
|
+
*
|
|
1138
|
+
* The default implementation sets these properties back into the
|
|
1139
|
+
* setter at instance time. This method is provided as an override
|
|
1140
|
+
* point for customizing or providing more efficient initialization.
|
|
1141
|
+
*
|
|
1142
|
+
* @param {Object} props Bag of property values that were overwritten
|
|
1143
|
+
* when creating property accessors.
|
|
1144
|
+
* @return {void}
|
|
1145
|
+
* @protected
|
|
1146
|
+
* @override
|
|
1147
|
+
*/
|
|
1148
|
+
_initializeProtoProperties(props) {
|
|
1149
|
+
for (let p in props) {
|
|
1150
|
+
this._setProperty(p, props[p]);
|
|
1151
|
+
}
|
|
1152
|
+
}
|
|
1153
|
+
/**
|
|
1154
|
+
* Ensures the element has the given attribute. If it does not,
|
|
1155
|
+
* assigns the given value to the attribute.
|
|
1156
|
+
*
|
|
1157
|
+
* @suppress {invalidCasts} Closure can't figure out `this` is infact an
|
|
1158
|
+
* element
|
|
1159
|
+
*
|
|
1160
|
+
* @param {string} attribute Name of attribute to ensure is set.
|
|
1161
|
+
* @param {string} value of the attribute.
|
|
1162
|
+
* @return {void}
|
|
1163
|
+
* @override
|
|
1164
|
+
*/
|
|
1165
|
+
_ensureAttribute(attribute, value) {
|
|
1166
|
+
const el = (
|
|
1167
|
+
/** @type {!HTMLElement} */
|
|
1168
|
+
this
|
|
1169
|
+
);
|
|
1170
|
+
if (!el.hasAttribute(attribute)) {
|
|
1171
|
+
this._valueToNodeAttribute(el, value, attribute);
|
|
1172
|
+
}
|
|
1173
|
+
}
|
|
1174
|
+
/**
|
|
1175
|
+
* Overrides PropertiesChanged implemention to serialize objects as JSON.
|
|
1176
|
+
*
|
|
1177
|
+
* @param {*} value Property value to serialize.
|
|
1178
|
+
* @return {string | undefined} String serialized from the provided property
|
|
1179
|
+
* value.
|
|
1180
|
+
* @override
|
|
1181
|
+
*/
|
|
1182
|
+
_serializeValue(value) {
|
|
1183
|
+
switch (typeof value) {
|
|
1184
|
+
case "object":
|
|
1185
|
+
if (value instanceof Date) {
|
|
1186
|
+
return value.toString();
|
|
1187
|
+
} else if (value) {
|
|
1188
|
+
if (isTrustedType(value)) {
|
|
1189
|
+
return (
|
|
1190
|
+
/** @type {?} */
|
|
1191
|
+
value
|
|
1192
|
+
);
|
|
1193
|
+
}
|
|
1194
|
+
try {
|
|
1195
|
+
return JSON.stringify(value);
|
|
1196
|
+
} catch (x) {
|
|
1197
|
+
return "";
|
|
1198
|
+
}
|
|
1199
|
+
}
|
|
1200
|
+
default:
|
|
1201
|
+
return super._serializeValue(value);
|
|
1202
|
+
}
|
|
1203
|
+
}
|
|
1204
|
+
/**
|
|
1205
|
+
* Converts a string to a typed JavaScript value.
|
|
1206
|
+
*
|
|
1207
|
+
* This method is called by Polymer when reading HTML attribute values to
|
|
1208
|
+
* JS properties. Users may override this method on Polymer element
|
|
1209
|
+
* prototypes to provide deserialization for custom `type`s. Note,
|
|
1210
|
+
* the `type` argument is the value of the `type` field provided in the
|
|
1211
|
+
* `properties` configuration object for a given property, and is
|
|
1212
|
+
* by convention the constructor for the type to deserialize.
|
|
1213
|
+
*
|
|
1214
|
+
*
|
|
1215
|
+
* @param {?string} value Attribute value to deserialize.
|
|
1216
|
+
* @param {*=} type Type to deserialize the string to.
|
|
1217
|
+
* @return {*} Typed value deserialized from the provided string.
|
|
1218
|
+
* @override
|
|
1219
|
+
*/
|
|
1220
|
+
_deserializeValue(value, type) {
|
|
1221
|
+
let outValue;
|
|
1222
|
+
switch (type) {
|
|
1223
|
+
case Object:
|
|
1224
|
+
try {
|
|
1225
|
+
outValue = JSON.parse(
|
|
1226
|
+
/** @type {string} */
|
|
1227
|
+
value
|
|
1228
|
+
);
|
|
1229
|
+
} catch (x) {
|
|
1230
|
+
outValue = value;
|
|
1231
|
+
}
|
|
1232
|
+
break;
|
|
1233
|
+
case Array:
|
|
1234
|
+
try {
|
|
1235
|
+
outValue = JSON.parse(
|
|
1236
|
+
/** @type {string} */
|
|
1237
|
+
value
|
|
1238
|
+
);
|
|
1239
|
+
} catch (x) {
|
|
1240
|
+
outValue = null;
|
|
1241
|
+
console.warn(`Polymer::Attributes: couldn't decode Array as JSON: ${value}`);
|
|
1242
|
+
}
|
|
1243
|
+
break;
|
|
1244
|
+
case Date:
|
|
1245
|
+
outValue = isNaN(value) ? String(value) : Number(value);
|
|
1246
|
+
outValue = new Date(outValue);
|
|
1247
|
+
break;
|
|
1248
|
+
default:
|
|
1249
|
+
outValue = super._deserializeValue(value, type);
|
|
1250
|
+
break;
|
|
1251
|
+
}
|
|
1252
|
+
return outValue;
|
|
1253
|
+
}
|
|
1254
|
+
/* eslint-enable no-fallthrough */
|
|
1255
|
+
/**
|
|
1256
|
+
* Overrides PropertiesChanged implementation to save existing prototype
|
|
1257
|
+
* property value so that it can be reset.
|
|
1258
|
+
* @param {string} property Name of the property
|
|
1259
|
+
* @param {boolean=} readOnly When true, no setter is created
|
|
1260
|
+
*
|
|
1261
|
+
* When calling on a prototype, any overwritten values are saved in
|
|
1262
|
+
* `__dataProto`, and it is up to the subclasser to decide how/when
|
|
1263
|
+
* to set those properties back into the accessor. When calling on an
|
|
1264
|
+
* instance, the overwritten value is set via `_setPendingProperty`,
|
|
1265
|
+
* and the user should call `_invalidateProperties` or `_flushProperties`
|
|
1266
|
+
* for the values to take effect.
|
|
1267
|
+
* @protected
|
|
1268
|
+
* @return {void}
|
|
1269
|
+
* @override
|
|
1270
|
+
*/
|
|
1271
|
+
_definePropertyAccessor(property, readOnly) {
|
|
1272
|
+
saveAccessorValue(this, property);
|
|
1273
|
+
super._definePropertyAccessor(property, readOnly);
|
|
1274
|
+
}
|
|
1275
|
+
/**
|
|
1276
|
+
* Returns true if this library created an accessor for the given property.
|
|
1277
|
+
*
|
|
1278
|
+
* @param {string} property Property name
|
|
1279
|
+
* @return {boolean} True if an accessor was created
|
|
1280
|
+
* @override
|
|
1281
|
+
*/
|
|
1282
|
+
_hasAccessor(property) {
|
|
1283
|
+
return this.__dataHasAccessor && this.__dataHasAccessor[property];
|
|
1284
|
+
}
|
|
1285
|
+
/**
|
|
1286
|
+
* Returns true if the specified property has a pending change.
|
|
1287
|
+
*
|
|
1288
|
+
* @param {string} prop Property name
|
|
1289
|
+
* @return {boolean} True if property has a pending change
|
|
1290
|
+
* @protected
|
|
1291
|
+
* @override
|
|
1292
|
+
*/
|
|
1293
|
+
_isPropertyPending(prop) {
|
|
1294
|
+
return Boolean(this.__dataPending && prop in this.__dataPending);
|
|
1295
|
+
}
|
|
1296
|
+
}
|
|
1297
|
+
return PropertyAccessors2;
|
|
1298
|
+
});
|
|
1299
|
+
|
|
1300
|
+
// ../../../node_modules/@polymer/polymer/lib/mixins/template-stamp.js
|
|
1301
|
+
var templateExtensions = {
|
|
1302
|
+
"dom-if": true,
|
|
1303
|
+
"dom-repeat": true
|
|
1304
|
+
};
|
|
1305
|
+
var placeholderBugDetect = false;
|
|
1306
|
+
var placeholderBug = false;
|
|
1307
|
+
function hasPlaceholderBug() {
|
|
1308
|
+
if (!placeholderBugDetect) {
|
|
1309
|
+
placeholderBugDetect = true;
|
|
1310
|
+
const t = document.createElement("textarea");
|
|
1311
|
+
t.placeholder = "a";
|
|
1312
|
+
placeholderBug = t.placeholder === t.textContent;
|
|
1313
|
+
}
|
|
1314
|
+
return placeholderBug;
|
|
1315
|
+
}
|
|
1316
|
+
function fixPlaceholder(node) {
|
|
1317
|
+
if (hasPlaceholderBug() && node.localName === "textarea" && node.placeholder && node.placeholder === node.textContent) {
|
|
1318
|
+
node.textContent = null;
|
|
1319
|
+
}
|
|
1320
|
+
}
|
|
1321
|
+
var copyAttributeWithTemplateEventPolicy = (() => {
|
|
1322
|
+
const polymerTemplateEventAttributePolicy = window.trustedTypes && window.trustedTypes.createPolicy(
|
|
1323
|
+
"polymer-template-event-attribute-policy",
|
|
1324
|
+
{
|
|
1325
|
+
createScript: (x) => x
|
|
1326
|
+
}
|
|
1327
|
+
);
|
|
1328
|
+
return (dest, src, name) => {
|
|
1329
|
+
const value = src.getAttribute(name);
|
|
1330
|
+
if (polymerTemplateEventAttributePolicy && name.startsWith("on-")) {
|
|
1331
|
+
dest.setAttribute(
|
|
1332
|
+
name,
|
|
1333
|
+
polymerTemplateEventAttributePolicy.createScript(value, name)
|
|
1334
|
+
);
|
|
1335
|
+
return;
|
|
1336
|
+
}
|
|
1337
|
+
dest.setAttribute(name, value);
|
|
1338
|
+
};
|
|
1339
|
+
})();
|
|
1340
|
+
function wrapTemplateExtension(node) {
|
|
1341
|
+
let is = node.getAttribute("is");
|
|
1342
|
+
if (is && templateExtensions[is]) {
|
|
1343
|
+
let t = node;
|
|
1344
|
+
t.removeAttribute("is");
|
|
1345
|
+
node = t.ownerDocument.createElement(is);
|
|
1346
|
+
t.parentNode.replaceChild(node, t);
|
|
1347
|
+
node.appendChild(t);
|
|
1348
|
+
while (t.attributes.length) {
|
|
1349
|
+
const { name } = t.attributes[0];
|
|
1350
|
+
copyAttributeWithTemplateEventPolicy(node, t, name);
|
|
1351
|
+
t.removeAttribute(name);
|
|
1352
|
+
}
|
|
1353
|
+
}
|
|
1354
|
+
return node;
|
|
1355
|
+
}
|
|
1356
|
+
function findTemplateNode(root2, nodeInfo) {
|
|
1357
|
+
let parent = nodeInfo.parentInfo && findTemplateNode(root2, nodeInfo.parentInfo);
|
|
1358
|
+
if (parent) {
|
|
1359
|
+
for (let n = parent.firstChild, i = 0; n; n = n.nextSibling) {
|
|
1360
|
+
if (nodeInfo.parentIndex === i++) {
|
|
1361
|
+
return n;
|
|
1362
|
+
}
|
|
1363
|
+
}
|
|
1364
|
+
} else {
|
|
1365
|
+
return root2;
|
|
1366
|
+
}
|
|
1367
|
+
}
|
|
1368
|
+
function applyIdToMap(inst, map, node, nodeInfo) {
|
|
1369
|
+
if (nodeInfo.id) {
|
|
1370
|
+
map[nodeInfo.id] = node;
|
|
1371
|
+
}
|
|
1372
|
+
}
|
|
1373
|
+
function applyEventListener(inst, node, nodeInfo) {
|
|
1374
|
+
if (nodeInfo.events && nodeInfo.events.length) {
|
|
1375
|
+
for (let j = 0, e$ = nodeInfo.events, e; j < e$.length && (e = e$[j]); j++) {
|
|
1376
|
+
inst._addMethodEventListenerToNode(node, e.name, e.value, inst);
|
|
1377
|
+
}
|
|
1378
|
+
}
|
|
1379
|
+
}
|
|
1380
|
+
function applyTemplateInfo(inst, node, nodeInfo, parentTemplateInfo) {
|
|
1381
|
+
if (nodeInfo.templateInfo) {
|
|
1382
|
+
node._templateInfo = nodeInfo.templateInfo;
|
|
1383
|
+
node._parentTemplateInfo = parentTemplateInfo;
|
|
1384
|
+
}
|
|
1385
|
+
}
|
|
1386
|
+
function createNodeEventHandler(context, eventName, methodName) {
|
|
1387
|
+
context = context._methodHost || context;
|
|
1388
|
+
let handler = function(e) {
|
|
1389
|
+
if (context[methodName]) {
|
|
1390
|
+
context[methodName](e, e.detail);
|
|
1391
|
+
} else {
|
|
1392
|
+
console.warn("listener method `" + methodName + "` not defined");
|
|
1393
|
+
}
|
|
1394
|
+
};
|
|
1395
|
+
return handler;
|
|
1396
|
+
}
|
|
1397
|
+
var TemplateStamp = dedupingMixin(
|
|
1398
|
+
/**
|
|
1399
|
+
* @template T
|
|
1400
|
+
* @param {function(new:T)} superClass Class to apply mixin to.
|
|
1401
|
+
* @return {function(new:T)} superClass with mixin applied.
|
|
1402
|
+
*/
|
|
1403
|
+
(superClass) => {
|
|
1404
|
+
class TemplateStamp2 extends superClass {
|
|
1405
|
+
/**
|
|
1406
|
+
* Scans a template to produce template metadata.
|
|
1407
|
+
*
|
|
1408
|
+
* Template-specific metadata are stored in the object returned, and node-
|
|
1409
|
+
* specific metadata are stored in objects in its flattened `nodeInfoList`
|
|
1410
|
+
* array. Only nodes in the template that were parsed as nodes of
|
|
1411
|
+
* interest contain an object in `nodeInfoList`. Each `nodeInfo` object
|
|
1412
|
+
* contains an `index` (`childNodes` index in parent) and optionally
|
|
1413
|
+
* `parent`, which points to node info of its parent (including its index).
|
|
1414
|
+
*
|
|
1415
|
+
* The template metadata object returned from this method has the following
|
|
1416
|
+
* structure (many fields optional):
|
|
1417
|
+
*
|
|
1418
|
+
* ```js
|
|
1419
|
+
* {
|
|
1420
|
+
* // Flattened list of node metadata (for nodes that generated metadata)
|
|
1421
|
+
* nodeInfoList: [
|
|
1422
|
+
* {
|
|
1423
|
+
* // `id` attribute for any nodes with id's for generating `$` map
|
|
1424
|
+
* id: {string},
|
|
1425
|
+
* // `on-event="handler"` metadata
|
|
1426
|
+
* events: [
|
|
1427
|
+
* {
|
|
1428
|
+
* name: {string}, // event name
|
|
1429
|
+
* value: {string}, // handler method name
|
|
1430
|
+
* }, ...
|
|
1431
|
+
* ],
|
|
1432
|
+
* // Notes when the template contained a `<slot>` for shady DOM
|
|
1433
|
+
* // optimization purposes
|
|
1434
|
+
* hasInsertionPoint: {boolean},
|
|
1435
|
+
* // For nested `<template>`` nodes, nested template metadata
|
|
1436
|
+
* templateInfo: {object}, // nested template metadata
|
|
1437
|
+
* // Metadata to allow efficient retrieval of instanced node
|
|
1438
|
+
* // corresponding to this metadata
|
|
1439
|
+
* parentInfo: {number}, // reference to parent nodeInfo>
|
|
1440
|
+
* parentIndex: {number}, // index in parent's `childNodes` collection
|
|
1441
|
+
* infoIndex: {number}, // index of this `nodeInfo` in `templateInfo.nodeInfoList`
|
|
1442
|
+
* },
|
|
1443
|
+
* ...
|
|
1444
|
+
* ],
|
|
1445
|
+
* // When true, the template had the `strip-whitespace` attribute
|
|
1446
|
+
* // or was nested in a template with that setting
|
|
1447
|
+
* stripWhitespace: {boolean},
|
|
1448
|
+
* // For nested templates, nested template content is moved into
|
|
1449
|
+
* // a document fragment stored here; this is an optimization to
|
|
1450
|
+
* // avoid the cost of nested template cloning
|
|
1451
|
+
* content: {DocumentFragment}
|
|
1452
|
+
* }
|
|
1453
|
+
* ```
|
|
1454
|
+
*
|
|
1455
|
+
* This method kicks off a recursive treewalk as follows:
|
|
1456
|
+
*
|
|
1457
|
+
* ```
|
|
1458
|
+
* _parseTemplate <---------------------+
|
|
1459
|
+
* _parseTemplateContent |
|
|
1460
|
+
* _parseTemplateNode <------------|--+
|
|
1461
|
+
* _parseTemplateNestedTemplate --+ |
|
|
1462
|
+
* _parseTemplateChildNodes ---------+
|
|
1463
|
+
* _parseTemplateNodeAttributes
|
|
1464
|
+
* _parseTemplateNodeAttribute
|
|
1465
|
+
*
|
|
1466
|
+
* ```
|
|
1467
|
+
*
|
|
1468
|
+
* These methods may be overridden to add custom metadata about templates
|
|
1469
|
+
* to either `templateInfo` or `nodeInfo`.
|
|
1470
|
+
*
|
|
1471
|
+
* Note that this method may be destructive to the template, in that
|
|
1472
|
+
* e.g. event annotations may be removed after being noted in the
|
|
1473
|
+
* template metadata.
|
|
1474
|
+
*
|
|
1475
|
+
* @param {!HTMLTemplateElement} template Template to parse
|
|
1476
|
+
* @param {TemplateInfo=} outerTemplateInfo Template metadata from the outer
|
|
1477
|
+
* template, for parsing nested templates
|
|
1478
|
+
* @return {!TemplateInfo} Parsed template metadata
|
|
1479
|
+
* @nocollapse
|
|
1480
|
+
*/
|
|
1481
|
+
static _parseTemplate(template, outerTemplateInfo) {
|
|
1482
|
+
if (!template._templateInfo) {
|
|
1483
|
+
let templateInfo = template._templateInfo = {};
|
|
1484
|
+
templateInfo.nodeInfoList = [];
|
|
1485
|
+
templateInfo.nestedTemplate = Boolean(outerTemplateInfo);
|
|
1486
|
+
templateInfo.stripWhiteSpace = outerTemplateInfo && outerTemplateInfo.stripWhiteSpace || template.hasAttribute && template.hasAttribute("strip-whitespace");
|
|
1487
|
+
this._parseTemplateContent(
|
|
1488
|
+
template,
|
|
1489
|
+
templateInfo,
|
|
1490
|
+
/** @type {?} */
|
|
1491
|
+
{ parent: null }
|
|
1492
|
+
);
|
|
1493
|
+
}
|
|
1494
|
+
return template._templateInfo;
|
|
1495
|
+
}
|
|
1496
|
+
/**
|
|
1497
|
+
* See docs for _parseTemplateNode.
|
|
1498
|
+
*
|
|
1499
|
+
* @param {!HTMLTemplateElement} template .
|
|
1500
|
+
* @param {!TemplateInfo} templateInfo .
|
|
1501
|
+
* @param {!NodeInfo} nodeInfo .
|
|
1502
|
+
* @return {boolean} .
|
|
1503
|
+
* @nocollapse
|
|
1504
|
+
*/
|
|
1505
|
+
static _parseTemplateContent(template, templateInfo, nodeInfo) {
|
|
1506
|
+
return this._parseTemplateNode(template.content, templateInfo, nodeInfo);
|
|
1507
|
+
}
|
|
1508
|
+
/**
|
|
1509
|
+
* Parses template node and adds template and node metadata based on
|
|
1510
|
+
* the current node, and its `childNodes` and `attributes`.
|
|
1511
|
+
*
|
|
1512
|
+
* This method may be overridden to add custom node or template specific
|
|
1513
|
+
* metadata based on this node.
|
|
1514
|
+
*
|
|
1515
|
+
* @param {Node} node Node to parse
|
|
1516
|
+
* @param {!TemplateInfo} templateInfo Template metadata for current template
|
|
1517
|
+
* @param {!NodeInfo} nodeInfo Node metadata for current template.
|
|
1518
|
+
* @return {boolean} `true` if the visited node added node-specific
|
|
1519
|
+
* metadata to `nodeInfo`
|
|
1520
|
+
* @nocollapse
|
|
1521
|
+
*/
|
|
1522
|
+
static _parseTemplateNode(node, templateInfo, nodeInfo) {
|
|
1523
|
+
let noted = false;
|
|
1524
|
+
let element = (
|
|
1525
|
+
/** @type {!HTMLTemplateElement} */
|
|
1526
|
+
node
|
|
1527
|
+
);
|
|
1528
|
+
if (element.localName == "template" && !element.hasAttribute("preserve-content")) {
|
|
1529
|
+
noted = this._parseTemplateNestedTemplate(element, templateInfo, nodeInfo) || noted;
|
|
1530
|
+
} else if (element.localName === "slot") {
|
|
1531
|
+
templateInfo.hasInsertionPoint = true;
|
|
1532
|
+
}
|
|
1533
|
+
fixPlaceholder(element);
|
|
1534
|
+
if (element.firstChild) {
|
|
1535
|
+
this._parseTemplateChildNodes(element, templateInfo, nodeInfo);
|
|
1536
|
+
}
|
|
1537
|
+
if (element.hasAttributes && element.hasAttributes()) {
|
|
1538
|
+
noted = this._parseTemplateNodeAttributes(element, templateInfo, nodeInfo) || noted;
|
|
1539
|
+
}
|
|
1540
|
+
return noted || nodeInfo.noted;
|
|
1541
|
+
}
|
|
1542
|
+
/**
|
|
1543
|
+
* Parses template child nodes for the given root node.
|
|
1544
|
+
*
|
|
1545
|
+
* This method also wraps whitelisted legacy template extensions
|
|
1546
|
+
* (`is="dom-if"` and `is="dom-repeat"`) with their equivalent element
|
|
1547
|
+
* wrappers, collapses text nodes, and strips whitespace from the template
|
|
1548
|
+
* if the `templateInfo.stripWhitespace` setting was provided.
|
|
1549
|
+
*
|
|
1550
|
+
* @param {Node} root Root node whose `childNodes` will be parsed
|
|
1551
|
+
* @param {!TemplateInfo} templateInfo Template metadata for current template
|
|
1552
|
+
* @param {!NodeInfo} nodeInfo Node metadata for current template.
|
|
1553
|
+
* @return {void}
|
|
1554
|
+
*/
|
|
1555
|
+
static _parseTemplateChildNodes(root2, templateInfo, nodeInfo) {
|
|
1556
|
+
if (root2.localName === "script" || root2.localName === "style") {
|
|
1557
|
+
return;
|
|
1558
|
+
}
|
|
1559
|
+
for (let node = root2.firstChild, parentIndex = 0, next; node; node = next) {
|
|
1560
|
+
if (node.localName == "template") {
|
|
1561
|
+
node = wrapTemplateExtension(node);
|
|
1562
|
+
}
|
|
1563
|
+
next = node.nextSibling;
|
|
1564
|
+
if (node.nodeType === Node.TEXT_NODE) {
|
|
1565
|
+
let n = next;
|
|
1566
|
+
while (n && n.nodeType === Node.TEXT_NODE) {
|
|
1567
|
+
node.textContent += n.textContent;
|
|
1568
|
+
next = n.nextSibling;
|
|
1569
|
+
root2.removeChild(n);
|
|
1570
|
+
n = next;
|
|
1571
|
+
}
|
|
1572
|
+
if (templateInfo.stripWhiteSpace && !node.textContent.trim()) {
|
|
1573
|
+
root2.removeChild(node);
|
|
1574
|
+
continue;
|
|
1575
|
+
}
|
|
1576
|
+
}
|
|
1577
|
+
let childInfo = (
|
|
1578
|
+
/** @type {!NodeInfo} */
|
|
1579
|
+
{ parentIndex, parentInfo: nodeInfo }
|
|
1580
|
+
);
|
|
1581
|
+
if (this._parseTemplateNode(node, templateInfo, childInfo)) {
|
|
1582
|
+
childInfo.infoIndex = templateInfo.nodeInfoList.push(childInfo) - 1;
|
|
1583
|
+
}
|
|
1584
|
+
if (node.parentNode) {
|
|
1585
|
+
parentIndex++;
|
|
1586
|
+
}
|
|
1587
|
+
}
|
|
1588
|
+
}
|
|
1589
|
+
/**
|
|
1590
|
+
* Parses template content for the given nested `<template>`.
|
|
1591
|
+
*
|
|
1592
|
+
* Nested template info is stored as `templateInfo` in the current node's
|
|
1593
|
+
* `nodeInfo`. `template.content` is removed and stored in `templateInfo`.
|
|
1594
|
+
* It will then be the responsibility of the host to set it back to the
|
|
1595
|
+
* template and for users stamping nested templates to use the
|
|
1596
|
+
* `_contentForTemplate` method to retrieve the content for this template
|
|
1597
|
+
* (an optimization to avoid the cost of cloning nested template content).
|
|
1598
|
+
*
|
|
1599
|
+
* @param {HTMLTemplateElement} node Node to parse (a <template>)
|
|
1600
|
+
* @param {TemplateInfo} outerTemplateInfo Template metadata for current template
|
|
1601
|
+
* that includes the template `node`
|
|
1602
|
+
* @param {!NodeInfo} nodeInfo Node metadata for current template.
|
|
1603
|
+
* @return {boolean} `true` if the visited node added node-specific
|
|
1604
|
+
* metadata to `nodeInfo`
|
|
1605
|
+
* @nocollapse
|
|
1606
|
+
*/
|
|
1607
|
+
static _parseTemplateNestedTemplate(node, outerTemplateInfo, nodeInfo) {
|
|
1608
|
+
let element = (
|
|
1609
|
+
/** @type {!HTMLTemplateElement} */
|
|
1610
|
+
node
|
|
1611
|
+
);
|
|
1612
|
+
let templateInfo = this._parseTemplate(element, outerTemplateInfo);
|
|
1613
|
+
let content = templateInfo.content = element.content.ownerDocument.createDocumentFragment();
|
|
1614
|
+
content.appendChild(element.content);
|
|
1615
|
+
nodeInfo.templateInfo = templateInfo;
|
|
1616
|
+
return true;
|
|
1617
|
+
}
|
|
1618
|
+
/**
|
|
1619
|
+
* Parses template node attributes and adds node metadata to `nodeInfo`
|
|
1620
|
+
* for nodes of interest.
|
|
1621
|
+
*
|
|
1622
|
+
* @param {Element} node Node to parse
|
|
1623
|
+
* @param {!TemplateInfo} templateInfo Template metadata for current
|
|
1624
|
+
* template
|
|
1625
|
+
* @param {!NodeInfo} nodeInfo Node metadata for current template.
|
|
1626
|
+
* @return {boolean} `true` if the visited node added node-specific
|
|
1627
|
+
* metadata to `nodeInfo`
|
|
1628
|
+
* @nocollapse
|
|
1629
|
+
*/
|
|
1630
|
+
static _parseTemplateNodeAttributes(node, templateInfo, nodeInfo) {
|
|
1631
|
+
let noted = false;
|
|
1632
|
+
let attrs = Array.from(node.attributes);
|
|
1633
|
+
for (let i = attrs.length - 1, a; a = attrs[i]; i--) {
|
|
1634
|
+
noted = this._parseTemplateNodeAttribute(node, templateInfo, nodeInfo, a.name, a.value) || noted;
|
|
1635
|
+
}
|
|
1636
|
+
return noted;
|
|
1637
|
+
}
|
|
1638
|
+
/**
|
|
1639
|
+
* Parses a single template node attribute and adds node metadata to
|
|
1640
|
+
* `nodeInfo` for attributes of interest.
|
|
1641
|
+
*
|
|
1642
|
+
* This implementation adds metadata for `on-event="handler"` attributes
|
|
1643
|
+
* and `id` attributes.
|
|
1644
|
+
*
|
|
1645
|
+
* @param {Element} node Node to parse
|
|
1646
|
+
* @param {!TemplateInfo} templateInfo Template metadata for current template
|
|
1647
|
+
* @param {!NodeInfo} nodeInfo Node metadata for current template.
|
|
1648
|
+
* @param {string} name Attribute name
|
|
1649
|
+
* @param {string} value Attribute value
|
|
1650
|
+
* @return {boolean} `true` if the visited node added node-specific
|
|
1651
|
+
* metadata to `nodeInfo`
|
|
1652
|
+
* @nocollapse
|
|
1653
|
+
*/
|
|
1654
|
+
static _parseTemplateNodeAttribute(node, templateInfo, nodeInfo, name, value) {
|
|
1655
|
+
if (name.slice(0, 3) === "on-") {
|
|
1656
|
+
node.removeAttribute(name);
|
|
1657
|
+
nodeInfo.events = nodeInfo.events || [];
|
|
1658
|
+
nodeInfo.events.push({
|
|
1659
|
+
name: name.slice(3),
|
|
1660
|
+
value
|
|
1661
|
+
});
|
|
1662
|
+
return true;
|
|
1663
|
+
} else if (name === "id") {
|
|
1664
|
+
nodeInfo.id = value;
|
|
1665
|
+
return true;
|
|
1666
|
+
}
|
|
1667
|
+
return false;
|
|
1668
|
+
}
|
|
1669
|
+
/**
|
|
1670
|
+
* Returns the `content` document fragment for a given template.
|
|
1671
|
+
*
|
|
1672
|
+
* For nested templates, Polymer performs an optimization to cache nested
|
|
1673
|
+
* template content to avoid the cost of cloning deeply nested templates.
|
|
1674
|
+
* This method retrieves the cached content for a given template.
|
|
1675
|
+
*
|
|
1676
|
+
* @param {HTMLTemplateElement} template Template to retrieve `content` for
|
|
1677
|
+
* @return {DocumentFragment} Content fragment
|
|
1678
|
+
* @nocollapse
|
|
1679
|
+
*/
|
|
1680
|
+
static _contentForTemplate(template) {
|
|
1681
|
+
let templateInfo = (
|
|
1682
|
+
/** @type {HTMLTemplateElementWithInfo} */
|
|
1683
|
+
template._templateInfo
|
|
1684
|
+
);
|
|
1685
|
+
return templateInfo && templateInfo.content || template.content;
|
|
1686
|
+
}
|
|
1687
|
+
/**
|
|
1688
|
+
* Clones the provided template content and returns a document fragment
|
|
1689
|
+
* containing the cloned dom.
|
|
1690
|
+
*
|
|
1691
|
+
* The template is parsed (once and memoized) using this library's
|
|
1692
|
+
* template parsing features, and provides the following value-added
|
|
1693
|
+
* features:
|
|
1694
|
+
* * Adds declarative event listeners for `on-event="handler"` attributes
|
|
1695
|
+
* * Generates an "id map" for all nodes with id's under `$` on returned
|
|
1696
|
+
* document fragment
|
|
1697
|
+
* * Passes template info including `content` back to templates as
|
|
1698
|
+
* `_templateInfo` (a performance optimization to avoid deep template
|
|
1699
|
+
* cloning)
|
|
1700
|
+
*
|
|
1701
|
+
* Note that the memoized template parsing process is destructive to the
|
|
1702
|
+
* template: attributes for bindings and declarative event listeners are
|
|
1703
|
+
* removed after being noted in notes, and any nested `<template>.content`
|
|
1704
|
+
* is removed and stored in notes as well.
|
|
1705
|
+
*
|
|
1706
|
+
* @param {!HTMLTemplateElement} template Template to stamp
|
|
1707
|
+
* @param {TemplateInfo=} templateInfo Optional template info associated
|
|
1708
|
+
* with the template to be stamped; if omitted the template will be
|
|
1709
|
+
* automatically parsed.
|
|
1710
|
+
* @return {!StampedTemplate} Cloned template content
|
|
1711
|
+
* @override
|
|
1712
|
+
*/
|
|
1713
|
+
_stampTemplate(template, templateInfo) {
|
|
1714
|
+
if (template && !template.content && window.HTMLTemplateElement && HTMLTemplateElement.decorate) {
|
|
1715
|
+
HTMLTemplateElement.decorate(template);
|
|
1716
|
+
}
|
|
1717
|
+
templateInfo = templateInfo || this.constructor._parseTemplate(template);
|
|
1718
|
+
let nodeInfo = templateInfo.nodeInfoList;
|
|
1719
|
+
let content = templateInfo.content || template.content;
|
|
1720
|
+
let dom = (
|
|
1721
|
+
/** @type {DocumentFragment} */
|
|
1722
|
+
document.importNode(content, true)
|
|
1723
|
+
);
|
|
1724
|
+
dom.__noInsertionPoint = !templateInfo.hasInsertionPoint;
|
|
1725
|
+
let nodes = dom.nodeList = new Array(nodeInfo.length);
|
|
1726
|
+
dom.$ = {};
|
|
1727
|
+
for (let i = 0, l = nodeInfo.length, info; i < l && (info = nodeInfo[i]); i++) {
|
|
1728
|
+
let node = nodes[i] = findTemplateNode(dom, info);
|
|
1729
|
+
applyIdToMap(this, dom.$, node, info);
|
|
1730
|
+
applyTemplateInfo(this, node, info, templateInfo);
|
|
1731
|
+
applyEventListener(this, node, info);
|
|
1732
|
+
}
|
|
1733
|
+
dom = /** @type {!StampedTemplate} */
|
|
1734
|
+
dom;
|
|
1735
|
+
return dom;
|
|
1736
|
+
}
|
|
1737
|
+
/**
|
|
1738
|
+
* Adds an event listener by method name for the event provided.
|
|
1739
|
+
*
|
|
1740
|
+
* This method generates a handler function that looks up the method
|
|
1741
|
+
* name at handling time.
|
|
1742
|
+
*
|
|
1743
|
+
* @param {!EventTarget} node Node to add listener on
|
|
1744
|
+
* @param {string} eventName Name of event
|
|
1745
|
+
* @param {string} methodName Name of method
|
|
1746
|
+
* @param {*=} context Context the method will be called on (defaults
|
|
1747
|
+
* to `node`)
|
|
1748
|
+
* @return {Function} Generated handler function
|
|
1749
|
+
* @override
|
|
1750
|
+
*/
|
|
1751
|
+
_addMethodEventListenerToNode(node, eventName, methodName, context) {
|
|
1752
|
+
context = context || node;
|
|
1753
|
+
let handler = createNodeEventHandler(context, eventName, methodName);
|
|
1754
|
+
this._addEventListenerToNode(node, eventName, handler);
|
|
1755
|
+
return handler;
|
|
1756
|
+
}
|
|
1757
|
+
/**
|
|
1758
|
+
* Override point for adding custom or simulated event handling.
|
|
1759
|
+
*
|
|
1760
|
+
* @param {!EventTarget} node Node to add event listener to
|
|
1761
|
+
* @param {string} eventName Name of event
|
|
1762
|
+
* @param {function(!Event):void} handler Listener function to add
|
|
1763
|
+
* @return {void}
|
|
1764
|
+
* @override
|
|
1765
|
+
*/
|
|
1766
|
+
_addEventListenerToNode(node, eventName, handler) {
|
|
1767
|
+
node.addEventListener(eventName, handler);
|
|
1768
|
+
}
|
|
1769
|
+
/**
|
|
1770
|
+
* Override point for adding custom or simulated event handling.
|
|
1771
|
+
*
|
|
1772
|
+
* @param {!EventTarget} node Node to remove event listener from
|
|
1773
|
+
* @param {string} eventName Name of event
|
|
1774
|
+
* @param {function(!Event):void} handler Listener function to remove
|
|
1775
|
+
* @return {void}
|
|
1776
|
+
* @override
|
|
1777
|
+
*/
|
|
1778
|
+
_removeEventListenerFromNode(node, eventName, handler) {
|
|
1779
|
+
node.removeEventListener(eventName, handler);
|
|
1780
|
+
}
|
|
1781
|
+
}
|
|
1782
|
+
return TemplateStamp2;
|
|
1783
|
+
}
|
|
1784
|
+
);
|
|
1785
|
+
|
|
1786
|
+
// ../../../node_modules/@polymer/polymer/lib/mixins/property-effects.js
|
|
1787
|
+
var dedupeId = 0;
|
|
1788
|
+
var NOOP = [];
|
|
1789
|
+
var TYPES = {
|
|
1790
|
+
COMPUTE: "__computeEffects",
|
|
1791
|
+
REFLECT: "__reflectEffects",
|
|
1792
|
+
NOTIFY: "__notifyEffects",
|
|
1793
|
+
PROPAGATE: "__propagateEffects",
|
|
1794
|
+
OBSERVE: "__observeEffects",
|
|
1795
|
+
READ_ONLY: "__readOnly"
|
|
1796
|
+
};
|
|
1797
|
+
var COMPUTE_INFO = "__computeInfo";
|
|
1798
|
+
var capitalAttributeRegex = /[A-Z]/;
|
|
1799
|
+
function ensureOwnEffectMap(model, type, cloneArrays) {
|
|
1800
|
+
let effects = model[type];
|
|
1801
|
+
if (!effects) {
|
|
1802
|
+
effects = model[type] = {};
|
|
1803
|
+
} else if (!model.hasOwnProperty(type)) {
|
|
1804
|
+
effects = model[type] = Object.create(model[type]);
|
|
1805
|
+
if (cloneArrays) {
|
|
1806
|
+
for (let p in effects) {
|
|
1807
|
+
let protoFx = effects[p];
|
|
1808
|
+
let instFx = effects[p] = Array(protoFx.length);
|
|
1809
|
+
for (let i = 0; i < protoFx.length; i++) {
|
|
1810
|
+
instFx[i] = protoFx[i];
|
|
1811
|
+
}
|
|
1812
|
+
}
|
|
1813
|
+
}
|
|
1814
|
+
}
|
|
1815
|
+
return effects;
|
|
1816
|
+
}
|
|
1817
|
+
function runEffects(inst, effects, props, oldProps, hasPaths, extraArgs) {
|
|
1818
|
+
if (effects) {
|
|
1819
|
+
let ran = false;
|
|
1820
|
+
const id = dedupeId++;
|
|
1821
|
+
for (let prop in props) {
|
|
1822
|
+
let rootProperty = hasPaths ? root(prop) : prop;
|
|
1823
|
+
let fxs = effects[rootProperty];
|
|
1824
|
+
if (fxs) {
|
|
1825
|
+
for (let i = 0, l = fxs.length, fx; i < l && (fx = fxs[i]); i++) {
|
|
1826
|
+
if ((!fx.info || fx.info.lastRun !== id) && (!hasPaths || pathMatchesTrigger(prop, fx.trigger))) {
|
|
1827
|
+
if (fx.info) {
|
|
1828
|
+
fx.info.lastRun = id;
|
|
1829
|
+
}
|
|
1830
|
+
fx.fn(inst, prop, props, oldProps, fx.info, hasPaths, extraArgs);
|
|
1831
|
+
ran = true;
|
|
1832
|
+
}
|
|
1833
|
+
}
|
|
1834
|
+
}
|
|
1835
|
+
}
|
|
1836
|
+
return ran;
|
|
1837
|
+
}
|
|
1838
|
+
return false;
|
|
1839
|
+
}
|
|
1840
|
+
function runEffectsForProperty(inst, effects, dedupeId2, prop, props, oldProps, hasPaths, extraArgs) {
|
|
1841
|
+
let ran = false;
|
|
1842
|
+
let rootProperty = hasPaths ? root(prop) : prop;
|
|
1843
|
+
let fxs = effects[rootProperty];
|
|
1844
|
+
if (fxs) {
|
|
1845
|
+
for (let i = 0, l = fxs.length, fx; i < l && (fx = fxs[i]); i++) {
|
|
1846
|
+
if ((!fx.info || fx.info.lastRun !== dedupeId2) && (!hasPaths || pathMatchesTrigger(prop, fx.trigger))) {
|
|
1847
|
+
if (fx.info) {
|
|
1848
|
+
fx.info.lastRun = dedupeId2;
|
|
1849
|
+
}
|
|
1850
|
+
fx.fn(inst, prop, props, oldProps, fx.info, hasPaths, extraArgs);
|
|
1851
|
+
ran = true;
|
|
1852
|
+
}
|
|
1853
|
+
}
|
|
1854
|
+
}
|
|
1855
|
+
return ran;
|
|
1856
|
+
}
|
|
1857
|
+
function pathMatchesTrigger(path, trigger) {
|
|
1858
|
+
if (trigger) {
|
|
1859
|
+
let triggerPath = (
|
|
1860
|
+
/** @type {string} */
|
|
1861
|
+
trigger.name
|
|
1862
|
+
);
|
|
1863
|
+
return triggerPath == path || !!(trigger.structured && isAncestor(triggerPath, path)) || !!(trigger.wildcard && isDescendant(triggerPath, path));
|
|
1864
|
+
} else {
|
|
1865
|
+
return true;
|
|
1866
|
+
}
|
|
1867
|
+
}
|
|
1868
|
+
function runObserverEffect(inst, property, props, oldProps, info) {
|
|
1869
|
+
let fn = typeof info.method === "string" ? inst[info.method] : info.method;
|
|
1870
|
+
let changedProp = info.property;
|
|
1871
|
+
if (fn) {
|
|
1872
|
+
fn.call(inst, inst.__data[changedProp], oldProps[changedProp]);
|
|
1873
|
+
} else if (!info.dynamicFn) {
|
|
1874
|
+
console.warn("observer method `" + info.method + "` not defined");
|
|
1875
|
+
}
|
|
1876
|
+
}
|
|
1877
|
+
function runNotifyEffects(inst, notifyProps, props, oldProps, hasPaths) {
|
|
1878
|
+
let fxs = inst[TYPES.NOTIFY];
|
|
1879
|
+
let notified;
|
|
1880
|
+
let id = dedupeId++;
|
|
1881
|
+
for (let prop in notifyProps) {
|
|
1882
|
+
if (notifyProps[prop]) {
|
|
1883
|
+
if (fxs && runEffectsForProperty(inst, fxs, id, prop, props, oldProps, hasPaths)) {
|
|
1884
|
+
notified = true;
|
|
1885
|
+
} else if (hasPaths && notifyPath(inst, prop, props)) {
|
|
1886
|
+
notified = true;
|
|
1887
|
+
}
|
|
1888
|
+
}
|
|
1889
|
+
}
|
|
1890
|
+
let host;
|
|
1891
|
+
if (notified && (host = inst.__dataHost) && host._invalidateProperties) {
|
|
1892
|
+
host._invalidateProperties();
|
|
1893
|
+
}
|
|
1894
|
+
}
|
|
1895
|
+
function notifyPath(inst, path, props) {
|
|
1896
|
+
let rootProperty = root(path);
|
|
1897
|
+
if (rootProperty !== path) {
|
|
1898
|
+
let eventName = camelToDashCase(rootProperty) + "-changed";
|
|
1899
|
+
dispatchNotifyEvent(inst, eventName, props[path], path);
|
|
1900
|
+
return true;
|
|
1901
|
+
}
|
|
1902
|
+
return false;
|
|
1903
|
+
}
|
|
1904
|
+
function dispatchNotifyEvent(inst, eventName, value, path) {
|
|
1905
|
+
let detail = {
|
|
1906
|
+
value,
|
|
1907
|
+
queueProperty: true
|
|
1908
|
+
};
|
|
1909
|
+
if (path) {
|
|
1910
|
+
detail.path = path;
|
|
1911
|
+
}
|
|
1912
|
+
wrap(
|
|
1913
|
+
/** @type {!HTMLElement} */
|
|
1914
|
+
inst
|
|
1915
|
+
).dispatchEvent(new CustomEvent(eventName, { detail }));
|
|
1916
|
+
}
|
|
1917
|
+
function runNotifyEffect(inst, property, props, oldProps, info, hasPaths) {
|
|
1918
|
+
let rootProperty = hasPaths ? root(property) : property;
|
|
1919
|
+
let path = rootProperty != property ? property : null;
|
|
1920
|
+
let value = path ? get(inst, path) : inst.__data[property];
|
|
1921
|
+
if (path && value === void 0) {
|
|
1922
|
+
value = props[property];
|
|
1923
|
+
}
|
|
1924
|
+
dispatchNotifyEvent(inst, info.eventName, value, path);
|
|
1925
|
+
}
|
|
1926
|
+
function handleNotification(event, inst, fromProp, toPath, negate) {
|
|
1927
|
+
let value;
|
|
1928
|
+
let detail = (
|
|
1929
|
+
/** @type {Object} */
|
|
1930
|
+
event.detail
|
|
1931
|
+
);
|
|
1932
|
+
let fromPath = detail && detail.path;
|
|
1933
|
+
if (fromPath) {
|
|
1934
|
+
toPath = translate(fromProp, toPath, fromPath);
|
|
1935
|
+
value = detail && detail.value;
|
|
1936
|
+
} else {
|
|
1937
|
+
value = event.currentTarget[fromProp];
|
|
1938
|
+
}
|
|
1939
|
+
value = negate ? !value : value;
|
|
1940
|
+
if (!inst[TYPES.READ_ONLY] || !inst[TYPES.READ_ONLY][toPath]) {
|
|
1941
|
+
if (inst._setPendingPropertyOrPath(toPath, value, true, Boolean(fromPath)) && (!detail || !detail.queueProperty)) {
|
|
1942
|
+
inst._invalidateProperties();
|
|
1943
|
+
}
|
|
1944
|
+
}
|
|
1945
|
+
}
|
|
1946
|
+
function runReflectEffect(inst, property, props, oldProps, info) {
|
|
1947
|
+
let value = inst.__data[property];
|
|
1948
|
+
if (sanitizeDOMValue) {
|
|
1949
|
+
value = sanitizeDOMValue(
|
|
1950
|
+
value,
|
|
1951
|
+
info.attrName,
|
|
1952
|
+
"attribute",
|
|
1953
|
+
/** @type {Node} */
|
|
1954
|
+
inst
|
|
1955
|
+
);
|
|
1956
|
+
}
|
|
1957
|
+
inst._propertyToAttribute(property, info.attrName, value);
|
|
1958
|
+
}
|
|
1959
|
+
function runComputedEffects(inst, changedProps, oldProps, hasPaths) {
|
|
1960
|
+
let computeEffects = inst[TYPES.COMPUTE];
|
|
1961
|
+
if (computeEffects) {
|
|
1962
|
+
if (orderedComputed) {
|
|
1963
|
+
dedupeId++;
|
|
1964
|
+
const order = getComputedOrder(inst);
|
|
1965
|
+
const queue = [];
|
|
1966
|
+
for (let p in changedProps) {
|
|
1967
|
+
enqueueEffectsFor(p, computeEffects, queue, order, hasPaths);
|
|
1968
|
+
}
|
|
1969
|
+
let info;
|
|
1970
|
+
while (info = queue.shift()) {
|
|
1971
|
+
if (runComputedEffect(inst, "", changedProps, oldProps, info)) {
|
|
1972
|
+
enqueueEffectsFor(info.methodInfo, computeEffects, queue, order, hasPaths);
|
|
1973
|
+
}
|
|
1974
|
+
}
|
|
1975
|
+
Object.assign(
|
|
1976
|
+
/** @type {!Object} */
|
|
1977
|
+
oldProps,
|
|
1978
|
+
inst.__dataOld
|
|
1979
|
+
);
|
|
1980
|
+
Object.assign(
|
|
1981
|
+
/** @type {!Object} */
|
|
1982
|
+
changedProps,
|
|
1983
|
+
inst.__dataPending
|
|
1984
|
+
);
|
|
1985
|
+
inst.__dataPending = null;
|
|
1986
|
+
} else {
|
|
1987
|
+
let inputProps = changedProps;
|
|
1988
|
+
while (runEffects(inst, computeEffects, inputProps, oldProps, hasPaths)) {
|
|
1989
|
+
Object.assign(
|
|
1990
|
+
/** @type {!Object} */
|
|
1991
|
+
oldProps,
|
|
1992
|
+
inst.__dataOld
|
|
1993
|
+
);
|
|
1994
|
+
Object.assign(
|
|
1995
|
+
/** @type {!Object} */
|
|
1996
|
+
changedProps,
|
|
1997
|
+
inst.__dataPending
|
|
1998
|
+
);
|
|
1999
|
+
inputProps = inst.__dataPending;
|
|
2000
|
+
inst.__dataPending = null;
|
|
2001
|
+
}
|
|
2002
|
+
}
|
|
2003
|
+
}
|
|
2004
|
+
}
|
|
2005
|
+
var insertEffect = (info, queue, order) => {
|
|
2006
|
+
let start = 0;
|
|
2007
|
+
let end = queue.length - 1;
|
|
2008
|
+
let idx = -1;
|
|
2009
|
+
while (start <= end) {
|
|
2010
|
+
const mid = start + end >> 1;
|
|
2011
|
+
const cmp = order.get(queue[mid].methodInfo) - order.get(info.methodInfo);
|
|
2012
|
+
if (cmp < 0) {
|
|
2013
|
+
start = mid + 1;
|
|
2014
|
+
} else if (cmp > 0) {
|
|
2015
|
+
end = mid - 1;
|
|
2016
|
+
} else {
|
|
2017
|
+
idx = mid;
|
|
2018
|
+
break;
|
|
2019
|
+
}
|
|
2020
|
+
}
|
|
2021
|
+
if (idx < 0) {
|
|
2022
|
+
idx = end + 1;
|
|
2023
|
+
}
|
|
2024
|
+
queue.splice(idx, 0, info);
|
|
2025
|
+
};
|
|
2026
|
+
var enqueueEffectsFor = (prop, computeEffects, queue, order, hasPaths) => {
|
|
2027
|
+
const rootProperty = hasPaths ? root(prop) : prop;
|
|
2028
|
+
const fxs = computeEffects[rootProperty];
|
|
2029
|
+
if (fxs) {
|
|
2030
|
+
for (let i = 0; i < fxs.length; i++) {
|
|
2031
|
+
const fx = fxs[i];
|
|
2032
|
+
if (fx.info.lastRun !== dedupeId && (!hasPaths || pathMatchesTrigger(prop, fx.trigger))) {
|
|
2033
|
+
fx.info.lastRun = dedupeId;
|
|
2034
|
+
insertEffect(fx.info, queue, order);
|
|
2035
|
+
}
|
|
2036
|
+
}
|
|
2037
|
+
}
|
|
2038
|
+
};
|
|
2039
|
+
function getComputedOrder(inst) {
|
|
2040
|
+
let ordered = inst.constructor.__orderedComputedDeps;
|
|
2041
|
+
if (!ordered) {
|
|
2042
|
+
ordered = /* @__PURE__ */ new Map();
|
|
2043
|
+
const effects = inst[TYPES.COMPUTE];
|
|
2044
|
+
let { counts, ready, total } = dependencyCounts(inst);
|
|
2045
|
+
let curr;
|
|
2046
|
+
while (curr = ready.shift()) {
|
|
2047
|
+
ordered.set(curr, ordered.size);
|
|
2048
|
+
const computedByCurr = effects[curr];
|
|
2049
|
+
if (computedByCurr) {
|
|
2050
|
+
computedByCurr.forEach((fx) => {
|
|
2051
|
+
const computedProp = fx.info.methodInfo;
|
|
2052
|
+
--total;
|
|
2053
|
+
if (--counts[computedProp] === 0) {
|
|
2054
|
+
ready.push(computedProp);
|
|
2055
|
+
}
|
|
2056
|
+
});
|
|
2057
|
+
}
|
|
2058
|
+
}
|
|
2059
|
+
if (total !== 0) {
|
|
2060
|
+
const el = (
|
|
2061
|
+
/** @type {HTMLElement} */
|
|
2062
|
+
inst
|
|
2063
|
+
);
|
|
2064
|
+
console.warn(`Computed graph for ${el.localName} incomplete; circular?`);
|
|
2065
|
+
}
|
|
2066
|
+
inst.constructor.__orderedComputedDeps = ordered;
|
|
2067
|
+
}
|
|
2068
|
+
return ordered;
|
|
2069
|
+
}
|
|
2070
|
+
function dependencyCounts(inst) {
|
|
2071
|
+
const infoForComputed = inst[COMPUTE_INFO];
|
|
2072
|
+
const counts = {};
|
|
2073
|
+
const computedDeps = inst[TYPES.COMPUTE];
|
|
2074
|
+
const ready = [];
|
|
2075
|
+
let total = 0;
|
|
2076
|
+
for (let p in infoForComputed) {
|
|
2077
|
+
const info = infoForComputed[p];
|
|
2078
|
+
total += counts[p] = info.args.filter((a) => !a.literal).length + (info.dynamicFn ? 1 : 0);
|
|
2079
|
+
}
|
|
2080
|
+
for (let p in computedDeps) {
|
|
2081
|
+
if (!infoForComputed[p]) {
|
|
2082
|
+
ready.push(p);
|
|
2083
|
+
}
|
|
2084
|
+
}
|
|
2085
|
+
return { counts, ready, total };
|
|
2086
|
+
}
|
|
2087
|
+
function runComputedEffect(inst, property, changedProps, oldProps, info) {
|
|
2088
|
+
let result = runMethodEffect(inst, property, changedProps, oldProps, info);
|
|
2089
|
+
if (result === NOOP) {
|
|
2090
|
+
return false;
|
|
2091
|
+
}
|
|
2092
|
+
let computedProp = info.methodInfo;
|
|
2093
|
+
if (inst.__dataHasAccessor && inst.__dataHasAccessor[computedProp]) {
|
|
2094
|
+
return inst._setPendingProperty(computedProp, result, true);
|
|
2095
|
+
} else {
|
|
2096
|
+
inst[computedProp] = result;
|
|
2097
|
+
return false;
|
|
2098
|
+
}
|
|
2099
|
+
}
|
|
2100
|
+
function computeLinkedPaths(inst, path, value) {
|
|
2101
|
+
let links = inst.__dataLinkedPaths;
|
|
2102
|
+
if (links) {
|
|
2103
|
+
let link;
|
|
2104
|
+
for (let a in links) {
|
|
2105
|
+
let b = links[a];
|
|
2106
|
+
if (isDescendant(a, path)) {
|
|
2107
|
+
link = translate(a, b, path);
|
|
2108
|
+
inst._setPendingPropertyOrPath(link, value, true, true);
|
|
2109
|
+
} else if (isDescendant(b, path)) {
|
|
2110
|
+
link = translate(b, a, path);
|
|
2111
|
+
inst._setPendingPropertyOrPath(link, value, true, true);
|
|
2112
|
+
}
|
|
2113
|
+
}
|
|
2114
|
+
}
|
|
2115
|
+
}
|
|
2116
|
+
function addBinding(constructor, templateInfo, nodeInfo, kind, target, parts, literal) {
|
|
2117
|
+
nodeInfo.bindings = nodeInfo.bindings || [];
|
|
2118
|
+
let binding = { kind, target, parts, literal, isCompound: parts.length !== 1 };
|
|
2119
|
+
nodeInfo.bindings.push(binding);
|
|
2120
|
+
if (shouldAddListener(binding)) {
|
|
2121
|
+
let { event, negate } = binding.parts[0];
|
|
2122
|
+
binding.listenerEvent = event || camelToDashCase(target) + "-changed";
|
|
2123
|
+
binding.listenerNegate = negate;
|
|
2124
|
+
}
|
|
2125
|
+
let index = templateInfo.nodeInfoList.length;
|
|
2126
|
+
for (let i = 0; i < binding.parts.length; i++) {
|
|
2127
|
+
let part = binding.parts[i];
|
|
2128
|
+
part.compoundIndex = i;
|
|
2129
|
+
addEffectForBindingPart(constructor, templateInfo, binding, part, index);
|
|
2130
|
+
}
|
|
2131
|
+
}
|
|
2132
|
+
function addEffectForBindingPart(constructor, templateInfo, binding, part, index) {
|
|
2133
|
+
if (!part.literal) {
|
|
2134
|
+
if (binding.kind === "attribute" && binding.target[0] === "-") {
|
|
2135
|
+
console.warn("Cannot set attribute " + binding.target + ' because "-" is not a valid attribute starting character');
|
|
2136
|
+
} else {
|
|
2137
|
+
let dependencies = part.dependencies;
|
|
2138
|
+
let info = { index, binding, part, evaluator: constructor };
|
|
2139
|
+
for (let j = 0; j < dependencies.length; j++) {
|
|
2140
|
+
let trigger = dependencies[j];
|
|
2141
|
+
if (typeof trigger == "string") {
|
|
2142
|
+
trigger = parseArg(trigger);
|
|
2143
|
+
trigger.wildcard = true;
|
|
2144
|
+
}
|
|
2145
|
+
constructor._addTemplatePropertyEffect(templateInfo, trigger.rootProperty, {
|
|
2146
|
+
fn: runBindingEffect,
|
|
2147
|
+
info,
|
|
2148
|
+
trigger
|
|
2149
|
+
});
|
|
2150
|
+
}
|
|
2151
|
+
}
|
|
2152
|
+
}
|
|
2153
|
+
}
|
|
2154
|
+
function runBindingEffect(inst, path, props, oldProps, info, hasPaths, nodeList) {
|
|
2155
|
+
let node = nodeList[info.index];
|
|
2156
|
+
let binding = info.binding;
|
|
2157
|
+
let part = info.part;
|
|
2158
|
+
if (hasPaths && part.source && path.length > part.source.length && binding.kind == "property" && !binding.isCompound && node.__isPropertyEffectsClient && node.__dataHasAccessor && node.__dataHasAccessor[binding.target]) {
|
|
2159
|
+
let value = props[path];
|
|
2160
|
+
path = translate(part.source, binding.target, path);
|
|
2161
|
+
if (node._setPendingPropertyOrPath(path, value, false, true)) {
|
|
2162
|
+
inst._enqueueClient(node);
|
|
2163
|
+
}
|
|
2164
|
+
} else {
|
|
2165
|
+
let value = info.evaluator._evaluateBinding(inst, part, path, props, oldProps, hasPaths);
|
|
2166
|
+
if (value !== NOOP) {
|
|
2167
|
+
applyBindingValue(inst, node, binding, part, value);
|
|
2168
|
+
}
|
|
2169
|
+
}
|
|
2170
|
+
}
|
|
2171
|
+
function applyBindingValue(inst, node, binding, part, value) {
|
|
2172
|
+
value = computeBindingValue(node, value, binding, part);
|
|
2173
|
+
if (sanitizeDOMValue) {
|
|
2174
|
+
value = sanitizeDOMValue(value, binding.target, binding.kind, node);
|
|
2175
|
+
}
|
|
2176
|
+
if (binding.kind == "attribute") {
|
|
2177
|
+
inst._valueToNodeAttribute(
|
|
2178
|
+
/** @type {Element} */
|
|
2179
|
+
node,
|
|
2180
|
+
value,
|
|
2181
|
+
binding.target
|
|
2182
|
+
);
|
|
2183
|
+
} else {
|
|
2184
|
+
let prop = binding.target;
|
|
2185
|
+
if (node.__isPropertyEffectsClient && node.__dataHasAccessor && node.__dataHasAccessor[prop]) {
|
|
2186
|
+
if (!node[TYPES.READ_ONLY] || !node[TYPES.READ_ONLY][prop]) {
|
|
2187
|
+
if (node._setPendingProperty(prop, value)) {
|
|
2188
|
+
inst._enqueueClient(node);
|
|
2189
|
+
}
|
|
2190
|
+
}
|
|
2191
|
+
} else {
|
|
2192
|
+
inst._setUnmanagedPropertyToNode(node, prop, value);
|
|
2193
|
+
}
|
|
2194
|
+
}
|
|
2195
|
+
}
|
|
2196
|
+
function computeBindingValue(node, value, binding, part) {
|
|
2197
|
+
if (binding.isCompound) {
|
|
2198
|
+
let storage = node.__dataCompoundStorage[binding.target];
|
|
2199
|
+
storage[part.compoundIndex] = value;
|
|
2200
|
+
value = storage.join("");
|
|
2201
|
+
}
|
|
2202
|
+
if (binding.kind !== "attribute") {
|
|
2203
|
+
if (binding.target === "textContent" || binding.target === "value" && (node.localName === "input" || node.localName === "textarea")) {
|
|
2204
|
+
value = value == void 0 ? "" : value;
|
|
2205
|
+
}
|
|
2206
|
+
}
|
|
2207
|
+
return value;
|
|
2208
|
+
}
|
|
2209
|
+
function shouldAddListener(binding) {
|
|
2210
|
+
return Boolean(binding.target) && binding.kind != "attribute" && binding.kind != "text" && !binding.isCompound && binding.parts[0].mode === "{";
|
|
2211
|
+
}
|
|
2212
|
+
function setupBindings(inst, templateInfo) {
|
|
2213
|
+
let { nodeList, nodeInfoList } = templateInfo;
|
|
2214
|
+
if (nodeInfoList.length) {
|
|
2215
|
+
for (let i = 0; i < nodeInfoList.length; i++) {
|
|
2216
|
+
let info = nodeInfoList[i];
|
|
2217
|
+
let node = nodeList[i];
|
|
2218
|
+
let bindings = info.bindings;
|
|
2219
|
+
if (bindings) {
|
|
2220
|
+
for (let i2 = 0; i2 < bindings.length; i2++) {
|
|
2221
|
+
let binding = bindings[i2];
|
|
2222
|
+
setupCompoundStorage(node, binding);
|
|
2223
|
+
addNotifyListener(node, inst, binding);
|
|
2224
|
+
}
|
|
2225
|
+
}
|
|
2226
|
+
node.__dataHost = inst;
|
|
2227
|
+
}
|
|
2228
|
+
}
|
|
2229
|
+
}
|
|
2230
|
+
function setupCompoundStorage(node, binding) {
|
|
2231
|
+
if (binding.isCompound) {
|
|
2232
|
+
let storage = node.__dataCompoundStorage || (node.__dataCompoundStorage = {});
|
|
2233
|
+
let parts = binding.parts;
|
|
2234
|
+
let literals = new Array(parts.length);
|
|
2235
|
+
for (let j = 0; j < parts.length; j++) {
|
|
2236
|
+
literals[j] = parts[j].literal;
|
|
2237
|
+
}
|
|
2238
|
+
let target = binding.target;
|
|
2239
|
+
storage[target] = literals;
|
|
2240
|
+
if (binding.literal && binding.kind == "property") {
|
|
2241
|
+
if (target === "className") {
|
|
2242
|
+
node = wrap(node);
|
|
2243
|
+
}
|
|
2244
|
+
node[target] = binding.literal;
|
|
2245
|
+
}
|
|
2246
|
+
}
|
|
2247
|
+
}
|
|
2248
|
+
function addNotifyListener(node, inst, binding) {
|
|
2249
|
+
if (binding.listenerEvent) {
|
|
2250
|
+
let part = binding.parts[0];
|
|
2251
|
+
node.addEventListener(binding.listenerEvent, function(e) {
|
|
2252
|
+
handleNotification(e, inst, binding.target, part.source, part.negate);
|
|
2253
|
+
});
|
|
2254
|
+
}
|
|
2255
|
+
}
|
|
2256
|
+
function createMethodEffect(model, sig, type, effectFn, methodInfo, dynamicFn) {
|
|
2257
|
+
dynamicFn = sig.static || dynamicFn && (typeof dynamicFn !== "object" || dynamicFn[sig.methodName]);
|
|
2258
|
+
let info = {
|
|
2259
|
+
methodName: sig.methodName,
|
|
2260
|
+
args: sig.args,
|
|
2261
|
+
methodInfo,
|
|
2262
|
+
dynamicFn
|
|
2263
|
+
};
|
|
2264
|
+
for (let i = 0, arg; i < sig.args.length && (arg = sig.args[i]); i++) {
|
|
2265
|
+
if (!arg.literal) {
|
|
2266
|
+
model._addPropertyEffect(arg.rootProperty, type, {
|
|
2267
|
+
fn: effectFn,
|
|
2268
|
+
info,
|
|
2269
|
+
trigger: arg
|
|
2270
|
+
});
|
|
2271
|
+
}
|
|
2272
|
+
}
|
|
2273
|
+
if (dynamicFn) {
|
|
2274
|
+
model._addPropertyEffect(sig.methodName, type, {
|
|
2275
|
+
fn: effectFn,
|
|
2276
|
+
info
|
|
2277
|
+
});
|
|
2278
|
+
}
|
|
2279
|
+
return info;
|
|
2280
|
+
}
|
|
2281
|
+
function runMethodEffect(inst, property, props, oldProps, info) {
|
|
2282
|
+
let context = inst._methodHost || inst;
|
|
2283
|
+
let fn = context[info.methodName];
|
|
2284
|
+
if (fn) {
|
|
2285
|
+
let args = inst._marshalArgs(info.args, property, props);
|
|
2286
|
+
return args === NOOP ? NOOP : fn.apply(context, args);
|
|
2287
|
+
} else if (!info.dynamicFn) {
|
|
2288
|
+
console.warn("method `" + info.methodName + "` not defined");
|
|
2289
|
+
}
|
|
2290
|
+
}
|
|
2291
|
+
var emptyArray = [];
|
|
2292
|
+
var IDENT = "(?:[a-zA-Z_$][\\w.:$\\-*]*)";
|
|
2293
|
+
var NUMBER = "(?:[-+]?[0-9]*\\.?[0-9]+(?:[eE][-+]?[0-9]+)?)";
|
|
2294
|
+
var SQUOTE_STRING = "(?:'(?:[^'\\\\]|\\\\.)*')";
|
|
2295
|
+
var DQUOTE_STRING = '(?:"(?:[^"\\\\]|\\\\.)*")';
|
|
2296
|
+
var STRING = "(?:" + SQUOTE_STRING + "|" + DQUOTE_STRING + ")";
|
|
2297
|
+
var ARGUMENT = "(?:(" + IDENT + "|" + NUMBER + "|" + STRING + ")\\s*)";
|
|
2298
|
+
var ARGUMENTS = "(?:" + ARGUMENT + "(?:,\\s*" + ARGUMENT + ")*)";
|
|
2299
|
+
var ARGUMENT_LIST = "(?:\\(\\s*(?:" + ARGUMENTS + "?)\\)\\s*)";
|
|
2300
|
+
var BINDING = "(" + IDENT + "\\s*" + ARGUMENT_LIST + "?)";
|
|
2301
|
+
var OPEN_BRACKET = "(\\[\\[|{{)\\s*";
|
|
2302
|
+
var CLOSE_BRACKET = "(?:]]|}})";
|
|
2303
|
+
var NEGATE = "(?:(!)\\s*)?";
|
|
2304
|
+
var EXPRESSION = OPEN_BRACKET + NEGATE + BINDING + CLOSE_BRACKET;
|
|
2305
|
+
var bindingRegex = new RegExp(EXPRESSION, "g");
|
|
2306
|
+
function literalFromParts(parts) {
|
|
2307
|
+
let s = "";
|
|
2308
|
+
for (let i = 0; i < parts.length; i++) {
|
|
2309
|
+
let literal = parts[i].literal;
|
|
2310
|
+
s += literal || "";
|
|
2311
|
+
}
|
|
2312
|
+
return s;
|
|
2313
|
+
}
|
|
2314
|
+
function parseMethod(expression) {
|
|
2315
|
+
let m = expression.match(/([^\s]+?)\(([\s\S]*)\)/);
|
|
2316
|
+
if (m) {
|
|
2317
|
+
let methodName = m[1];
|
|
2318
|
+
let sig = { methodName, static: true, args: emptyArray };
|
|
2319
|
+
if (m[2].trim()) {
|
|
2320
|
+
let args = m[2].replace(/\\,/g, ",").split(",");
|
|
2321
|
+
return parseArgs(args, sig);
|
|
2322
|
+
} else {
|
|
2323
|
+
return sig;
|
|
2324
|
+
}
|
|
2325
|
+
}
|
|
2326
|
+
return null;
|
|
2327
|
+
}
|
|
2328
|
+
function parseArgs(argList, sig) {
|
|
2329
|
+
sig.args = argList.map(function(rawArg) {
|
|
2330
|
+
let arg = parseArg(rawArg);
|
|
2331
|
+
if (!arg.literal) {
|
|
2332
|
+
sig.static = false;
|
|
2333
|
+
}
|
|
2334
|
+
return arg;
|
|
2335
|
+
}, this);
|
|
2336
|
+
return sig;
|
|
2337
|
+
}
|
|
2338
|
+
function parseArg(rawArg) {
|
|
2339
|
+
let arg = rawArg.trim().replace(/,/g, ",").replace(/\\(.)/g, "$1");
|
|
2340
|
+
let a = {
|
|
2341
|
+
name: arg,
|
|
2342
|
+
value: "",
|
|
2343
|
+
literal: false
|
|
2344
|
+
};
|
|
2345
|
+
let fc = arg[0];
|
|
2346
|
+
if (fc === "-") {
|
|
2347
|
+
fc = arg[1];
|
|
2348
|
+
}
|
|
2349
|
+
if (fc >= "0" && fc <= "9") {
|
|
2350
|
+
fc = "#";
|
|
2351
|
+
}
|
|
2352
|
+
switch (fc) {
|
|
2353
|
+
case "'":
|
|
2354
|
+
case '"':
|
|
2355
|
+
a.value = arg.slice(1, -1);
|
|
2356
|
+
a.literal = true;
|
|
2357
|
+
break;
|
|
2358
|
+
case "#":
|
|
2359
|
+
a.value = Number(arg);
|
|
2360
|
+
a.literal = true;
|
|
2361
|
+
break;
|
|
2362
|
+
}
|
|
2363
|
+
if (!a.literal) {
|
|
2364
|
+
a.rootProperty = root(arg);
|
|
2365
|
+
a.structured = isPath(arg);
|
|
2366
|
+
if (a.structured) {
|
|
2367
|
+
a.wildcard = arg.slice(-2) == ".*";
|
|
2368
|
+
if (a.wildcard) {
|
|
2369
|
+
a.name = arg.slice(0, -2);
|
|
2370
|
+
}
|
|
2371
|
+
}
|
|
2372
|
+
}
|
|
2373
|
+
return a;
|
|
2374
|
+
}
|
|
2375
|
+
function getArgValue(data, props, path) {
|
|
2376
|
+
let value = get(data, path);
|
|
2377
|
+
if (value === void 0) {
|
|
2378
|
+
value = props[path];
|
|
2379
|
+
}
|
|
2380
|
+
return value;
|
|
2381
|
+
}
|
|
2382
|
+
function notifySplices(inst, array, path, splices) {
|
|
2383
|
+
const splicesData = { indexSplices: splices };
|
|
2384
|
+
if (legacyUndefined && !inst._overrideLegacyUndefined) {
|
|
2385
|
+
array.splices = splicesData;
|
|
2386
|
+
}
|
|
2387
|
+
inst.notifyPath(path + ".splices", splicesData);
|
|
2388
|
+
inst.notifyPath(path + ".length", array.length);
|
|
2389
|
+
if (legacyUndefined && !inst._overrideLegacyUndefined) {
|
|
2390
|
+
splicesData.indexSplices = [];
|
|
2391
|
+
}
|
|
2392
|
+
}
|
|
2393
|
+
function notifySplice(inst, array, path, index, addedCount, removed) {
|
|
2394
|
+
notifySplices(inst, array, path, [{
|
|
2395
|
+
index,
|
|
2396
|
+
addedCount,
|
|
2397
|
+
removed,
|
|
2398
|
+
object: array,
|
|
2399
|
+
type: "splice"
|
|
2400
|
+
}]);
|
|
2401
|
+
}
|
|
2402
|
+
function upper(name) {
|
|
2403
|
+
return name[0].toUpperCase() + name.substring(1);
|
|
2404
|
+
}
|
|
2405
|
+
var PropertyEffects = dedupingMixin((superClass) => {
|
|
2406
|
+
const propertyEffectsBase = TemplateStamp(PropertyAccessors(superClass));
|
|
2407
|
+
class PropertyEffects2 extends propertyEffectsBase {
|
|
2408
|
+
constructor() {
|
|
2409
|
+
super();
|
|
2410
|
+
this.__isPropertyEffectsClient = true;
|
|
2411
|
+
this.__dataClientsReady;
|
|
2412
|
+
this.__dataPendingClients;
|
|
2413
|
+
this.__dataToNotify;
|
|
2414
|
+
this.__dataLinkedPaths;
|
|
2415
|
+
this.__dataHasPaths;
|
|
2416
|
+
this.__dataCompoundStorage;
|
|
2417
|
+
this.__dataHost;
|
|
2418
|
+
this.__dataTemp;
|
|
2419
|
+
this.__dataClientsInitialized;
|
|
2420
|
+
this.__data;
|
|
2421
|
+
this.__dataPending;
|
|
2422
|
+
this.__dataOld;
|
|
2423
|
+
this.__computeEffects;
|
|
2424
|
+
this.__computeInfo;
|
|
2425
|
+
this.__reflectEffects;
|
|
2426
|
+
this.__notifyEffects;
|
|
2427
|
+
this.__propagateEffects;
|
|
2428
|
+
this.__observeEffects;
|
|
2429
|
+
this.__readOnly;
|
|
2430
|
+
this.__templateInfo;
|
|
2431
|
+
this._overrideLegacyUndefined;
|
|
2432
|
+
}
|
|
2433
|
+
get PROPERTY_EFFECT_TYPES() {
|
|
2434
|
+
return TYPES;
|
|
2435
|
+
}
|
|
2436
|
+
/**
|
|
2437
|
+
* @override
|
|
2438
|
+
* @return {void}
|
|
2439
|
+
*/
|
|
2440
|
+
_initializeProperties() {
|
|
2441
|
+
super._initializeProperties();
|
|
2442
|
+
this._registerHost();
|
|
2443
|
+
this.__dataClientsReady = false;
|
|
2444
|
+
this.__dataPendingClients = null;
|
|
2445
|
+
this.__dataToNotify = null;
|
|
2446
|
+
this.__dataLinkedPaths = null;
|
|
2447
|
+
this.__dataHasPaths = false;
|
|
2448
|
+
this.__dataCompoundStorage = this.__dataCompoundStorage || null;
|
|
2449
|
+
this.__dataHost = this.__dataHost || null;
|
|
2450
|
+
this.__dataTemp = {};
|
|
2451
|
+
this.__dataClientsInitialized = false;
|
|
2452
|
+
}
|
|
2453
|
+
_registerHost() {
|
|
2454
|
+
if (hostStack.length) {
|
|
2455
|
+
let host = hostStack[hostStack.length - 1];
|
|
2456
|
+
host._enqueueClient(this);
|
|
2457
|
+
this.__dataHost = host;
|
|
2458
|
+
}
|
|
2459
|
+
}
|
|
2460
|
+
/**
|
|
2461
|
+
* Overrides `PropertyAccessors` implementation to provide a
|
|
2462
|
+
* more efficient implementation of initializing properties from
|
|
2463
|
+
* the prototype on the instance.
|
|
2464
|
+
*
|
|
2465
|
+
* @override
|
|
2466
|
+
* @param {Object} props Properties to initialize on the prototype
|
|
2467
|
+
* @return {void}
|
|
2468
|
+
*/
|
|
2469
|
+
_initializeProtoProperties(props) {
|
|
2470
|
+
this.__data = Object.create(props);
|
|
2471
|
+
this.__dataPending = Object.create(props);
|
|
2472
|
+
this.__dataOld = {};
|
|
2473
|
+
}
|
|
2474
|
+
/**
|
|
2475
|
+
* Overrides `PropertyAccessors` implementation to avoid setting
|
|
2476
|
+
* `_setProperty`'s `shouldNotify: true`.
|
|
2477
|
+
*
|
|
2478
|
+
* @override
|
|
2479
|
+
* @param {Object} props Properties to initialize on the instance
|
|
2480
|
+
* @return {void}
|
|
2481
|
+
*/
|
|
2482
|
+
_initializeInstanceProperties(props) {
|
|
2483
|
+
let readOnly = this[TYPES.READ_ONLY];
|
|
2484
|
+
for (let prop in props) {
|
|
2485
|
+
if (!readOnly || !readOnly[prop]) {
|
|
2486
|
+
this.__dataPending = this.__dataPending || {};
|
|
2487
|
+
this.__dataOld = this.__dataOld || {};
|
|
2488
|
+
this.__data[prop] = this.__dataPending[prop] = props[prop];
|
|
2489
|
+
}
|
|
2490
|
+
}
|
|
2491
|
+
}
|
|
2492
|
+
// Prototype setup ----------------------------------------
|
|
2493
|
+
/**
|
|
2494
|
+
* Equivalent to static `addPropertyEffect` API but can be called on
|
|
2495
|
+
* an instance to add effects at runtime. See that method for
|
|
2496
|
+
* full API docs.
|
|
2497
|
+
*
|
|
2498
|
+
* @override
|
|
2499
|
+
* @param {string} property Property that should trigger the effect
|
|
2500
|
+
* @param {string} type Effect type, from this.PROPERTY_EFFECT_TYPES
|
|
2501
|
+
* @param {Object=} effect Effect metadata object
|
|
2502
|
+
* @return {void}
|
|
2503
|
+
* @protected
|
|
2504
|
+
*/
|
|
2505
|
+
_addPropertyEffect(property, type, effect) {
|
|
2506
|
+
this._createPropertyAccessor(property, type == TYPES.READ_ONLY);
|
|
2507
|
+
let effects = ensureOwnEffectMap(this, type, true)[property];
|
|
2508
|
+
if (!effects) {
|
|
2509
|
+
effects = this[type][property] = [];
|
|
2510
|
+
}
|
|
2511
|
+
effects.push(effect);
|
|
2512
|
+
}
|
|
2513
|
+
/**
|
|
2514
|
+
* Removes the given property effect.
|
|
2515
|
+
*
|
|
2516
|
+
* @override
|
|
2517
|
+
* @param {string} property Property the effect was associated with
|
|
2518
|
+
* @param {string} type Effect type, from this.PROPERTY_EFFECT_TYPES
|
|
2519
|
+
* @param {Object=} effect Effect metadata object to remove
|
|
2520
|
+
* @return {void}
|
|
2521
|
+
*/
|
|
2522
|
+
_removePropertyEffect(property, type, effect) {
|
|
2523
|
+
let effects = ensureOwnEffectMap(this, type, true)[property];
|
|
2524
|
+
let idx = effects.indexOf(effect);
|
|
2525
|
+
if (idx >= 0) {
|
|
2526
|
+
effects.splice(idx, 1);
|
|
2527
|
+
}
|
|
2528
|
+
}
|
|
2529
|
+
/**
|
|
2530
|
+
* Returns whether the current prototype/instance has a property effect
|
|
2531
|
+
* of a certain type.
|
|
2532
|
+
*
|
|
2533
|
+
* @override
|
|
2534
|
+
* @param {string} property Property name
|
|
2535
|
+
* @param {string=} type Effect type, from this.PROPERTY_EFFECT_TYPES
|
|
2536
|
+
* @return {boolean} True if the prototype/instance has an effect of this
|
|
2537
|
+
* type
|
|
2538
|
+
* @protected
|
|
2539
|
+
*/
|
|
2540
|
+
_hasPropertyEffect(property, type) {
|
|
2541
|
+
let effects = this[type];
|
|
2542
|
+
return Boolean(effects && effects[property]);
|
|
2543
|
+
}
|
|
2544
|
+
/**
|
|
2545
|
+
* Returns whether the current prototype/instance has a "read only"
|
|
2546
|
+
* accessor for the given property.
|
|
2547
|
+
*
|
|
2548
|
+
* @override
|
|
2549
|
+
* @param {string} property Property name
|
|
2550
|
+
* @return {boolean} True if the prototype/instance has an effect of this
|
|
2551
|
+
* type
|
|
2552
|
+
* @protected
|
|
2553
|
+
*/
|
|
2554
|
+
_hasReadOnlyEffect(property) {
|
|
2555
|
+
return this._hasPropertyEffect(property, TYPES.READ_ONLY);
|
|
2556
|
+
}
|
|
2557
|
+
/**
|
|
2558
|
+
* Returns whether the current prototype/instance has a "notify"
|
|
2559
|
+
* property effect for the given property.
|
|
2560
|
+
*
|
|
2561
|
+
* @override
|
|
2562
|
+
* @param {string} property Property name
|
|
2563
|
+
* @return {boolean} True if the prototype/instance has an effect of this
|
|
2564
|
+
* type
|
|
2565
|
+
* @protected
|
|
2566
|
+
*/
|
|
2567
|
+
_hasNotifyEffect(property) {
|
|
2568
|
+
return this._hasPropertyEffect(property, TYPES.NOTIFY);
|
|
2569
|
+
}
|
|
2570
|
+
/**
|
|
2571
|
+
* Returns whether the current prototype/instance has a "reflect to
|
|
2572
|
+
* attribute" property effect for the given property.
|
|
2573
|
+
*
|
|
2574
|
+
* @override
|
|
2575
|
+
* @param {string} property Property name
|
|
2576
|
+
* @return {boolean} True if the prototype/instance has an effect of this
|
|
2577
|
+
* type
|
|
2578
|
+
* @protected
|
|
2579
|
+
*/
|
|
2580
|
+
_hasReflectEffect(property) {
|
|
2581
|
+
return this._hasPropertyEffect(property, TYPES.REFLECT);
|
|
2582
|
+
}
|
|
2583
|
+
/**
|
|
2584
|
+
* Returns whether the current prototype/instance has a "computed"
|
|
2585
|
+
* property effect for the given property.
|
|
2586
|
+
*
|
|
2587
|
+
* @override
|
|
2588
|
+
* @param {string} property Property name
|
|
2589
|
+
* @return {boolean} True if the prototype/instance has an effect of this
|
|
2590
|
+
* type
|
|
2591
|
+
* @protected
|
|
2592
|
+
*/
|
|
2593
|
+
_hasComputedEffect(property) {
|
|
2594
|
+
return this._hasPropertyEffect(property, TYPES.COMPUTE);
|
|
2595
|
+
}
|
|
2596
|
+
// Runtime ----------------------------------------
|
|
2597
|
+
/**
|
|
2598
|
+
* Sets a pending property or path. If the root property of the path in
|
|
2599
|
+
* question had no accessor, the path is set, otherwise it is enqueued
|
|
2600
|
+
* via `_setPendingProperty`.
|
|
2601
|
+
*
|
|
2602
|
+
* This function isolates relatively expensive functionality necessary
|
|
2603
|
+
* for the public API (`set`, `setProperties`, `notifyPath`, and property
|
|
2604
|
+
* change listeners via {{...}} bindings), such that it is only done
|
|
2605
|
+
* when paths enter the system, and not at every propagation step. It
|
|
2606
|
+
* also sets a `__dataHasPaths` flag on the instance which is used to
|
|
2607
|
+
* fast-path slower path-matching code in the property effects host paths.
|
|
2608
|
+
*
|
|
2609
|
+
* `path` can be a path string or array of path parts as accepted by the
|
|
2610
|
+
* public API.
|
|
2611
|
+
*
|
|
2612
|
+
* @override
|
|
2613
|
+
* @param {string | !Array<number|string>} path Path to set
|
|
2614
|
+
* @param {*} value Value to set
|
|
2615
|
+
* @param {boolean=} shouldNotify Set to true if this change should
|
|
2616
|
+
* cause a property notification event dispatch
|
|
2617
|
+
* @param {boolean=} isPathNotification If the path being set is a path
|
|
2618
|
+
* notification of an already changed value, as opposed to a request
|
|
2619
|
+
* to set and notify the change. In the latter `false` case, a dirty
|
|
2620
|
+
* check is performed and then the value is set to the path before
|
|
2621
|
+
* enqueuing the pending property change.
|
|
2622
|
+
* @return {boolean} Returns true if the property/path was enqueued in
|
|
2623
|
+
* the pending changes bag.
|
|
2624
|
+
* @protected
|
|
2625
|
+
*/
|
|
2626
|
+
_setPendingPropertyOrPath(path, value, shouldNotify, isPathNotification) {
|
|
2627
|
+
if (isPathNotification || root(Array.isArray(path) ? path[0] : path) !== path) {
|
|
2628
|
+
if (!isPathNotification) {
|
|
2629
|
+
let old = get(this, path);
|
|
2630
|
+
path = /** @type {string} */
|
|
2631
|
+
set(this, path, value);
|
|
2632
|
+
if (!path || !super._shouldPropertyChange(path, value, old)) {
|
|
2633
|
+
return false;
|
|
2634
|
+
}
|
|
2635
|
+
}
|
|
2636
|
+
this.__dataHasPaths = true;
|
|
2637
|
+
if (this._setPendingProperty(
|
|
2638
|
+
/**@type{string}*/
|
|
2639
|
+
path,
|
|
2640
|
+
value,
|
|
2641
|
+
shouldNotify
|
|
2642
|
+
)) {
|
|
2643
|
+
computeLinkedPaths(
|
|
2644
|
+
this,
|
|
2645
|
+
/**@type{string}*/
|
|
2646
|
+
path,
|
|
2647
|
+
value
|
|
2648
|
+
);
|
|
2649
|
+
return true;
|
|
2650
|
+
}
|
|
2651
|
+
} else {
|
|
2652
|
+
if (this.__dataHasAccessor && this.__dataHasAccessor[path]) {
|
|
2653
|
+
return this._setPendingProperty(
|
|
2654
|
+
/**@type{string}*/
|
|
2655
|
+
path,
|
|
2656
|
+
value,
|
|
2657
|
+
shouldNotify
|
|
2658
|
+
);
|
|
2659
|
+
} else {
|
|
2660
|
+
this[path] = value;
|
|
2661
|
+
}
|
|
2662
|
+
}
|
|
2663
|
+
return false;
|
|
2664
|
+
}
|
|
2665
|
+
/**
|
|
2666
|
+
* Applies a value to a non-Polymer element/node's property.
|
|
2667
|
+
*
|
|
2668
|
+
* The implementation makes a best-effort at binding interop:
|
|
2669
|
+
* Some native element properties have side-effects when
|
|
2670
|
+
* re-setting the same value (e.g. setting `<input>.value` resets the
|
|
2671
|
+
* cursor position), so we do a dirty-check before setting the value.
|
|
2672
|
+
* However, for better interop with non-Polymer custom elements that
|
|
2673
|
+
* accept objects, we explicitly re-set object changes coming from the
|
|
2674
|
+
* Polymer world (which may include deep object changes without the
|
|
2675
|
+
* top reference changing), erring on the side of providing more
|
|
2676
|
+
* information.
|
|
2677
|
+
*
|
|
2678
|
+
* Users may override this method to provide alternate approaches.
|
|
2679
|
+
*
|
|
2680
|
+
* @override
|
|
2681
|
+
* @param {!Node} node The node to set a property on
|
|
2682
|
+
* @param {string} prop The property to set
|
|
2683
|
+
* @param {*} value The value to set
|
|
2684
|
+
* @return {void}
|
|
2685
|
+
* @protected
|
|
2686
|
+
*/
|
|
2687
|
+
_setUnmanagedPropertyToNode(node, prop, value) {
|
|
2688
|
+
if (value !== node[prop] || typeof value == "object") {
|
|
2689
|
+
if (prop === "className") {
|
|
2690
|
+
node = /** @type {!Node} */
|
|
2691
|
+
wrap(node);
|
|
2692
|
+
}
|
|
2693
|
+
node[prop] = value;
|
|
2694
|
+
}
|
|
2695
|
+
}
|
|
2696
|
+
/**
|
|
2697
|
+
* Overrides the `PropertiesChanged` implementation to introduce special
|
|
2698
|
+
* dirty check logic depending on the property & value being set:
|
|
2699
|
+
*
|
|
2700
|
+
* 1. Any value set to a path (e.g. 'obj.prop': 42 or 'obj.prop': {...})
|
|
2701
|
+
* Stored in `__dataTemp`, dirty checked against `__dataTemp`
|
|
2702
|
+
* 2. Object set to simple property (e.g. 'prop': {...})
|
|
2703
|
+
* Stored in `__dataTemp` and `__data`, dirty checked against
|
|
2704
|
+
* `__dataTemp` by default implementation of `_shouldPropertyChange`
|
|
2705
|
+
* 3. Primitive value set to simple property (e.g. 'prop': 42)
|
|
2706
|
+
* Stored in `__data`, dirty checked against `__data`
|
|
2707
|
+
*
|
|
2708
|
+
* The dirty-check is important to prevent cycles due to two-way
|
|
2709
|
+
* notification, but paths and objects are only dirty checked against any
|
|
2710
|
+
* previous value set during this turn via a "temporary cache" that is
|
|
2711
|
+
* cleared when the last `_propertiesChanged` exits. This is so:
|
|
2712
|
+
* a. any cached array paths (e.g. 'array.3.prop') may be invalidated
|
|
2713
|
+
* due to array mutations like shift/unshift/splice; this is fine
|
|
2714
|
+
* since path changes are dirty-checked at user entry points like `set`
|
|
2715
|
+
* b. dirty-checking for objects only lasts one turn to allow the user
|
|
2716
|
+
* to mutate the object in-place and re-set it with the same identity
|
|
2717
|
+
* and have all sub-properties re-propagated in a subsequent turn.
|
|
2718
|
+
*
|
|
2719
|
+
* The temp cache is not necessarily sufficient to prevent invalid array
|
|
2720
|
+
* paths, since a splice can happen during the same turn (with pathological
|
|
2721
|
+
* user code); we could introduce a "fixup" for temporarily cached array
|
|
2722
|
+
* paths if needed: https://github.com/Polymer/polymer/issues/4227
|
|
2723
|
+
*
|
|
2724
|
+
* @override
|
|
2725
|
+
* @param {string} property Name of the property
|
|
2726
|
+
* @param {*} value Value to set
|
|
2727
|
+
* @param {boolean=} shouldNotify True if property should fire notification
|
|
2728
|
+
* event (applies only for `notify: true` properties)
|
|
2729
|
+
* @return {boolean} Returns true if the property changed
|
|
2730
|
+
*/
|
|
2731
|
+
_setPendingProperty(property, value, shouldNotify) {
|
|
2732
|
+
let propIsPath = this.__dataHasPaths && isPath(property);
|
|
2733
|
+
let prevProps = propIsPath ? this.__dataTemp : this.__data;
|
|
2734
|
+
if (this._shouldPropertyChange(property, value, prevProps[property])) {
|
|
2735
|
+
if (!this.__dataPending) {
|
|
2736
|
+
this.__dataPending = {};
|
|
2737
|
+
this.__dataOld = {};
|
|
2738
|
+
}
|
|
2739
|
+
if (!(property in this.__dataOld)) {
|
|
2740
|
+
this.__dataOld[property] = this.__data[property];
|
|
2741
|
+
}
|
|
2742
|
+
if (propIsPath) {
|
|
2743
|
+
this.__dataTemp[property] = value;
|
|
2744
|
+
} else {
|
|
2745
|
+
this.__data[property] = value;
|
|
2746
|
+
}
|
|
2747
|
+
this.__dataPending[property] = value;
|
|
2748
|
+
if (propIsPath || this[TYPES.NOTIFY] && this[TYPES.NOTIFY][property]) {
|
|
2749
|
+
this.__dataToNotify = this.__dataToNotify || {};
|
|
2750
|
+
this.__dataToNotify[property] = shouldNotify;
|
|
2751
|
+
}
|
|
2752
|
+
return true;
|
|
2753
|
+
}
|
|
2754
|
+
return false;
|
|
2755
|
+
}
|
|
2756
|
+
/**
|
|
2757
|
+
* Overrides base implementation to ensure all accessors set `shouldNotify`
|
|
2758
|
+
* to true, for per-property notification tracking.
|
|
2759
|
+
*
|
|
2760
|
+
* @override
|
|
2761
|
+
* @param {string} property Name of the property
|
|
2762
|
+
* @param {*} value Value to set
|
|
2763
|
+
* @return {void}
|
|
2764
|
+
*/
|
|
2765
|
+
_setProperty(property, value) {
|
|
2766
|
+
if (this._setPendingProperty(property, value, true)) {
|
|
2767
|
+
this._invalidateProperties();
|
|
2768
|
+
}
|
|
2769
|
+
}
|
|
2770
|
+
/**
|
|
2771
|
+
* Overrides `PropertyAccessor`'s default async queuing of
|
|
2772
|
+
* `_propertiesChanged`: if `__dataReady` is false (has not yet been
|
|
2773
|
+
* manually flushed), the function no-ops; otherwise flushes
|
|
2774
|
+
* `_propertiesChanged` synchronously.
|
|
2775
|
+
*
|
|
2776
|
+
* @override
|
|
2777
|
+
* @return {void}
|
|
2778
|
+
*/
|
|
2779
|
+
_invalidateProperties() {
|
|
2780
|
+
if (this.__dataReady) {
|
|
2781
|
+
this._flushProperties();
|
|
2782
|
+
}
|
|
2783
|
+
}
|
|
2784
|
+
/**
|
|
2785
|
+
* Enqueues the given client on a list of pending clients, whose
|
|
2786
|
+
* pending property changes can later be flushed via a call to
|
|
2787
|
+
* `_flushClients`.
|
|
2788
|
+
*
|
|
2789
|
+
* @override
|
|
2790
|
+
* @param {Object} client PropertyEffects client to enqueue
|
|
2791
|
+
* @return {void}
|
|
2792
|
+
* @protected
|
|
2793
|
+
*/
|
|
2794
|
+
_enqueueClient(client) {
|
|
2795
|
+
this.__dataPendingClients = this.__dataPendingClients || [];
|
|
2796
|
+
if (client !== this) {
|
|
2797
|
+
this.__dataPendingClients.push(client);
|
|
2798
|
+
}
|
|
2799
|
+
}
|
|
2800
|
+
/**
|
|
2801
|
+
* Flushes any clients previously enqueued via `_enqueueClient`, causing
|
|
2802
|
+
* their `_flushProperties` method to run.
|
|
2803
|
+
*
|
|
2804
|
+
* @override
|
|
2805
|
+
* @return {void}
|
|
2806
|
+
* @protected
|
|
2807
|
+
*/
|
|
2808
|
+
_flushClients() {
|
|
2809
|
+
if (!this.__dataClientsReady) {
|
|
2810
|
+
this.__dataClientsReady = true;
|
|
2811
|
+
this._readyClients();
|
|
2812
|
+
this.__dataReady = true;
|
|
2813
|
+
} else {
|
|
2814
|
+
this.__enableOrFlushClients();
|
|
2815
|
+
}
|
|
2816
|
+
}
|
|
2817
|
+
// NOTE: We ensure clients either enable or flush as appropriate. This
|
|
2818
|
+
// handles two corner cases:
|
|
2819
|
+
// (1) clients flush properly when connected/enabled before the host
|
|
2820
|
+
// enables; e.g.
|
|
2821
|
+
// (a) Templatize stamps with no properties and does not flush and
|
|
2822
|
+
// (b) the instance is inserted into dom and
|
|
2823
|
+
// (c) then the instance flushes.
|
|
2824
|
+
// (2) clients enable properly when not connected/enabled when the host
|
|
2825
|
+
// flushes; e.g.
|
|
2826
|
+
// (a) a template is runtime stamped and not yet connected/enabled
|
|
2827
|
+
// (b) a host sets a property, causing stamped dom to flush
|
|
2828
|
+
// (c) the stamped dom enables.
|
|
2829
|
+
__enableOrFlushClients() {
|
|
2830
|
+
let clients = this.__dataPendingClients;
|
|
2831
|
+
if (clients) {
|
|
2832
|
+
this.__dataPendingClients = null;
|
|
2833
|
+
for (let i = 0; i < clients.length; i++) {
|
|
2834
|
+
let client = clients[i];
|
|
2835
|
+
if (!client.__dataEnabled) {
|
|
2836
|
+
client._enableProperties();
|
|
2837
|
+
} else if (client.__dataPending) {
|
|
2838
|
+
client._flushProperties();
|
|
2839
|
+
}
|
|
2840
|
+
}
|
|
2841
|
+
}
|
|
2842
|
+
}
|
|
2843
|
+
/**
|
|
2844
|
+
* Perform any initial setup on client dom. Called before the first
|
|
2845
|
+
* `_flushProperties` call on client dom and before any element
|
|
2846
|
+
* observers are called.
|
|
2847
|
+
*
|
|
2848
|
+
* @override
|
|
2849
|
+
* @return {void}
|
|
2850
|
+
* @protected
|
|
2851
|
+
*/
|
|
2852
|
+
_readyClients() {
|
|
2853
|
+
this.__enableOrFlushClients();
|
|
2854
|
+
}
|
|
2855
|
+
/**
|
|
2856
|
+
* Sets a bag of property changes to this instance, and
|
|
2857
|
+
* synchronously processes all effects of the properties as a batch.
|
|
2858
|
+
*
|
|
2859
|
+
* Property names must be simple properties, not paths. Batched
|
|
2860
|
+
* path propagation is not supported.
|
|
2861
|
+
*
|
|
2862
|
+
* @override
|
|
2863
|
+
* @param {Object} props Bag of one or more key-value pairs whose key is
|
|
2864
|
+
* a property and value is the new value to set for that property.
|
|
2865
|
+
* @param {boolean=} setReadOnly When true, any private values set in
|
|
2866
|
+
* `props` will be set. By default, `setProperties` will not set
|
|
2867
|
+
* `readOnly: true` root properties.
|
|
2868
|
+
* @return {void}
|
|
2869
|
+
* @public
|
|
2870
|
+
*/
|
|
2871
|
+
setProperties(props, setReadOnly) {
|
|
2872
|
+
for (let path in props) {
|
|
2873
|
+
if (setReadOnly || !this[TYPES.READ_ONLY] || !this[TYPES.READ_ONLY][path]) {
|
|
2874
|
+
this._setPendingPropertyOrPath(path, props[path], true);
|
|
2875
|
+
}
|
|
2876
|
+
}
|
|
2877
|
+
this._invalidateProperties();
|
|
2878
|
+
}
|
|
2879
|
+
/**
|
|
2880
|
+
* Overrides `PropertyAccessors` so that property accessor
|
|
2881
|
+
* side effects are not enabled until after client dom is fully ready.
|
|
2882
|
+
* Also calls `_flushClients` callback to ensure client dom is enabled
|
|
2883
|
+
* that was not enabled as a result of flushing properties.
|
|
2884
|
+
*
|
|
2885
|
+
* @override
|
|
2886
|
+
* @return {void}
|
|
2887
|
+
*/
|
|
2888
|
+
ready() {
|
|
2889
|
+
this._flushProperties();
|
|
2890
|
+
if (!this.__dataClientsReady) {
|
|
2891
|
+
this._flushClients();
|
|
2892
|
+
}
|
|
2893
|
+
if (this.__dataPending) {
|
|
2894
|
+
this._flushProperties();
|
|
2895
|
+
}
|
|
2896
|
+
}
|
|
2897
|
+
/**
|
|
2898
|
+
* Implements `PropertyAccessors`'s properties changed callback.
|
|
2899
|
+
*
|
|
2900
|
+
* Runs each class of effects for the batch of changed properties in
|
|
2901
|
+
* a specific order (compute, propagate, reflect, observe, notify).
|
|
2902
|
+
*
|
|
2903
|
+
* @override
|
|
2904
|
+
* @param {!Object} currentProps Bag of all current accessor values
|
|
2905
|
+
* @param {?Object} changedProps Bag of properties changed since the last
|
|
2906
|
+
* call to `_propertiesChanged`
|
|
2907
|
+
* @param {?Object} oldProps Bag of previous values for each property
|
|
2908
|
+
* in `changedProps`
|
|
2909
|
+
* @return {void}
|
|
2910
|
+
*/
|
|
2911
|
+
_propertiesChanged(currentProps, changedProps, oldProps) {
|
|
2912
|
+
let hasPaths = this.__dataHasPaths;
|
|
2913
|
+
this.__dataHasPaths = false;
|
|
2914
|
+
let notifyProps;
|
|
2915
|
+
runComputedEffects(this, changedProps, oldProps, hasPaths);
|
|
2916
|
+
notifyProps = this.__dataToNotify;
|
|
2917
|
+
this.__dataToNotify = null;
|
|
2918
|
+
this._propagatePropertyChanges(changedProps, oldProps, hasPaths);
|
|
2919
|
+
this._flushClients();
|
|
2920
|
+
runEffects(this, this[TYPES.REFLECT], changedProps, oldProps, hasPaths);
|
|
2921
|
+
runEffects(this, this[TYPES.OBSERVE], changedProps, oldProps, hasPaths);
|
|
2922
|
+
if (notifyProps) {
|
|
2923
|
+
runNotifyEffects(this, notifyProps, changedProps, oldProps, hasPaths);
|
|
2924
|
+
}
|
|
2925
|
+
if (this.__dataCounter == 1) {
|
|
2926
|
+
this.__dataTemp = {};
|
|
2927
|
+
}
|
|
2928
|
+
}
|
|
2929
|
+
/**
|
|
2930
|
+
* Called to propagate any property changes to stamped template nodes
|
|
2931
|
+
* managed by this element.
|
|
2932
|
+
*
|
|
2933
|
+
* @override
|
|
2934
|
+
* @param {Object} changedProps Bag of changed properties
|
|
2935
|
+
* @param {Object} oldProps Bag of previous values for changed properties
|
|
2936
|
+
* @param {boolean} hasPaths True with `props` contains one or more paths
|
|
2937
|
+
* @return {void}
|
|
2938
|
+
* @protected
|
|
2939
|
+
*/
|
|
2940
|
+
_propagatePropertyChanges(changedProps, oldProps, hasPaths) {
|
|
2941
|
+
if (this[TYPES.PROPAGATE]) {
|
|
2942
|
+
runEffects(this, this[TYPES.PROPAGATE], changedProps, oldProps, hasPaths);
|
|
2943
|
+
}
|
|
2944
|
+
if (this.__templateInfo) {
|
|
2945
|
+
this._runEffectsForTemplate(this.__templateInfo, changedProps, oldProps, hasPaths);
|
|
2946
|
+
}
|
|
2947
|
+
}
|
|
2948
|
+
_runEffectsForTemplate(templateInfo, changedProps, oldProps, hasPaths) {
|
|
2949
|
+
const baseRunEffects = (changedProps2, hasPaths2) => {
|
|
2950
|
+
runEffects(
|
|
2951
|
+
this,
|
|
2952
|
+
templateInfo.propertyEffects,
|
|
2953
|
+
changedProps2,
|
|
2954
|
+
oldProps,
|
|
2955
|
+
hasPaths2,
|
|
2956
|
+
templateInfo.nodeList
|
|
2957
|
+
);
|
|
2958
|
+
for (let info = templateInfo.firstChild; info; info = info.nextSibling) {
|
|
2959
|
+
this._runEffectsForTemplate(info, changedProps2, oldProps, hasPaths2);
|
|
2960
|
+
}
|
|
2961
|
+
};
|
|
2962
|
+
if (templateInfo.runEffects) {
|
|
2963
|
+
templateInfo.runEffects(baseRunEffects, changedProps, hasPaths);
|
|
2964
|
+
} else {
|
|
2965
|
+
baseRunEffects(changedProps, hasPaths);
|
|
2966
|
+
}
|
|
2967
|
+
}
|
|
2968
|
+
/**
|
|
2969
|
+
* Aliases one data path as another, such that path notifications from one
|
|
2970
|
+
* are routed to the other.
|
|
2971
|
+
*
|
|
2972
|
+
* @override
|
|
2973
|
+
* @param {string | !Array<string|number>} to Target path to link.
|
|
2974
|
+
* @param {string | !Array<string|number>} from Source path to link.
|
|
2975
|
+
* @return {void}
|
|
2976
|
+
* @public
|
|
2977
|
+
*/
|
|
2978
|
+
linkPaths(to, from) {
|
|
2979
|
+
to = normalize(to);
|
|
2980
|
+
from = normalize(from);
|
|
2981
|
+
this.__dataLinkedPaths = this.__dataLinkedPaths || {};
|
|
2982
|
+
this.__dataLinkedPaths[to] = from;
|
|
2983
|
+
}
|
|
2984
|
+
/**
|
|
2985
|
+
* Removes a data path alias previously established with `_linkPaths`.
|
|
2986
|
+
*
|
|
2987
|
+
* Note, the path to unlink should be the target (`to`) used when
|
|
2988
|
+
* linking the paths.
|
|
2989
|
+
*
|
|
2990
|
+
* @override
|
|
2991
|
+
* @param {string | !Array<string|number>} path Target path to unlink.
|
|
2992
|
+
* @return {void}
|
|
2993
|
+
* @public
|
|
2994
|
+
*/
|
|
2995
|
+
unlinkPaths(path) {
|
|
2996
|
+
path = normalize(path);
|
|
2997
|
+
if (this.__dataLinkedPaths) {
|
|
2998
|
+
delete this.__dataLinkedPaths[path];
|
|
2999
|
+
}
|
|
3000
|
+
}
|
|
3001
|
+
/**
|
|
3002
|
+
* Notify that an array has changed.
|
|
3003
|
+
*
|
|
3004
|
+
* Example:
|
|
3005
|
+
*
|
|
3006
|
+
* this.items = [ {name: 'Jim'}, {name: 'Todd'}, {name: 'Bill'} ];
|
|
3007
|
+
* ...
|
|
3008
|
+
* this.items.splice(1, 1, {name: 'Sam'});
|
|
3009
|
+
* this.items.push({name: 'Bob'});
|
|
3010
|
+
* this.notifySplices('items', [
|
|
3011
|
+
* { index: 1, removed: [{name: 'Todd'}], addedCount: 1,
|
|
3012
|
+
* object: this.items, type: 'splice' },
|
|
3013
|
+
* { index: 3, removed: [], addedCount: 1,
|
|
3014
|
+
* object: this.items, type: 'splice'}
|
|
3015
|
+
* ]);
|
|
3016
|
+
*
|
|
3017
|
+
* @param {string} path Path that should be notified.
|
|
3018
|
+
* @param {Array} splices Array of splice records indicating ordered
|
|
3019
|
+
* changes that occurred to the array. Each record should have the
|
|
3020
|
+
* following fields:
|
|
3021
|
+
* * index: index at which the change occurred
|
|
3022
|
+
* * removed: array of items that were removed from this index
|
|
3023
|
+
* * addedCount: number of new items added at this index
|
|
3024
|
+
* * object: a reference to the array in question
|
|
3025
|
+
* * type: the string literal 'splice'
|
|
3026
|
+
*
|
|
3027
|
+
* Note that splice records _must_ be normalized such that they are
|
|
3028
|
+
* reported in index order (raw results from `Object.observe` are not
|
|
3029
|
+
* ordered and must be normalized/merged before notifying).
|
|
3030
|
+
*
|
|
3031
|
+
* @override
|
|
3032
|
+
* @return {void}
|
|
3033
|
+
* @public
|
|
3034
|
+
*/
|
|
3035
|
+
notifySplices(path, splices) {
|
|
3036
|
+
let info = { path: "" };
|
|
3037
|
+
let array = (
|
|
3038
|
+
/** @type {Array} */
|
|
3039
|
+
get(this, path, info)
|
|
3040
|
+
);
|
|
3041
|
+
notifySplices(this, array, info.path, splices);
|
|
3042
|
+
}
|
|
3043
|
+
/**
|
|
3044
|
+
* Convenience method for reading a value from a path.
|
|
3045
|
+
*
|
|
3046
|
+
* Note, if any part in the path is undefined, this method returns
|
|
3047
|
+
* `undefined` (this method does not throw when dereferencing undefined
|
|
3048
|
+
* paths).
|
|
3049
|
+
*
|
|
3050
|
+
* @override
|
|
3051
|
+
* @param {(string|!Array<(string|number)>)} path Path to the value
|
|
3052
|
+
* to read. The path may be specified as a string (e.g. `foo.bar.baz`)
|
|
3053
|
+
* or an array of path parts (e.g. `['foo.bar', 'baz']`). Note that
|
|
3054
|
+
* bracketed expressions are not supported; string-based path parts
|
|
3055
|
+
* *must* be separated by dots. Note that when dereferencing array
|
|
3056
|
+
* indices, the index may be used as a dotted part directly
|
|
3057
|
+
* (e.g. `users.12.name` or `['users', 12, 'name']`).
|
|
3058
|
+
* @param {Object=} root Root object from which the path is evaluated.
|
|
3059
|
+
* @return {*} Value at the path, or `undefined` if any part of the path
|
|
3060
|
+
* is undefined.
|
|
3061
|
+
* @public
|
|
3062
|
+
*/
|
|
3063
|
+
get(path, root2) {
|
|
3064
|
+
return get(root2 || this, path);
|
|
3065
|
+
}
|
|
3066
|
+
/**
|
|
3067
|
+
* Convenience method for setting a value to a path and notifying any
|
|
3068
|
+
* elements bound to the same path.
|
|
3069
|
+
*
|
|
3070
|
+
* Note, if any part in the path except for the last is undefined,
|
|
3071
|
+
* this method does nothing (this method does not throw when
|
|
3072
|
+
* dereferencing undefined paths).
|
|
3073
|
+
*
|
|
3074
|
+
* @override
|
|
3075
|
+
* @param {(string|!Array<(string|number)>)} path Path to the value
|
|
3076
|
+
* to write. The path may be specified as a string (e.g. `'foo.bar.baz'`)
|
|
3077
|
+
* or an array of path parts (e.g. `['foo.bar', 'baz']`). Note that
|
|
3078
|
+
* bracketed expressions are not supported; string-based path parts
|
|
3079
|
+
* *must* be separated by dots. Note that when dereferencing array
|
|
3080
|
+
* indices, the index may be used as a dotted part directly
|
|
3081
|
+
* (e.g. `'users.12.name'` or `['users', 12, 'name']`).
|
|
3082
|
+
* @param {*} value Value to set at the specified path.
|
|
3083
|
+
* @param {Object=} root Root object from which the path is evaluated.
|
|
3084
|
+
* When specified, no notification will occur.
|
|
3085
|
+
* @return {void}
|
|
3086
|
+
* @public
|
|
3087
|
+
*/
|
|
3088
|
+
set(path, value, root2) {
|
|
3089
|
+
if (root2) {
|
|
3090
|
+
set(root2, path, value);
|
|
3091
|
+
} else {
|
|
3092
|
+
if (!this[TYPES.READ_ONLY] || !this[TYPES.READ_ONLY][
|
|
3093
|
+
/** @type {string} */
|
|
3094
|
+
path
|
|
3095
|
+
]) {
|
|
3096
|
+
if (this._setPendingPropertyOrPath(path, value, true)) {
|
|
3097
|
+
this._invalidateProperties();
|
|
3098
|
+
}
|
|
3099
|
+
}
|
|
3100
|
+
}
|
|
3101
|
+
}
|
|
3102
|
+
/**
|
|
3103
|
+
* Adds items onto the end of the array at the path specified.
|
|
3104
|
+
*
|
|
3105
|
+
* The arguments after `path` and return value match that of
|
|
3106
|
+
* `Array.prototype.push`.
|
|
3107
|
+
*
|
|
3108
|
+
* This method notifies other paths to the same array that a
|
|
3109
|
+
* splice occurred to the array.
|
|
3110
|
+
*
|
|
3111
|
+
* @override
|
|
3112
|
+
* @param {string | !Array<string|number>} path Path to array.
|
|
3113
|
+
* @param {...*} items Items to push onto array
|
|
3114
|
+
* @return {number} New length of the array.
|
|
3115
|
+
* @public
|
|
3116
|
+
*/
|
|
3117
|
+
push(path, ...items) {
|
|
3118
|
+
let info = { path: "" };
|
|
3119
|
+
let array = (
|
|
3120
|
+
/** @type {Array}*/
|
|
3121
|
+
get(this, path, info)
|
|
3122
|
+
);
|
|
3123
|
+
let len = array.length;
|
|
3124
|
+
let ret = array.push(...items);
|
|
3125
|
+
if (items.length) {
|
|
3126
|
+
notifySplice(this, array, info.path, len, items.length, []);
|
|
3127
|
+
}
|
|
3128
|
+
return ret;
|
|
3129
|
+
}
|
|
3130
|
+
/**
|
|
3131
|
+
* Removes an item from the end of array at the path specified.
|
|
3132
|
+
*
|
|
3133
|
+
* The arguments after `path` and return value match that of
|
|
3134
|
+
* `Array.prototype.pop`.
|
|
3135
|
+
*
|
|
3136
|
+
* This method notifies other paths to the same array that a
|
|
3137
|
+
* splice occurred to the array.
|
|
3138
|
+
*
|
|
3139
|
+
* @override
|
|
3140
|
+
* @param {string | !Array<string|number>} path Path to array.
|
|
3141
|
+
* @return {*} Item that was removed.
|
|
3142
|
+
* @public
|
|
3143
|
+
*/
|
|
3144
|
+
pop(path) {
|
|
3145
|
+
let info = { path: "" };
|
|
3146
|
+
let array = (
|
|
3147
|
+
/** @type {Array} */
|
|
3148
|
+
get(this, path, info)
|
|
3149
|
+
);
|
|
3150
|
+
let hadLength = Boolean(array.length);
|
|
3151
|
+
let ret = array.pop();
|
|
3152
|
+
if (hadLength) {
|
|
3153
|
+
notifySplice(this, array, info.path, array.length, 0, [ret]);
|
|
3154
|
+
}
|
|
3155
|
+
return ret;
|
|
3156
|
+
}
|
|
3157
|
+
/**
|
|
3158
|
+
* Starting from the start index specified, removes 0 or more items
|
|
3159
|
+
* from the array and inserts 0 or more new items in their place.
|
|
3160
|
+
*
|
|
3161
|
+
* The arguments after `path` and return value match that of
|
|
3162
|
+
* `Array.prototype.splice`.
|
|
3163
|
+
*
|
|
3164
|
+
* This method notifies other paths to the same array that a
|
|
3165
|
+
* splice occurred to the array.
|
|
3166
|
+
*
|
|
3167
|
+
* @override
|
|
3168
|
+
* @param {string | !Array<string|number>} path Path to array.
|
|
3169
|
+
* @param {number} start Index from which to start removing/inserting.
|
|
3170
|
+
* @param {number=} deleteCount Number of items to remove.
|
|
3171
|
+
* @param {...*} items Items to insert into array.
|
|
3172
|
+
* @return {!Array} Array of removed items.
|
|
3173
|
+
* @public
|
|
3174
|
+
*/
|
|
3175
|
+
splice(path, start, deleteCount, ...items) {
|
|
3176
|
+
let info = { path: "" };
|
|
3177
|
+
let array = (
|
|
3178
|
+
/** @type {Array} */
|
|
3179
|
+
get(this, path, info)
|
|
3180
|
+
);
|
|
3181
|
+
if (start < 0) {
|
|
3182
|
+
start = array.length - Math.floor(-start);
|
|
3183
|
+
} else if (start) {
|
|
3184
|
+
start = Math.floor(start);
|
|
3185
|
+
}
|
|
3186
|
+
let ret;
|
|
3187
|
+
if (arguments.length === 2) {
|
|
3188
|
+
ret = array.splice(start);
|
|
3189
|
+
} else {
|
|
3190
|
+
ret = array.splice(start, deleteCount, ...items);
|
|
3191
|
+
}
|
|
3192
|
+
if (items.length || ret.length) {
|
|
3193
|
+
notifySplice(this, array, info.path, start, items.length, ret);
|
|
3194
|
+
}
|
|
3195
|
+
return ret;
|
|
3196
|
+
}
|
|
3197
|
+
/**
|
|
3198
|
+
* Removes an item from the beginning of array at the path specified.
|
|
3199
|
+
*
|
|
3200
|
+
* The arguments after `path` and return value match that of
|
|
3201
|
+
* `Array.prototype.pop`.
|
|
3202
|
+
*
|
|
3203
|
+
* This method notifies other paths to the same array that a
|
|
3204
|
+
* splice occurred to the array.
|
|
3205
|
+
*
|
|
3206
|
+
* @override
|
|
3207
|
+
* @param {string | !Array<string|number>} path Path to array.
|
|
3208
|
+
* @return {*} Item that was removed.
|
|
3209
|
+
* @public
|
|
3210
|
+
*/
|
|
3211
|
+
shift(path) {
|
|
3212
|
+
let info = { path: "" };
|
|
3213
|
+
let array = (
|
|
3214
|
+
/** @type {Array} */
|
|
3215
|
+
get(this, path, info)
|
|
3216
|
+
);
|
|
3217
|
+
let hadLength = Boolean(array.length);
|
|
3218
|
+
let ret = array.shift();
|
|
3219
|
+
if (hadLength) {
|
|
3220
|
+
notifySplice(this, array, info.path, 0, 0, [ret]);
|
|
3221
|
+
}
|
|
3222
|
+
return ret;
|
|
3223
|
+
}
|
|
3224
|
+
/**
|
|
3225
|
+
* Adds items onto the beginning of the array at the path specified.
|
|
3226
|
+
*
|
|
3227
|
+
* The arguments after `path` and return value match that of
|
|
3228
|
+
* `Array.prototype.push`.
|
|
3229
|
+
*
|
|
3230
|
+
* This method notifies other paths to the same array that a
|
|
3231
|
+
* splice occurred to the array.
|
|
3232
|
+
*
|
|
3233
|
+
* @override
|
|
3234
|
+
* @param {string | !Array<string|number>} path Path to array.
|
|
3235
|
+
* @param {...*} items Items to insert info array
|
|
3236
|
+
* @return {number} New length of the array.
|
|
3237
|
+
* @public
|
|
3238
|
+
*/
|
|
3239
|
+
unshift(path, ...items) {
|
|
3240
|
+
let info = { path: "" };
|
|
3241
|
+
let array = (
|
|
3242
|
+
/** @type {Array} */
|
|
3243
|
+
get(this, path, info)
|
|
3244
|
+
);
|
|
3245
|
+
let ret = array.unshift(...items);
|
|
3246
|
+
if (items.length) {
|
|
3247
|
+
notifySplice(this, array, info.path, 0, items.length, []);
|
|
3248
|
+
}
|
|
3249
|
+
return ret;
|
|
3250
|
+
}
|
|
3251
|
+
/**
|
|
3252
|
+
* Notify that a path has changed.
|
|
3253
|
+
*
|
|
3254
|
+
* Example:
|
|
3255
|
+
*
|
|
3256
|
+
* this.item.user.name = 'Bob';
|
|
3257
|
+
* this.notifyPath('item.user.name');
|
|
3258
|
+
*
|
|
3259
|
+
* @override
|
|
3260
|
+
* @param {string} path Path that should be notified.
|
|
3261
|
+
* @param {*=} value Value at the path (optional).
|
|
3262
|
+
* @return {void}
|
|
3263
|
+
* @public
|
|
3264
|
+
*/
|
|
3265
|
+
notifyPath(path, value) {
|
|
3266
|
+
let propPath;
|
|
3267
|
+
if (arguments.length == 1) {
|
|
3268
|
+
let info = { path: "" };
|
|
3269
|
+
value = get(this, path, info);
|
|
3270
|
+
propPath = info.path;
|
|
3271
|
+
} else if (Array.isArray(path)) {
|
|
3272
|
+
propPath = normalize(path);
|
|
3273
|
+
} else {
|
|
3274
|
+
propPath = /** @type{string} */
|
|
3275
|
+
path;
|
|
3276
|
+
}
|
|
3277
|
+
if (this._setPendingPropertyOrPath(propPath, value, true, true)) {
|
|
3278
|
+
this._invalidateProperties();
|
|
3279
|
+
}
|
|
3280
|
+
}
|
|
3281
|
+
/**
|
|
3282
|
+
* Equivalent to static `createReadOnlyProperty` API but can be called on
|
|
3283
|
+
* an instance to add effects at runtime. See that method for
|
|
3284
|
+
* full API docs.
|
|
3285
|
+
*
|
|
3286
|
+
* @override
|
|
3287
|
+
* @param {string} property Property name
|
|
3288
|
+
* @param {boolean=} protectedSetter Creates a custom protected setter
|
|
3289
|
+
* when `true`.
|
|
3290
|
+
* @return {void}
|
|
3291
|
+
* @protected
|
|
3292
|
+
*/
|
|
3293
|
+
_createReadOnlyProperty(property, protectedSetter) {
|
|
3294
|
+
this._addPropertyEffect(property, TYPES.READ_ONLY);
|
|
3295
|
+
if (protectedSetter) {
|
|
3296
|
+
this["_set" + upper(property)] = /** @this {PropertyEffects} */
|
|
3297
|
+
function(value) {
|
|
3298
|
+
this._setProperty(property, value);
|
|
3299
|
+
};
|
|
3300
|
+
}
|
|
3301
|
+
}
|
|
3302
|
+
/**
|
|
3303
|
+
* Equivalent to static `createPropertyObserver` API but can be called on
|
|
3304
|
+
* an instance to add effects at runtime. See that method for
|
|
3305
|
+
* full API docs.
|
|
3306
|
+
*
|
|
3307
|
+
* @override
|
|
3308
|
+
* @param {string} property Property name
|
|
3309
|
+
* @param {string|function(*,*)} method Function or name of observer method
|
|
3310
|
+
* to call
|
|
3311
|
+
* @param {boolean=} dynamicFn Whether the method name should be included as
|
|
3312
|
+
* a dependency to the effect.
|
|
3313
|
+
* @return {void}
|
|
3314
|
+
* @protected
|
|
3315
|
+
*/
|
|
3316
|
+
_createPropertyObserver(property, method, dynamicFn) {
|
|
3317
|
+
let info = { property, method, dynamicFn: Boolean(dynamicFn) };
|
|
3318
|
+
this._addPropertyEffect(property, TYPES.OBSERVE, {
|
|
3319
|
+
fn: runObserverEffect,
|
|
3320
|
+
info,
|
|
3321
|
+
trigger: { name: property }
|
|
3322
|
+
});
|
|
3323
|
+
if (dynamicFn) {
|
|
3324
|
+
this._addPropertyEffect(
|
|
3325
|
+
/** @type {string} */
|
|
3326
|
+
method,
|
|
3327
|
+
TYPES.OBSERVE,
|
|
3328
|
+
{
|
|
3329
|
+
fn: runObserverEffect,
|
|
3330
|
+
info,
|
|
3331
|
+
trigger: { name: method }
|
|
3332
|
+
}
|
|
3333
|
+
);
|
|
3334
|
+
}
|
|
3335
|
+
}
|
|
3336
|
+
/**
|
|
3337
|
+
* Equivalent to static `createMethodObserver` API but can be called on
|
|
3338
|
+
* an instance to add effects at runtime. See that method for
|
|
3339
|
+
* full API docs.
|
|
3340
|
+
*
|
|
3341
|
+
* @override
|
|
3342
|
+
* @param {string} expression Method expression
|
|
3343
|
+
* @param {boolean|Object=} dynamicFn Boolean or object map indicating
|
|
3344
|
+
* whether method names should be included as a dependency to the effect.
|
|
3345
|
+
* @return {void}
|
|
3346
|
+
* @protected
|
|
3347
|
+
*/
|
|
3348
|
+
_createMethodObserver(expression, dynamicFn) {
|
|
3349
|
+
let sig = parseMethod(expression);
|
|
3350
|
+
if (!sig) {
|
|
3351
|
+
throw new Error("Malformed observer expression '" + expression + "'");
|
|
3352
|
+
}
|
|
3353
|
+
createMethodEffect(this, sig, TYPES.OBSERVE, runMethodEffect, null, dynamicFn);
|
|
3354
|
+
}
|
|
3355
|
+
/**
|
|
3356
|
+
* Equivalent to static `createNotifyingProperty` API but can be called on
|
|
3357
|
+
* an instance to add effects at runtime. See that method for
|
|
3358
|
+
* full API docs.
|
|
3359
|
+
*
|
|
3360
|
+
* @override
|
|
3361
|
+
* @param {string} property Property name
|
|
3362
|
+
* @return {void}
|
|
3363
|
+
* @protected
|
|
3364
|
+
*/
|
|
3365
|
+
_createNotifyingProperty(property) {
|
|
3366
|
+
this._addPropertyEffect(property, TYPES.NOTIFY, {
|
|
3367
|
+
fn: runNotifyEffect,
|
|
3368
|
+
info: {
|
|
3369
|
+
eventName: camelToDashCase(property) + "-changed",
|
|
3370
|
+
property
|
|
3371
|
+
}
|
|
3372
|
+
});
|
|
3373
|
+
}
|
|
3374
|
+
/**
|
|
3375
|
+
* Equivalent to static `createReflectedProperty` API but can be called on
|
|
3376
|
+
* an instance to add effects at runtime. See that method for
|
|
3377
|
+
* full API docs.
|
|
3378
|
+
*
|
|
3379
|
+
* @override
|
|
3380
|
+
* @param {string} property Property name
|
|
3381
|
+
* @return {void}
|
|
3382
|
+
* @protected
|
|
3383
|
+
* @suppress {missingProperties} go/missingfnprops
|
|
3384
|
+
*/
|
|
3385
|
+
_createReflectedProperty(property) {
|
|
3386
|
+
let attr = this.constructor.attributeNameForProperty(property);
|
|
3387
|
+
if (attr[0] === "-") {
|
|
3388
|
+
console.warn("Property " + property + " cannot be reflected to attribute " + attr + ' because "-" is not a valid starting attribute name. Use a lowercase first letter for the property instead.');
|
|
3389
|
+
} else {
|
|
3390
|
+
this._addPropertyEffect(property, TYPES.REFLECT, {
|
|
3391
|
+
fn: runReflectEffect,
|
|
3392
|
+
info: {
|
|
3393
|
+
attrName: attr
|
|
3394
|
+
}
|
|
3395
|
+
});
|
|
3396
|
+
}
|
|
3397
|
+
}
|
|
3398
|
+
/**
|
|
3399
|
+
* Equivalent to static `createComputedProperty` API but can be called on
|
|
3400
|
+
* an instance to add effects at runtime. See that method for
|
|
3401
|
+
* full API docs.
|
|
3402
|
+
*
|
|
3403
|
+
* @override
|
|
3404
|
+
* @param {string} property Name of computed property to set
|
|
3405
|
+
* @param {string} expression Method expression
|
|
3406
|
+
* @param {boolean|Object=} dynamicFn Boolean or object map indicating
|
|
3407
|
+
* whether method names should be included as a dependency to the effect.
|
|
3408
|
+
* @return {void}
|
|
3409
|
+
* @protected
|
|
3410
|
+
*/
|
|
3411
|
+
_createComputedProperty(property, expression, dynamicFn) {
|
|
3412
|
+
let sig = parseMethod(expression);
|
|
3413
|
+
if (!sig) {
|
|
3414
|
+
throw new Error("Malformed computed expression '" + expression + "'");
|
|
3415
|
+
}
|
|
3416
|
+
const info = createMethodEffect(this, sig, TYPES.COMPUTE, runComputedEffect, property, dynamicFn);
|
|
3417
|
+
ensureOwnEffectMap(this, COMPUTE_INFO)[property] = info;
|
|
3418
|
+
}
|
|
3419
|
+
/**
|
|
3420
|
+
* Gather the argument values for a method specified in the provided array
|
|
3421
|
+
* of argument metadata.
|
|
3422
|
+
*
|
|
3423
|
+
* The `path` and `value` arguments are used to fill in wildcard descriptor
|
|
3424
|
+
* when the method is being called as a result of a path notification.
|
|
3425
|
+
*
|
|
3426
|
+
* @param {!Array<!MethodArg>} args Array of argument metadata
|
|
3427
|
+
* @param {string} path Property/path name that triggered the method effect
|
|
3428
|
+
* @param {Object} props Bag of current property changes
|
|
3429
|
+
* @return {!Array<*>} Array of argument values
|
|
3430
|
+
* @private
|
|
3431
|
+
*/
|
|
3432
|
+
_marshalArgs(args, path, props) {
|
|
3433
|
+
const data = this.__data;
|
|
3434
|
+
const values = [];
|
|
3435
|
+
for (let i = 0, l = args.length; i < l; i++) {
|
|
3436
|
+
let { name, structured, wildcard, value, literal } = args[i];
|
|
3437
|
+
if (!literal) {
|
|
3438
|
+
if (wildcard) {
|
|
3439
|
+
const matches2 = isDescendant(name, path);
|
|
3440
|
+
const pathValue = getArgValue(data, props, matches2 ? path : name);
|
|
3441
|
+
value = {
|
|
3442
|
+
path: matches2 ? path : name,
|
|
3443
|
+
value: pathValue,
|
|
3444
|
+
base: matches2 ? get(data, name) : pathValue
|
|
3445
|
+
};
|
|
3446
|
+
} else {
|
|
3447
|
+
value = structured ? getArgValue(data, props, name) : data[name];
|
|
3448
|
+
}
|
|
3449
|
+
}
|
|
3450
|
+
if (legacyUndefined && !this._overrideLegacyUndefined && value === void 0 && args.length > 1) {
|
|
3451
|
+
return NOOP;
|
|
3452
|
+
}
|
|
3453
|
+
values[i] = value;
|
|
3454
|
+
}
|
|
3455
|
+
return values;
|
|
3456
|
+
}
|
|
3457
|
+
// -- static class methods ------------
|
|
3458
|
+
/**
|
|
3459
|
+
* Ensures an accessor exists for the specified property, and adds
|
|
3460
|
+
* to a list of "property effects" that will run when the accessor for
|
|
3461
|
+
* the specified property is set. Effects are grouped by "type", which
|
|
3462
|
+
* roughly corresponds to a phase in effect processing. The effect
|
|
3463
|
+
* metadata should be in the following form:
|
|
3464
|
+
*
|
|
3465
|
+
* {
|
|
3466
|
+
* fn: effectFunction, // Reference to function to call to perform effect
|
|
3467
|
+
* info: { ... } // Effect metadata passed to function
|
|
3468
|
+
* trigger: { // Optional triggering metadata; if not provided
|
|
3469
|
+
* name: string // the property is treated as a wildcard
|
|
3470
|
+
* structured: boolean
|
|
3471
|
+
* wildcard: boolean
|
|
3472
|
+
* }
|
|
3473
|
+
* }
|
|
3474
|
+
*
|
|
3475
|
+
* Effects are called from `_propertiesChanged` in the following order by
|
|
3476
|
+
* type:
|
|
3477
|
+
*
|
|
3478
|
+
* 1. COMPUTE
|
|
3479
|
+
* 2. PROPAGATE
|
|
3480
|
+
* 3. REFLECT
|
|
3481
|
+
* 4. OBSERVE
|
|
3482
|
+
* 5. NOTIFY
|
|
3483
|
+
*
|
|
3484
|
+
* Effect functions are called with the following signature:
|
|
3485
|
+
*
|
|
3486
|
+
* effectFunction(inst, path, props, oldProps, info, hasPaths)
|
|
3487
|
+
*
|
|
3488
|
+
* @param {string} property Property that should trigger the effect
|
|
3489
|
+
* @param {string} type Effect type, from this.PROPERTY_EFFECT_TYPES
|
|
3490
|
+
* @param {Object=} effect Effect metadata object
|
|
3491
|
+
* @return {void}
|
|
3492
|
+
* @protected
|
|
3493
|
+
* @nocollapse
|
|
3494
|
+
*/
|
|
3495
|
+
static addPropertyEffect(property, type, effect) {
|
|
3496
|
+
this.prototype._addPropertyEffect(property, type, effect);
|
|
3497
|
+
}
|
|
3498
|
+
/**
|
|
3499
|
+
* Creates a single-property observer for the given property.
|
|
3500
|
+
*
|
|
3501
|
+
* @param {string} property Property name
|
|
3502
|
+
* @param {string|function(*,*)} method Function or name of observer method to call
|
|
3503
|
+
* @param {boolean=} dynamicFn Whether the method name should be included as
|
|
3504
|
+
* a dependency to the effect.
|
|
3505
|
+
* @return {void}
|
|
3506
|
+
* @protected
|
|
3507
|
+
* @nocollapse
|
|
3508
|
+
*/
|
|
3509
|
+
static createPropertyObserver(property, method, dynamicFn) {
|
|
3510
|
+
this.prototype._createPropertyObserver(property, method, dynamicFn);
|
|
3511
|
+
}
|
|
3512
|
+
/**
|
|
3513
|
+
* Creates a multi-property "method observer" based on the provided
|
|
3514
|
+
* expression, which should be a string in the form of a normal JavaScript
|
|
3515
|
+
* function signature: `'methodName(arg1, [..., argn])'`. Each argument
|
|
3516
|
+
* should correspond to a property or path in the context of this
|
|
3517
|
+
* prototype (or instance), or may be a literal string or number.
|
|
3518
|
+
*
|
|
3519
|
+
* @param {string} expression Method expression
|
|
3520
|
+
* @param {boolean|Object=} dynamicFn Boolean or object map indicating
|
|
3521
|
+
* @return {void}
|
|
3522
|
+
* whether method names should be included as a dependency to the effect.
|
|
3523
|
+
* @protected
|
|
3524
|
+
* @nocollapse
|
|
3525
|
+
*/
|
|
3526
|
+
static createMethodObserver(expression, dynamicFn) {
|
|
3527
|
+
this.prototype._createMethodObserver(expression, dynamicFn);
|
|
3528
|
+
}
|
|
3529
|
+
/**
|
|
3530
|
+
* Causes the setter for the given property to dispatch `<property>-changed`
|
|
3531
|
+
* events to notify of changes to the property.
|
|
3532
|
+
*
|
|
3533
|
+
* @param {string} property Property name
|
|
3534
|
+
* @return {void}
|
|
3535
|
+
* @protected
|
|
3536
|
+
* @nocollapse
|
|
3537
|
+
*/
|
|
3538
|
+
static createNotifyingProperty(property) {
|
|
3539
|
+
this.prototype._createNotifyingProperty(property);
|
|
3540
|
+
}
|
|
3541
|
+
/**
|
|
3542
|
+
* Creates a read-only accessor for the given property.
|
|
3543
|
+
*
|
|
3544
|
+
* To set the property, use the protected `_setProperty` API.
|
|
3545
|
+
* To create a custom protected setter (e.g. `_setMyProp()` for
|
|
3546
|
+
* property `myProp`), pass `true` for `protectedSetter`.
|
|
3547
|
+
*
|
|
3548
|
+
* Note, if the property will have other property effects, this method
|
|
3549
|
+
* should be called first, before adding other effects.
|
|
3550
|
+
*
|
|
3551
|
+
* @param {string} property Property name
|
|
3552
|
+
* @param {boolean=} protectedSetter Creates a custom protected setter
|
|
3553
|
+
* when `true`.
|
|
3554
|
+
* @return {void}
|
|
3555
|
+
* @protected
|
|
3556
|
+
* @nocollapse
|
|
3557
|
+
*/
|
|
3558
|
+
static createReadOnlyProperty(property, protectedSetter) {
|
|
3559
|
+
this.prototype._createReadOnlyProperty(property, protectedSetter);
|
|
3560
|
+
}
|
|
3561
|
+
/**
|
|
3562
|
+
* Causes the setter for the given property to reflect the property value
|
|
3563
|
+
* to a (dash-cased) attribute of the same name.
|
|
3564
|
+
*
|
|
3565
|
+
* @param {string} property Property name
|
|
3566
|
+
* @return {void}
|
|
3567
|
+
* @protected
|
|
3568
|
+
* @nocollapse
|
|
3569
|
+
*/
|
|
3570
|
+
static createReflectedProperty(property) {
|
|
3571
|
+
this.prototype._createReflectedProperty(property);
|
|
3572
|
+
}
|
|
3573
|
+
/**
|
|
3574
|
+
* Creates a computed property whose value is set to the result of the
|
|
3575
|
+
* method described by the given `expression` each time one or more
|
|
3576
|
+
* arguments to the method changes. The expression should be a string
|
|
3577
|
+
* in the form of a normal JavaScript function signature:
|
|
3578
|
+
* `'methodName(arg1, [..., argn])'`
|
|
3579
|
+
*
|
|
3580
|
+
* @param {string} property Name of computed property to set
|
|
3581
|
+
* @param {string} expression Method expression
|
|
3582
|
+
* @param {boolean|Object=} dynamicFn Boolean or object map indicating whether
|
|
3583
|
+
* method names should be included as a dependency to the effect.
|
|
3584
|
+
* @return {void}
|
|
3585
|
+
* @protected
|
|
3586
|
+
* @nocollapse
|
|
3587
|
+
*/
|
|
3588
|
+
static createComputedProperty(property, expression, dynamicFn) {
|
|
3589
|
+
this.prototype._createComputedProperty(property, expression, dynamicFn);
|
|
3590
|
+
}
|
|
3591
|
+
/**
|
|
3592
|
+
* Parses the provided template to ensure binding effects are created
|
|
3593
|
+
* for them, and then ensures property accessors are created for any
|
|
3594
|
+
* dependent properties in the template. Binding effects for bound
|
|
3595
|
+
* templates are stored in a linked list on the instance so that
|
|
3596
|
+
* templates can be efficiently stamped and unstamped.
|
|
3597
|
+
*
|
|
3598
|
+
* @param {!HTMLTemplateElement} template Template containing binding
|
|
3599
|
+
* bindings
|
|
3600
|
+
* @return {!TemplateInfo} Template metadata object
|
|
3601
|
+
* @protected
|
|
3602
|
+
* @nocollapse
|
|
3603
|
+
*/
|
|
3604
|
+
static bindTemplate(template) {
|
|
3605
|
+
return this.prototype._bindTemplate(template);
|
|
3606
|
+
}
|
|
3607
|
+
// -- binding ----------------------------------------------
|
|
3608
|
+
/*
|
|
3609
|
+
* Overview of binding flow:
|
|
3610
|
+
*
|
|
3611
|
+
* During finalization (`instanceBinding==false`, `wasPreBound==false`):
|
|
3612
|
+
* `_bindTemplate(t, false)` called directly during finalization - parses
|
|
3613
|
+
* the template (for the first time), and then assigns that _prototypical_
|
|
3614
|
+
* template info to `__preboundTemplateInfo` _on the prototype_; note in
|
|
3615
|
+
* this case `wasPreBound` is false; this is the first time we're binding
|
|
3616
|
+
* it, thus we create accessors.
|
|
3617
|
+
*
|
|
3618
|
+
* During first stamping (`instanceBinding==true`, `wasPreBound==true`):
|
|
3619
|
+
* `_stampTemplate` calls `_bindTemplate(t, true)`: the `templateInfo`
|
|
3620
|
+
* returned matches the prebound one, and so this is `wasPreBound == true`
|
|
3621
|
+
* state; thus we _skip_ creating accessors, but _do_ create an instance
|
|
3622
|
+
* of the template info to serve as the start of our linked list (needs to
|
|
3623
|
+
* be an instance, not the prototypical one, so that we can add `nodeList`
|
|
3624
|
+
* to it to contain the `nodeInfo`-ordered list of instance nodes for
|
|
3625
|
+
* bindings, and so we can chain runtime-stamped template infos off of
|
|
3626
|
+
* it). At this point, the call to `_stampTemplate` calls
|
|
3627
|
+
* `applyTemplateInfo` for each nested `<template>` found during parsing
|
|
3628
|
+
* to hand prototypical `_templateInfo` to them; we also pass the _parent_
|
|
3629
|
+
* `templateInfo` to the `<template>` so that we have the instance-time
|
|
3630
|
+
* parent to link the `templateInfo` under in the case it was
|
|
3631
|
+
* runtime-stamped.
|
|
3632
|
+
*
|
|
3633
|
+
* During subsequent runtime stamping (`instanceBinding==true`,
|
|
3634
|
+
* `wasPreBound==false`): `_stampTemplate` calls `_bindTemplate(t, true)`
|
|
3635
|
+
* - here `templateInfo` is guaranteed to _not_ match the prebound one,
|
|
3636
|
+
* because it was either a different template altogether, or even if it
|
|
3637
|
+
* was the same template, the step above created a instance of the info;
|
|
3638
|
+
* in this case `wasPreBound == false`, so we _do_ create accessors, _and_
|
|
3639
|
+
* link a instance into the linked list.
|
|
3640
|
+
*/
|
|
3641
|
+
/**
|
|
3642
|
+
* Equivalent to static `bindTemplate` API but can be called on an instance
|
|
3643
|
+
* to add effects at runtime. See that method for full API docs.
|
|
3644
|
+
*
|
|
3645
|
+
* This method may be called on the prototype (for prototypical template
|
|
3646
|
+
* binding, to avoid creating accessors every instance) once per prototype,
|
|
3647
|
+
* and will be called with `runtimeBinding: true` by `_stampTemplate` to
|
|
3648
|
+
* create and link an instance of the template metadata associated with a
|
|
3649
|
+
* particular stamping.
|
|
3650
|
+
*
|
|
3651
|
+
* @override
|
|
3652
|
+
* @param {!HTMLTemplateElement} template Template containing binding
|
|
3653
|
+
* bindings
|
|
3654
|
+
* @param {boolean=} instanceBinding When false (default), performs
|
|
3655
|
+
* "prototypical" binding of the template and overwrites any previously
|
|
3656
|
+
* bound template for the class. When true (as passed from
|
|
3657
|
+
* `_stampTemplate`), the template info is instanced and linked into the
|
|
3658
|
+
* list of bound templates.
|
|
3659
|
+
* @return {!TemplateInfo} Template metadata object; for `runtimeBinding`,
|
|
3660
|
+
* this is an instance of the prototypical template info
|
|
3661
|
+
* @protected
|
|
3662
|
+
* @suppress {missingProperties} go/missingfnprops
|
|
3663
|
+
*/
|
|
3664
|
+
_bindTemplate(template, instanceBinding) {
|
|
3665
|
+
let templateInfo = this.constructor._parseTemplate(template);
|
|
3666
|
+
let wasPreBound = this.__preBoundTemplateInfo == templateInfo;
|
|
3667
|
+
if (!wasPreBound) {
|
|
3668
|
+
for (let prop in templateInfo.propertyEffects) {
|
|
3669
|
+
this._createPropertyAccessor(prop);
|
|
3670
|
+
}
|
|
3671
|
+
}
|
|
3672
|
+
if (instanceBinding) {
|
|
3673
|
+
templateInfo = /** @type {!TemplateInfo} */
|
|
3674
|
+
Object.create(templateInfo);
|
|
3675
|
+
templateInfo.wasPreBound = wasPreBound;
|
|
3676
|
+
if (!this.__templateInfo) {
|
|
3677
|
+
this.__templateInfo = templateInfo;
|
|
3678
|
+
} else {
|
|
3679
|
+
const parent = template._parentTemplateInfo || this.__templateInfo;
|
|
3680
|
+
const previous = parent.lastChild;
|
|
3681
|
+
templateInfo.parent = parent;
|
|
3682
|
+
parent.lastChild = templateInfo;
|
|
3683
|
+
templateInfo.previousSibling = previous;
|
|
3684
|
+
if (previous) {
|
|
3685
|
+
previous.nextSibling = templateInfo;
|
|
3686
|
+
} else {
|
|
3687
|
+
parent.firstChild = templateInfo;
|
|
3688
|
+
}
|
|
3689
|
+
}
|
|
3690
|
+
} else {
|
|
3691
|
+
this.__preBoundTemplateInfo = templateInfo;
|
|
3692
|
+
}
|
|
3693
|
+
return templateInfo;
|
|
3694
|
+
}
|
|
3695
|
+
/**
|
|
3696
|
+
* Adds a property effect to the given template metadata, which is run
|
|
3697
|
+
* at the "propagate" stage of `_propertiesChanged` when the template
|
|
3698
|
+
* has been bound to the element via `_bindTemplate`.
|
|
3699
|
+
*
|
|
3700
|
+
* The `effect` object should match the format in `_addPropertyEffect`.
|
|
3701
|
+
*
|
|
3702
|
+
* @param {Object} templateInfo Template metadata to add effect to
|
|
3703
|
+
* @param {string} prop Property that should trigger the effect
|
|
3704
|
+
* @param {Object=} effect Effect metadata object
|
|
3705
|
+
* @return {void}
|
|
3706
|
+
* @protected
|
|
3707
|
+
* @nocollapse
|
|
3708
|
+
*/
|
|
3709
|
+
static _addTemplatePropertyEffect(templateInfo, prop, effect) {
|
|
3710
|
+
let hostProps = templateInfo.hostProps = templateInfo.hostProps || {};
|
|
3711
|
+
hostProps[prop] = true;
|
|
3712
|
+
let effects = templateInfo.propertyEffects = templateInfo.propertyEffects || {};
|
|
3713
|
+
let propEffects = effects[prop] = effects[prop] || [];
|
|
3714
|
+
propEffects.push(effect);
|
|
3715
|
+
}
|
|
3716
|
+
/**
|
|
3717
|
+
* Stamps the provided template and performs instance-time setup for
|
|
3718
|
+
* Polymer template features, including data bindings, declarative event
|
|
3719
|
+
* listeners, and the `this.$` map of `id`'s to nodes. A document fragment
|
|
3720
|
+
* is returned containing the stamped DOM, ready for insertion into the
|
|
3721
|
+
* DOM.
|
|
3722
|
+
*
|
|
3723
|
+
* This method may be called more than once; however note that due to
|
|
3724
|
+
* `shadycss` polyfill limitations, only styles from templates prepared
|
|
3725
|
+
* using `ShadyCSS.prepareTemplate` will be correctly polyfilled (scoped
|
|
3726
|
+
* to the shadow root and support CSS custom properties), and note that
|
|
3727
|
+
* `ShadyCSS.prepareTemplate` may only be called once per element. As such,
|
|
3728
|
+
* any styles required by in runtime-stamped templates must be included
|
|
3729
|
+
* in the main element template.
|
|
3730
|
+
*
|
|
3731
|
+
* @param {!HTMLTemplateElement} template Template to stamp
|
|
3732
|
+
* @param {TemplateInfo=} templateInfo Optional bound template info associated
|
|
3733
|
+
* with the template to be stamped; if omitted the template will be
|
|
3734
|
+
* automatically bound.
|
|
3735
|
+
* @return {!StampedTemplate} Cloned template content
|
|
3736
|
+
* @override
|
|
3737
|
+
* @protected
|
|
3738
|
+
*/
|
|
3739
|
+
_stampTemplate(template, templateInfo) {
|
|
3740
|
+
templateInfo = templateInfo || /** @type {!TemplateInfo} */
|
|
3741
|
+
this._bindTemplate(template, true);
|
|
3742
|
+
hostStack.push(this);
|
|
3743
|
+
let dom = super._stampTemplate(template, templateInfo);
|
|
3744
|
+
hostStack.pop();
|
|
3745
|
+
templateInfo.nodeList = dom.nodeList;
|
|
3746
|
+
if (!templateInfo.wasPreBound) {
|
|
3747
|
+
let nodes = templateInfo.childNodes = [];
|
|
3748
|
+
for (let n = dom.firstChild; n; n = n.nextSibling) {
|
|
3749
|
+
nodes.push(n);
|
|
3750
|
+
}
|
|
3751
|
+
}
|
|
3752
|
+
dom.templateInfo = templateInfo;
|
|
3753
|
+
setupBindings(this, templateInfo);
|
|
3754
|
+
if (this.__dataClientsReady) {
|
|
3755
|
+
this._runEffectsForTemplate(templateInfo, this.__data, null, false);
|
|
3756
|
+
this._flushClients();
|
|
3757
|
+
}
|
|
3758
|
+
return dom;
|
|
3759
|
+
}
|
|
3760
|
+
/**
|
|
3761
|
+
* Removes and unbinds the nodes previously contained in the provided
|
|
3762
|
+
* DocumentFragment returned from `_stampTemplate`.
|
|
3763
|
+
*
|
|
3764
|
+
* @override
|
|
3765
|
+
* @param {!StampedTemplate} dom DocumentFragment previously returned
|
|
3766
|
+
* from `_stampTemplate` associated with the nodes to be removed
|
|
3767
|
+
* @return {void}
|
|
3768
|
+
* @protected
|
|
3769
|
+
*/
|
|
3770
|
+
_removeBoundDom(dom) {
|
|
3771
|
+
const templateInfo = dom.templateInfo;
|
|
3772
|
+
const { previousSibling, nextSibling, parent } = templateInfo;
|
|
3773
|
+
if (previousSibling) {
|
|
3774
|
+
previousSibling.nextSibling = nextSibling;
|
|
3775
|
+
} else if (parent) {
|
|
3776
|
+
parent.firstChild = nextSibling;
|
|
3777
|
+
}
|
|
3778
|
+
if (nextSibling) {
|
|
3779
|
+
nextSibling.previousSibling = previousSibling;
|
|
3780
|
+
} else if (parent) {
|
|
3781
|
+
parent.lastChild = previousSibling;
|
|
3782
|
+
}
|
|
3783
|
+
templateInfo.nextSibling = templateInfo.previousSibling = null;
|
|
3784
|
+
let nodes = templateInfo.childNodes;
|
|
3785
|
+
for (let i = 0; i < nodes.length; i++) {
|
|
3786
|
+
let node = nodes[i];
|
|
3787
|
+
wrap(wrap(node).parentNode).removeChild(node);
|
|
3788
|
+
}
|
|
3789
|
+
}
|
|
3790
|
+
/**
|
|
3791
|
+
* Overrides default `TemplateStamp` implementation to add support for
|
|
3792
|
+
* parsing bindings from `TextNode`'s' `textContent`. A `bindings`
|
|
3793
|
+
* array is added to `nodeInfo` and populated with binding metadata
|
|
3794
|
+
* with information capturing the binding target, and a `parts` array
|
|
3795
|
+
* with one or more metadata objects capturing the source(s) of the
|
|
3796
|
+
* binding.
|
|
3797
|
+
*
|
|
3798
|
+
* @param {Node} node Node to parse
|
|
3799
|
+
* @param {TemplateInfo} templateInfo Template metadata for current template
|
|
3800
|
+
* @param {NodeInfo} nodeInfo Node metadata for current template node
|
|
3801
|
+
* @return {boolean} `true` if the visited node added node-specific
|
|
3802
|
+
* metadata to `nodeInfo`
|
|
3803
|
+
* @protected
|
|
3804
|
+
* @suppress {missingProperties} Interfaces in closure do not inherit statics, but classes do
|
|
3805
|
+
* @nocollapse
|
|
3806
|
+
*/
|
|
3807
|
+
static _parseTemplateNode(node, templateInfo, nodeInfo) {
|
|
3808
|
+
let noted = propertyEffectsBase._parseTemplateNode.call(
|
|
3809
|
+
this,
|
|
3810
|
+
node,
|
|
3811
|
+
templateInfo,
|
|
3812
|
+
nodeInfo
|
|
3813
|
+
);
|
|
3814
|
+
if (node.nodeType === Node.TEXT_NODE) {
|
|
3815
|
+
let parts = this._parseBindings(node.textContent, templateInfo);
|
|
3816
|
+
if (parts) {
|
|
3817
|
+
node.textContent = literalFromParts(parts) || " ";
|
|
3818
|
+
addBinding(this, templateInfo, nodeInfo, "text", "textContent", parts);
|
|
3819
|
+
noted = true;
|
|
3820
|
+
}
|
|
3821
|
+
}
|
|
3822
|
+
return noted;
|
|
3823
|
+
}
|
|
3824
|
+
/**
|
|
3825
|
+
* Overrides default `TemplateStamp` implementation to add support for
|
|
3826
|
+
* parsing bindings from attributes. A `bindings`
|
|
3827
|
+
* array is added to `nodeInfo` and populated with binding metadata
|
|
3828
|
+
* with information capturing the binding target, and a `parts` array
|
|
3829
|
+
* with one or more metadata objects capturing the source(s) of the
|
|
3830
|
+
* binding.
|
|
3831
|
+
*
|
|
3832
|
+
* @param {Element} node Node to parse
|
|
3833
|
+
* @param {TemplateInfo} templateInfo Template metadata for current template
|
|
3834
|
+
* @param {NodeInfo} nodeInfo Node metadata for current template node
|
|
3835
|
+
* @param {string} name Attribute name
|
|
3836
|
+
* @param {string} value Attribute value
|
|
3837
|
+
* @return {boolean} `true` if the visited node added node-specific
|
|
3838
|
+
* metadata to `nodeInfo`
|
|
3839
|
+
* @protected
|
|
3840
|
+
* @suppress {missingProperties} Interfaces in closure do not inherit statics, but classes do
|
|
3841
|
+
* @nocollapse
|
|
3842
|
+
*/
|
|
3843
|
+
static _parseTemplateNodeAttribute(node, templateInfo, nodeInfo, name, value) {
|
|
3844
|
+
let parts = this._parseBindings(value, templateInfo);
|
|
3845
|
+
if (parts) {
|
|
3846
|
+
let origName = name;
|
|
3847
|
+
let kind = "property";
|
|
3848
|
+
if (capitalAttributeRegex.test(name)) {
|
|
3849
|
+
kind = "attribute";
|
|
3850
|
+
} else if (name[name.length - 1] == "$") {
|
|
3851
|
+
name = name.slice(0, -1);
|
|
3852
|
+
kind = "attribute";
|
|
3853
|
+
}
|
|
3854
|
+
let literal = literalFromParts(parts);
|
|
3855
|
+
if (literal && kind == "attribute") {
|
|
3856
|
+
if (name == "class" && node.hasAttribute("class")) {
|
|
3857
|
+
literal += " " + node.getAttribute(name);
|
|
3858
|
+
}
|
|
3859
|
+
node.setAttribute(name, literal);
|
|
3860
|
+
}
|
|
3861
|
+
if (kind == "attribute" && origName == "disable-upgrade$") {
|
|
3862
|
+
node.setAttribute(name, "");
|
|
3863
|
+
}
|
|
3864
|
+
if (node.localName === "input" && origName === "value") {
|
|
3865
|
+
node.setAttribute(origName, "");
|
|
3866
|
+
}
|
|
3867
|
+
node.removeAttribute(origName);
|
|
3868
|
+
if (kind === "property") {
|
|
3869
|
+
name = dashToCamelCase(name);
|
|
3870
|
+
}
|
|
3871
|
+
addBinding(this, templateInfo, nodeInfo, kind, name, parts, literal);
|
|
3872
|
+
return true;
|
|
3873
|
+
} else {
|
|
3874
|
+
return propertyEffectsBase._parseTemplateNodeAttribute.call(
|
|
3875
|
+
this,
|
|
3876
|
+
node,
|
|
3877
|
+
templateInfo,
|
|
3878
|
+
nodeInfo,
|
|
3879
|
+
name,
|
|
3880
|
+
value
|
|
3881
|
+
);
|
|
3882
|
+
}
|
|
3883
|
+
}
|
|
3884
|
+
/**
|
|
3885
|
+
* Overrides default `TemplateStamp` implementation to add support for
|
|
3886
|
+
* binding the properties that a nested template depends on to the template
|
|
3887
|
+
* as `_host_<property>`.
|
|
3888
|
+
*
|
|
3889
|
+
* @param {Node} node Node to parse
|
|
3890
|
+
* @param {TemplateInfo} templateInfo Template metadata for current template
|
|
3891
|
+
* @param {NodeInfo} nodeInfo Node metadata for current template node
|
|
3892
|
+
* @return {boolean} `true` if the visited node added node-specific
|
|
3893
|
+
* metadata to `nodeInfo`
|
|
3894
|
+
* @protected
|
|
3895
|
+
* @suppress {missingProperties} Interfaces in closure do not inherit statics, but classes do
|
|
3896
|
+
* @nocollapse
|
|
3897
|
+
*/
|
|
3898
|
+
static _parseTemplateNestedTemplate(node, templateInfo, nodeInfo) {
|
|
3899
|
+
let noted = propertyEffectsBase._parseTemplateNestedTemplate.call(
|
|
3900
|
+
this,
|
|
3901
|
+
node,
|
|
3902
|
+
templateInfo,
|
|
3903
|
+
nodeInfo
|
|
3904
|
+
);
|
|
3905
|
+
const parent = node.parentNode;
|
|
3906
|
+
const nestedTemplateInfo = nodeInfo.templateInfo;
|
|
3907
|
+
const isDomIf = parent.localName === "dom-if";
|
|
3908
|
+
const isDomRepeat = parent.localName === "dom-repeat";
|
|
3909
|
+
if (removeNestedTemplates && (isDomIf || isDomRepeat)) {
|
|
3910
|
+
parent.removeChild(node);
|
|
3911
|
+
nodeInfo = nodeInfo.parentInfo;
|
|
3912
|
+
nodeInfo.templateInfo = nestedTemplateInfo;
|
|
3913
|
+
nodeInfo.noted = true;
|
|
3914
|
+
noted = false;
|
|
3915
|
+
}
|
|
3916
|
+
let hostProps = nestedTemplateInfo.hostProps;
|
|
3917
|
+
if (fastDomIf && isDomIf) {
|
|
3918
|
+
if (hostProps) {
|
|
3919
|
+
templateInfo.hostProps = Object.assign(templateInfo.hostProps || {}, hostProps);
|
|
3920
|
+
if (!removeNestedTemplates) {
|
|
3921
|
+
nodeInfo.parentInfo.noted = true;
|
|
3922
|
+
}
|
|
3923
|
+
}
|
|
3924
|
+
} else {
|
|
3925
|
+
let mode = "{";
|
|
3926
|
+
for (let source in hostProps) {
|
|
3927
|
+
let parts = [{ mode, source, dependencies: [source], hostProp: true }];
|
|
3928
|
+
addBinding(this, templateInfo, nodeInfo, "property", "_host_" + source, parts);
|
|
3929
|
+
}
|
|
3930
|
+
}
|
|
3931
|
+
return noted;
|
|
3932
|
+
}
|
|
3933
|
+
/**
|
|
3934
|
+
* Called to parse text in a template (either attribute values or
|
|
3935
|
+
* textContent) into binding metadata.
|
|
3936
|
+
*
|
|
3937
|
+
* Any overrides of this method should return an array of binding part
|
|
3938
|
+
* metadata representing one or more bindings found in the provided text
|
|
3939
|
+
* and any "literal" text in between. Any non-literal parts will be passed
|
|
3940
|
+
* to `_evaluateBinding` when any dependencies change. The only required
|
|
3941
|
+
* fields of each "part" in the returned array are as follows:
|
|
3942
|
+
*
|
|
3943
|
+
* - `dependencies` - Array containing trigger metadata for each property
|
|
3944
|
+
* that should trigger the binding to update
|
|
3945
|
+
* - `literal` - String containing text if the part represents a literal;
|
|
3946
|
+
* in this case no `dependencies` are needed
|
|
3947
|
+
*
|
|
3948
|
+
* Additional metadata for use by `_evaluateBinding` may be provided in
|
|
3949
|
+
* each part object as needed.
|
|
3950
|
+
*
|
|
3951
|
+
* The default implementation handles the following types of bindings
|
|
3952
|
+
* (one or more may be intermixed with literal strings):
|
|
3953
|
+
* - Property binding: `[[prop]]`
|
|
3954
|
+
* - Path binding: `[[object.prop]]`
|
|
3955
|
+
* - Negated property or path bindings: `[[!prop]]` or `[[!object.prop]]`
|
|
3956
|
+
* - Two-way property or path bindings (supports negation):
|
|
3957
|
+
* `{{prop}}`, `{{object.prop}}`, `{{!prop}}` or `{{!object.prop}}`
|
|
3958
|
+
* - Inline computed method (supports negation):
|
|
3959
|
+
* `[[compute(a, 'literal', b)]]`, `[[!compute(a, 'literal', b)]]`
|
|
3960
|
+
*
|
|
3961
|
+
* The default implementation uses a regular expression for best
|
|
3962
|
+
* performance. However, the regular expression uses a white-list of
|
|
3963
|
+
* allowed characters in a data-binding, which causes problems for
|
|
3964
|
+
* data-bindings that do use characters not in this white-list.
|
|
3965
|
+
*
|
|
3966
|
+
* Instead of updating the white-list with all allowed characters,
|
|
3967
|
+
* there is a StrictBindingParser (see lib/mixins/strict-binding-parser)
|
|
3968
|
+
* that uses a state machine instead. This state machine is able to handle
|
|
3969
|
+
* all characters. However, it is slightly less performant, therefore we
|
|
3970
|
+
* extracted it into a separate optional mixin.
|
|
3971
|
+
*
|
|
3972
|
+
* @param {string} text Text to parse from attribute or textContent
|
|
3973
|
+
* @param {Object} templateInfo Current template metadata
|
|
3974
|
+
* @return {Array<!BindingPart>} Array of binding part metadata
|
|
3975
|
+
* @protected
|
|
3976
|
+
* @nocollapse
|
|
3977
|
+
*/
|
|
3978
|
+
static _parseBindings(text, templateInfo) {
|
|
3979
|
+
let parts = [];
|
|
3980
|
+
let lastIndex = 0;
|
|
3981
|
+
let m;
|
|
3982
|
+
while ((m = bindingRegex.exec(text)) !== null) {
|
|
3983
|
+
if (m.index > lastIndex) {
|
|
3984
|
+
parts.push({ literal: text.slice(lastIndex, m.index) });
|
|
3985
|
+
}
|
|
3986
|
+
let mode = m[1][0];
|
|
3987
|
+
let negate = Boolean(m[2]);
|
|
3988
|
+
let source = m[3].trim();
|
|
3989
|
+
let customEvent = false, notifyEvent = "", colon = -1;
|
|
3990
|
+
if (mode == "{" && (colon = source.indexOf("::")) > 0) {
|
|
3991
|
+
notifyEvent = source.substring(colon + 2);
|
|
3992
|
+
source = source.substring(0, colon);
|
|
3993
|
+
customEvent = true;
|
|
3994
|
+
}
|
|
3995
|
+
let signature = parseMethod(source);
|
|
3996
|
+
let dependencies = [];
|
|
3997
|
+
if (signature) {
|
|
3998
|
+
let { args, methodName } = signature;
|
|
3999
|
+
for (let i = 0; i < args.length; i++) {
|
|
4000
|
+
let arg = args[i];
|
|
4001
|
+
if (!arg.literal) {
|
|
4002
|
+
dependencies.push(arg);
|
|
4003
|
+
}
|
|
4004
|
+
}
|
|
4005
|
+
let dynamicFns = templateInfo.dynamicFns;
|
|
4006
|
+
if (dynamicFns && dynamicFns[methodName] || signature.static) {
|
|
4007
|
+
dependencies.push(methodName);
|
|
4008
|
+
signature.dynamicFn = true;
|
|
4009
|
+
}
|
|
4010
|
+
} else {
|
|
4011
|
+
dependencies.push(source);
|
|
4012
|
+
}
|
|
4013
|
+
parts.push({
|
|
4014
|
+
source,
|
|
4015
|
+
mode,
|
|
4016
|
+
negate,
|
|
4017
|
+
customEvent,
|
|
4018
|
+
signature,
|
|
4019
|
+
dependencies,
|
|
4020
|
+
event: notifyEvent
|
|
4021
|
+
});
|
|
4022
|
+
lastIndex = bindingRegex.lastIndex;
|
|
4023
|
+
}
|
|
4024
|
+
if (lastIndex && lastIndex < text.length) {
|
|
4025
|
+
let literal = text.substring(lastIndex);
|
|
4026
|
+
if (literal) {
|
|
4027
|
+
parts.push({
|
|
4028
|
+
literal
|
|
4029
|
+
});
|
|
4030
|
+
}
|
|
4031
|
+
}
|
|
4032
|
+
if (parts.length) {
|
|
4033
|
+
return parts;
|
|
4034
|
+
} else {
|
|
4035
|
+
return null;
|
|
4036
|
+
}
|
|
4037
|
+
}
|
|
4038
|
+
/**
|
|
4039
|
+
* Called to evaluate a previously parsed binding part based on a set of
|
|
4040
|
+
* one or more changed dependencies.
|
|
4041
|
+
*
|
|
4042
|
+
* @param {!Polymer_PropertyEffects} inst Element that should be used as
|
|
4043
|
+
* scope for binding dependencies
|
|
4044
|
+
* @param {BindingPart} part Binding part metadata
|
|
4045
|
+
* @param {string} path Property/path that triggered this effect
|
|
4046
|
+
* @param {Object} props Bag of current property changes
|
|
4047
|
+
* @param {Object} oldProps Bag of previous values for changed properties
|
|
4048
|
+
* @param {boolean} hasPaths True with `props` contains one or more paths
|
|
4049
|
+
* @return {*} Value the binding part evaluated to
|
|
4050
|
+
* @protected
|
|
4051
|
+
* @nocollapse
|
|
4052
|
+
*/
|
|
4053
|
+
static _evaluateBinding(inst, part, path, props, oldProps, hasPaths) {
|
|
4054
|
+
let value;
|
|
4055
|
+
if (part.signature) {
|
|
4056
|
+
value = runMethodEffect(inst, path, props, oldProps, part.signature);
|
|
4057
|
+
} else if (path != part.source) {
|
|
4058
|
+
value = get(inst, part.source);
|
|
4059
|
+
} else {
|
|
4060
|
+
if (hasPaths && isPath(path)) {
|
|
4061
|
+
value = get(inst, path);
|
|
4062
|
+
} else {
|
|
4063
|
+
value = inst.__data[path];
|
|
4064
|
+
}
|
|
4065
|
+
}
|
|
4066
|
+
if (part.negate) {
|
|
4067
|
+
value = !value;
|
|
4068
|
+
}
|
|
4069
|
+
return value;
|
|
4070
|
+
}
|
|
4071
|
+
}
|
|
4072
|
+
return PropertyEffects2;
|
|
4073
|
+
});
|
|
4074
|
+
var hostStack = [];
|
|
4075
|
+
|
|
4076
|
+
// ../../../node_modules/@polymer/polymer/lib/utils/telemetry.js
|
|
4077
|
+
var instanceCount = 0;
|
|
4078
|
+
function incrementInstanceCount() {
|
|
4079
|
+
instanceCount++;
|
|
4080
|
+
}
|
|
4081
|
+
var registrations = [];
|
|
4082
|
+
function register(prototype) {
|
|
4083
|
+
registrations.push(prototype);
|
|
4084
|
+
}
|
|
4085
|
+
|
|
4086
|
+
// ../../../node_modules/@polymer/polymer/lib/mixins/properties-mixin.js
|
|
4087
|
+
function normalizeProperties(props) {
|
|
4088
|
+
const output = {};
|
|
4089
|
+
for (let p in props) {
|
|
4090
|
+
const o = props[p];
|
|
4091
|
+
output[p] = typeof o === "function" ? { type: o } : o;
|
|
4092
|
+
}
|
|
4093
|
+
return output;
|
|
4094
|
+
}
|
|
4095
|
+
var PropertiesMixin = dedupingMixin((superClass) => {
|
|
4096
|
+
const base = PropertiesChanged(superClass);
|
|
4097
|
+
function superPropertiesClass(constructor) {
|
|
4098
|
+
const superCtor = Object.getPrototypeOf(constructor);
|
|
4099
|
+
return superCtor.prototype instanceof PropertiesMixin2 ? (
|
|
4100
|
+
/** @type {!PropertiesMixinConstructor} */
|
|
4101
|
+
superCtor
|
|
4102
|
+
) : null;
|
|
4103
|
+
}
|
|
4104
|
+
function ownProperties(constructor) {
|
|
4105
|
+
if (!constructor.hasOwnProperty(JSCompiler_renameProperty("__ownProperties", constructor))) {
|
|
4106
|
+
let props = null;
|
|
4107
|
+
if (constructor.hasOwnProperty(JSCompiler_renameProperty("properties", constructor))) {
|
|
4108
|
+
const properties = constructor.properties;
|
|
4109
|
+
if (properties) {
|
|
4110
|
+
props = normalizeProperties(properties);
|
|
4111
|
+
}
|
|
4112
|
+
}
|
|
4113
|
+
constructor.__ownProperties = props;
|
|
4114
|
+
}
|
|
4115
|
+
return constructor.__ownProperties;
|
|
4116
|
+
}
|
|
4117
|
+
class PropertiesMixin2 extends base {
|
|
4118
|
+
/**
|
|
4119
|
+
* Implements standard custom elements getter to observes the attributes
|
|
4120
|
+
* listed in `properties`.
|
|
4121
|
+
* @suppress {missingProperties} Interfaces in closure do not inherit statics, but classes do
|
|
4122
|
+
* @nocollapse
|
|
4123
|
+
*/
|
|
4124
|
+
static get observedAttributes() {
|
|
4125
|
+
if (!this.hasOwnProperty(JSCompiler_renameProperty("__observedAttributes", this))) {
|
|
4126
|
+
register(this.prototype);
|
|
4127
|
+
const props = this._properties;
|
|
4128
|
+
this.__observedAttributes = props ? Object.keys(props).map((p) => this.prototype._addPropertyToAttributeMap(p)) : [];
|
|
4129
|
+
}
|
|
4130
|
+
return this.__observedAttributes;
|
|
4131
|
+
}
|
|
4132
|
+
/**
|
|
4133
|
+
* Finalizes an element definition, including ensuring any super classes
|
|
4134
|
+
* are also finalized. This includes ensuring property
|
|
4135
|
+
* accessors exist on the element prototype. This method calls
|
|
4136
|
+
* `_finalizeClass` to finalize each constructor in the prototype chain.
|
|
4137
|
+
* @return {void}
|
|
4138
|
+
* @nocollapse
|
|
4139
|
+
*/
|
|
4140
|
+
static finalize() {
|
|
4141
|
+
if (!this.hasOwnProperty(JSCompiler_renameProperty("__finalized", this))) {
|
|
4142
|
+
const superCtor = superPropertiesClass(
|
|
4143
|
+
/** @type {!PropertiesMixinConstructor} */
|
|
4144
|
+
this
|
|
4145
|
+
);
|
|
4146
|
+
if (superCtor) {
|
|
4147
|
+
superCtor.finalize();
|
|
4148
|
+
}
|
|
4149
|
+
this.__finalized = true;
|
|
4150
|
+
this._finalizeClass();
|
|
4151
|
+
}
|
|
4152
|
+
}
|
|
4153
|
+
/**
|
|
4154
|
+
* Finalize an element class. This includes ensuring property
|
|
4155
|
+
* accessors exist on the element prototype. This method is called by
|
|
4156
|
+
* `finalize` and finalizes the class constructor.
|
|
4157
|
+
*
|
|
4158
|
+
* @protected
|
|
4159
|
+
* @nocollapse
|
|
4160
|
+
*/
|
|
4161
|
+
static _finalizeClass() {
|
|
4162
|
+
const props = ownProperties(
|
|
4163
|
+
/** @type {!PropertiesMixinConstructor} */
|
|
4164
|
+
this
|
|
4165
|
+
);
|
|
4166
|
+
if (props) {
|
|
4167
|
+
this.createProperties(props);
|
|
4168
|
+
}
|
|
4169
|
+
}
|
|
4170
|
+
/**
|
|
4171
|
+
* Returns a memoized version of all properties, including those inherited
|
|
4172
|
+
* from super classes. Properties not in object format are converted to
|
|
4173
|
+
* at least {type}.
|
|
4174
|
+
*
|
|
4175
|
+
* @return {Object} Object containing properties for this class
|
|
4176
|
+
* @protected
|
|
4177
|
+
* @nocollapse
|
|
4178
|
+
*/
|
|
4179
|
+
static get _properties() {
|
|
4180
|
+
if (!this.hasOwnProperty(
|
|
4181
|
+
JSCompiler_renameProperty("__properties", this)
|
|
4182
|
+
)) {
|
|
4183
|
+
const superCtor = superPropertiesClass(
|
|
4184
|
+
/** @type {!PropertiesMixinConstructor} */
|
|
4185
|
+
this
|
|
4186
|
+
);
|
|
4187
|
+
this.__properties = Object.assign(
|
|
4188
|
+
{},
|
|
4189
|
+
superCtor && superCtor._properties,
|
|
4190
|
+
ownProperties(
|
|
4191
|
+
/** @type {PropertiesMixinConstructor} */
|
|
4192
|
+
this
|
|
4193
|
+
)
|
|
4194
|
+
);
|
|
4195
|
+
}
|
|
4196
|
+
return this.__properties;
|
|
4197
|
+
}
|
|
4198
|
+
/**
|
|
4199
|
+
* Overrides `PropertiesChanged` method to return type specified in the
|
|
4200
|
+
* static `properties` object for the given property.
|
|
4201
|
+
* @param {string} name Name of property
|
|
4202
|
+
* @return {*} Type to which to deserialize attribute
|
|
4203
|
+
*
|
|
4204
|
+
* @protected
|
|
4205
|
+
* @nocollapse
|
|
4206
|
+
*/
|
|
4207
|
+
static typeForProperty(name) {
|
|
4208
|
+
const info = this._properties[name];
|
|
4209
|
+
return info && info.type;
|
|
4210
|
+
}
|
|
4211
|
+
/**
|
|
4212
|
+
* Overrides `PropertiesChanged` method and adds a call to
|
|
4213
|
+
* `finalize` which lazily configures the element's property accessors.
|
|
4214
|
+
* @override
|
|
4215
|
+
* @return {void}
|
|
4216
|
+
*/
|
|
4217
|
+
_initializeProperties() {
|
|
4218
|
+
incrementInstanceCount();
|
|
4219
|
+
this.constructor.finalize();
|
|
4220
|
+
super._initializeProperties();
|
|
4221
|
+
}
|
|
4222
|
+
/**
|
|
4223
|
+
* Called when the element is added to a document.
|
|
4224
|
+
* Calls `_enableProperties` to turn on property system from
|
|
4225
|
+
* `PropertiesChanged`.
|
|
4226
|
+
* @suppress {missingProperties} Super may or may not implement the callback
|
|
4227
|
+
* @return {void}
|
|
4228
|
+
* @override
|
|
4229
|
+
*/
|
|
4230
|
+
connectedCallback() {
|
|
4231
|
+
if (super.connectedCallback) {
|
|
4232
|
+
super.connectedCallback();
|
|
4233
|
+
}
|
|
4234
|
+
this._enableProperties();
|
|
4235
|
+
}
|
|
4236
|
+
/**
|
|
4237
|
+
* Called when the element is removed from a document
|
|
4238
|
+
* @suppress {missingProperties} Super may or may not implement the callback
|
|
4239
|
+
* @return {void}
|
|
4240
|
+
* @override
|
|
4241
|
+
*/
|
|
4242
|
+
disconnectedCallback() {
|
|
4243
|
+
if (super.disconnectedCallback) {
|
|
4244
|
+
super.disconnectedCallback();
|
|
4245
|
+
}
|
|
4246
|
+
}
|
|
4247
|
+
}
|
|
4248
|
+
return PropertiesMixin2;
|
|
4249
|
+
});
|
|
4250
|
+
|
|
4251
|
+
// ../../../node_modules/@polymer/polymer/lib/mixins/element-mixin.js
|
|
4252
|
+
var version = "3.5.2";
|
|
4253
|
+
var builtCSS = window.ShadyCSS && window.ShadyCSS["cssBuild"];
|
|
4254
|
+
var ElementMixin = dedupingMixin((base) => {
|
|
4255
|
+
const polymerElementBase = PropertiesMixin(PropertyEffects(base));
|
|
4256
|
+
function propertyDefaults(constructor) {
|
|
4257
|
+
if (!constructor.hasOwnProperty(
|
|
4258
|
+
JSCompiler_renameProperty("__propertyDefaults", constructor)
|
|
4259
|
+
)) {
|
|
4260
|
+
constructor.__propertyDefaults = null;
|
|
4261
|
+
let props = constructor._properties;
|
|
4262
|
+
for (let p in props) {
|
|
4263
|
+
let info = props[p];
|
|
4264
|
+
if ("value" in info) {
|
|
4265
|
+
constructor.__propertyDefaults = constructor.__propertyDefaults || {};
|
|
4266
|
+
constructor.__propertyDefaults[p] = info;
|
|
4267
|
+
}
|
|
4268
|
+
}
|
|
4269
|
+
}
|
|
4270
|
+
return constructor.__propertyDefaults;
|
|
4271
|
+
}
|
|
4272
|
+
function ownObservers(constructor) {
|
|
4273
|
+
if (!constructor.hasOwnProperty(
|
|
4274
|
+
JSCompiler_renameProperty("__ownObservers", constructor)
|
|
4275
|
+
)) {
|
|
4276
|
+
constructor.__ownObservers = constructor.hasOwnProperty(
|
|
4277
|
+
JSCompiler_renameProperty("observers", constructor)
|
|
4278
|
+
) ? (
|
|
4279
|
+
/** @type {PolymerElementConstructor} */
|
|
4280
|
+
constructor.observers
|
|
4281
|
+
) : null;
|
|
4282
|
+
}
|
|
4283
|
+
return constructor.__ownObservers;
|
|
4284
|
+
}
|
|
4285
|
+
function createPropertyFromConfig(proto2, name, info, allProps) {
|
|
4286
|
+
if (info.computed) {
|
|
4287
|
+
info.readOnly = true;
|
|
4288
|
+
}
|
|
4289
|
+
if (info.computed) {
|
|
4290
|
+
if (proto2._hasReadOnlyEffect(name)) {
|
|
4291
|
+
console.warn(`Cannot redefine computed property '${name}'.`);
|
|
4292
|
+
} else {
|
|
4293
|
+
proto2._createComputedProperty(name, info.computed, allProps);
|
|
4294
|
+
}
|
|
4295
|
+
}
|
|
4296
|
+
if (info.readOnly && !proto2._hasReadOnlyEffect(name)) {
|
|
4297
|
+
proto2._createReadOnlyProperty(name, !info.computed);
|
|
4298
|
+
} else if (info.readOnly === false && proto2._hasReadOnlyEffect(name)) {
|
|
4299
|
+
console.warn(`Cannot make readOnly property '${name}' non-readOnly.`);
|
|
4300
|
+
}
|
|
4301
|
+
if (info.reflectToAttribute && !proto2._hasReflectEffect(name)) {
|
|
4302
|
+
proto2._createReflectedProperty(name);
|
|
4303
|
+
} else if (info.reflectToAttribute === false && proto2._hasReflectEffect(name)) {
|
|
4304
|
+
console.warn(`Cannot make reflected property '${name}' non-reflected.`);
|
|
4305
|
+
}
|
|
4306
|
+
if (info.notify && !proto2._hasNotifyEffect(name)) {
|
|
4307
|
+
proto2._createNotifyingProperty(name);
|
|
4308
|
+
} else if (info.notify === false && proto2._hasNotifyEffect(name)) {
|
|
4309
|
+
console.warn(`Cannot make notify property '${name}' non-notify.`);
|
|
4310
|
+
}
|
|
4311
|
+
if (info.observer) {
|
|
4312
|
+
proto2._createPropertyObserver(name, info.observer, allProps[info.observer]);
|
|
4313
|
+
}
|
|
4314
|
+
proto2._addPropertyToAttributeMap(name);
|
|
4315
|
+
}
|
|
4316
|
+
function processElementStyles(klass, template, is, baseURI) {
|
|
4317
|
+
if (!builtCSS) {
|
|
4318
|
+
const templateStyles = template.content.querySelectorAll("style");
|
|
4319
|
+
const stylesWithImports = stylesFromTemplate(template);
|
|
4320
|
+
const linkedStyles = stylesFromModuleImports(is);
|
|
4321
|
+
const firstTemplateChild = template.content.firstElementChild;
|
|
4322
|
+
for (let idx = 0; idx < linkedStyles.length; idx++) {
|
|
4323
|
+
let s = linkedStyles[idx];
|
|
4324
|
+
s.textContent = klass._processStyleText(s.textContent, baseURI);
|
|
4325
|
+
template.content.insertBefore(s, firstTemplateChild);
|
|
4326
|
+
}
|
|
4327
|
+
let templateStyleIndex = 0;
|
|
4328
|
+
for (let i = 0; i < stylesWithImports.length; i++) {
|
|
4329
|
+
let s = stylesWithImports[i];
|
|
4330
|
+
let templateStyle = templateStyles[templateStyleIndex];
|
|
4331
|
+
if (templateStyle !== s) {
|
|
4332
|
+
s = s.cloneNode(true);
|
|
4333
|
+
templateStyle.parentNode.insertBefore(s, templateStyle);
|
|
4334
|
+
} else {
|
|
4335
|
+
templateStyleIndex++;
|
|
4336
|
+
}
|
|
4337
|
+
s.textContent = klass._processStyleText(s.textContent, baseURI);
|
|
4338
|
+
}
|
|
4339
|
+
}
|
|
4340
|
+
if (window.ShadyCSS) {
|
|
4341
|
+
window.ShadyCSS.prepareTemplate(template, is);
|
|
4342
|
+
}
|
|
4343
|
+
if (useAdoptedStyleSheetsWithBuiltCSS && builtCSS && supportsAdoptingStyleSheets) {
|
|
4344
|
+
const styles = template.content.querySelectorAll("style");
|
|
4345
|
+
if (styles) {
|
|
4346
|
+
let css = "";
|
|
4347
|
+
Array.from(styles).forEach((s) => {
|
|
4348
|
+
css += s.textContent;
|
|
4349
|
+
s.parentNode.removeChild(s);
|
|
4350
|
+
});
|
|
4351
|
+
klass._styleSheet = new CSSStyleSheet();
|
|
4352
|
+
klass._styleSheet.replaceSync(css);
|
|
4353
|
+
}
|
|
4354
|
+
}
|
|
4355
|
+
}
|
|
4356
|
+
function getTemplateFromDomModule(is) {
|
|
4357
|
+
let template = null;
|
|
4358
|
+
if (is && (!strictTemplatePolicy || allowTemplateFromDomModule)) {
|
|
4359
|
+
template = /** @type {?HTMLTemplateElement} */
|
|
4360
|
+
DomModule.import(is, "template");
|
|
4361
|
+
if (strictTemplatePolicy && !template) {
|
|
4362
|
+
throw new Error(`strictTemplatePolicy: expecting dom-module or null template for ${is}`);
|
|
4363
|
+
}
|
|
4364
|
+
}
|
|
4365
|
+
return template;
|
|
4366
|
+
}
|
|
4367
|
+
class PolymerElement extends polymerElementBase {
|
|
4368
|
+
/**
|
|
4369
|
+
* Current Polymer version in Semver notation.
|
|
4370
|
+
* @type {string} Semver notation of the current version of Polymer.
|
|
4371
|
+
* @nocollapse
|
|
4372
|
+
*/
|
|
4373
|
+
static get polymerElementVersion() {
|
|
4374
|
+
return version;
|
|
4375
|
+
}
|
|
4376
|
+
/**
|
|
4377
|
+
* Override of PropertiesMixin _finalizeClass to create observers and
|
|
4378
|
+
* find the template.
|
|
4379
|
+
* @return {void}
|
|
4380
|
+
* @protected
|
|
4381
|
+
* @suppress {missingProperties} Interfaces in closure do not inherit statics, but classes do
|
|
4382
|
+
* @nocollapse
|
|
4383
|
+
*/
|
|
4384
|
+
static _finalizeClass() {
|
|
4385
|
+
polymerElementBase._finalizeClass.call(this);
|
|
4386
|
+
const observers = ownObservers(this);
|
|
4387
|
+
if (observers) {
|
|
4388
|
+
this.createObservers(observers, this._properties);
|
|
4389
|
+
}
|
|
4390
|
+
this._prepareTemplate();
|
|
4391
|
+
}
|
|
4392
|
+
/** @nocollapse */
|
|
4393
|
+
static _prepareTemplate() {
|
|
4394
|
+
let template = (
|
|
4395
|
+
/** @type {PolymerElementConstructor} */
|
|
4396
|
+
this.template
|
|
4397
|
+
);
|
|
4398
|
+
if (template) {
|
|
4399
|
+
if (typeof template === "string") {
|
|
4400
|
+
console.error("template getter must return HTMLTemplateElement");
|
|
4401
|
+
template = null;
|
|
4402
|
+
} else if (!legacyOptimizations) {
|
|
4403
|
+
template = template.cloneNode(true);
|
|
4404
|
+
}
|
|
4405
|
+
}
|
|
4406
|
+
this.prototype._template = template;
|
|
4407
|
+
}
|
|
4408
|
+
/**
|
|
4409
|
+
* Override of PropertiesChanged createProperties to create accessors
|
|
4410
|
+
* and property effects for all of the properties.
|
|
4411
|
+
* @param {!Object} props .
|
|
4412
|
+
* @return {void}
|
|
4413
|
+
* @protected
|
|
4414
|
+
* @nocollapse
|
|
4415
|
+
*/
|
|
4416
|
+
static createProperties(props) {
|
|
4417
|
+
for (let p in props) {
|
|
4418
|
+
createPropertyFromConfig(
|
|
4419
|
+
/** @type {?} */
|
|
4420
|
+
this.prototype,
|
|
4421
|
+
p,
|
|
4422
|
+
props[p],
|
|
4423
|
+
props
|
|
4424
|
+
);
|
|
4425
|
+
}
|
|
4426
|
+
}
|
|
4427
|
+
/**
|
|
4428
|
+
* Creates observers for the given `observers` array.
|
|
4429
|
+
* Leverages `PropertyEffects` to create observers.
|
|
4430
|
+
* @param {Object} observers Array of observer descriptors for
|
|
4431
|
+
* this class
|
|
4432
|
+
* @param {Object} dynamicFns Object containing keys for any properties
|
|
4433
|
+
* that are functions and should trigger the effect when the function
|
|
4434
|
+
* reference is changed
|
|
4435
|
+
* @return {void}
|
|
4436
|
+
* @protected
|
|
4437
|
+
* @nocollapse
|
|
4438
|
+
*/
|
|
4439
|
+
static createObservers(observers, dynamicFns) {
|
|
4440
|
+
const proto2 = this.prototype;
|
|
4441
|
+
for (let i = 0; i < observers.length; i++) {
|
|
4442
|
+
proto2._createMethodObserver(observers[i], dynamicFns);
|
|
4443
|
+
}
|
|
4444
|
+
}
|
|
4445
|
+
/**
|
|
4446
|
+
* Returns the template that will be stamped into this element's shadow root.
|
|
4447
|
+
*
|
|
4448
|
+
* If a `static get is()` getter is defined, the default implementation will
|
|
4449
|
+
* return the first `<template>` in a `dom-module` whose `id` matches this
|
|
4450
|
+
* element's `is` (note that a `_template` property on the class prototype
|
|
4451
|
+
* takes precedence over the `dom-module` template, to maintain legacy
|
|
4452
|
+
* element semantics; a subclass will subsequently fall back to its super
|
|
4453
|
+
* class template if neither a `prototype._template` or a `dom-module` for
|
|
4454
|
+
* the class's `is` was found).
|
|
4455
|
+
*
|
|
4456
|
+
* Users may override this getter to return an arbitrary template
|
|
4457
|
+
* (in which case the `is` getter is unnecessary). The template returned
|
|
4458
|
+
* must be an `HTMLTemplateElement`.
|
|
4459
|
+
*
|
|
4460
|
+
* Note that when subclassing, if the super class overrode the default
|
|
4461
|
+
* implementation and the subclass would like to provide an alternate
|
|
4462
|
+
* template via a `dom-module`, it should override this getter and
|
|
4463
|
+
* return `DomModule.import(this.is, 'template')`.
|
|
4464
|
+
*
|
|
4465
|
+
* If a subclass would like to modify the super class template, it should
|
|
4466
|
+
* clone it rather than modify it in place. If the getter does expensive
|
|
4467
|
+
* work such as cloning/modifying a template, it should memoize the
|
|
4468
|
+
* template for maximum performance:
|
|
4469
|
+
*
|
|
4470
|
+
* let memoizedTemplate;
|
|
4471
|
+
* class MySubClass extends MySuperClass {
|
|
4472
|
+
* static get template() {
|
|
4473
|
+
* if (!memoizedTemplate) {
|
|
4474
|
+
* memoizedTemplate = super.template.cloneNode(true);
|
|
4475
|
+
* let subContent = document.createElement('div');
|
|
4476
|
+
* subContent.textContent = 'This came from MySubClass';
|
|
4477
|
+
* memoizedTemplate.content.appendChild(subContent);
|
|
4478
|
+
* }
|
|
4479
|
+
* return memoizedTemplate;
|
|
4480
|
+
* }
|
|
4481
|
+
* }
|
|
4482
|
+
*
|
|
4483
|
+
* @return {!HTMLTemplateElement|string} Template to be stamped
|
|
4484
|
+
* @nocollapse
|
|
4485
|
+
*/
|
|
4486
|
+
static get template() {
|
|
4487
|
+
if (!this.hasOwnProperty(JSCompiler_renameProperty("_template", this))) {
|
|
4488
|
+
let protoTemplate = this.prototype.hasOwnProperty(
|
|
4489
|
+
JSCompiler_renameProperty("_template", this.prototype)
|
|
4490
|
+
) ? this.prototype._template : void 0;
|
|
4491
|
+
if (typeof protoTemplate === "function") {
|
|
4492
|
+
protoTemplate = protoTemplate();
|
|
4493
|
+
}
|
|
4494
|
+
this._template = // If user has put template on prototype (e.g. in legacy via registered
|
|
4495
|
+
// callback or info object), prefer that first. Note that `null` is
|
|
4496
|
+
// used as a sentinel to indicate "no template" and can be used to
|
|
4497
|
+
// override a super template, whereas `undefined` is used as a
|
|
4498
|
+
// sentinel to mean "fall-back to default template lookup" via
|
|
4499
|
+
// dom-module and/or super.template.
|
|
4500
|
+
protoTemplate !== void 0 ? protoTemplate : (
|
|
4501
|
+
// Look in dom-module associated with this element's is
|
|
4502
|
+
this.hasOwnProperty(JSCompiler_renameProperty("is", this)) && getTemplateFromDomModule(
|
|
4503
|
+
/** @type {PolymerElementConstructor}*/
|
|
4504
|
+
this.is
|
|
4505
|
+
) || // Next look for superclass template (call the super impl this
|
|
4506
|
+
// way so that `this` points to the superclass)
|
|
4507
|
+
Object.getPrototypeOf(
|
|
4508
|
+
/** @type {PolymerElementConstructor}*/
|
|
4509
|
+
this.prototype
|
|
4510
|
+
).constructor.template
|
|
4511
|
+
);
|
|
4512
|
+
}
|
|
4513
|
+
return this._template;
|
|
4514
|
+
}
|
|
4515
|
+
/**
|
|
4516
|
+
* Set the template.
|
|
4517
|
+
*
|
|
4518
|
+
* @param {!HTMLTemplateElement|string} value Template to set.
|
|
4519
|
+
* @nocollapse
|
|
4520
|
+
*/
|
|
4521
|
+
static set template(value) {
|
|
4522
|
+
this._template = value;
|
|
4523
|
+
}
|
|
4524
|
+
/**
|
|
4525
|
+
* Path matching the url from which the element was imported.
|
|
4526
|
+
*
|
|
4527
|
+
* This path is used to resolve url's in template style cssText.
|
|
4528
|
+
* The `importPath` property is also set on element instances and can be
|
|
4529
|
+
* used to create bindings relative to the import path.
|
|
4530
|
+
*
|
|
4531
|
+
* For elements defined in ES modules, users should implement
|
|
4532
|
+
* `static get importMeta() { return import.meta; }`, and the default
|
|
4533
|
+
* implementation of `importPath` will return `import.meta.url`'s path.
|
|
4534
|
+
* For elements defined in HTML imports, this getter will return the path
|
|
4535
|
+
* to the document containing a `dom-module` element matching this
|
|
4536
|
+
* element's static `is` property.
|
|
4537
|
+
*
|
|
4538
|
+
* Note, this path should contain a trailing `/`.
|
|
4539
|
+
*
|
|
4540
|
+
* @return {string} The import path for this element class
|
|
4541
|
+
* @suppress {missingProperties}
|
|
4542
|
+
* @nocollapse
|
|
4543
|
+
*/
|
|
4544
|
+
static get importPath() {
|
|
4545
|
+
if (!this.hasOwnProperty(JSCompiler_renameProperty("_importPath", this))) {
|
|
4546
|
+
const meta = this.importMeta;
|
|
4547
|
+
if (meta) {
|
|
4548
|
+
this._importPath = pathFromUrl(meta.url);
|
|
4549
|
+
} else {
|
|
4550
|
+
const module = DomModule.import(
|
|
4551
|
+
/** @type {PolymerElementConstructor} */
|
|
4552
|
+
this.is
|
|
4553
|
+
);
|
|
4554
|
+
this._importPath = module && module.assetpath || Object.getPrototypeOf(
|
|
4555
|
+
/** @type {PolymerElementConstructor}*/
|
|
4556
|
+
this.prototype
|
|
4557
|
+
).constructor.importPath;
|
|
4558
|
+
}
|
|
4559
|
+
}
|
|
4560
|
+
return this._importPath;
|
|
4561
|
+
}
|
|
4562
|
+
constructor() {
|
|
4563
|
+
super();
|
|
4564
|
+
this._template;
|
|
4565
|
+
this._importPath;
|
|
4566
|
+
this.rootPath;
|
|
4567
|
+
this.importPath;
|
|
4568
|
+
this.root;
|
|
4569
|
+
this.$;
|
|
4570
|
+
}
|
|
4571
|
+
/**
|
|
4572
|
+
* Overrides the default `PropertyAccessors` to ensure class
|
|
4573
|
+
* metaprogramming related to property accessors and effects has
|
|
4574
|
+
* completed (calls `finalize`).
|
|
4575
|
+
*
|
|
4576
|
+
* It also initializes any property defaults provided via `value` in
|
|
4577
|
+
* `properties` metadata.
|
|
4578
|
+
*
|
|
4579
|
+
* @return {void}
|
|
4580
|
+
* @override
|
|
4581
|
+
* @suppress {invalidCasts,missingProperties} go/missingfnprops
|
|
4582
|
+
*/
|
|
4583
|
+
_initializeProperties() {
|
|
4584
|
+
this.constructor.finalize();
|
|
4585
|
+
this.constructor._finalizeTemplate(
|
|
4586
|
+
/** @type {!HTMLElement} */
|
|
4587
|
+
this.localName
|
|
4588
|
+
);
|
|
4589
|
+
super._initializeProperties();
|
|
4590
|
+
this.rootPath = rootPath;
|
|
4591
|
+
this.importPath = this.constructor.importPath;
|
|
4592
|
+
let p$ = propertyDefaults(this.constructor);
|
|
4593
|
+
if (!p$) {
|
|
4594
|
+
return;
|
|
4595
|
+
}
|
|
4596
|
+
for (let p in p$) {
|
|
4597
|
+
let info = p$[p];
|
|
4598
|
+
if (this._canApplyPropertyDefault(p)) {
|
|
4599
|
+
let value = typeof info.value == "function" ? info.value.call(this) : info.value;
|
|
4600
|
+
if (this._hasAccessor(p)) {
|
|
4601
|
+
this._setPendingProperty(p, value, true);
|
|
4602
|
+
} else {
|
|
4603
|
+
this[p] = value;
|
|
4604
|
+
}
|
|
4605
|
+
}
|
|
4606
|
+
}
|
|
4607
|
+
}
|
|
4608
|
+
/**
|
|
4609
|
+
* Determines if a property dfeault can be applied. For example, this
|
|
4610
|
+
* prevents a default from being applied when a property that has no
|
|
4611
|
+
* accessor is overridden by its host before upgrade (e.g. via a binding).
|
|
4612
|
+
* @override
|
|
4613
|
+
* @param {string} property Name of the property
|
|
4614
|
+
* @return {boolean} Returns true if the property default can be applied.
|
|
4615
|
+
*/
|
|
4616
|
+
_canApplyPropertyDefault(property) {
|
|
4617
|
+
return !this.hasOwnProperty(property);
|
|
4618
|
+
}
|
|
4619
|
+
/**
|
|
4620
|
+
* Gather style text for a style element in the template.
|
|
4621
|
+
*
|
|
4622
|
+
* @param {string} cssText Text containing styling to process
|
|
4623
|
+
* @param {string} baseURI Base URI to rebase CSS paths against
|
|
4624
|
+
* @return {string} The processed CSS text
|
|
4625
|
+
* @protected
|
|
4626
|
+
* @nocollapse
|
|
4627
|
+
*/
|
|
4628
|
+
static _processStyleText(cssText, baseURI) {
|
|
4629
|
+
return resolveCss(cssText, baseURI);
|
|
4630
|
+
}
|
|
4631
|
+
/**
|
|
4632
|
+
* Configures an element `proto` to function with a given `template`.
|
|
4633
|
+
* The element name `is` and extends `ext` must be specified for ShadyCSS
|
|
4634
|
+
* style scoping.
|
|
4635
|
+
*
|
|
4636
|
+
* @param {string} is Tag name (or type extension name) for this element
|
|
4637
|
+
* @return {void}
|
|
4638
|
+
* @protected
|
|
4639
|
+
* @nocollapse
|
|
4640
|
+
*/
|
|
4641
|
+
static _finalizeTemplate(is) {
|
|
4642
|
+
const template = this.prototype._template;
|
|
4643
|
+
if (template && !template.__polymerFinalized) {
|
|
4644
|
+
template.__polymerFinalized = true;
|
|
4645
|
+
const importPath = this.importPath;
|
|
4646
|
+
const baseURI = importPath ? resolveUrl(importPath) : "";
|
|
4647
|
+
processElementStyles(this, template, is, baseURI);
|
|
4648
|
+
this.prototype._bindTemplate(template);
|
|
4649
|
+
}
|
|
4650
|
+
}
|
|
4651
|
+
/**
|
|
4652
|
+
* Provides a default implementation of the standard Custom Elements
|
|
4653
|
+
* `connectedCallback`.
|
|
4654
|
+
*
|
|
4655
|
+
* The default implementation enables the property effects system and
|
|
4656
|
+
* flushes any pending properties, and updates shimmed CSS properties
|
|
4657
|
+
* when using the ShadyCSS scoping/custom properties polyfill.
|
|
4658
|
+
*
|
|
4659
|
+
* @override
|
|
4660
|
+
* @suppress {missingProperties, invalidCasts} Super may or may not
|
|
4661
|
+
* implement the callback
|
|
4662
|
+
* @return {void}
|
|
4663
|
+
*/
|
|
4664
|
+
connectedCallback() {
|
|
4665
|
+
if (window.ShadyCSS && this._template) {
|
|
4666
|
+
window.ShadyCSS.styleElement(
|
|
4667
|
+
/** @type {!HTMLElement} */
|
|
4668
|
+
this
|
|
4669
|
+
);
|
|
4670
|
+
}
|
|
4671
|
+
super.connectedCallback();
|
|
4672
|
+
}
|
|
4673
|
+
/**
|
|
4674
|
+
* Stamps the element template.
|
|
4675
|
+
*
|
|
4676
|
+
* @return {void}
|
|
4677
|
+
* @override
|
|
4678
|
+
*/
|
|
4679
|
+
ready() {
|
|
4680
|
+
if (this._template) {
|
|
4681
|
+
this.root = this._stampTemplate(this._template);
|
|
4682
|
+
this.$ = this.root.$;
|
|
4683
|
+
}
|
|
4684
|
+
super.ready();
|
|
4685
|
+
}
|
|
4686
|
+
/**
|
|
4687
|
+
* Implements `PropertyEffects`'s `_readyClients` call. Attaches
|
|
4688
|
+
* element dom by calling `_attachDom` with the dom stamped from the
|
|
4689
|
+
* element's template via `_stampTemplate`. Note that this allows
|
|
4690
|
+
* client dom to be attached to the element prior to any observers
|
|
4691
|
+
* running.
|
|
4692
|
+
*
|
|
4693
|
+
* @return {void}
|
|
4694
|
+
* @override
|
|
4695
|
+
*/
|
|
4696
|
+
_readyClients() {
|
|
4697
|
+
if (this._template) {
|
|
4698
|
+
this.root = this._attachDom(
|
|
4699
|
+
/** @type {StampedTemplate} */
|
|
4700
|
+
this.root
|
|
4701
|
+
);
|
|
4702
|
+
}
|
|
4703
|
+
super._readyClients();
|
|
4704
|
+
}
|
|
4705
|
+
/**
|
|
4706
|
+
* Attaches an element's stamped dom to itself. By default,
|
|
4707
|
+
* this method creates a `shadowRoot` and adds the dom to it.
|
|
4708
|
+
* However, this method may be overridden to allow an element
|
|
4709
|
+
* to put its dom in another location.
|
|
4710
|
+
*
|
|
4711
|
+
* @override
|
|
4712
|
+
* @throws {Error}
|
|
4713
|
+
* @suppress {missingReturn}
|
|
4714
|
+
* @param {StampedTemplate} dom to attach to the element.
|
|
4715
|
+
* @return {ShadowRoot} node to which the dom has been attached.
|
|
4716
|
+
*/
|
|
4717
|
+
_attachDom(dom) {
|
|
4718
|
+
const n = wrap(this);
|
|
4719
|
+
if (n.attachShadow) {
|
|
4720
|
+
if (dom) {
|
|
4721
|
+
if (!n.shadowRoot) {
|
|
4722
|
+
n.attachShadow({ mode: "open", shadyUpgradeFragment: dom });
|
|
4723
|
+
n.shadowRoot.appendChild(dom);
|
|
4724
|
+
if (this.constructor._styleSheet) {
|
|
4725
|
+
n.shadowRoot.adoptedStyleSheets = [this.constructor._styleSheet];
|
|
4726
|
+
}
|
|
4727
|
+
}
|
|
4728
|
+
if (syncInitialRender && window.ShadyDOM) {
|
|
4729
|
+
window.ShadyDOM.flushInitial(n.shadowRoot);
|
|
4730
|
+
}
|
|
4731
|
+
return n.shadowRoot;
|
|
4732
|
+
}
|
|
4733
|
+
return null;
|
|
4734
|
+
} else {
|
|
4735
|
+
throw new Error("ShadowDOM not available. PolymerElement can create dom as children instead of in ShadowDOM by setting `this.root = this;` before `ready`.");
|
|
4736
|
+
}
|
|
4737
|
+
}
|
|
4738
|
+
/**
|
|
4739
|
+
* When using the ShadyCSS scoping and custom property shim, causes all
|
|
4740
|
+
* shimmed styles in this element (and its subtree) to be updated
|
|
4741
|
+
* based on current custom property values.
|
|
4742
|
+
*
|
|
4743
|
+
* The optional parameter overrides inline custom property styles with an
|
|
4744
|
+
* object of properties where the keys are CSS properties, and the values
|
|
4745
|
+
* are strings.
|
|
4746
|
+
*
|
|
4747
|
+
* Example: `this.updateStyles({'--color': 'blue'})`
|
|
4748
|
+
*
|
|
4749
|
+
* These properties are retained unless a value of `null` is set.
|
|
4750
|
+
*
|
|
4751
|
+
* Note: This function does not support updating CSS mixins.
|
|
4752
|
+
* You can not dynamically change the value of an `@apply`.
|
|
4753
|
+
*
|
|
4754
|
+
* @override
|
|
4755
|
+
* @param {Object=} properties Bag of custom property key/values to
|
|
4756
|
+
* apply to this element.
|
|
4757
|
+
* @return {void}
|
|
4758
|
+
* @suppress {invalidCasts}
|
|
4759
|
+
*/
|
|
4760
|
+
updateStyles(properties) {
|
|
4761
|
+
if (window.ShadyCSS) {
|
|
4762
|
+
window.ShadyCSS.styleSubtree(
|
|
4763
|
+
/** @type {!HTMLElement} */
|
|
4764
|
+
this,
|
|
4765
|
+
properties
|
|
4766
|
+
);
|
|
4767
|
+
}
|
|
4768
|
+
}
|
|
4769
|
+
/**
|
|
4770
|
+
* Rewrites a given URL relative to a base URL. The base URL defaults to
|
|
4771
|
+
* the original location of the document containing the `dom-module` for
|
|
4772
|
+
* this element. This method will return the same URL before and after
|
|
4773
|
+
* bundling.
|
|
4774
|
+
*
|
|
4775
|
+
* Note that this function performs no resolution for URLs that start
|
|
4776
|
+
* with `/` (absolute URLs) or `#` (hash identifiers). For general purpose
|
|
4777
|
+
* URL resolution, use `window.URL`.
|
|
4778
|
+
*
|
|
4779
|
+
* @override
|
|
4780
|
+
* @param {string} url URL to resolve.
|
|
4781
|
+
* @param {string=} base Optional base URL to resolve against, defaults
|
|
4782
|
+
* to the element's `importPath`
|
|
4783
|
+
* @return {string} Rewritten URL relative to base
|
|
4784
|
+
*/
|
|
4785
|
+
resolveUrl(url, base2) {
|
|
4786
|
+
if (!base2 && this.importPath) {
|
|
4787
|
+
base2 = resolveUrl(this.importPath);
|
|
4788
|
+
}
|
|
4789
|
+
return resolveUrl(url, base2);
|
|
4790
|
+
}
|
|
4791
|
+
/**
|
|
4792
|
+
* Overrides `PropertyEffects` to add map of dynamic functions on
|
|
4793
|
+
* template info, for consumption by `PropertyEffects` template binding
|
|
4794
|
+
* code. This map determines which method templates should have accessors
|
|
4795
|
+
* created for them.
|
|
4796
|
+
*
|
|
4797
|
+
* @param {!HTMLTemplateElement} template Template
|
|
4798
|
+
* @param {!TemplateInfo} templateInfo Template metadata for current template
|
|
4799
|
+
* @param {!NodeInfo} nodeInfo Node metadata for current template.
|
|
4800
|
+
* @return {boolean} .
|
|
4801
|
+
* @suppress {missingProperties} Interfaces in closure do not inherit statics, but classes do
|
|
4802
|
+
* @nocollapse
|
|
4803
|
+
*/
|
|
4804
|
+
static _parseTemplateContent(template, templateInfo, nodeInfo) {
|
|
4805
|
+
templateInfo.dynamicFns = templateInfo.dynamicFns || this._properties;
|
|
4806
|
+
return polymerElementBase._parseTemplateContent.call(
|
|
4807
|
+
this,
|
|
4808
|
+
template,
|
|
4809
|
+
templateInfo,
|
|
4810
|
+
nodeInfo
|
|
4811
|
+
);
|
|
4812
|
+
}
|
|
4813
|
+
/**
|
|
4814
|
+
* Overrides `PropertyEffects` to warn on use of undeclared properties in
|
|
4815
|
+
* template.
|
|
4816
|
+
*
|
|
4817
|
+
* @param {Object} templateInfo Template metadata to add effect to
|
|
4818
|
+
* @param {string} prop Property that should trigger the effect
|
|
4819
|
+
* @param {Object=} effect Effect metadata object
|
|
4820
|
+
* @return {void}
|
|
4821
|
+
* @protected
|
|
4822
|
+
* @suppress {missingProperties} Interfaces in closure do not inherit statics, but classes do
|
|
4823
|
+
* @nocollapse
|
|
4824
|
+
*/
|
|
4825
|
+
static _addTemplatePropertyEffect(templateInfo, prop, effect) {
|
|
4826
|
+
if (legacyWarnings && !(prop in this._properties) && // Methods used in templates with no dependencies (or only literal
|
|
4827
|
+
// dependencies) become accessors with template effects; ignore these
|
|
4828
|
+
!(effect.info.part.signature && effect.info.part.signature.static) && // Warnings for bindings added to nested templates are handled by
|
|
4829
|
+
// templatizer so ignore both the host-to-template bindings
|
|
4830
|
+
// (`hostProp`) and TemplateInstance-to-child bindings
|
|
4831
|
+
// (`nestedTemplate`)
|
|
4832
|
+
!effect.info.part.hostProp && !templateInfo.nestedTemplate) {
|
|
4833
|
+
console.warn(`Property '${prop}' used in template but not declared in 'properties'; attribute will not be observed.`);
|
|
4834
|
+
}
|
|
4835
|
+
return polymerElementBase._addTemplatePropertyEffect.call(
|
|
4836
|
+
this,
|
|
4837
|
+
templateInfo,
|
|
4838
|
+
prop,
|
|
4839
|
+
effect
|
|
4840
|
+
);
|
|
4841
|
+
}
|
|
4842
|
+
}
|
|
4843
|
+
return PolymerElement;
|
|
4844
|
+
});
|
|
4845
|
+
|
|
4846
|
+
export {
|
|
4847
|
+
useShadow,
|
|
4848
|
+
passiveTouchGestures,
|
|
4849
|
+
strictTemplatePolicy,
|
|
4850
|
+
legacyOptimizations,
|
|
4851
|
+
legacyWarnings,
|
|
4852
|
+
cancelSyntheticClickEvents,
|
|
4853
|
+
fastDomIf,
|
|
4854
|
+
suppressTemplateNotifications,
|
|
4855
|
+
legacyNoObservedAttributes,
|
|
4856
|
+
cssFromModules,
|
|
4857
|
+
wrap,
|
|
4858
|
+
root,
|
|
4859
|
+
translate,
|
|
4860
|
+
matches,
|
|
4861
|
+
get,
|
|
4862
|
+
timeOut,
|
|
4863
|
+
microTask,
|
|
4864
|
+
PropertyAccessors,
|
|
4865
|
+
PropertyEffects,
|
|
4866
|
+
register,
|
|
4867
|
+
version,
|
|
4868
|
+
builtCSS,
|
|
4869
|
+
ElementMixin
|
|
4870
|
+
};
|
|
4871
|
+
//# sourceMappingURL=chunk-PRUGAEYJ.js.map
|