{"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":["AsyncReplaceDirective","AsyncDirective","constructor","this","__weakThis","PseudoWeakRef","__pauser","Pauser","render","value","_mapper","noChange","update","_part","mapper","isConnected","disconnected","__value","i","weakThis","pauser","forAwaitOf","async","v","get","_this","deref","undefined","commitValue","_index","setValue","disconnect","pause","reconnected","reconnect","resume","asyncReplace","directive"],"mappings":";;;;;GAgBM,MAAOA,UAA8BC,EAA3C,WAAAC,uBAEUC,KAAAC,KAAa,IAAIC,EAAcF,MAC/BA,KAAAG,KAAW,IAAIC,CA4EzB,CAxEE,MAAAC,CAAUC,EAAyBC,GACjC,OAAOC,CACT,CAES,MAAAC,CACPC,GACCJ,EAAOK,IASR,GALKX,KAAKY,aACRZ,KAAKa,eAIHP,IAAUN,KAAKc,KACjB,OAAON,EAETR,KAAKc,KAAUR,EACf,IAAIS,EAAI,EACR,MAAOd,KAAYe,EAAUb,KAAUc,GAAUjB,KAmCjD,OA9BAkB,EAAWZ,EAAOa,MAAOC,IAGvB,KAAOH,EAAOI,aACNJ,EAAOI,MAKf,MAAMC,EAAQN,EAASO,QACvB,QAAcC,IAAVF,EAAqB,CAGvB,GAAIA,EAAMR,OAAYR,EACpB,OAAO,OAOMkB,IAAXb,IACFS,EAAIT,EAAOS,EAAGL,IAGhBO,EAAMG,YAAYL,EAAGL,GACrBA,GACF,CACA,OAAO,IAEFP,CACT,CAGU,WAAAiB,CAAYnB,EAAgBoB,GACpC1B,KAAK2B,SAASrB,EAChB,CAES,YAAAO,GACPb,KAAKC,KAAW2B,aAChB5B,KAAKG,KAAS0B,OAChB,CAES,WAAAC,GACP9B,KAAKC,KAAW8B,UAAU/B,MAC1BA,KAAKG,KAAS6B,QAChB,QAqBWC,EAAeC,EAAUrC"}