| Index: appengine/config_service/ui/bower_components/polymer/lib/mixins/property-accessors.html
|
| diff --git a/appengine/config_service/ui/bower_components/polymer/lib/mixins/property-accessors.html b/appengine/config_service/ui/bower_components/polymer/lib/mixins/property-accessors.html
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..3500266aef7709dd5d4f3565979be55e81e93ae3
|
| --- /dev/null
|
| +++ b/appengine/config_service/ui/bower_components/polymer/lib/mixins/property-accessors.html
|
| @@ -0,0 +1,586 @@
|
| +<!--
|
| +@license
|
| +Copyright (c) 2017 The Polymer Project Authors. All rights reserved.
|
| +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
|
| +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
|
| +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
|
| +Code distributed by Google as part of the polymer project is also
|
| +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
|
| +-->
|
| +
|
| +<link rel="import" href="../utils/boot.html">
|
| +<link rel="import" href="../utils/mixin.html">
|
| +<link rel="import" href="../utils/case-map.html">
|
| +<link rel="import" href="../utils/async.html">
|
| +
|
| +<script>
|
| +(function() {
|
| +
|
| + 'use strict';
|
| +
|
| + let caseMap = Polymer.CaseMap;
|
| +
|
| + let microtask = Polymer.Async.microTask;
|
| +
|
| + // Save map of native properties; this forms a blacklist or properties
|
| + // that won't have their values "saved" by `saveAccessorValue`, since
|
| + // reading from an HTMLElement accessor from the context of a prototype throws
|
| + const nativeProperties = {};
|
| + let proto = HTMLElement.prototype;
|
| + while (proto) {
|
| + let props = Object.getOwnPropertyNames(proto);
|
| + for (let i=0; i<props.length; i++) {
|
| + nativeProperties[props[i]] = true;
|
| + }
|
| + proto = Object.getPrototypeOf(proto);
|
| + }
|
| +
|
| + /**
|
| + * Used to save the value of a property that will be overridden with
|
| + * an accessor. If the `model` is a prototype, the values will be saved
|
| + * in `__dataProto`, and it's up to the user (or downstream mixin) to
|
| + * decide how/when to set these values back into the accessors.
|
| + * If `model` is already an instance (it has a `__data` property), then
|
| + * the value will be set as a pending property, meaning the user should
|
| + * call `_invalidateProperties` or `_flushProperties` to take effect
|
| + *
|
| + * @param {Object} model Prototype or instance
|
| + * @param {string} property Name of property
|
| + * @private
|
| + */
|
| + function saveAccessorValue(model, property) {
|
| + // Don't read/store value for any native properties since they could throw
|
| + if (!nativeProperties[property]) {
|
| + let value = model[property];
|
| + if (value !== undefined) {
|
| + if (model.__data) {
|
| + // Adding accessor to instance; update the property
|
| + // It is the user's responsibility to call _flushProperties
|
| + model._setPendingProperty(property, value);
|
| + } else {
|
| + // Adding accessor to proto; save proto's value for instance-time use
|
| + if (!model.__dataProto) {
|
| + model.__dataProto = {};
|
| + } else if (!model.hasOwnProperty(JSCompiler_renameProperty('__dataProto', model))) {
|
| + model.__dataProto = Object.create(model.__dataProto);
|
| + }
|
| + model.__dataProto[property] = value;
|
| + }
|
| + }
|
| + }
|
| + }
|
| +
|
| + /**
|
| + * Element class mixin that provides basic meta-programming for creating one
|
| + * or more property accessors (getter/setter pair) that enqueue an async
|
| + * (batched) `_propertiesChanged` callback.
|
| + *
|
| + * For basic usage of this mixin, simply declare attributes to observe via
|
| + * the standard `static get observedAttributes()`, implement `_propertiesChanged`
|
| + * on the class, and then call `MyClass.createPropertiesForAttributes()` once
|
| + * on the class to generate property accessors for each observed attribute
|
| + * prior to instancing. Last, call `this._flushProperties()` once to enable
|
| + * the accessors.
|
| + *
|
| + * Any `observedAttributes` will automatically be
|
| + * deserialized via `attributeChangedCallback` and set to the associated
|
| + * property using `dash-case`-to-`camelCase` convention.
|
| + *
|
| + * @polymerMixin
|
| + * @memberof Polymer
|
| + * @summary Element class mixin for reacting to property changes from
|
| + * generated property accessors.
|
| + */
|
| + Polymer.PropertyAccessors = Polymer.dedupingMixin(superClass => {
|
| +
|
| + /**
|
| + * @polymerMixinClass
|
| + * @implements {Polymer_PropertyAccessors}
|
| + * @unrestricted
|
| + */
|
| + class PropertyAccessors extends superClass {
|
| +
|
| + /**
|
| + * Generates property accessors for all attributes in the standard
|
| + * static `observedAttributes` array.
|
| + *
|
| + * Attribute names are mapped to property names using the `dash-case` to
|
| + * `camelCase` convention
|
| + *
|
| + */
|
| + static createPropertiesForAttributes() {
|
| + let a$ = this.observedAttributes;
|
| + for (let i=0; i < a$.length; i++) {
|
| + this.prototype._createPropertyAccessor(caseMap.dashToCamelCase(a$[i]));
|
| + }
|
| + }
|
| +
|
| + constructor() {
|
| + super();
|
| + this._initializeProperties();
|
| + }
|
| +
|
| + attributeChangedCallback(name, old, value) {
|
| + if (old !== value) {
|
| + this._attributeToProperty(name, value);
|
| + }
|
| + }
|
| +
|
| + /**
|
| + * Initializes the local storage for property accessors.
|
| + *
|
| + * Provided as an override point for performing any setup work prior
|
| + * to initializing the property accessor system.
|
| + *
|
| + * @protected
|
| + */
|
| + _initializeProperties() {
|
| + this.__serializing = false;
|
| + this.__dataCounter = 0;
|
| + this.__dataEnabled = false;
|
| + this.__dataReady = false;
|
| + this.__dataInvalid = false;
|
| + // initialize data with prototype values saved when creating accessors
|
| + this.__data = {};
|
| + this.__dataPending = null;
|
| + this.__dataOld = null;
|
| + if (this.__dataProto) {
|
| + this._initializeProtoProperties(this.__dataProto);
|
| + this.__dataProto = null;
|
| + }
|
| + // Capture instance properties; these will be set into accessors
|
| + // during first flush. Don't set them here, since we want
|
| + // these to overwrite defaults/constructor assignments
|
| + for (let p in this.__dataHasAccessor) {
|
| + if (this.hasOwnProperty(p)) {
|
| + this.__dataInstanceProps = this.__dataInstanceProps || {};
|
| + this.__dataInstanceProps[p] = this[p];
|
| + delete this[p];
|
| + }
|
| + }
|
| + }
|
| +
|
| + /**
|
| + * Called at instance time with bag of properties that were overwritten
|
| + * by accessors on the prototype when accessors were created.
|
| + *
|
| + * The default implementation sets these properties back into the
|
| + * setter at instance time. This method is provided as an override
|
| + * point for customizing or providing more efficient initialization.
|
| + *
|
| + * @param {Object} props Bag of property values that were overwritten
|
| + * when creating property accessors.
|
| + * @protected
|
| + */
|
| + _initializeProtoProperties(props) {
|
| + for (let p in props) {
|
| + this._setProperty(p, props[p]);
|
| + }
|
| + }
|
| +
|
| + /**
|
| + * Called at ready time with bag of instance properties that overwrote
|
| + * accessors when the element upgraded.
|
| + *
|
| + * The default implementation sets these properties back into the
|
| + * setter at ready time. This method is provided as an override
|
| + * point for customizing or providing more efficient initialization.
|
| + *
|
| + * @param {Object} props Bag of property values that were overwritten
|
| + * when creating property accessors.
|
| + * @protected
|
| + */
|
| + _initializeInstanceProperties(props) {
|
| + Object.assign(this, props);
|
| + }
|
| +
|
| + /**
|
| + * Ensures the element has the given attribute. If it does not,
|
| + * assigns the given value to the attribute.
|
| + *
|
| + *
|
| + * @param {string} attribute Name of attribute to ensure is set.
|
| + * @param {string} value of the attribute.
|
| + */
|
| + _ensureAttribute(attribute, value) {
|
| + if (!this.hasAttribute(attribute)) {
|
| + this._valueToNodeAttribute(this, value, attribute);
|
| + }
|
| + }
|
| +
|
| + /**
|
| + * Deserializes an attribute to its associated property.
|
| + *
|
| + * This method calls the `_deserializeValue` method to convert the string to
|
| + * a typed value.
|
| + *
|
| + * @param {string} attribute Name of attribute to deserialize.
|
| + * @param {string} value of the attribute.
|
| + * @param {*} type type to deserialize to.
|
| + */
|
| + _attributeToProperty(attribute, value, type) {
|
| + // Don't deserialize back to property if currently reflecting
|
| + if (!this.__serializing) {
|
| + let property = caseMap.dashToCamelCase(attribute);
|
| + this[property] = this._deserializeValue(value, type);
|
| + }
|
| + }
|
| +
|
| + /**
|
| + * Serializes a property to its associated attribute.
|
| + *
|
| + * @param {string} property Property name to reflect.
|
| + * @param {string=} attribute Attribute name to reflect.
|
| + * @param {*=} value Property value to refect.
|
| + */
|
| + _propertyToAttribute(property, attribute, value) {
|
| + this.__serializing = true;
|
| + value = (arguments.length < 3) ? this[property] : value;
|
| + this._valueToNodeAttribute(this, value,
|
| + attribute || caseMap.camelToDashCase(property));
|
| + this.__serializing = false;
|
| + }
|
| +
|
| + /**
|
| + * Sets a typed value to an HTML attribute on a node.
|
| + *
|
| + * This method calls the `_serializeValue` method to convert the typed
|
| + * value to a string. If the `_serializeValue` method returns `undefined`,
|
| + * the attribute will be removed (this is the default for boolean
|
| + * type `false`).
|
| + *
|
| + * @param {Element} node Element to set attribute to.
|
| + * @param {*} value Value to serialize.
|
| + * @param {string} attribute Attribute name to serialize to.
|
| + */
|
| + _valueToNodeAttribute(node, value, attribute) {
|
| + let str = this._serializeValue(value);
|
| + if (str === undefined) {
|
| + node.removeAttribute(attribute);
|
| + } else {
|
| + node.setAttribute(attribute, str);
|
| + }
|
| + }
|
| +
|
| + /**
|
| + * Converts a typed JavaScript value to a string.
|
| + *
|
| + * This method is called by Polymer when setting JS property values to
|
| + * HTML attributes. Users may override this method on Polymer element
|
| + * prototypes to provide serialization for custom types.
|
| + *
|
| + * @param {*} value Property value to serialize.
|
| + * @return {string | undefined} String serialized from the provided property value.
|
| + */
|
| + _serializeValue(value) {
|
| + /* eslint-disable no-fallthrough */
|
| + switch (typeof value) {
|
| + case 'boolean':
|
| + return value ? '' : undefined;
|
| +
|
| + case 'object':
|
| + if (value instanceof Date) {
|
| + return value.toString();
|
| + } else if (value) {
|
| + try {
|
| + return JSON.stringify(value);
|
| + } catch(x) {
|
| + return '';
|
| + }
|
| + }
|
| +
|
| + default:
|
| + return value != null ? value.toString() : undefined;
|
| + }
|
| + }
|
| +
|
| + /**
|
| + * Converts a string to a typed JavaScript value.
|
| + *
|
| + * This method is called by Polymer when reading HTML attribute values to
|
| + * JS properties. Users may override this method on Polymer element
|
| + * prototypes to provide deserialization for custom `type`s. Note,
|
| + * the `type` argument is the value of the `type` field provided in the
|
| + * `properties` configuration object for a given property, and is
|
| + * by convention the constructor for the type to deserialize.
|
| + *
|
| + * Note: The return value of `undefined` is used as a sentinel value to
|
| + * indicate the attribute should be removed.
|
| + *
|
| + * @param {string} value Attribute value to deserialize.
|
| + * @param {*} type Type to deserialize the string to.
|
| + * @return {*} Typed value deserialized from the provided string.
|
| + */
|
| + _deserializeValue(value, type) {
|
| + /**
|
| + * @type {*}
|
| + */
|
| + let outValue;
|
| + switch (type) {
|
| + case Number:
|
| + outValue = Number(value);
|
| + break;
|
| +
|
| + case Boolean:
|
| + outValue = (value !== null);
|
| + break;
|
| +
|
| + case Object:
|
| + try {
|
| + outValue = JSON.parse(value);
|
| + } catch(x) {
|
| + // allow non-JSON literals like Strings and Numbers
|
| + }
|
| + break;
|
| +
|
| + case Array:
|
| + try {
|
| + outValue = JSON.parse(value);
|
| + } catch(x) {
|
| + outValue = null;
|
| + console.warn(`Polymer::Attributes: couldn't decode Array as JSON: ${value}`);
|
| + }
|
| + break;
|
| +
|
| + case Date:
|
| + outValue = new Date(value);
|
| + break;
|
| +
|
| + case String:
|
| + default:
|
| + outValue = value;
|
| + break;
|
| + }
|
| +
|
| + return outValue;
|
| + }
|
| + /* eslint-enable no-fallthrough */
|
| +
|
| + /**
|
| + * Creates a setter/getter pair for the named property with its own
|
| + * local storage. The getter returns the value in the local storage,
|
| + * and the setter calls `_setProperty`, which updates the local storage
|
| + * for the property and enqueues a `_propertiesChanged` callback.
|
| + *
|
| + * This method may be called on a prototype or an instance. Calling
|
| + * this method may overwrite a property value that already exists on
|
| + * the prototype/instance by creating the accessor. When calling on
|
| + * a prototype, any overwritten values are saved in `__dataProto`,
|
| + * and it is up to the subclasser to decide how/when to set those
|
| + * properties back into the accessor. When calling on an instance,
|
| + * the overwritten value is set via `_setPendingProperty`, and the
|
| + * user should call `_invalidateProperties` or `_flushProperties`
|
| + * for the values to take effect.
|
| + *
|
| + * @param {string} property Name of the property
|
| + * @param {boolean=} readOnly When true, no setter is created; the
|
| + * protected `_setProperty` function must be used to set the property
|
| + * @protected
|
| + */
|
| + _createPropertyAccessor(property, readOnly) {
|
| + if (!this.hasOwnProperty('__dataHasAccessor')) {
|
| + this.__dataHasAccessor = Object.assign({}, this.__dataHasAccessor);
|
| + }
|
| + if (!this.__dataHasAccessor[property]) {
|
| + this.__dataHasAccessor[property] = true;
|
| + saveAccessorValue(this, property);
|
| + Object.defineProperty(this, property, {
|
| + get: function() {
|
| + return this.__data[property];
|
| + },
|
| + set: readOnly ? function() { } : function(value) {
|
| + this._setProperty(property, value);
|
| + }
|
| + });
|
| + }
|
| + }
|
| +
|
| + /**
|
| + * Returns true if this library created an accessor for the given property.
|
| + *
|
| + * @param {string} property Property name
|
| + * @return {boolean} True if an accessor was created
|
| + */
|
| + _hasAccessor(property) {
|
| + return this.__dataHasAccessor && this.__dataHasAccessor[property];
|
| + }
|
| +
|
| + /**
|
| + * Updates the local storage for a property (via `_setPendingProperty`)
|
| + * and enqueues a `_proeprtiesChanged` callback.
|
| + *
|
| + * @param {string} property Name of the property
|
| + * @param {*} value Value to set
|
| + * @protected
|
| + */
|
| + _setProperty(property, value) {
|
| + if (this._setPendingProperty(property, value)) {
|
| + this._invalidateProperties();
|
| + }
|
| + }
|
| +
|
| + /**
|
| + * Updates the local storage for a property, records the previous value,
|
| + * and adds it to the set of "pending changes" that will be passed to the
|
| + * `_propertiesChanged` callback. This method does not enqueue the
|
| + * `_propertiesChanged` callback.
|
| + *
|
| + * @param {string} property Name of the property
|
| + * @param {*} value Value to set
|
| + * @return {boolean} Returns true if the property changed
|
| + * @protected
|
| + */
|
| + _setPendingProperty(property, value) {
|
| + let old = this.__data[property];
|
| + if (this._shouldPropertyChange(property, value, old)) {
|
| + if (!this.__dataPending) {
|
| + this.__dataPending = {};
|
| + this.__dataOld = {};
|
| + }
|
| + // Ensure old is captured from the last turn
|
| + if (!(property in this.__dataOld)) {
|
| + this.__dataOld[property] = old;
|
| + }
|
| + this.__data[property] = value;
|
| + this.__dataPending[property] = value;
|
| + return true;
|
| + }
|
| + }
|
| +
|
| + /**
|
| + * Returns true if the specified property has a pending change.
|
| + *
|
| + * @param {string} prop Property name
|
| + * @return {boolean} True if property has a pending change
|
| + * @protected
|
| + */
|
| + _isPropertyPending(prop) {
|
| + return this.__dataPending && (prop in this.__dataPending);
|
| + }
|
| +
|
| + /**
|
| + * Marks the properties as invalid, and enqueues an async
|
| + * `_propertiesChanged` callback.
|
| + *
|
| + * @protected
|
| + */
|
| + _invalidateProperties() {
|
| + if (!this.__dataInvalid && this.__dataReady) {
|
| + this.__dataInvalid = true;
|
| + microtask.run(() => {
|
| + if (this.__dataInvalid) {
|
| + this.__dataInvalid = false;
|
| + this._flushProperties();
|
| + }
|
| + });
|
| + }
|
| + }
|
| +
|
| + /**
|
| + * Call to enable property accessor processing. Before this method is
|
| + * called accessor values will be set but side effects are
|
| + * queued. When called, any pending side effects occur immediately.
|
| + * For elements, generally `connectedCallback` is a normal spot to do so.
|
| + * It is safe to call this method multiple times as it only turns on
|
| + * property accessors once.
|
| + */
|
| + _enableProperties() {
|
| + if (!this.__dataEnabled) {
|
| + this.__dataEnabled = true;
|
| + if (this.__dataInstanceProps) {
|
| + this._initializeInstanceProperties(this.__dataInstanceProps);
|
| + this.__dataInstanceProps = null;
|
| + }
|
| + this.ready()
|
| + }
|
| + }
|
| +
|
| + /**
|
| + * Calls the `_propertiesChanged` callback with the current set of
|
| + * pending changes (and old values recorded when pending changes were
|
| + * set), and resets the pending set of changes. Generally, this method
|
| + * should not be called in user code.
|
| + *
|
| + *
|
| + * @protected
|
| + */
|
| + _flushProperties() {
|
| + if (this.__dataPending) {
|
| + let changedProps = this.__dataPending;
|
| + this.__dataPending = null;
|
| + this.__dataCounter++;
|
| + this._propertiesChanged(this.__data, changedProps, this.__dataOld);
|
| + this.__dataCounter--;
|
| + }
|
| + }
|
| +
|
| + /**
|
| + * Lifecycle callback called the first time properties are being flushed.
|
| + * Prior to `ready`, all property sets through accessors are queued and
|
| + * their effects are flushed after this method returns.
|
| + *
|
| + * Users may override this function to implement behavior that is
|
| + * dependent on the element having its properties initialized, e.g.
|
| + * from defaults (initialized from `constructor`, `_initializeProperties`),
|
| + * `attributeChangedCallback`, or values propagated from host e.g. via
|
| + * bindings. `super.ready()` must be called to ensure the data system
|
| + * becomes enabled.
|
| + *
|
| + * @public
|
| + */
|
| + ready() {
|
| + this.__dataReady = true;
|
| + // Run normal flush
|
| + this._flushProperties();
|
| + }
|
| +
|
| + /**
|
| + * Callback called when any properties with accessors created via
|
| + * `_createPropertyAccessor` have been set.
|
| + *
|
| + * @param {Object} currentProps Bag of all current accessor values
|
| + * @param {Object} changedProps Bag of properties changed since the last
|
| + * call to `_propertiesChanged`
|
| + * @param {Object} oldProps Bag of previous values for each property
|
| + * in `changedProps`
|
| + * @protected
|
| + */
|
| + _propertiesChanged(currentProps, changedProps, oldProps) { // eslint-disable-line no-unused-vars
|
| + }
|
| +
|
| + /**
|
| + * Method called to determine whether a property value should be
|
| + * considered as a change and cause the `_propertiesChanged` callback
|
| + * to be enqueued.
|
| + *
|
| + * The default implementation returns `true` for primitive types if a
|
| + * strict equality check fails, and returns `true` for all Object/Arrays.
|
| + * The method always returns false for `NaN`.
|
| + *
|
| + * Override this method to e.g. provide stricter checking for
|
| + * Objects/Arrays when using immutable patterns.
|
| + *
|
| + * @param {string} property Property name
|
| + * @param {*} value New property value
|
| + * @param {*} old Previous property value
|
| + * @return {boolean} Whether the property should be considered a change
|
| + * and enqueue a `_proeprtiesChanged` callback
|
| + * @protected
|
| + */
|
| + _shouldPropertyChange(property, value, old) {
|
| + return (
|
| + // Strict equality check
|
| + (old !== value &&
|
| + // This ensures (old==NaN, value==NaN) always returns false
|
| + (old === old || value === value))
|
| + );
|
| + }
|
| +
|
| + }
|
| +
|
| + return PropertyAccessors;
|
| +
|
| + });
|
| +
|
| +})();
|
| +</script>
|
|
|