Buckets:
| /** | |
| * @license | |
| * Copyright 2017 Google LLC | |
| * SPDX-License-Identifier: BSD-3-Clause | |
| */ | |
| import { isSingleExpression } from './directive-helpers.js'; | |
| import { Directive, PartType } from './directive.js'; | |
| export * from './directive.js'; | |
| const DEV_MODE = true; | |
| /** | |
| * Recursively walks down the tree of Parts/TemplateInstances/Directives to set | |
| * the connected state of directives and run `disconnected`/ `reconnected` | |
| * callbacks. | |
| * | |
| * @return True if there were children to disconnect; false otherwise | |
| */ | |
| const notifyChildrenConnectedChanged = (parent, isConnected) => { | |
| const children = parent._$disconnectableChildren; | |
| if (children === undefined) { | |
| return false; | |
| } | |
| for (const obj of children) { | |
| // The existence of `_$notifyDirectiveConnectionChanged` is used as a "brand" to | |
| // disambiguate AsyncDirectives from other DisconnectableChildren | |
| // (as opposed to using an instanceof check to know when to call it); the | |
| // redundancy of "Directive" in the API name is to avoid conflicting with | |
| // `_$notifyConnectionChanged`, which exists `ChildParts` which are also in | |
| // this list | |
| // Disconnect Directive (and any nested directives contained within) | |
| // This property needs to remain unminified. | |
| obj['_$notifyDirectiveConnectionChanged']?.(isConnected, false); | |
| // Disconnect Part/TemplateInstance | |
| notifyChildrenConnectedChanged(obj, isConnected); | |
| } | |
| return true; | |
| }; | |
| /** | |
| * Removes the given child from its parent list of disconnectable children, and | |
| * if the parent list becomes empty as a result, removes the parent from its | |
| * parent, and so forth up the tree when that causes subsequent parent lists to | |
| * become empty. | |
| */ | |
| const removeDisconnectableFromParent = (obj) => { | |
| let parent, children; | |
| do { | |
| if ((parent = obj._$parent) === undefined) { | |
| break; | |
| } | |
| children = parent._$disconnectableChildren; | |
| children.delete(obj); | |
| obj = parent; | |
| } while (children?.size === 0); | |
| }; | |
| const addDisconnectableToParent = (obj) => { | |
| // Climb the parent tree, creating a sparse tree of children needing | |
| // disconnection | |
| for (let parent; (parent = obj._$parent); obj = parent) { | |
| let children = parent._$disconnectableChildren; | |
| if (children === undefined) { | |
| parent._$disconnectableChildren = children = new Set(); | |
| } | |
| else if (children.has(obj)) { | |
| // Once we've reached a parent that already contains this child, we | |
| // can short-circuit | |
| break; | |
| } | |
| children.add(obj); | |
| installDisconnectAPI(parent); | |
| } | |
| }; | |
| /** | |
| * Changes the parent reference of the ChildPart, and updates the sparse tree of | |
| * Disconnectable children accordingly. | |
| * | |
| * Note, this method will be patched onto ChildPart instances and called from | |
| * the core code when parts are moved between different parents. | |
| */ | |
| function reparentDisconnectables(newParent) { | |
| if (this._$disconnectableChildren !== undefined) { | |
| removeDisconnectableFromParent(this); | |
| this._$parent = newParent; | |
| addDisconnectableToParent(this); | |
| } | |
| else { | |
| this._$parent = newParent; | |
| } | |
| } | |
| /** | |
| * Sets the connected state on any directives contained within the committed | |
| * value of this part (i.e. within a TemplateInstance or iterable of | |
| * ChildParts) and runs their `disconnected`/`reconnected`s, as well as within | |
| * any directives stored on the ChildPart (when `valueOnly` is false). | |
| * | |
| * `isClearingValue` should be passed as `true` on a top-level part that is | |
| * clearing itself, and not as a result of recursively disconnecting directives | |
| * as part of a `clear` operation higher up the tree. This both ensures that any | |
| * directive on this ChildPart that produced a value that caused the clear | |
| * operation is not disconnected, and also serves as a performance optimization | |
| * to avoid needless bookkeeping when a subtree is going away; when clearing a | |
| * subtree, only the top-most part need to remove itself from the parent. | |
| * | |
| * `fromPartIndex` is passed only in the case of a partial `_clear` running as a | |
| * result of truncating an iterable. | |
| * | |
| * Note, this method will be patched onto ChildPart instances and called from the | |
| * core code when parts are cleared or the connection state is changed by the | |
| * user. | |
| */ | |
| function notifyChildPartConnectedChanged(isConnected, isClearingValue = false, fromPartIndex = 0) { | |
| const value = this._$committedValue; | |
| const children = this._$disconnectableChildren; | |
| if (children === undefined || children.size === 0) { | |
| return; | |
| } | |
| if (isClearingValue) { | |
| if (Array.isArray(value)) { | |
| // Iterable case: Any ChildParts created by the iterable should be | |
| // disconnected and removed from this ChildPart's disconnectable | |
| // children (starting at `fromPartIndex` in the case of truncation) | |
| for (let i = fromPartIndex; i < value.length; i++) { | |
| notifyChildrenConnectedChanged(value[i], false); | |
| removeDisconnectableFromParent(value[i]); | |
| } | |
| } | |
| else if (value != null) { | |
| // TemplateInstance case: If the value has disconnectable children (will | |
| // only be in the case that it is a TemplateInstance), we disconnect it | |
| // and remove it from this ChildPart's disconnectable children | |
| notifyChildrenConnectedChanged(value, false); | |
| removeDisconnectableFromParent(value); | |
| } | |
| } | |
| else { | |
| notifyChildrenConnectedChanged(this, isConnected); | |
| } | |
| } | |
| /** | |
| * Patches disconnection API onto ChildParts. | |
| */ | |
| const installDisconnectAPI = (obj) => { | |
| if (obj.type == PartType.CHILD) { | |
| obj._$notifyConnectionChanged ??= | |
| notifyChildPartConnectedChanged; | |
| obj._$reparentDisconnectables ??= reparentDisconnectables; | |
| } | |
| }; | |
| /** | |
| * An abstract `Directive` base class whose `disconnected` method will be | |
| * called when the part containing the directive is cleared as a result of | |
| * re-rendering, or when the user calls `part.setConnected(false)` on | |
| * a part that was previously rendered containing the directive (as happens | |
| * when e.g. a LitElement disconnects from the DOM). | |
| * | |
| * If `part.setConnected(true)` is subsequently called on a | |
| * containing part, the directive's `reconnected` method will be called prior | |
| * to its next `update`/`render` callbacks. When implementing `disconnected`, | |
| * `reconnected` should also be implemented to be compatible with reconnection. | |
| * | |
| * Note that updates may occur while the directive is disconnected. As such, | |
| * directives should generally check the `this.isConnected` flag during | |
| * render/update to determine whether it is safe to subscribe to resources | |
| * that may prevent garbage collection. | |
| */ | |
| export class AsyncDirective extends Directive { | |
| constructor() { | |
| super(...arguments); | |
| // @internal | |
| this._$disconnectableChildren = undefined; | |
| } | |
| /** | |
| * Initialize the part with internal fields | |
| * @param part | |
| * @param parent | |
| * @param attributeIndex | |
| */ | |
| _$initialize(part, parent, attributeIndex) { | |
| super._$initialize(part, parent, attributeIndex); | |
| addDisconnectableToParent(this); | |
| this.isConnected = part._$isConnected; | |
| } | |
| // This property needs to remain unminified. | |
| /** | |
| * Called from the core code when a directive is going away from a part (in | |
| * which case `shouldRemoveFromParent` should be true), and from the | |
| * `setChildrenConnected` helper function when recursively changing the | |
| * connection state of a tree (in which case `shouldRemoveFromParent` should | |
| * be false). | |
| * | |
| * @param isConnected | |
| * @param isClearingDirective - True when the directive itself is being | |
| * removed; false when the tree is being disconnected | |
| * @internal | |
| */ | |
| ['_$notifyDirectiveConnectionChanged'](isConnected, isClearingDirective = true) { | |
| if (isConnected !== this.isConnected) { | |
| this.isConnected = isConnected; | |
| if (isConnected) { | |
| this.reconnected?.(); | |
| } | |
| else { | |
| this.disconnected?.(); | |
| } | |
| } | |
| if (isClearingDirective) { | |
| notifyChildrenConnectedChanged(this, isConnected); | |
| removeDisconnectableFromParent(this); | |
| } | |
| } | |
| /** | |
| * Sets the value of the directive's Part outside the normal `update`/`render` | |
| * lifecycle of a directive. | |
| * | |
| * This method should not be called synchronously from a directive's `update` | |
| * or `render`. | |
| * | |
| * @param directive The directive to update | |
| * @param value The value to set | |
| */ | |
| setValue(value) { | |
| if (isSingleExpression(this.__part)) { | |
| this.__part._$setValue(value, this); | |
| } | |
| else { | |
| // this.__attributeIndex will be defined in this case, but | |
| // assert it in dev mode | |
| if (DEV_MODE && this.__attributeIndex === undefined) { | |
| throw new Error(`Expected this.__attributeIndex to be a number`); | |
| } | |
| const newValues = [...this.__part._$committedValue]; | |
| newValues[this.__attributeIndex] = value; | |
| this.__part._$setValue(newValues, this, 0); | |
| } | |
| } | |
| /** | |
| * User callbacks for implementing logic to release any resources/subscriptions | |
| * that may have been retained by this directive. Since directives may also be | |
| * re-connected, `reconnected` should also be implemented to restore the | |
| * working state of the directive prior to the next render. | |
| */ | |
| disconnected() { } | |
| reconnected() { } | |
| } | |
| //# sourceMappingURL=async-directive.js.map |
Xet Storage Details
- Size:
- 9.82 kB
- Xet hash:
- 4563725afbd803a95f076250a67b9289bab8e435d854534dc12935b89180b41a
·
Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.