{"version":3,"file":"async-replace.js","sources":["../../../src/directives/async-replace.ts"],"sourcesContent":["/**\n * @license\n * Copyright 2017 Google LLC\n * SPDX-License-Identifier: BSD-3-Clause\n */\n\nimport {ChildPart, noChange} from '../lit-html.js';\nimport {\n  AsyncDirective,\n  directive,\n  DirectiveParameters,\n} from '../async-directive.js';\nimport {Pauser, PseudoWeakRef, forAwaitOf} from './private-async-helpers.js';\n\ntype Mapper<T> = (v: T, index?: number) => unknown;\n\nexport class AsyncReplaceDirective extends AsyncDirective {\n  private __value?: AsyncIterable<unknown>;\n  private __weakThis = new PseudoWeakRef(this);\n  private __pauser = new Pauser();\n\n  // @ts-expect-error value not used, but we want a nice parameter for docs\n  // eslint-disable-next-line @typescript-eslint/no-unused-vars\n  render<T>(value: AsyncIterable<T>, _mapper?: Mapper<T>) {\n    return noChange;\n  }\n\n  override update(\n    _part: ChildPart,\n    [value, mapper]: DirectiveParameters<this>\n  ) {\n    // If our initial render occurs while disconnected, ensure that the pauser\n    // and weakThis are in the disconnected state\n    if (!this.isConnected) {\n      this.disconnected();\n    }\n    // If we've already set up this particular iterable, we don't need\n    // to do anything.\n    if (value === this.__value) {\n      return noChange;\n    }\n    this.__value = value;\n    let i = 0;\n    const {__weakThis: weakThis, __pauser: pauser} = this;\n    // Note, the callback avoids closing over `this` so that the directive\n    // can be gc'ed before the promise resolves; instead `this` is retrieved\n    // from `weakThis`, which can break the hard reference in the closure when\n    // the directive disconnects\n    forAwaitOf(value, async (v: unknown) => {\n      // The while loop here handles the case that the connection state\n      // thrashes, causing the pauser to resume and then get re-paused\n      while (pauser.get()) {\n        await pauser.get();\n      }\n      // If the callback gets here and there is no `this`, it means that the\n      // directive has been disconnected and garbage collected and we don't\n      // need to do anything else\n      const _this = weakThis.deref();\n      if (_this !== undefined) {\n        // Check to make sure that value is the still the current value of\n        // the part, and if not bail because a new value owns this part\n        if (_this.__value !== value) {\n          return false;\n        }\n\n        // As a convenience, because functional-programming-style\n        // transforms of iterables and async iterables requires a library,\n        // we accept a mapper function. This is especially convenient for\n        // rendering a template for each item.\n        if (mapper !== undefined) {\n          v = mapper(v, i);\n        }\n\n        _this.commitValue(v, i);\n        i++;\n      }\n      return true;\n    });\n    return noChange;\n  }\n\n  // Override point for AsyncAppend to append rather than replace\n  protected commitValue(value: unknown, _index: number) {\n    this.setValue(value);\n  }\n\n  override disconnected() {\n    this.__weakThis.disconnect();\n    this.__pauser.pause();\n  }\n\n  override reconnected() {\n    this.__weakThis.reconnect(this);\n    this.__pauser.resume();\n  }\n}\n\n/**\n * A directive that renders the items of an async iterable[1], replacing\n * previous values with new values, so that only one value is ever rendered\n * at a time. This directive may be used in any expression type.\n *\n * Async iterables are objects with a `[Symbol.asyncIterator]` method, which\n * returns an iterator who's `next()` method returns a Promise. When a new\n * value is available, the Promise resolves and the value is rendered to the\n * Part controlled by the directive. If another value other than this\n * directive has been set on the Part, the iterable will no longer be listened\n * to and new values won't be written to the Part.\n *\n * [1]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for-await...of\n *\n * @param value An async iterable\n * @param mapper An optional function that maps from (value, index) to another\n *     value. Useful for generating templates for each item in the iterable.\n */\nexport const asyncReplace = directive(AsyncReplaceDirective);\n"],"names":[],"mappings":";;;;;AAAA;;;;AAIG;AAYG,MAAO,qBAAsB,SAAQ,cAAc,CAAA;AAAzD,IAAA,WAAA,GAAA;;AAEU,QAAA,IAAA,CAAA,UAAU,GAAG,IAAI,aAAa,CAAC,IAAI,CAAC;AACpC,QAAA,IAAA,CAAA,QAAQ,GAAG,IAAI,MAAM,EAAE;IA4EjC;;;IAxEE,MAAM,CAAI,KAAuB,EAAE,OAAmB,EAAA;AACpD,QAAA,OAAO,QAAQ;IACjB;AAES,IAAA,MAAM,CACb,KAAgB,EAChB,CAAC,KAAK,EAAE,MAAM,CAA4B,EAAA;;;AAI1C,QAAA,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE;YACrB,IAAI,CAAC,YAAY,EAAE;QACrB;;;AAGA,QAAA,IAAI,KAAK,KAAK,IAAI,CAAC,OAAO,EAAE;AAC1B,YAAA,OAAO,QAAQ;QACjB;AACA,QAAA,IAAI,CAAC,OAAO,GAAG,KAAK;QACpB,IAAI,CAAC,GAAG,CAAC;QACT,MAAM,EAAC,UAAU,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,EAAC,GAAG,IAAI;;;;;AAKrD,QAAA,UAAU,CAAC,KAAK,EAAE,OAAO,CAAU,KAAI;;;AAGrC,YAAA,OAAO,MAAM,CAAC,GAAG,EAAE,EAAE;AACnB,gBAAA,MAAM,MAAM,CAAC,GAAG,EAAE;YACpB;;;;AAIA,YAAA,MAAM,KAAK,GAAG,QAAQ,CAAC,KAAK,EAAE;AAC9B,YAAA,IAAI,KAAK,KAAK,SAAS,EAAE;;;AAGvB,gBAAA,IAAI,KAAK,CAAC,OAAO,KAAK,KAAK,EAAE;AAC3B,oBAAA,OAAO,KAAK;gBACd;;;;;AAMA,gBAAA,IAAI,MAAM,KAAK,SAAS,EAAE;AACxB,oBAAA,CAAC,GAAG,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC;gBAClB;AAEA,gBAAA,KAAK,CAAC,WAAW,CAAC,CAAC,EAAE,CAAC,CAAC;AACvB,gBAAA,CAAC,EAAE;YACL;AACA,YAAA,OAAO,IAAI;AACb,QAAA,CAAC,CAAC;AACF,QAAA,OAAO,QAAQ;IACjB;;IAGU,WAAW,CAAC,KAAc,EAAE,MAAc,EAAA;AAClD,QAAA,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC;IACtB;IAES,YAAY,GAAA;AACnB,QAAA,IAAI,CAAC,UAAU,CAAC,UAAU,EAAE;AAC5B,QAAA,IAAI,CAAC,QAAQ,CAAC,KAAK,EAAE;IACvB;IAES,WAAW,GAAA;AAClB,QAAA,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC,IAAI,CAAC;AAC/B,QAAA,IAAI,CAAC,QAAQ,CAAC,MAAM,EAAE;IACxB;AACD;AAED;;;;;;;;;;;;;;;;;AAiBG;MACU,YAAY,GAAG,SAAS,CAAC,qBAAqB;;;;"}