[
  {
    "path": ".editorconfig",
    "content": "root = true\r\n\r\n[*]\r\nend_of_line = lf\r\nindent_size = 2\r\nindent_style = space\r\ntrim_trailing_whitespace = true\r\n"
  },
  {
    "path": ".eslintignore",
    "content": "packages/rxjs/integration/import/fixtures"
  },
  {
    "path": ".eslintrc.json",
    "content": "{\n  \"root\": true,\n  \"ignorePatterns\": [\"**/*\"],\n  \"plugins\": [\"@nx\"],\n  \"overrides\": [\n    {\n      \"files\": [\"*.ts\", \"*.tsx\"],\n      \"extends\": [\"plugin:@nx/typescript\"],\n      \"rules\": {\n        \"@typescript-eslint/no-explicit-any\": \"off\",\n        \"@typescript-eslint/no-unsafe-declaration-merging\": \"off\",\n        \"@typescript-eslint/consistent-type-imports\": \"warn\",\n        \"@typescript-eslint/consistent-type-exports\": \"warn\",\n        \"no-prototype-builtins\": \"off\",\n        \"@typescript-eslint/no-inferrable-types\": \"warn\",\n        \"@typescript-eslint/no-empty-function\": \"off\",\n        \"@typescript-eslint/no-empty-interface\": \"off\"\n      }\n    },\n    {\n      \"files\": [\"*.js\", \"*.jsx\"],\n      \"extends\": [\"plugin:@nx/javascript\"],\n      \"rules\": {}\n    },\n    {\n      \"files\": [\"*.ts\", \"*.tsx\", \"*.js\", \"*.jsx\"],\n      \"rules\": {\n        \"@nx/enforce-module-boundaries\": [\n          \"error\",\n          {\n            \"enforceBuildableLibDependency\": true,\n            \"allow\": [],\n            \"depConstraints\": [\n              {\n                \"sourceTag\": \"*\",\n                \"onlyDependOnLibsWithTags\": [\"*\"]\n              }\n            ]\n          }\n        ],\n        \"@typescript-eslint/no-unused-vars\": \"off\"\n      }\n    }\n  ]\n}\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/bug_report.yml",
    "content": "name: Bug Report\ndescription: Bug report for RxJS core behavior.\nbody:\n  - type: textarea\n    id: description\n    attributes:\n      label: Describe the bug\n      description: |\n        A clear and concise description of the behavior.\n    validations:\n      required: true\n  - type: textarea\n    id: expected-behavior\n    attributes:\n      label: Expected behavior\n      description: A clear and concise description of what you expect to happen.\n    validations:\n      required: true\n  - type: textarea\n    id: code\n    attributes:\n      label: Reproduction code\n      description: Code to create a minimal reproduction.\n      render: typescript\n  - type: input\n    id: repro-link\n    attributes:\n      label: Reproduction URL\n      description: Use [Stackblitz](https://stackblitz.com/fork/rxjs) or a git repo to show a minimal reproduction of the issue. Please also paste the example code in the \"Reproduction code\" section above.\n  - type: input\n    id: version\n    attributes:\n      label: Version\n    validations:\n      required: true\n  - type: textarea\n    id: environment\n    attributes:\n      label: Environment\n      placeholder: Version of runtime environment, build configuration, etc, that can affect behavior of RxJS.\n  - type: textarea\n    id: addition\n    attributes:\n      label: Additional context\n      placeholder: Add any other context about the problem here.\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/config.yml",
    "content": "blank_issues_enabled: false\ncontact_links:\n  - name: Questions, request, issues other than Rx core bugs\n    url: https://github.com/ReactiveX/rxjs/discussions\n    about: For general discussions, or request please use discussions.\n"
  },
  {
    "path": ".github/PULL_REQUEST_TEMPLATE.md",
    "content": "<!--\nThank you very much for your pull request!\n\nIf your PR is the addition of a new operator, please make sure all these boxes are ticked with an x:\n\n- [ ] Add the operator to Rx\n- [ ] It must have a `-spec.ts` tests file covering the canonical corner cases, with marble diagram tests\n- [ ] The spec file should have a type definition test at the end of the spec to verify type definition for various use cases\n- [ ] The operator must be documented in JSDoc style in the implementation file, including also the PNG marble diagram image\n- [ ] The operator should be listed in `apps/rxjs.dev/content/guide/operators.md` in a category of operators\n- [ ] The operator should also be documented. See [Documentation Guidelines](../CONTRIBUTING.md).\n- [ ] You may need to update `MIGRATION.md` if the operator differs from the corresponding one in RxJS v4\n-->\n\n**Description:**\n\n<!--\nIf this PR introduces a breaking change, it must contain a notice for it to be included in the CHANGELOG.\n-->\n\n**BREAKING CHANGE:** <!-- add description or remove entirely if not breaking -->\n\n**Related issue (if exists):**\n"
  },
  {
    "path": ".github/actions/install-dependencies/action.yml",
    "content": "name: Install Dependencies\ndescription: 'Prepares the repo by installing dependencies'\ninputs:\n  node-version:\n    description: 'The node version to setup'\n    required: true\n  registry-url:\n    description: 'Define registry-url'\n    required: false\n    default: 'https://registry.npmjs.org'\n\n# outputs: - no outputs\n\nruns:\n  using: 'composite'\n  steps:\n    - name: Use Node.js ${{ inputs.node-version }}\n      uses: actions/setup-node@v4\n      with:\n        node-version: ${{ inputs.node-version }}\n        registry-url: ${{ inputs.registry-url }}\n\n    - name: Get yarn cache directory path\n      id: yarn-cache-dir-path\n      run: echo \"dir=$(yarn cache dir)\" >> $GITHUB_OUTPUT\n      shell: bash\n\n    - uses: actions/cache@v3\n      id: yarn-cache\n      with:\n        path: ${{ steps.yarn-cache-dir-path.outputs.dir }}\n        key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }}\n        restore-keys: |\n          ${{ runner.os }}-yarn-\n\n    - name: Install dependencies\n      run: yarn install --frozen-lockfile\n      shell: bash\n      env:\n        YARN_CACHE_FOLDER: ${{ steps.yarn-cache-dir-path.outputs.dir }}\n"
  },
  {
    "path": ".github/lock.yml",
    "content": "# Configuration for lock-threads - https://github.com/dessant/lock-threads\n\n# Number of days of inactivity before a closed issue or pull request is locked\ndaysUntilLock: 30\n\n# Issues and pull requests with these labels will not be locked. Set to `[]` to disable\nexemptLabels: []\n\n# Label to add before locking, such as `outdated`. Set to `false` to disable\nlockLabel: false\n\n# Comment to post before locking. Set to `false` to disable\nlockComment: false\n\n# Limit to only `issues` or `pulls`\n# only: issues\n\n# Optionally, specify configuration settings just for `issues` or `pulls`\n# issues:\n#   exemptLabels:\n#     - help-wanted\n#   lockLabel: outdated\n\n# pulls:\n#   daysUntilLock: 30\n"
  },
  {
    "path": ".github/workflows/ci_main.yml",
    "content": "name: CI\n\non:\n  pull_request:\n    types: ['opened', 'reopened', 'synchronize']\n\npermissions:\n  contents: read\n\njobs:\n  build:\n    runs-on: ubuntu-latest\n    strategy:\n      matrix:\n        node: ['18', '20']\n\n    name: Node ${{ matrix.node }} build\n\n    steps:\n      - uses: actions/checkout@v4\n\n      - name: Install Dependencies\n        uses: ./.github/actions/install-dependencies\n        with:\n          node-version: ${{ matrix.node }}\n\n      - name: Build, test and lint all projects (except website)\n        run: yarn nx run-many -t build lint test --exclude=rxjs.dev\n\n      - name: rxjs lint\n        run: yarn workspace rxjs lint\n      - name: rxjs build\n        run: yarn workspace rxjs build\n      - name: rxjs test\n        run: yarn workspace rxjs test\n      - name: rxjs dtslint\n        run: yarn workspace rxjs dtslint\n      - name: rxjs test:import\n        run: yarn workspace rxjs test:import\n      - name: rxjs test:esm\n        run: yarn workspace rxjs test:esm\n      - name: rxjs.dev build\n        run: yarn workspace rxjs.dev build --prod\n      - name: rxjs.dev test\n        run: yarn workspace rxjs.dev test --watch=false --browsers=ChromeHeadless\n"
  },
  {
    "path": ".github/workflows/ci_ts_latest.yml",
    "content": "name: CI (ts@latest)\n\non:\n  pull_request:\n    types: ['opened', 'reopened', 'synchronize']\n\npermissions:\n  contents: read\n\njobs:\n  build:\n    runs-on: ubuntu-latest\n    strategy:\n      matrix:\n        node: ['20']\n\n    name: ts@latest\n\n    steps:\n      - uses: actions/checkout@v4\n\n      - name: Install Dependencies\n        uses: ./.github/actions/install-dependencies\n        with:\n          node-version: ${{ matrix.node }}\n\n      - name: build\n        run: |\n          yarn workspace rxjs add typescript@latest @types/node@latest --peer --no-save\n          yarn nx compile rxjs\n"
  },
  {
    "path": ".github/workflows/publish.yml",
    "content": "name: publish\n\non:\n  # Run manually using the GitHub UI\n  workflow_dispatch:\n    inputs:\n      version:\n        description: 'Version to publish'\n        required: false\n        default: ''\n  # ...or whenever a GitHub release gets created\n  release:\n    types: [published]\n\njobs:\n  publish:\n    name: Publish to npm\n    runs-on: ubuntu-latest\n    permissions:\n      id-token: write # needed for provenance data generation\n    steps:\n      - name: Checkout\n        uses: actions/checkout@v4\n        with:\n          fetch-depth: 0 # include tags\n\n      - name: Install Dependencies\n        uses: ./.github/actions/install-dependencies\n        with:\n          node-version: 20\n\n      - name: Prepare packages for publishing\n        run: yarn prepare-packages\n\n      - name: Apply updated version to packages\n        run: |\n          # Use the version from the workflow input if it's set, otherwise use the tag name from the release\n          VERSION=${{ github.event.inputs.version || github.ref_name }}\n          yarn nx release version $VERSION\n\n      - name: Publish packages to npm\n        run: node ./scripts/publish.js\n        env:\n          NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}\n          NPM_CONFIG_PROVENANCE: true\n"
  },
  {
    "path": ".github/workflows/rebase.yml",
    "content": "on: \n  issue_comment:\n    types: [created]\npermissions:\n  contents: read\nname: Automatic Rebase\njobs:\n  rebase:\n    permissions:\n      contents: write  # for cirrus-actions/rebase to push code to rebase\n      pull-requests: read  # for cirrus-actions/rebase to get info about PR\n    name: Rebase\n    if: github.event.issue.pull_request != '' && contains(github.event.comment.body, '/rebase')\n    runs-on: ubuntu-latest\n    steps:\n    - uses: actions/checkout@v4\n      with:\n        fetch-depth: 0\n    - name: Automatic Rebase\n      uses: cirrus-actions/rebase@1.2\n      env:\n        GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}\n  # https://github.community/t5/GitHub-Actions/Workflow-is-failing-if-no-job-can-be-ran-due-to-condition/m-p/38186#M3250\n  always_job:\n    name: Always run job\n    runs-on: ubuntu-latest\n    steps:\n      - name: Always run\n        run: echo \"This job is used to prevent the workflow to fail when all other jobs are skipped.\"\n"
  },
  {
    "path": ".gitignore",
    "content": "# Editor-specific\n.idea/\n*.iml\n*.sublime-project\n*.sublime-workspace\n.settings\n.vscode\n\n# Installed libs\nnode_modules/\ntypings/\n\n# Generated\ndist/\n.tshy-build\n\n# Import location artifacts\npackages/rxjs/ajax/\npackages/rxjs/fetch/\npackages/rxjs/operators/\npackages/rxjs/testing/\npackages/rxjs/webSocket/\n\n# Copied Package Files\npackages/**/LICENSE.txt\npackages/**/CODE_OF_CONDUCT.md\n\n# Misc\nnpm-debug.log\n.DS_STORE\n*.tgz\n.eslintcache\npackage-lock.json\n\nintegration/import/**/rx.json\nintegration/import/**/operators.json\n\n\n.nx/cache"
  },
  {
    "path": ".prettierrc.json",
    "content": "{\n  \"trailingComma\": \"es5\",\n  \"singleQuote\": true,\n  \"printWidth\": 140,\n  \"overrides\": [\n    {\n      \"files\": [\"spec/**/*.ts\", \"spec-dtslint/**/*.ts\"],\n      \"options\": {\n        \"requirePragma\": true\n      }\n    },\n    {\n      \"files\": [\"spec/operators/**/*.ts\", \"spec/subjects/**/*.ts\"],\n      \"options\": {\n        \"requirePragma\": false\n      }\n    }\n  ]\n}\n"
  },
  {
    "path": "CODE_OF_CONDUCT.md",
    "content": "# Contributor Covenant Code of Conduct\n\n## Our Pledge\n\nIn the interest of fostering an open and welcoming environment, we as\ncontributors and maintainers pledge to making participation in our project and\nour community a harassment-free experience for everyone, regardless of age, body\nsize, disability, ethnicity, gender identity and expression, level of experience,\neducation, socio-economic status, nationality, personal appearance, race,\nreligion, or sexual identity and orientation.\n\n## Our Standards\n\nExamples of behavior that contributes to creating a positive environment\ninclude:\n\n* Using welcoming and inclusive language\n* Being respectful of differing viewpoints and experiences\n* Gracefully accepting constructive criticism\n* Focusing on what is best for the community\n* Showing empathy towards other community members\n\nExamples of unacceptable behavior by participants include:\n\n* The use of sexualized language or imagery and unwelcome sexual attention or\n  advances\n* Trolling, insulting/derogatory comments, and personal or political attacks\n* Public or private harassment\n* Publishing others' private information, such as a physical or electronic\n  address, without explicit permission\n* Other conduct which could reasonably be considered inappropriate in a\n  professional setting\n\n## Our Responsibilities\n\nProject maintainers are responsible for clarifying the standards of acceptable\nbehavior and are expected to take appropriate and fair corrective action in\nresponse to any instances of unacceptable behavior.\n\nProject maintainers have the right and responsibility to remove, edit, or\nreject comments, commits, code, wiki edits, issues, and other contributions\nthat are not aligned to this Code of Conduct, or to ban temporarily or\npermanently any contributor for other behaviors that they deem inappropriate,\nthreatening, offensive, or harmful.\n\n## Scope\n\nThis Code of Conduct applies both within project spaces and in public spaces\nwhen an individual is representing the project or its community. Examples of\nrepresenting a project or community include using an official project e-mail\naddress, posting via an official social media account, or acting as an appointed\nrepresentative at an online or offline event. Representation of a project may be\nfurther defined and clarified by project maintainers.\n\n## Enforcement\n\nInstances of abusive, harassing, or otherwise unacceptable behavior may be\nreported by contacting Ben Lesh (ben@benlesh.com), Tracy Lee (tracy@thisdot.co) or OJ Kwon (kwon.ohjoong@gmail.com). All\ncomplaints will be reviewed and investigated and will result in a response that\nis deemed necessary and appropriate to the circumstances. The project team is\nobligated to maintain confidentiality with regard to the reporter of an incident.\nFurther details of specific enforcement policies may be posted separately.\n\nProject maintainers who do not follow or enforce the Code of Conduct in good\nfaith may face temporary or permanent repercussions as determined by other\nmembers of the project's leadership.\n\n## Attribution\n\nThis Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,\navailable at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html\n\n[homepage]: https://www.contributor-covenant.org\n"
  },
  {
    "path": "CONTRIBUTING.md",
    "content": "# Contributing to RxJS\n\n[Read and abide by the Code of Conduct](CODE_OF_CONDUCT.md)! Even if you don't read it,\nit still applies to you. Ignorance is not an exemption.\n\nContents\n\n- [Contributing to RxJS](#contributing-to-rxjs)\n  - [Submitting a Pull Request (PR)](#submitting-a-pull-request-pr)\n    - [After your pull request is merged](#after-your-pull-request-is-merged)\n  - [Coding Style Guidelines](#coding-style-guidelines)\n  - [Documentation](#documentation)\n  - [Unit Tests](#unit-tests)\n    - [CI Tests](#ci-tests)\n  - [Performance Tests](#performance-tests)\n    - [Macro](#macro)\n    - [Micro](#micro)\n  - [Commit Message Guidelines](#commit-message-guidelines)\n    - [Commit Message Format](#commit-message-format)\n    - [Revert](#revert)\n    - [Type](#type)\n    - [Scope](#scope)\n    - [Subject](#subject)\n    - [Body](#body)\n    - [Footer](#footer)\n\n---\n\n- Related documents\n  - [Creating Operators](apps/rxjs.dev/content/guide/operators.md#creating-custom-operators)\n  - [Writing Marble Tests](apps/rxjs.dev/content/guide/testing/marble-testing.md)\n\n---\n\n(This document is a work in progress and is subject to change)\n\n## Submitting a Pull Request (PR)\n\nBefore you submit your Pull Request (PR) consider the following guidelines:\n\n- Search [GitHub](https://github.com/ReactiveX/RxJS/pulls) for an open or closed PR\n  that relates to your submission. You don't want to duplicate effort.\n- Make your changes in a new git branch:\n\n  ```shell\n  git checkout -b my-fix-branch master\n  ```\n\n- Create your patch, following [code style guidelines](#coding-style-guidelines), and **including appropriate test cases**.\n- Run the full test suite and ensure that all tests pass.\n- Commit your changes using a descriptive commit message that follows our\n  [commit message guidelines](#commit-message-guidelines). Adherence to these conventions\n  is necessary because release notes are automatically generated from these messages.\n\n  ```shell\n  git commit -a\n  ```\n\n  Note: the optional commit `-a` command line option will automatically \"add\" and \"rm\" edited files.\n\n- Push your branch to GitHub:\n\n  ```shell\n  git push origin my-fix-branch\n  ```\n\n- In GitHub, send a pull request to `RxJS:master`.\n- If we suggest changes then:\n\n  - Make the required updates.\n  - Re-run the test suites to ensure tests are still passing.\n  - Re-run performance tests to make sure your changes didn't hurt performance.\n  - Rebase your branch and force push to your GitHub repository (this will update your Pull Request):\n\n    ```shell\n    git rebase master -i\n    git push -f\n    ```\n\n  - When updating your feature branch with the requested changes, please do not overwrite the commit history, but rather contain the changes in new commits. This is for the sake of a clearer and easier review process.\n\nThat's it! Thank you for your contribution!\n\n### After your pull request is merged\n\nAfter your pull request is merged, you can safely delete your branch and pull the changes\nfrom the main (upstream) repository:\n\n- Delete the remote branch on GitHub either through the GitHub web UI or your local shell as follows:\n\n  ```shell\n  git push origin --delete my-fix-branch\n  ```\n\n- Check out the master branch:\n\n  ```shell\n  git checkout master -f\n  ```\n\n- Delete the local branch:\n\n  ```shell\n  git branch -D my-fix-branch\n  ```\n\n- Update your master with the latest upstream version:\n\n  ```shell\n  git pull --ff upstream master\n  ```\n\n## Coding Style Guidelines\n\n- Please use proper types and generics throughout your code.\n- 2 space indentation only\n- favor readability over terseness\n\n(TBD): For now, try to follow the style that exists elsewhere in the source, and use your best judgment.\n\n## Documentation\n\n- The documentation is auto-generated directly from the source code.\n- In short: From the source code we generate JSON documents, describing each operator, function ... and render this JSON within an Angular application\n- The folder `apps/rxjs.dev` contains everything you need for building and developing the docs\n- The [Documentation README](apps/rxjs.dev/README.md) will support you\n- After a PR is merged to master the docs will be published to https://rxjs.dev/\n\n## Unit Tests\n\nUnit tests are located under the [spec directory](/spec). Unit tests over synchronous operators and operations\ncan be written in a standard [chai](https://www.chaijs.com/) style. Unit tests written against any\nasynchronous operator should be written in [Marble Test Style outlined in detail here](apps/rxjs.dev/content/guide/testing/marble-testing.md).\n\nEach operator under test must be in its own file to cover the following cases:\n\n- Never\n- Empty\n- Single/Multiple Values\n- Error in the sequence\n- Never ending sequences\n- Early disposal in sequences\n\nIf the operator accepts a function as an argument from the user/developer (for example `filter(fn)` or `zip(a, fn)`),\nthen it must cover the following cases:\n\n- Success with all values in the callback\n- Success with the context, if any allowed in the operator signature\n- If an error is thrown\n\n### CI Tests\n\n- Using [Travis](https://travis-ci.org/) on your forked version of RxJS will allow running CI tests on that fork before submitting a PR to master\n- Simply create a `Travis` account and add your fork as a new project\n- [Sauce Labs](https://saucelabs.com/) setup will allow performing automated browser tests on the fork. Since `saucelabs` doesn't perform browser tests on a PR, this will help verify test results before PR's are checked into master.\n- In your `Travis` repo configuration, set the environment variables SAUCE_USERNAME and SAUCE_ACCESS_KEY to your `saucelabs` account ([reference](https://cloud.githubusercontent.com/assets/1210596/12679038/b9ba4eb6-c656-11e5-8c9b-b063c9a3f9dc.png))\n- As master runs both of these tests per each check in, it'd be welcome to setup those test before creating your PR\n\n## Performance Tests\n\nOne of the primary goals of this library is (and will continue to be) great performance. As such, we've employed a variety of performance\ntesting techniques.\n\n- DON'T labor over minute variations in ops/sec or milliseconds, there will always be variance in perf test results.\n- DON'T alter a performance test unless absolutely necessary. Performance tests may be compared to previous results from previous builds.\n- DO run tests multiple times and make sure the margins of error are low\n- DO run tests in your feature branches and compare them to master\n- DO add performance tests for all new operators\n- DO add performance tests that you feel are missing from other operators\n- DO add additional performance tests for all worthy code paths. If you develop an operator with special handling for scalar observables,\n  please add tests for those scenarios\n\n### Macro\n\n[Macro performance tests](perf/macro) are best written for scenarios where many object instance allocations (or deallocations) are occurring. Operators\nthat create a lot of child subscriptions or operators that emit new objects like Observables and Subjects are definitely worth creating\nmacro performance tests for.\n\nOther scenarios for macro performance testing may include common end-to-end scenarios from real-world apps. If you have a situation in your\napp where you feel RxJS is performing poorly, please [submit an issue](https://github.com/ReactiveX/rxjs/issues/) and include a minimal code example showing\nyour performance issues. We would love to solve perf for your real-world problems and add those tests to our perf test battery.\n\nMacro performance tests can be run by hosting the root directory with any web server (we use [http-server](https://www.npmjs.com/package/http-server)),\nthen running:\n\n```sh\nyarn build_all\nprotractor protractor.conf.js\n```\n\n### Micro\n\n[Micro performance tests](perf/micro) really only serve to test operations per second. They're quick and easy to develop, and provide a reasonable look into the\nrelative performance of our operators versus prior versions. All operators should have corresponding micro performance tests.\n\nMicro performance test can be run with:\n\n```sh\nyarn build_all\nnode perf/micro\n```\n\nIf you wish to run a single micro performance test, you can do so by providing a single argument with the name of the perf test file(s):\n\n```sh\nnode perf/micro zip\n```\n\n## Commit Message Guidelines\n\nWe have very precise rules over how our git commit messages can be formatted. This leads to **more\nreadable messages** that are easy to follow when looking through the **project history**. But also,\nwe use the git commit messages to **generate the RxJS change log**. Helper script `yarn commit`\nprovides command line based wizard to format commit message easily.\n\n### Commit Message Format\n\nEach commit message consists of a **header**, a **body** and a **footer**. The header has a special\nformat that includes a **type**, a **scope** and a **subject**:\n\n```\n<type>(<scope>): <subject>\n<BLANK LINE>\n<body>\n<BLANK LINE>\n<footer>\n```\n\nThe **header** is mandatory and the **scope** of the header is optional.\n\nAny line of the commit message cannot be longer than 100 characters! This allows the message to be easier\nto read on GitHub as well as in various git tools.\n\n### Revert\n\nIf the commit reverts a previous commit, it should begin with `revert:`, followed by the header of the reverted commit. In the body it should say: `This reverts commit <hash>.`, where the hash is the SHA of the commit being reverted.\n\n### Type\n\nMust be one of the following:\n\n- **feat**: A new feature\n- **fix**: A bug fix\n- **docs**: Documentation only changes\n- **style**: Changes that do not affect the meaning of the code (white-space, formatting, missing\n  semi-colons, etc)\n- **refactor**: A code change that neither fixes a bug nor adds a feature\n- **perf**: A code change that improves performance\n- **test**: Adding missing tests\n- **chore**: Changes to the build process or auxiliary tools and libraries such as documentation\n  generation\n\n### Scope\n\nThe scope could be anything specifying the place of the commit change. For example\n`Observable`, `Subject`, `switchMap`, etc.\n\n### Subject\n\nThe subject contains succinct description of the change:\n\n- use the imperative, present tense: \"change\" not \"changed\" nor \"changes\"\n- don't capitalize first letter\n- no dot (.) at the end\n\n### Body\n\nJust as in the **subject**, use the imperative, present tense: \"change\" not \"changed\" nor \"changes\".\nThe body should include the motivation for the change and contrast this with previous behavior.\n\n### Footer\n\nThe footer should contain any information about **Breaking Changes** and is also the place to\nreference GitHub issues that this commit **Closes**.\n\n**Breaking Changes** should start with the word `BREAKING CHANGE:` with a space or two newlines. The rest of the commit message is then used for this.\n"
  },
  {
    "path": "LICENSE.txt",
    "content": "                               Apache License\n                         Version 2.0, January 2004\n                      http://www.apache.org/licenses/\n\n TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION\n\n 1. Definitions.\n\n    \"License\" shall mean the terms and conditions for use, reproduction,\n    and distribution as defined by Sections 1 through 9 of this document.\n\n    \"Licensor\" shall mean the copyright owner or entity authorized by\n    the copyright owner that is granting the License.\n\n    \"Legal Entity\" shall mean the union of the acting entity and all\n    other entities that control, are controlled by, or are under common\n    control with that entity. For the purposes of this definition,\n    \"control\" means (i) the power, direct or indirect, to cause the\n    direction or management of such entity, whether by contract or\n    otherwise, or (ii) ownership of fifty percent (50%) or more of the\n    outstanding shares, or (iii) beneficial ownership of such entity.\n\n    \"You\" (or \"Your\") shall mean an individual or Legal Entity\n    exercising permissions granted by this License.\n\n    \"Source\" form shall mean the preferred form for making modifications,\n    including but not limited to software source code, documentation\n    source, and configuration files.\n\n    \"Object\" form shall mean any form resulting from mechanical\n    transformation or translation of a Source form, including but\n    not limited to compiled object code, generated documentation,\n    and conversions to other media types.\n\n    \"Work\" shall mean the work of authorship, whether in Source or\n    Object form, made available under the License, as indicated by a\n    copyright notice that is included in or attached to the work\n    (an example is provided in the Appendix below).\n\n    \"Derivative Works\" shall mean any work, whether in Source or Object\n    form, that is based on (or derived from) the Work and for which the\n    editorial revisions, annotations, elaborations, or other modifications\n    represent, as a whole, an original work of authorship. For the purposes\n    of this License, Derivative Works shall not include works that remain\n    separable from, or merely link (or bind by name) to the interfaces of,\n    the Work and Derivative Works thereof.\n\n    \"Contribution\" shall mean any work of authorship, including\n    the original version of the Work and any modifications or additions\n    to that Work or Derivative Works thereof, that is intentionally\n    submitted to Licensor for inclusion in the Work by the copyright owner\n    or by an individual or Legal Entity authorized to submit on behalf of\n    the copyright owner. For the purposes of this definition, \"submitted\"\n    means any form of electronic, verbal, or written communication sent\n    to the Licensor or its representatives, including but not limited to\n    communication on electronic mailing lists, source code control systems,\n    and issue tracking systems that are managed by, or on behalf of, the\n    Licensor for the purpose of discussing and improving the Work, but\n    excluding communication that is conspicuously marked or otherwise\n    designated in writing by the copyright owner as \"Not a Contribution.\"\n\n    \"Contributor\" shall mean Licensor and any individual or Legal Entity\n    on behalf of whom a Contribution has been received by Licensor and\n    subsequently incorporated within the Work.\n\n 2. Grant of Copyright License. Subject to the terms and conditions of\n    this License, each Contributor hereby grants to You a perpetual,\n    worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n    copyright license to reproduce, prepare Derivative Works of,\n    publicly display, publicly perform, sublicense, and distribute the\n    Work and such Derivative Works in Source or Object form.\n\n 3. Grant of Patent License. Subject to the terms and conditions of\n    this License, each Contributor hereby grants to You a perpetual,\n    worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n    (except as stated in this section) patent license to make, have made,\n    use, offer to sell, sell, import, and otherwise transfer the Work,\n    where such license applies only to those patent claims licensable\n    by such Contributor that are necessarily infringed by their\n    Contribution(s) alone or by combination of their Contribution(s)\n    with the Work to which such Contribution(s) was submitted. If You\n    institute patent litigation against any entity (including a\n    cross-claim or counterclaim in a lawsuit) alleging that the Work\n    or a Contribution incorporated within the Work constitutes direct\n    or contributory patent infringement, then any patent licenses\n    granted to You under this License for that Work shall terminate\n    as of the date such litigation is filed.\n\n 4. Redistribution. You may reproduce and distribute copies of the\n    Work or Derivative Works thereof in any medium, with or without\n    modifications, and in Source or Object form, provided that You\n    meet the following conditions:\n\n    (a) You must give any other recipients of the Work or\n        Derivative Works a copy of this License; and\n\n    (b) You must cause any modified files to carry prominent notices\n        stating that You changed the files; and\n\n    (c) You must retain, in the Source form of any Derivative Works\n        that You distribute, all copyright, patent, trademark, and\n        attribution notices from the Source form of the Work,\n        excluding those notices that do not pertain to any part of\n        the Derivative Works; and\n\n    (d) If the Work includes a \"NOTICE\" text file as part of its\n        distribution, then any Derivative Works that You distribute must\n        include a readable copy of the attribution notices contained\n        within such NOTICE file, excluding those notices that do not\n        pertain to any part of the Derivative Works, in at least one\n        of the following places: within a NOTICE text file distributed\n        as part of the Derivative Works; within the Source form or\n        documentation, if provided along with the Derivative Works; or,\n        within a display generated by the Derivative Works, if and\n        wherever such third-party notices normally appear. The contents\n        of the NOTICE file are for informational purposes only and\n        do not modify the License. You may add Your own attribution\n        notices within Derivative Works that You distribute, alongside\n        or as an addendum to the NOTICE text from the Work, provided\n        that such additional attribution notices cannot be construed\n        as modifying the License.\n\n    You may add Your own copyright statement to Your modifications and\n    may provide additional or different license terms and conditions\n    for use, reproduction, or distribution of Your modifications, or\n    for any such Derivative Works as a whole, provided Your use,\n    reproduction, and distribution of the Work otherwise complies with\n    the conditions stated in this License.\n\n 5. Submission of Contributions. Unless You explicitly state otherwise,\n    any Contribution intentionally submitted for inclusion in the Work\n    by You to the Licensor shall be under the terms and conditions of\n    this License, without any additional terms or conditions.\n    Notwithstanding the above, nothing herein shall supersede or modify\n    the terms of any separate license agreement you may have executed\n    with Licensor regarding such Contributions.\n\n 6. Trademarks. This License does not grant permission to use the trade\n    names, trademarks, service marks, or product names of the Licensor,\n    except as required for reasonable and customary use in describing the\n    origin of the Work and reproducing the content of the NOTICE file.\n\n 7. Disclaimer of Warranty. Unless required by applicable law or\n    agreed to in writing, Licensor provides the Work (and each\n    Contributor provides its Contributions) on an \"AS IS\" BASIS,\n    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n    implied, including, without limitation, any warranties or conditions\n    of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A\n    PARTICULAR PURPOSE. You are solely responsible for determining the\n    appropriateness of using or redistributing the Work and assume any\n    risks associated with Your exercise of permissions under this License.\n\n 8. Limitation of Liability. In no event and under no legal theory,\n    whether in tort (including negligence), contract, or otherwise,\n    unless required by applicable law (such as deliberate and grossly\n    negligent acts) or agreed to in writing, shall any Contributor be\n    liable to You for damages, including any direct, indirect, special,\n    incidental, or consequential damages of any character arising as a\n    result of this License or out of the use or inability to use the\n    Work (including but not limited to damages for loss of goodwill,\n    work stoppage, computer failure or malfunction, or any and all\n    other commercial damages or losses), even if such Contributor\n    has been advised of the possibility of such damages.\n\n 9. Accepting Warranty or Additional Liability. While redistributing\n    the Work or Derivative Works thereof, You may choose to offer,\n    and charge a fee for, acceptance of support, warranty, indemnity,\n    or other liability obligations and/or rights consistent with this\n    License. However, in accepting such obligations, You may act only\n    on Your own behalf and on Your sole responsibility, not on behalf\n    of any other Contributor, and only if You agree to indemnify,\n    defend, and hold each Contributor harmless for any liability\n    incurred by, or claims asserted against, such Contributor by reason\n    of your accepting any such warranty or additional liability.\n\n END OF TERMS AND CONDITIONS\n\n APPENDIX: How to apply the Apache License to your work.\n\n    To apply the Apache License to your work, attach the following\n    boilerplate notice, with the fields enclosed by brackets \"[]\"\n    replaced with your own identifying information. (Don't include\n    the brackets!)  The text should be enclosed in the appropriate\n    comment syntax for the file format. We also recommend that a\n    file or class name and description of purpose be included on the\n    same \"printed page\" as the copyright notice for easier\n    identification within third-party archives.\n\nCopyright (c) 2015-2025 \n    Ben Lesh <ben@benlesh.com>\n    Google, Inc.\n    Netflix, Inc.\n    Microsoft Corp.\n    and contributors\n\n Licensed under the Apache License, Version 2.0 (the \"License\");\n you may not use this file except in compliance with the License.\n You may obtain a copy of the License at\n\n     http://www.apache.org/licenses/LICENSE-2.0\n\n Unless required by applicable law or agreed to in writing, software\n distributed under the License is distributed on an \"AS IS\" BASIS,\n WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n See the License for the specific language governing permissions and\n limitations under the License.\n \n"
  },
  {
    "path": "README.md",
    "content": "# <img src=\"apps/rxjs.dev/src/assets/images/logos/Rx_Logo_S.png\" alt=\"RxJS Logo\" width=\"86\" height=\"86\"> RxJS: Reactive Extensions For JavaScript\n\n![CI](https://github.com/reactivex/rxjs/workflows/CI/badge.svg)\n[![npm version](https://badge.fury.io/js/rxjs.svg)](http://badge.fury.io/js/rxjs)\n[![Join the chat at https://gitter.im/Reactive-Extensions/RxJS](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/Reactive-Extensions/RxJS?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)\n\n# RxJS 8 Monorepo\n\nLook for RxJS and related packages under the [/packages](/packages/) directory. Applications like the [rxjs.dev](https://rxjs.dev) documentation site are under the [/apps](/apps/) directory.\n\n[Apache 2.0 License](LICENSE.txt)\n\n- [Code of Conduct](CODE_OF_CONDUCT.md)\n- [Contribution Guidelines](CONTRIBUTING.md)\n- [Maintainer Guidelines](apps/rxjs.dev/content/maintainer-guidelines.md)\n- [API Documentation](https://rxjs.dev/)\n\nReactive Extensions Library for JavaScript. This is a rewrite of [Reactive-Extensions/RxJS](https://github.com/Reactive-Extensions/RxJS) and is the latest production-ready version of RxJS. This rewrite is meant to have better performance, better modularity, better debuggable call stacks, while staying mostly backwards compatible, with some breaking changes that reduce the API surface.\n\n## Versions In This Repository\n\n- [master](https://github.com/ReactiveX/rxjs/commits/master) - This is all of the current work, which is against v8 of RxJS right now\n- [7.x](https://github.com/ReactiveX/rxjs/tree/7.x) - This is the branch for version 7.X\n- [6.x](https://github.com/ReactiveX/rxjs/tree/6.x) - This is the branch for version 6.X\n\nMost PRs should be made to **master**.\n\n## Important\n\nBy contributing or commenting on issues in this repository, whether you've read them or not, you're agreeing to the [Contributor Code of Conduct](CODE_OF_CONDUCT.md). Much like traffic laws, ignorance doesn't grant you immunity.\n\n## Development\n\nBecause of [this issue](https://github.com/npm/rfcs/issues/287#issuecomment-1727960500) we're using `yarn`. (Basically the docs app uses `@types/jasmine`, and the package uses `@types/mocha` and they get hoisted to the top level by `npm install` with workspaces, and then TypeScript vomits everywhere when you try to build).\n\n1. `cd` to the repository root\n2. `yarn install` to install all dependencies\n3. `yarn workspace rxjs test` will run the RxJS test suite\n4. `yarn workspace rxjs.dev start` will start the rxjs.dev documentation site local development server\n"
  },
  {
    "path": "SECURITY.md",
    "content": "# Security Policy\n\n## Supported Versions\n\nSecurity updates are applied only to the latest release.\n\n## Reporting a Vulnerability\n\nIf you have discovered a security vulnerability in this project, please report it privately. **Do not disclose it as a public issue.** This gives us time to work with you to fix the issue before public exposure, reducing the chance that the exploit will be used before a patch is released. Besides, make sure to align with us before any public disclosure to ensure no dangerous information goes public too soon.\n\nPlease disclose it at [security advisory](https://github.com/ReactiveX/rxjs/security/advisories/new).\n\nAlthough we will be working to solve any security issue as fast as possible, it is also important to notice that, in accordance with Apache 2.0 terms, no RxJS contributor can be liable for damages, including the ones caused by a security issue.\n"
  },
  {
    "path": "apps/rxjs.dev/.browserslistrc",
    "content": "# This file is used by the build system to adjust CSS and JS output to support the specified browsers below.\n# For additional information regarding the format and rule options, please see:\n# https://github.com/browserslist/browserslist#queries\n\n# You can see what browsers were selected by your queries by running:\n#   npx browserslist\n\n> 0.5%\nlast 2 versions\nFirefox ESR\nnot dead\nnot IE 9-11 # For IE 9-11 support, remove 'not'.\nnot ios_saf 15.2-15.3\nnot safari 15.2-15.3\n"
  },
  {
    "path": "apps/rxjs.dev/.eslintrc.js",
    "content": "module.exports = {\n  root: true,\n  overrides: [\n    {\n      files: ['*.ts'],\n      parserOptions: {\n        project: ['./tsconfig.json', './tests/e2e/tsconfig.e2e.json'],\n        createDefaultProgram: true,\n        tsconfigRootDir: __dirname,\n      },\n      extends: [\n        'plugin:@angular-eslint/ng-cli-compat',\n        'plugin:@angular-eslint/ng-cli-compat--formatting-add-on',\n        'plugin:@angular-eslint/template/process-inline-templates',\n      ],\n      rules: {\n        '@typescript-eslint/ban-types': 'error',\n        '@angular-eslint/component-selector': [\n          'error',\n          {\n            type: 'element',\n            prefix: 'aio',\n            style: 'kebab-case',\n          },\n        ],\n        '@angular-eslint/directive-selector': [\n          'error',\n          {\n            type: 'attribute',\n            prefix: 'aio',\n            style: 'camelCase',\n          },\n        ],\n        'dot-notation': 'error',\n        indent: 'off',\n        'max-len': ['error', 140],\n        '@typescript-eslint/member-delimiter-style': [\n          'error',\n          {\n            singleline: {\n              delimiter: 'comma',\n              requireLast: false,\n            },\n          },\n        ],\n        '@typescript-eslint/member-ordering': 'off',\n        '@typescript-eslint/naming-convention': 'off',\n        'no-console': ['error', { allow: ['log', 'warn', 'error'] }],\n        'no-empty-function': 'off',\n        '@angular-eslint/no-host-metadata-property': 'off',\n        'no-restricted-syntax': [\n          'error',\n          {\n            selector: 'CallExpression[callee.name=/^(fdescribe|fit)$/]',\n            message: \"Don't keep jasmine focus methods.\",\n          },\n        ],\n        'no-shadow': 'off',\n        '@typescript-eslint/no-shadow': ['error'],\n        'no-tabs': 'error',\n        'no-underscore-dangle': 'off',\n        'no-unused-expressions': 'off',\n        '@typescript-eslint/no-unused-expressions': ['error'],\n        'no-use-before-define': 'off',\n        'prefer-arrow/prefer-arrow-functions': 'off',\n        quotes: 'off',\n        '@typescript-eslint/quotes': ['error', 'single', { avoidEscape: true }],\n        semi: 'error',\n        'jsdoc/newline-after-description': 'off',\n        '@typescript-eslint/no-non-null-assertion': 'off',\n      },\n    },\n    {\n      files: ['*.html'],\n      extends: ['plugin:@angular-eslint/template/recommended'],\n      rules: {\n        '@angular-eslint/template/accessibility-alt-text': 'error',\n        '@angular-eslint/template/accessibility-elements-content': 'error',\n        '@angular-eslint/template/accessibility-label-has-associated-control': 'error',\n        '@angular-eslint/template/accessibility-table-scope': 'error',\n        '@angular-eslint/template/accessibility-valid-aria': 'error',\n        '@angular-eslint/template/click-events-have-key-events': 'error',\n        '@angular-eslint/template/eqeqeq': 'off',\n        '@angular-eslint/template/mouse-events-have-key-events': 'error',\n        '@angular-eslint/template/no-autofocus': 'error',\n        '@angular-eslint/template/no-distracting-elements': 'error',\n        '@angular-eslint/template/no-positive-tabindex': 'error',\n      },\n    },\n  ],\n};\n"
  },
  {
    "path": "apps/rxjs.dev/.firebaserc",
    "content": "{\n  \"targets\": {\n    \"rxjs-dev\": {\n      \"hosting\": {\n        \"stable\": [\n          \"rxjs-dev\"\n        ]\n      }\n    }\n  }\n}"
  },
  {
    "path": "apps/rxjs.dev/.gitignore",
    "content": "# See http://help.github.com/ignore-files/ for more about ignoring files.\n\n# compiled output\n/dist\n/out-tsc\n/src/generated\n/tmp\n\n# dependencies\n/node_modules\n\n# IDEs and editors\n/.idea\n.project\n.classpath\n.c9/\n*.launch\n.settings/\n*.sublime-workspace\n\n# IDE - VSCode\n.vscode/*\n!.vscode/settings.json\n!.vscode/tasks.json\n!.vscode/launch.json\n!.vscode/extensions.json\n\n# misc\n/.angular/cache\n/.sass-cache\n/connect.lock\n/coverage\n/libpeerconnection.log\ndebug.log\nnpm-debug.log\ntestem.log\n/typings\nyarn-error.log\n\n# e2e\n/e2e/*.js\n/e2e/*.map\nprotractor-results*.txt\n\n# System Files\n.DS_Store\nThumbs.db\n\nassets/images/svgs/*\n!assets/images/svgs/.gitkeep"
  },
  {
    "path": "apps/rxjs.dev/README.md",
    "content": "# RxJS documentation project\n\nEverything in this folder is part of the documentation project. This includes\n\n- the web site for displaying the documentation\n- the dgeni configuration for converting source files to rendered files that can be viewed in the web site.\n\n## Developer tasks\n\nWe use `npm` to manage the dependencies and to run build tasks.\nYou should run all these tasks from the `apps/rxjs.dev` folder.\nHere are the most important tasks you might need to use:\n\n- `npm install` - install all the dependencies.\n- `yarn setup` - install all the dependencies and run dgeni on the docs.\n\n- `yarn build` - create a production build of the application (after installing dependencies, etc).\n\n- `npm start` - run a development web server that watches the files; then builds the doc-viewer and reloads the page, as necessary.\n- `yarn serve-and-sync` - run both the `docs-watch` and `start` in the same console.\n- `yarn lint` - check that the doc-viewer code follows our style rules.\n- `npm test` - watch all the source files, for the doc-viewer, and run all the unit tests when any change.\n- `npm test -- --watch=false` - run all the unit tests once.\n- `yarn e2e` - run all the e2e tests for the doc-viewer.\n\n- `yarn docs` - generate all the docs from the source files.\n- `yarn docs-watch` - watch the RxJS source and the docs files and run a short-circuited doc-gen for the docs that changed (don't work properly at the moment).\n- `yarn docs-lint` - check that the doc gen code follows our style rules.\n- `yarn docs-test` - run the unit tests for the doc generation code.\n\n## Using ServiceWorker locally\n\nRunning `yarn start` (even when explicitly targeting production mode) does not set up the\nServiceWorker. If you want to test the ServiceWorker locally, you can use `yarn build` and then\nserve the files in `dist/` with `yarn http-server -- dist -p 4200`.\n\n## Running on Docker\n\nThe docs app (rxjs.dev) can run as a docker container.\nIn order to run the docs app on docker, use the following commands (**run from the rxjs folder**):\n\n- `docker build -t rxjs-docs:6.4.1 .` - building the rxjs docs app image\n- `docker run -p <host-port>:4200 rxjs-docs:6.4.1` - starting the container, listening on _<host-port>_ for your choice.\n\nThe container will run the documentation app with the script `start:docker` with the **stable configuration** and with 0.0.0.0 host support.\n\n- Saving the image for later offline usage is available by building the container and then using `sudo docker save rxjs-docs:6.4.1 > <tar-name>.tar`\n  and loading it afterwards with `sudo docker load < <tar-name>.tar`.\n\n> tested on ubuntu 18.04.2 with Docker 18.09.4\n\n## Guide to authoring\n\nThere are two types of content in the documentation:\n\n- **API docs**: descriptions of the modules, classes, interfaces, etc that make up RxJS.\n  API docs are generated directly from the source code.\n  The source code is contained in TypeScript files, located in the `/packages/rxjs/src` folder.\n  Each API item may have a preceding comment, which contains JSDoc style tags and content.\n  The content is written in markdown.\n\n- **Other content**: guides, tutorials, and other marketing material.\n  All other content is written using markdown in text files, located in the `apps/rxjs.dev/content` folder.\n  More specifically, there are sub-folders that contain particular types of content: guides, tutorial and marketing.\n\n### Generating the complete docs\n\nThe main task for generating the docs is `yarn docs`. This will process all the source files (API and other),\nextracting the documentation and generating JSON files that can be consumed by the doc-viewer.\n\n### Partial doc generation for editors\n\nFull doc generation can take up to one minute. That's too slow for efficient document creation and editing.\n\nYou can make small changes in a smart editor that displays formatted markdown:\n\n> In VS Code, _Cmd-K, V_ opens markdown preview in side pane; _Cmd-B_ toggles left sidebar\n\nYou also want to see those changes displayed properly in the doc viewer\nwith a quick, edit/view cycle time.\n\nFor this purpose, use the `yarn docs-watch` task, which watches for changes to source files and only\nre-processes the files necessary to generate the docs that are related to the file that has changed.\nSince this task takes shortcuts, it is much faster (often less than 1 second) but it won't produce full\nfidelity content. For example, links to other docs and code examples may not render correctly. This is\nmost particularly noticed in links to other docs and in the embedded examples, which may not always render\ncorrectly.\n\nThe general setup is as follows:\n\n- Open a terminal, ensure the dependencies are installed; run an initial doc generation; then start the doc-viewer:\n\n```bash\nyarn setup\nyarn start\n```\n\n- Open a second terminal and start watching the docs\n\n```bash\nyarn docs-watch\n```\n\n> Alternatively, try the consolidated `serve-and-sync` command that builds, watches and serves in the same terminal window\n\n```bash\nyarn serve-and-sync\n```\n\n- Open a browser at https://localhost:4200/ and navigate to the document on which you want to work.\n  You can automatically open the browser by using `npm start -- -o` in the first terminal.\n\n- Make changes to the page's associated doc or example files. Every time a file is saved, the doc will\n  be regenerated, the app will rebuild and the page will reload.\n\n- If you get a build error complaining about examples or any other odd behavior, be sure to consult\n  the [Authors Style Guide](https://angular.io/guide/docs-style-guide).\n\n## Disclaimer\n\nStarting the new documentation, we worked closely together with the Angular team and therefore adapted their way of generating docs. This leads to the effect, that there may be some references to angular (e.g. variable names, file names ...). Don't be confused by this, this shouldn't bother you. Thanks to the Angular Team for their support.\nAnyway RxJS will always be an independent project, which aims to work closely with other technologies and frameworks!\n"
  },
  {
    "path": "apps/rxjs.dev/angular.json",
    "content": "{\n  \"$schema\": \"../../node_modules/@angular/cli/lib/config/schema.json\",\n  \"version\": 1,\n  \"cli\": {\n    \"packageManager\": \"yarn\",\n    \"analytics\": false\n  },\n  \"newProjectRoot\": \"projects\",\n  \"projects\": {\n    \"site\": {\n      \"root\": \"\",\n      \"sourceRoot\": \"src\",\n      \"projectType\": \"application\",\n      \"prefix\": \"aio\",\n      \"architect\": {\n        \"build\": {\n          \"builder\": \"@angular-devkit/build-angular:browser\",\n          \"options\": {\n            \"outputPath\": \"dist\",\n            \"index\": \"src/index.html\",\n            \"main\": \"src/main.ts\",\n            \"tsConfig\": \"tsconfig.app.json\",\n            \"webWorkerTsConfig\": \"tsconfig.worker.json\",\n            \"namedChunks\": true,\n            \"polyfills\": \"src/polyfills.ts\",\n            \"assets\": [\n              \"src/img\",\n              \"src/assets\",\n              \"src/generated\",\n              \"src/app/search/search-worker.js\",\n              \"src/pwa-manifest.json\",\n              \"src/google385281288605d160.html\",\n              {\n                \"glob\": \"custom-elements.min.js\",\n                \"input\": \"node_modules/@webcomponents/custom-elements\",\n                \"output\": \"/assets/js\"\n              },\n              {\n                \"glob\": \"native-shim.js\",\n                \"input\": \"node_modules/@webcomponents/custom-elements/src\",\n                \"output\": \"/assets/js\"\n              }\n            ],\n            \"styles\": [\"src/styles.scss\"],\n            \"scripts\": [],\n            \"vendorChunk\": true,\n            \"extractLicenses\": false,\n            \"buildOptimizer\": false,\n            \"sourceMap\": true,\n            \"optimization\": {\n              \"fonts\": true,\n              \"scripts\": true,\n              \"styles\": {\n                \"inlineCritical\": false,\n                \"minify\": true\n              }\n            },\n            \"outputHashing\": \"all\"\n          },\n          \"configurations\": {\n            \"fast\": {\n              \"budgets\": [\n                {\n                  \"type\": \"anyComponentStyle\",\n                  \"maximumWarning\": \"6kb\"\n                }\n              ]\n            },\n            \"next\": {\n              \"budgets\": [\n                {\n                  \"type\": \"anyComponentStyle\",\n                  \"maximumWarning\": \"6kb\"\n                }\n              ],\n              \"optimization\": true,\n              \"outputHashing\": \"all\",\n              \"sourceMap\": false,\n              \"namedChunks\": false,\n              \"extractLicenses\": true,\n              \"vendorChunk\": false,\n              \"buildOptimizer\": true,\n              \"fileReplacements\": [\n                {\n                  \"replace\": \"src/environments/environment.ts\",\n                  \"with\": \"src/environments/environment.next.ts\"\n                }\n              ],\n              \"serviceWorker\": true\n            },\n            \"stable\": {\n              \"budgets\": [\n                {\n                  \"type\": \"anyComponentStyle\",\n                  \"maximumWarning\": \"6kb\"\n                }\n              ],\n              \"optimization\": true,\n              \"outputHashing\": \"all\",\n              \"sourceMap\": false,\n              \"namedChunks\": false,\n              \"extractLicenses\": true,\n              \"vendorChunk\": false,\n              \"buildOptimizer\": true,\n              \"fileReplacements\": [\n                {\n                  \"replace\": \"src/environments/environment.ts\",\n                  \"with\": \"src/environments/environment.stable.ts\"\n                }\n              ],\n              \"serviceWorker\": true\n            },\n            \"archive\": {\n              \"budgets\": [\n                {\n                  \"type\": \"anyComponentStyle\",\n                  \"maximumWarning\": \"6kb\"\n                }\n              ],\n              \"optimization\": true,\n              \"outputHashing\": \"all\",\n              \"sourceMap\": false,\n              \"namedChunks\": false,\n              \"extractLicenses\": true,\n              \"vendorChunk\": false,\n              \"buildOptimizer\": true,\n              \"fileReplacements\": [\n                {\n                  \"replace\": \"src/environments/environment.ts\",\n                  \"with\": \"src/environments/environment.archive.ts\"\n                }\n              ],\n              \"serviceWorker\": true\n            },\n            \"production\": {\n              \"budgets\": [\n                {\n                  \"type\": \"anyComponentStyle\",\n                  \"maximumWarning\": \"6kb\"\n                }\n              ],\n              \"optimization\": true,\n              \"outputHashing\": \"all\",\n              \"sourceMap\": false,\n              \"namedChunks\": false,\n              \"extractLicenses\": true,\n              \"vendorChunk\": false,\n              \"buildOptimizer\": true,\n              \"serviceWorker\": true\n            }\n          },\n          \"defaultConfiguration\": \"\"\n        },\n        \"serve\": {\n          \"builder\": \"@angular-devkit/build-angular:dev-server\",\n          \"options\": {\n            \"browserTarget\": \"site:build\"\n          },\n          \"configurations\": {\n            \"fast\": {\n              \"browserTarget\": \"site:build:fast\"\n            },\n            \"next\": {\n              \"browserTarget\": \"site:build:next\"\n            },\n            \"stable\": {\n              \"browserTarget\": \"site:build:stable\"\n            },\n            \"archive\": {\n              \"browserTarget\": \"site:build:archive\"\n            },\n            \"production\": {\n              \"browserTarget\": \"site:build:production\"\n            }\n          }\n        },\n        \"extract-i18n\": {\n          \"builder\": \"@angular-devkit/build-angular:extract-i18n\",\n          \"options\": {\n            \"browserTarget\": \"site:build\"\n          }\n        },\n        \"test\": {\n          \"builder\": \"@angular-devkit/build-angular:karma\",\n          \"options\": {\n            \"main\": \"src/test.ts\",\n            \"karmaConfig\": \"src/karma.conf.js\",\n            \"polyfills\": \"src/polyfills.ts\",\n            \"tsConfig\": \"tsconfig.spec.json\",\n            \"scripts\": [],\n            \"styles\": [\"src/styles.scss\"],\n            \"assets\": [\n              \"src/img\",\n              \"src/assets\",\n              \"src/generated\",\n              \"src/app/search/search-worker.js\",\n              \"src/pwa-manifest.json\",\n              \"src/google385281288605d160.html\",\n              {\n                \"glob\": \"custom-elements.min.js\",\n                \"input\": \"node_modules/@webcomponents/custom-elements\",\n                \"output\": \"/assets/js\"\n              },\n              {\n                \"glob\": \"native-shim.js\",\n                \"input\": \"node_modules/@webcomponents/custom-elements/src\",\n                \"output\": \"/assets/js\"\n              }\n            ]\n          }\n        },\n        \"lint\": {\n          \"builder\": \"@angular-eslint/builder:lint\",\n          \"options\": {\n            \"lintFilePatterns\": [\"src/!(generated)/**/*.ts\", \"src/!(generated)/**/*.html\", \"tests/**/*.ts\"]\n          }\n        },\n        \"e2e\": {\n          \"builder\": \"@angular-devkit/build-angular:protractor\",\n          \"options\": {\n            \"protractorConfig\": \"tests/e2e/protractor.conf.js\",\n            \"devServerTarget\": \"site:serve\"\n          }\n        }\n      }\n    }\n  },\n  \"defaultProject\": \"site\",\n  \"schematics\": {\n    \"@schematics/angular:application\": {\n      \"strict\": true\n    },\n    \"@schematics/angular:component\": {\n      \"inlineStyle\": true,\n      \"style\": \"scss\"\n    }\n  }\n}\n"
  },
  {
    "path": "apps/rxjs.dev/content/6-to-7-change-summary.md",
    "content": "# RxJS 6.x to 7.x Detailed Change List\n\nThis document contains a detailed list of changes between RxJS 6.x and RxJS 7.x, presented in the order they can be found when diffing the TypeScript APIs in various module files.\n\n## module `rxjs`\n\n### Breaking changes\n\n#### AsyncSubject\n\n- `_subscribe` method is no longer `public` and is now `protected`.\n- no longer has its own implementation of the `error` method inherited from `Subject`.\n\n#### BehaviorSubject\n\n- `_subscribe` method is no longer `public` and is now `protected`.\n- `value` property is a getter `get value()` instead of `readonly value`, and can no longer be forcibly set.\n\n#### bindCallback\n\n- Generic signatures have changed. Do not explicitly pass generics.\n\n#### combineLatest\n\n- Generic signatures have changed. Do not explicitly pass generics.\n\n#### concat\n\n- Generic signatures have changed. Do not explicitly pass generics.\n\n#### ConnectableObservable\n\n- `_isComplete` is no longer a property.\n- `_subscribe` method is no longer `public` and is now `protected`.\n\n#### defer\n\n- Generic argument no longer extends `void`.\n- `defer` no longer allows factories to return void or undefined. All factories passed to `defer` must return a proper `ObservableInput`, such as `Observable`, `Promise`, et al. To get the same behavior as you may have relied on previously, `return EMPTY` or `return of()` from the factory.\n\n#### forkJoin\n\n- Generic signatures have changed. Do not explicitly pass generics.\n\n#### fromEvent\n\n- The `fromEvent` signatures have been changed and there are now separate signatures for each type of target - DOM, Node, jQuery, etc. That means that an attempt to pass options - like `{ once: true }` - to a target that does not support an options argument will result in a TypeScript error.\n\n#### GroupedObservable\n\n- No longer publicly exposes `_subscribe`\n- `key` properly is `readonly`.\n- No longer publicly exposes `constructor`.\n\n#### iif\n\n- Generic signatures have changed. Do not explicitly pass generics.\n- `iif` will no longer allow result arguments that are `undefined`. This was a bad call pattern that was likely an error in most cases. If for some reason you are relying on this behavior, simply substitute `EMPTY` in place of the `undefined` argument. This ensures that the behavior was intentional and desired, rather than the result of an accidental `undefined` argument.\n\n#### isObservable\n\n- No longer has a generic and returns `Observable<unknown>`, you must cast the result.\n\n#### merge\n\n- Generic signatures have changed. Do not explicitly pass generics.\n\n#### Notification\n\n- The `error` property is now `readonly`.\n- The `hasValue` property is now `readonly`.\n- The `kind` property is now `readonly`.\n- The `value` property is now `readonly` and may be `undefined`.\n- `constructor` signature now only allows valid construction. For example `new Notification('C', 'some_value')` will be an error in TypeScript.\n\n#### Observable\n\n- `_isScalar` property removed.\n- `_subscribe` method is no longer `public` and is now marked `@internal`.\n- `_trySubscribe` method is no longer `public` and is now `@internal`.\n- `pipe` method calls with `9` or more arguments will now return `Observable<unknown>` rather than `Observable<{}>`.\n- `toPromise` method now correctly returns `Promise<T | undefined>` instead of `Promise<T>`. This is a correction without a runtime change, because if the observable does not emit a value before completion, the promise will resolve with `undefined`.\n- `static if` and `static throw` properties are no longer defined. They were unused in version 6.\n- `lift`, `source`, and `operator` properties are still **deprecated**, and should not be used. They are implementation details, and will very likely be renamed or missing in version 8.\n\n#### of\n\n- Generic signatures have changed. Do not explicitly pass generics.\n\n#### onErrorResumeNext\n\n- Generic signatures have changed. Do not explicitly pass generics.\n\n#### pairs\n\n- Generic signatures have changed. Do not explicitly pass generics.\n- `pairs` will no longer function in IE without a polyfill for `Object.entries`. `pairs` itself is also deprecated in favor of users just using `from(Object.entries(obj))`.\n\n#### partition\n\n- Generic signatures have changed. Do not explicitly pass generics.\n\n#### pipe\n\n- Calls with `9` or more arguments will now return `(arg: A) => unknown` rather than `(arg: A) => {}`.\n\n#### race\n\n- Generic signatures have changed. Do not explicitly pass generics.\n- `race` will no longer subscribe to subsequent observables if a provided source synchronously errors or completes. This means side effects that might have occurred during subscription in those rare cases will no longer occur.\n\n#### ReplaySubject\n\n- `_getNow` method has been removed.\n- `_subscribe` method is no longer `public` and is now `protected`.\n\n#### Subscribable\n\n- `subscribe` will accept `Partial<Observer<T>>` now. All overloads with functions as arguments have been removed. This is because `Subscribable` is intended to map to the basic observable contract from the TC39 proposal and the return type of a call to `[Symbol.observable]()`.\n\n#### SubscribableOrPromise\n\n- See notes on `Subscribable` above.\n\n#### Subscriber\n\n- `destination` property must now be a `Subscriber` or full `Observer`.\n- `syncErrorThrowable` property has been removed.\n- `syncErrorThrown` property has been removed.\n- `syncErrorValue` property has been removed.\n- `_unsubscribeAndRecycle` method has been removed.\n\n#### Subscription\n\n- `_parentOrParents` property has been removed.\n- `add` method returns `void` and no longer returns a `Subscription`. Returning `Subscription` was an old behavior from the early days of version 5. If you add a function to a subscription (i.e. `subscription.add(fn)`), you can remove that function directly by calling `remove` with the same function instance. (i.e. `subscription.remove(fn)`). Previously, you needed to get the returned `Subscription` object and pass _that_ to `remove`. In version 6 and lower, the `Subscription` returned by calling `add` with another `Subscription` was always the same subscription you passed in. (meaning `subscription.add(subs1).add(subs2)` was an antipattern and the same as `subscription.add(subs1); subs1.add(subs2);`.\n\n#### VirtualAction\n\n- The static `sortActions` method has been removed.\n\n#### zip\n\n- Generic signatures have changed. Do not explicitly pass generics.\n- Zipping a single array will now have a different result. This is an extreme corner-case, because it is very unlikely that anyone would want to zip an array with nothing at all. The workaround would be to wrap the array in another array `zip([[1,2,3]])`. But again, that's pretty weird.\n\n---\n\n### New Features\n\n#### animationFrames\n\n- A new method for creating a stream of animation frames. Each event will carry with it a high-resolution timestamp, and an elapsed time since observation was started.\n\n#### config\n\n##### onUnhandledError\n\n- A handler for dealing with errors that make it all the way down to the \"end\" of the observation chain when there is no error handler in the observer. Useful for doing things like logging unhandled errors in RxJS observable chains.\n\n##### onStoppedNotification\n\n- A handler for edge cases where a subscriber within RxJS is notified after it has already \"stopped\", that is, a point in time where it has received an error or complete, but hasn't yet finalized. This is mostly useful for logging purposes.\n\n##### useDeprecatedNextContext\n\n- In RxJS 6, a little-used feature allowed users to access the `subscriber` directly as `this` within a call to the `next` handler. The problem with this is it incurred heavy performance penalties. That behavior has been changed (because it wasn't really documented and it was barely ever used) to not change the `this` context of any user-provided subscription handlers. If you need to get that feature back, you can switch it on with this flag. Note this behavior will be removed completely in version 8.\n\n#### connectable\n\n- This is the new means for creating a `ConnectableObservable`, and really is a replacement for non-selector usage of `multicast` and `publish` variants. Simply pass your source observable to `connectable` with the `Subject` you'd like to connect through.\n\n#### firstValueFrom\n\n- A better, more tree-shakable replacement for `toPromise()` (which is now deprecated). This function allows the user to convert any `Observable` into a `Promise` that will resolve when the source observable emits its first value. If the source observable closes without emitting a value, the returned promise will reject with an `EmptyError`, or it will resolve with a configured `defaultValue`. For more information, see the [deprecation guide](/deprecations/to-promise).\n\n#### lastValueFrom\n\n- A better, more tree-shakable replacement for `toPromise()` (which is now deprecated). This function allows the user to convert any `Observable` in to a `Promise` that will resolve when the source observable emits the last value. If the source observable closes without emitting a value, the returned promise will reject with an `EmptyError`, or it will resolve with a configured `defaultValue`. For more information, see the [deprecation guide](/deprecations/to-promise).\n\n#### ObservableInput\n\n- This is just a type, but it's important. This type defines the allowed types that can be passed to almost every API within RxJS that accepts an Observable. It has always accepted `Observable`, `Promise`, `Iterable`, and `ArrayLike`. Now it will also accept `AsyncIterable` and `ReadableStream`.\n\n##### AsyncIterable\n\n- `AsyncIterables` such as those defined by `IxJS` or by async generators (`async function*`), may now be passed to any API that accepts an observable, and can be converted to an `Observable` directly using `from`.\n\n##### ReadableStream\n\n- `ReadableStream` such as those returned by `fetch`, et al, can be passed to any API that accepts an observable, and can be converted to `Observable` directly using `from`.\n\n#### ReplaySubject\n\n- A [bug was fixed](https://github.com/ReactiveX/rxjs/pull/5696) that prevented a completed or errored `ReplaySubject` from accumulating values in its buffer when resubscribed to another source. This breaks some uses - like [this StackOverflow answer](https://stackoverflow.com/a/54957061) - that depended upon the buggy behavior.\n\n#### Subscription\n\n- Now allows adding and removing of functions directly via `add` and `remove` methods.\n\n#### throwError\n\n- Now accepts an `errorFactory` of `() => any` to defer the creation of the error until the time it will be emitted. It is recommended to use this method, as Errors created in most popular JavaScript runtimes will retain all values in the current scope for debugging purposes.\n\n## module `rxjs/operators`\n\n### Breaking Changes\n\n#### audit\n\n- The observable returned by the `audit` operator's duration selector must emit a next notification to end the duration. Complete notifications no longer end the duration.\n- `audit` now emits the last value from the source when the source completes. Previously, `audit` would mirror the completion without emitting the value.\n\n#### auditTime\n\n- `auditTime` now emits the last value from the source when the source completes, after the audit duration elapses. Previously, `auditTime` would mirror the completion without emitting the value and without waiting for the audit duration to elapse.\n\n#### buffer\n\n- `buffer` now subscribes to the source observable before it subscribes to the closing notifier. Previously, it subscribed to the closing notifier first.\n- Final buffered values will now always be emitted. To get the same behavior as the previous release, you can use `endWith` and `skipLast(1)`, like so: `source$.pipe(buffer(notifier$.pipe(endWith(true))), skipLast(1))`\n- `closingNotifier` completion no longer completes the result of `buffer`. If that is truly a desired behavior, then you should use `takeUntil`. Something like: `source$.pipe(buffer(notifier$), takeUntil(notifier$.pipe(ignoreElements(), endWith(true))))`, where `notifier$` is multicast, although there are many ways to compose this behavior.\n\n#### bufferToggle\n\n- The observable returned by the `bufferToggle` operator's closing selector must emit a next notification to close the buffer. Complete notifications no longer close the buffer.\n\n#### bufferWhen\n\n- The observable returned by the `bufferWhen` operator's closing selector must emit a next notification to close the buffer. Complete notifications no longer close the buffer.\n\n#### combineLatest\n\n- Generic signatures have changed. Do not explicitly pass generics.\n\n#### concat\n\n- Generic signatures have changed. Do not explicitly pass generics.\n- Still deprecated, use the new `concatWith`.\n\n#### concatAll\n\n- Generic signatures have changed. Do not explicitly pass generics.\n\n#### concatMapTo\n\n- Generic signatures have changed. Do not explicitly pass generics.\n\n#### count\n\n- No longer passes `source` observable as a third argument to the predicate. That feature was rarely used, and of limited value. The workaround is to simply close over the source inside of the function if you need to access it in there.\n\n#### debounce\n\n- The observable returned by the `debounce` operator's duration selector must emit a next notification to end the duration. Complete notifications no longer end the duration.\n\n#### debounceTime\n\n- The `debounceTime` implementation is more efficient and no longer schedules an action for each received next notification. However, because the implementation now uses the scheduler's concept of time, any tests using Jasmine's `clock` will need to ensure that [`jasmine.clock().mockDate()`](https://jasmine.github.io/api/edge/Clock.html#mockDate) is called after `jasmine.clock().install()` - because Jasmine does not mock `Date.now()` by default.\n\n#### defaultIfEmpty\n\n- Generic signatures have changed. Do not explicitly pass generics.\n- `defaultIfEmpty` requires a value be passed. Will no longer convert `undefined` to `null` for no good reason.\n\n#### delayWhen\n\n- `delayWhen` will no longer emit if the duration selector simply completes without a value. Notifiers must notify with a value, not a completion.\n\n#### endWith\n\n- Generic signatures have changed. Do not explicitly pass generics.\n\n#### expand\n\n- Generic signatures have changed. Do not explicitly pass generics.\n\n#### finalize\n\n- `finalize` will now unsubscribe from its source _before_ it calls its callback. That means that `finalize` callbacks will run in the order in which they occur in the pipeline: `source.pipe(finalize(() => console.log(1)), finalize(() => console.log(2)))` will log `1` and then `2`. Previously, callbacks were called in the reverse order.\n\n#### map\n\n- `thisArg` will now default to `undefined`. The previous default of `MapSubscriber` never made any sense. This will only affect code that calls map with a `function` and references `this` like so: `source.pipe(map(function () { console.log(this); }))`. There wasn't anything useful about doing this, so the breakage is expected to be very minimal. If anything we're no longer leaking an implementation detail.\n\n#### merge\n\n- Generic signatures have changed. Do not explicitly pass generics.\n- Still deprecated, use the new `mergeWith`.\n\n#### mergeAll\n\n- Generic signatures have changed. Do not explicitly pass generics.\n\n#### mergeScan\n\n- `mergeScan` will no longer emit its inner state again upon completion.\n\n#### pluck\n\n- Generic signatures have changed. Do not explicitly pass generics.\n\n#### race\n\n- Generic signatures have changed. Do not explicitly pass generics.\n\n#### reduce\n\n- Generic signatures have changed. Do not explicitly pass generics.\n\n#### sample\n\n- The `sample` operator's notifier observable must emit a next notification to effect a sample. Complete notifications no longer effect a sample.\n\n#### scan\n\n- Generic signatures have changed. Do not explicitly pass generics.\n\n#### single\n\n- The `single` operator will now throw for scenarios where values coming in are either not present, or do not match the provided predicate. Error types have thrown have also been updated, please check documentation for changes.\n\n#### skipLast\n\n- `skipLast` will no longer error when passed a negative number, rather it will simply return the source, as though `0` was passed.\n\n#### startWith\n\n- Generic signatures have changed. Do not explicitly pass generics.\n\n#### switchAll\n\n- Generic signatures have changed. Do not explicitly pass generics.\n\n#### switchMapTo\n\n- Generic signatures have changed. Do not explicitly pass generics.\n\n#### take\n\n- `take` and will now throw runtime error for arguments that are negative or NaN, this includes non-TS calls like `take()`.\n\n#### takeLast\n\n- `takeLast` now has runtime assertions that throw `TypeError`s for invalid arguments. Calling `takeLast` without arguments or with an argument that is `NaN` will throw a `TypeError`.\n\n#### throttle\n\n- The observable returned by the `throttle` operator's duration selector must emit a next notification to end the duration. Complete notifications no longer end the duration.\n\n#### throwError\n\n- In an extreme corner case for usage, `throwError` is no longer able to emit a function as an error directly. If you need to push a function as an error, you will have to use the factory function to return the function like so: `throwError(() => functionToEmit)`, in other words `throwError(() => () => console.log('called later'))`.\n\n#### window\n\n- The `windowBoundaries` observable no longer completes the result. It was only ever meant to notify of the window boundary. To get the same behavior as the old behavior, you would need to add an `endWith` and a `skipLast(1)` like so: `source$.pipe(window(notifier$.pipe(endWith(true))), skipLast(1))`.\n\n#### windowToggle\n\n- The observable returned by the `windowToggle` operator's closing selector must emit a next notification to close the window. Complete notifications no longer close the window.\n\n#### withLatestFrom\n\n- Generic signatures have changed. Do not explicitly pass generics.\n\n#### zip\n\n- Generic signatures have changed. Do not explicitly pass generics.\n- Still deprecated, use the new `zipWith`.\n- `zip` operators will no longer iterate provided iterables \"as needed\", instead the iterables will be treated as push-streams just like they would be everywhere else in RxJS. This means that passing an endless iterable will result in the thread locking up, as it will endlessly try to read from that iterable. This puts us in line with all other Rx implementations. To work around this, it is probably best to use `map` or some combination of `map` and `zip`. For example, `zip(source$, iterator)` could be `source$.pipe(map(value => [value, iterator.next().value]))`.\n\n### New Features\n\n#### connect\n\n- New operator to cover the use cases of `publish` variants that use a `selector`. Wherein the selector allows the user to define multicast behavior prior to connection to the source observable for the multicast.\n\n#### share\n\n- Added functionality to allow complete configuration of what type of `Subject` is used to multicast, and when that subject is reset.\n\n#### timeout\n\n- Added more configuration options to `timeout`, so it could be used to timeout just if the first item doesn't arrive quickly enough, or it could be used as a timeout between each item. Users may also pass a `Date` object to define an absolute time for a timeout for the first time to arrive. Adds additional information to the timeout error, and the ability to pass along metadata with the timeout for identification purposes.\n\n#### zipWith, concatWith, mergeWith, raceWith\n\n- Simply renamed versions of the operators `zip`, `concat`, `merge`, and `race`. So we can deprecate those old names and use the new names without collisions.\n\n## module `rxjs/ajax`\n\n### Breaking Changes\n\n#### ajax\n\n- `ajax` body serialization will now use default XHR behavior in all cases. If the body is a `Blob`, `ArrayBuffer`, any array buffer view (like a byte sequence, e.g. `Uint8Array`, etc), `FormData`, `URLSearchParams`, `string`, or `ReadableStream`, default handling is used. If the `body` is otherwise `typeof` `\"object\"`, then it will be converted to JSON via `JSON.stringify`, and the `Content-Type` header will be set to `application/json;charset=utf-8`. All other types will emit an error.\n- The `Content-Type` header passed to `ajax` configuration no longer has any effect on the serialization behavior of the AJAX request.\n- For TypeScript users, `AjaxRequest` is no longer the type that should be explicitly used to create an `ajax`. It is now `AjaxConfig`, although the two types are compatible, only `AjaxConfig` has `progressSubscriber` and `createXHR`.\n- Ajax implementation drops support for IE10 and lower. This puts us in line with other implementations and helps clean up code in this area\n\n#### AjaxRequest\n\n- `AjaxRequest` is no longer used to type the configuration argument for calls to `ajax`. The new type is `AjaxConfig`. This was done to disambiguate two very similar types with different use cases. `AjaxRequest` is still there, but properties have changed, and it is used to show what final request information was sent as part of an event response.\n\n### New Features\n\n#### AjaxResponse\n\n- Now includes `responseHeaders`.\n- Now includes event `type` and `total` numbers for examining upload and download progress (see `includeUploadProgress` and `includeDownloadProgress`).\n\n#### includeUploadProgress\n\n- A flag to make a request that will include streaming upload progress events in the returned observable.\n\n#### includeDownloadProgress\n\n- A flag to make a request that will include streaming upload progress events in the returned observable.\n\n#### queryParams\n\n- Configuration for setting query parameters in the URL of the request to be made.\n\n#### XSRF (CSRF) additions:\n\n- `xsrfCookieName` and `xsrfHeaderName` were added for cross-site request forgery prevention capabilities.\n\n## module `rxjs/fetch`\n\nNo changes.\n\n## module `rxjs/testing`\n\n### New Features\n\n#### TestScheduler expectObservable().toEqual()\n\n- A new means of comparing the equality of two observables. If all emissions are the same, and at the same time, then they are equal. This is primarily useful for refactoring operator chains and making sure that they are equivalent.\n"
  },
  {
    "path": "apps/rxjs.dev/content/blackLivesMatter.md",
    "content": "<style>\n    .blm-background {\n        background-color: black; \n        color: white; \n        display: flex; \n        min-height: calc(100vh + 64px);\n        margin: -20px -50px;\n    }\n\n    .text-container.blm-container {\n        text-align: center;\n        line-height: inherit;\n        max-width: inherit;\n    }\n\n    .blm-text {\n        font-size: 2rem;\n        line-height: inherit\n    }\n\n    .blm-list-item {\n        margin: 10px 0\n    }\n</style>\n\n<article class=\"blm-background\">\n  <div layout=\"row\" layout-xs=\"column\" class=\"home-row homepage-container\">\n    <div class=\"text-container blm-container\">\n      <h1 class=\"no-anchor no-toc\" style=\"font-size: 3rem; line-height: inherit\">BLACK LIVES MATTER</h1>\n      <p class=\"blm-text\">\n        We stand in solidarity with the Black Lives Matter movement. We believe that technologists must not be silent in the fight to end racial inequality.      </p>\n      <p class=\"blm-text\">\n        We ask you to stand with us and help educate your team members and those in your network on how to help dismantle a system that oppresses Black people. Find a list of starting resources here: \n        <ul style=\"list-style-type: none; line-height: inherit; padding-inline-start: 0\">\n          <li class=\"blm-list-item\"><a class=\"blm-text\" href=\"https://www.youtube.com/watch?v=-aCn72iXO9s\">Let's get to the root of racial injustice by Megan Ming Francis</a></li>\n          <li class=\"blm-list-item\"><a class=\"blm-text\" href=\"http://www.changecadet.com/blog/2020/5/30/what-leaders-can-do-for-black-employees\">What Leaders can do for Black Employees by Dr. Akilah Cadet</a></li>\n          <li class=\"blm-list-item\"><a class=\"blm-text\" href=\"https://blacktechpipeline.substack.com/p/hey-employers-do-black-lives-matter\">Hey Employers: Do Black Lives Matter? by Pariss Athena</a></li>\n          <li class=\"blm-list-item\"><a class=\"blm-text\" href=\"https://safiyaunoble.com/\">Algorithms of Oppression by Safiya Umoja Noble</a></li>\n          <li class=\"blm-list-item\"><a class=\"blm-text\" href=\"https://www.rageinsidethemachine.com/\">Rage Inside The Machine by Robert Smith</a></li>\n          <li class=\"blm-list-item\"><a class=\"blm-text\" href=\"https://www.sarawb.com/\">Technically Wrong by Sara Wachter-Boettcher</a></li>\n        </ul>\n      </p>\n      <p class=\"blm-text\">\n        In solidarity, we ask you to consider financially supporting efforts such as <a class=\"blm-text\" href=\"https://secure.actblue.com/donate/ms_blm_homepage_2019\">Black Lives Matter</a>, \n        <a class=\"blm-text\" href=\"https://support.eji.org/give/153413/#!/donation/checkout\">The Equal Justice Initiative</a> or local charity organizations.\n      </p>\n    </div>\n  </div>\n</article>\n"
  },
  {
    "path": "apps/rxjs.dev/content/code-of-conduct.md",
    "content": "# Contributor Covenant Code of Conduct\n\n## Our Pledge\n\nIn the interest of fostering an open and welcoming environment, we as\ncontributors and maintainers pledge to making participation in our project and\nour community a harassment-free experience for everyone, regardless of age, body\nsize, disability, ethnicity, gender identity and expression, level of experience,\neducation, socio-economic status, nationality, personal appearance, race,\nreligion, or sexual identity and orientation.\n\n## Our Standards\n\nExamples of behavior that contributes to creating a positive environment\ninclude:\n\n* Using welcoming and inclusive language\n* Being respectful of differing viewpoints and experiences\n* Gracefully accepting constructive criticism\n* Focusing on what is best for the community\n* Showing empathy towards other community members\n\nExamples of unacceptable behavior by participants include:\n\n* The use of sexualized language or imagery and unwelcome sexual attention or\n  advances\n* Trolling, insulting/derogatory comments, and personal or political attacks\n* Public or private harassment\n* Publishing others' private information, such as a physical or electronic\n  address, without explicit permission\n* Other conduct which could reasonably be considered inappropriate in a\n  professional setting\n\n## Our Responsibilities\n\nProject maintainers are responsible for clarifying the standards of acceptable\nbehavior and are expected to take appropriate and fair corrective action in\nresponse to any instances of unacceptable behavior.\n\nProject maintainers have the right and responsibility to remove, edit, or\nreject comments, commits, code, wiki edits, issues, and other contributions\nthat are not aligned to this Code of Conduct, or to ban temporarily or\npermanently any contributor for other behaviors that they deem inappropriate,\nthreatening, offensive, or harmful.\n\n## Scope\n\nThis Code of Conduct applies both within project spaces and in public spaces\nwhen an individual is representing the project or its community. Examples of\nrepresenting a project or community include using an official project e-mail\naddress, posting via an official social media account, or acting as an appointed\nrepresentative at an online or offline event. Representation of a project may be\nfurther defined and clarified by project maintainers.\n\n## Enforcement\n\nInstances of abusive, harassing, or otherwise unacceptable behavior may be\nreported by contacting Ben Lesh (ben@benlesh.com), Tracy Lee (tracy@thisdot.co) or OJ Kwon (kwon.ohjoong@gmail.com). All\ncomplaints will be reviewed and investigated and will result in a response that\nis deemed necessary and appropriate to the circumstances. The project team is\nobligated to maintain confidentiality with regard to the reporter of an incident.\nFurther details of specific enforcement policies may be posted separately.\n\nProject maintainers who do not follow or enforce the Code of Conduct in good\nfaith may face temporary or permanent repercussions as determined by other\nmembers of the project's leadership.\n\n## Attribution\n\nThis Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,\navailable at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html\n\n[homepage]: https://www.contributor-covenant.org\n"
  },
  {
    "path": "apps/rxjs.dev/content/deprecations/array-argument.md",
    "content": "# Array Arguments\n\nTo unify the API surface of `forkJoin` and `combineLatest` we deprecated some signatures.\nSince that it is recommended to either pass an Object or an Array to these operators.\n\n<div class=\"alert is-important\">\n    <span>\n        This deprecation was introduced in RxJS 6.5.\n    </span>\n</div>\n\n## Operators affected by this Change\n\n- [combineLatest](/api/index/function/combineLatest)\n- [forkJoin](/api/index/function/forkJoin)\n\n## How to Refactor\n\nWe deprecated the signatures, where just pass all Observables directly as parameters to these operators.\n\n```ts\nimport {forkJoin, from} from 'rxjs';\n\nconst odd$ = from([1,3,5]);\nconst even$ = from([2,4,6]);\n\n// deprecated\nforkJoin(odd$, even$);\n// suggested change\nforkJoin([odd$, even$]);\n// or\nforkJoin({odd: odd$, even: even$})\n```"
  },
  {
    "path": "apps/rxjs.dev/content/deprecations/breaking-changes.md",
    "content": "# Breaking Changes in Version 7\n\n## General\n\n- **TS:** RxJS requires TS 4.2\n\n- **rxjs-compat:** `rxjs-compat` is not published for v7\n\n- **toPromise:** toPromise return type now returns `T | undefined` in TypeScript, which is correct, but may break builds.\n\n- **Subscription:** `add` no longer returns an unnecessary Subscription reference. This was done to prevent confusion caused by a legacy behavior. You can now add and remove functions and Subscriptions as teardowns to and from a `Subscription` using `add` and `remove` directly. Before this, `remove` only accepted subscriptions.\n\n- **Observable:** `lift` no longer exposed. It was _NEVER_ documented that end users of the library should be creating operators using `lift`. Lift has a [variety of issues](https://github.com/ReactiveX/rxjs/issues/5431) and was always an internal implementation detail of rxjs that might have been used by a few power users in the early days when it had the most value. The value of `lift`, originally, was that subclassed `Observable`s would compose through all operators that implemented lift. The reality is that feature is not widely known, used, or supported, and it was never documented as it was very experimental when it was first added. Until the end of v7, `lift` will remain on Observable. Standard JavaScript users will notice no difference. However, TypeScript users might see complaints about `lift` not being a member of observable. To workaround this issue there are two things you can do: 1. Rewrite your operators as [outlined in the documentation](https://rxjs.dev/guide/operators), such that they return `new Observable`. or 2. cast your observable as `any` and access `lift` that way. Method 1 is recommended if you do not want things to break when we move to version 8.\n\n- **Subscriber:** `new Subscriber` no longer takes 0-3 arguments. To create a `Subscriber` with 0-3 arguments, use `Subscriber.create`. However, please note that there is little to no reason that you should be creating `Subscriber` references directly, and `Subscriber.create` and `new Subscriber` are both deprecated.\n\n- **onUnhandledError:** Errors that occur during setup of an observable subscription after the subscription has emitted an error or completed will now throw in their own call stack. Before it would call `console.warn`. This is potentially breaking in edge cases for node applications, which may be configured to terminate for unhandled exceptions. In the unlikely event this affects you, you can configure the behavior to `console.warn` in the new configuration setting like so: `import { config } from 'rxjs'; config.onUnhandledError = (err) => console.warn(err);`\n\n- **RxJS Error types** Tests that are written with naive expectations against errors may fail now that errors have a proper `stack` property. In some testing frameworks, a deep equality check on two error instances will check the values in `stack`, which could be different.\n\n- `unsubscribe` no longer available via the `this` context of observer functions. To reenable, set `config.useDeprecatedNextContext = true` on the rxjs `config` found at `import { config } from 'rxjs';`. Note that enabling this will result in a performance penalty for all consumer subscriptions.\n\n- Leaked implementation detail `_unsubscribeAndRecycle` of `Subscriber` has been removed. Just use new `Subscription` objects\n\n- The static `sortActions` method on `VirtualTimeScheduler` is no longer publicly exposed by our TS types.\n\n- `Notification.createNext(undefined)` will no longer return the exact same reference every time.\n\n- Type signatures tightened up around `Notification` and `dematerialize`, may uncover issues with invalid types passed to those operators.\n\n- Experimental support for `for await` has been removed. Use https://github.com/benlesh/rxjs-for-await instead.\n\n- `ReplaySubject` no longer schedules emissions when a scheduler is provided. If you need that behavior,\n  please compose in `observeOn` using `pipe`, for example: `new ReplaySubject(2, 3000).pipe(observeOn(asap))`\n\n- **rxjs-compat:** `rxjs/Rx` is no longer a valid import site.\n\n## Operators\n\n### concat\n\n- **concat:** Generic signature changed. Recommend not explicitly passing generics, just let inference do its job. If you must, cast with `as`.\n- **of:** Generic signature changed, do not specify generics, allow them to be inferred or use `as`\n\n### count\n\n- **count:** No longer passes `source` observable as a third argument to the predicate. That feature was rarely used, and of limited value. The workaround is to simply close over the source inside of the function if you need to access it in there.\n\n### defer\n\n- `defer` no longer allows factories to return `void` or `undefined`. All factories passed to defer must return a proper `ObservableInput`, such as `Observable`, `Promise`, et al. To get the same behavior as you may have relied on previously, `return EMPTY` or `return of()` from the factory.\n\n### map\n\n- **map:** `thisArg` will now default to `undefined`. The previous default of `MapSubscriber` never made any sense. This will only affect code that calls map with a `function` and references `this` like so: `source.pipe(map(function () { console.log(this); }))`. There wasn't anything useful about doing this, so the breakage is expected to be very minimal. If anything we're no longer leaking an implementation detail.\n\n### mergeScan\n\n- **mergeScan:** `mergeScan` will no longer emit its inner state again upon completion.\n\n### of\n\n- **of:** Use with more than 9 arguments, where the last argument is a `SchedulerLike` may result in the wrong type which includes the `SchedulerLike`, even though the run time implementation does not support that. Developers should be using `scheduled` instead\n\n### pairs\n\n- **pairs:** `pairs` will no longer function in IE without a polyfill for `Object.entries`. `pairs` itself is also deprecated in favor of users just using `from(Object.entries(obj))`.\n\n### race\n\n- **race:** `race()` will no longer subscribe to subsequent observables if a provided source synchronously errors or completes. This means side effects that might have occurred during subscription in those rare cases will no longer occur.\n\n### repeat\n\n- An undocumented behavior where passing a negative count argument to `repeat` would result in an observable that repeats forever.\n\n### retry\n\n- Removed an undocumented behavior where passing a negative count argument to `retry` would result in an observable that repeats forever.\n\n### single\n\n- `single` operator will now throw for scenarios where values coming in are either not present, or do not match the provided predicate. Error types have thrown have also been updated, please check documentation for changes.\n\n### skipLast\n\n- **skipLast:** `skipLast` will no longer error when passed a negative number, rather it will simply return the source, as though `0` was passed.\n\n### startWith\n\n- **startWith:** `startWith` will return incorrect types when called with more than 7 arguments and a scheduler. Passing scheduler to startWith is deprecated\n\n### take\n\n- `take` and will now throw runtime error for arguments that are negative or NaN, this includes non-TS calls like `take()`.\n\n### takeLast\n\n- `takeLast` now has runtime assertions that throw `TypeError`s for invalid arguments. Calling takeLast without arguments or with an argument that is `NaN` will throw a `TypeError`\n\n### throwError\n\n- **throwError:** In an extreme corner case for usage, `throwError` is no longer able to emit a function as an error directly. If you need to push a function as an error, you will have to use the factory function to return the function like so: `throwError(() => functionToEmit)`, in other words `throwError(() => () => console.log('called later'))`.\n\n### timestamp\n\n- `timestamp` operator accepts a `TimestampProvider`, which is any object with a `now` method\n  that returns a number. This means pulling in less code for the use of the `timestamp` operator. This may cause\n  issues with `TestScheduler` run mode. (see [Issue here](https://github.com/ReactiveX/rxjs/issues/5553))\n\n### zip\n\n- **zip:** Zipping a single array will now have a different result. This is an extreme corner-case, because it is very unlikely that anyone would want to zip an array with nothing at all. The workaround would be to wrap the array in another array `zip([[1,2,3]])`. But again, that's pretty weird.\n\n- **zip:** `zip` operators will no longer iterate provided iterables \"as needed\", instead the iterables will be treated as push-streams just like they would be everywhere else in RxJS. This means that passing an endless iterable will result in the thread locking up, as it will endlessly try to read from that iterable. This puts us in-line with all other Rx implementations. To work around this, it is probably best to use `map` or some combination of `map` and `zip`. For example, `zip(source$, iterator)` could be `source$.pipe(map(value => [value, iterator.next().value]))`.\n\n## ajax\n\n- `ajax` body serialization will now use default XHR behavior in all cases. If the body is a `Blob`, `ArrayBuffer`, any array buffer view (like a byte sequence, e.g. `Uint8Array`, etc), `FormData`, `URLSearchParams`, `string`, or `ReadableStream`, default handling is use. If the `body` is otherwise `typeof` `\"object\"`, then it will be converted to JSON via `JSON.stringify`, and the `Content-Type` header will be set to `application/json;charset=utf-8`. All other types will emit an error.\n\n- The `Content-Type` header passed to `ajax` configuration no longer has any effect on the serialization behavior of the AJAX request.\n- For TypeScript users, `AjaxRequest` is no longer the type that should be explicitly used to create an `ajax`. It is now `AjaxConfig`, although the two types are compatible, only `AjaxConfig` has `progressSubscriber` and `createXHR`.\n\n- **ajax:** In an extreme corner-case... If an error occurs, the responseType is `\"json\"`, we're in IE, and the `responseType` is not valid JSON, the `ajax` observable will no longer emit a syntax error, rather it will emit a full `AjaxError` with more details.\n\n- **ajax:** Ajax implementation drops support for IE10 and lower. This puts us in-line with other implementations and helps clean up code in this area\n"
  },
  {
    "path": "apps/rxjs.dev/content/deprecations/index.md",
    "content": "# Deprecations and Breaking Changes\n\nWhile the core team always tries to limit changes, sometimes we have to deprecate APIs or do breaking changes for various reasons. \nThis section aims to describe some of the deprecations and breaking changes we did more in detail. Some of the changes are to extensive to describe\nthem appropriately in a changelog. Additionally, we can provide code examples in the documentation, to make required changes more comprehensible and therefore\nlower migration efforts.\n\nDo notice that this is not a complete list, please see the [changelog](https://github.com/ReactiveX/rxjs/blob/master/CHANGELOG.md) for the complete list."
  },
  {
    "path": "apps/rxjs.dev/content/deprecations/multicasting.md",
    "content": "# Multicasting\n\nIn version 7, the multicasting APIs were simplified to just a few functions:\n\n- [connectable](/api/index/function/connectable)\n- [connect](/api/operators/connect)\n- [share](/api/operators/share)\n\nAnd [shareReplay](/api/operators/shareReplay) - which is a thin wrapper around the now highly-configurable [share](/api/operators/share) operator.\n\nOther APIs that relate to multicasting are now deprecated.\n\n<div class=\"alert is-important\">\n    <span>\n        These deprecations were introduced in RxJS 7.0 and will become breaking in RxJS 8.\n    </span>\n</div>\n\n## APIs affected by this Change\n\n- [ConnectableObservable](/api/index/class/ConnectableObservable)\n- [multicast](/api/operators/multicast)\n- [publish](/api/operators/publish)\n- [publishBehavior](/api/operators/publishBehavior)\n- [publishLast](/api/operators/publishLast)\n- [publishReplay](/api/operators/publishReplay)\n- [refCount](/api/operators/refCount)\n\n## How to refactor\n\n### ConnectableObservable\n\nInstead of creating a [ConnectableObservable](/api/index/class/ConnectableObservable) instance, call the [connectable](/api/index/function/connectable) function to obtain a connectable observable.\n\n<!-- prettier-ignore -->\n```ts\nimport { ConnectableObservable, timer, Subject } from 'rxjs';\n\n// deprecated\nconst tick$ = new ConnectableObservable(\n  timer(1_000),\n  () => new Subject());\ntick$.connect();\n```\n\n<!-- prettier-ignore -->\n```ts\nimport { connectable, timer, Subject } from 'rxjs';\n\n// suggested refactor\nconst tick$ = connectable(timer(1_000), {\n  connector: () => new Subject()\n});\ntick$.connect();\n```\n\nIn situations in which the `refCount` method is used, the [share](/api/operators/share) operator can be used instead.\n\n<!-- prettier-ignore -->\n```ts\nimport { ConnectableObservable, timer, Subject } from 'rxjs';\n\n// deprecated\nconst tick$ = new ConnectableObservable(\n  timer(1_000),\n  () => new Subject()\n).refCount();\n```\n\n<!-- prettier-ignore -->\n```ts\nimport { timer, share, Subject } from 'rxjs';\n\n// suggested refactor\nconst tick$ = timer(1_000).pipe(\n  share({ connector: () => new Subject() })\n);\n```\n\n### multicast\n\nWhere [multicast](/api/operators/multicast) is called with a subject factory, can be replaced with [connectable](/api/index/function/connectable).\n\n<!-- prettier-ignore -->\n```ts\nimport { timer, multicast, Subject, ConnectableObservable } from 'rxjs';\n\n// deprecated\nconst tick$ = timer(1_000).pipe(\n  multicast(() => new Subject())\n) as ConnectableObservable<number>;\n```\n\n<!-- prettier-ignore -->\n```ts\nimport { connectable, timer, Subject } from 'rxjs';\n\n// suggested refactor\nconst tick$ = connectable(timer(1_000), {\n  connector: () => new Subject()\n});\n```\n\nWhere [multicast](/api/operators/multicast) is called with a subject instance, it can be replaced with [connectable](/api/index/function/connectable) and a local subject instance.\n\n<!-- prettier-ignore -->\n```ts\nimport { timer, multicast, Subject, ConnectableObservable } from 'rxjs';\n\n// deprecated\nconst tick$ = timer(1_000).pipe(\n  multicast(new Subject())\n) as ConnectableObservable<number>;\n```\n\n<!-- prettier-ignore -->\n```ts\nimport { connectable, timer, Subject } from 'rxjs';\n\n// suggested refactor\nconst tick$ = connectable(timer(1_000), {\n  connector: () => new Subject(),\n  resetOnDisconnect: false\n});\n```\n\nWhere [multicast](/api/operators/multicast) is used in conjunction with [refCount](/api/operators/refCount), it can be replaced with [share](/api/index/function/connectable).\n\n<!-- prettier-ignore -->\n```ts\nimport { timer, multicast, Subject, refCount } from 'rxjs';\n\n// deprecated\nconst tick$ = timer(1_000).pipe(\n  multicast(() => new Subject()),\n  refCount()\n);\n```\n\n<!-- prettier-ignore -->\n```ts\nimport { timer, share, Subject } from 'rxjs';\n\n// suggested refactor\nconst tick$ = timer(1_000).pipe(\n  share({ connector: () => new Subject() })\n);\n```\n\nWhere [multicast](/api/operators/multicast) is used with a selector, it can be replaced with [connect](/api/index/function/connect).\n\n<!-- prettier-ignore -->\n```ts\nimport { timer, multicast, Subject, combineLatest } from 'rxjs';\n\n// deprecated\nconst tick$ = timer(1_000).pipe(\n  multicast(\n    () => new Subject(),\n    (source) => combineLatest([source, source])\n  )\n);\n```\n\n<!-- prettier-ignore -->\n```ts\nimport { timer, connect, combineLatest, Subject } from 'rxjs';\n\n// suggested refactor\nconst tick$ = timer(1_000).pipe(\n  connect((source) => combineLatest([source, source]), {\n    connector: () => new Subject()\n  })\n);\n```\n\n### publish\n\nIf you're using [publish](/api/operators/publish) to create a [ConnectableObservable](/api/index/class/ConnectableObservable), you can use [connectable](/api/index/function/connectable) instead.\n\n<!-- prettier-ignore -->\n```ts\nimport { timer, publish, ConnectableObservable } from 'rxjs';\n\n// deprecated\nconst tick$ = timer(1_000).pipe(\n  publish()\n) as ConnectableObservable<number>;\n```\n\n<!-- prettier-ignore -->\n```ts\nimport { connectable, timer, Subject } from 'rxjs';\n\n// suggested refactor\nconst tick$ = connectable(timer(1_000), {\n  connector: () => new Subject<number>(),\n  resetOnDisconnect: false\n});\n```\n\nAnd if [refCount](/api/operators/refCount) is being applied to the result of [publish](/api/operators/publish), you can use [share](/api/operators/share) to replace both.\n\n<!-- prettier-ignore -->\n```ts\nimport { timer, publish, refCount } from 'rxjs';\n\n// deprecated\nconst tick$ = timer(1_000).pipe(\n  publish(),\n  refCount()\n);\n```\n\n<!-- prettier-ignore -->\n```ts\nimport { timer, share } from 'rxjs';\n\n// suggested refactor\nconst tick$ = timer(1_000).pipe(\n  share({\n    resetOnError: false,\n    resetOnComplete: false,\n    resetOnRefCountZero: false\n  })\n);\n```\n\nIf [publish](/api/operators/publish) is being called with a selector, you can use the [connect](/api/operators/connect) operator instead.\n\n<!-- prettier-ignore -->\n```ts\nimport { timer, publish, combineLatest } from 'rxjs';\n\n// deprecated\nconst tick$ = timer(1_000).pipe(\n  publish((source) => combineLatest([source, source]))\n);\n```\n\n<!-- prettier-ignore -->\n```ts\nimport { timer, connect, combineLatest } from 'rxjs';\n\n// suggested refactor\nconst tick$ = timer(1_000).pipe(\n  connect((source) => combineLatest([source, source]))\n);\n```\n\n### publishBehavior\n\nIf you're using [publishBehavior](/api/operators/publishBehavior) to create a [ConnectableObservable](/api/index/class/ConnectableObservable), you can use [connectable](/api/index/function/connectable) and a [BehaviorSubject](api/index/class/BehaviorSubject) instead.\n\n<!-- prettier-ignore -->\n```ts\nimport { timer, publishBehavior, ConnectableObservable } from 'rxjs';\n\n// deprecated\nconst tick$ = timer(1_000).pipe(\n  publishBehavior(0)\n) as ConnectableObservable<number>;\n```\n\n<!-- prettier-ignore -->\n```ts\nimport { connectable, timer, BehaviorSubject } from 'rxjs';\n\n// suggested refactor\nconst tick$ = connectable(timer(1_000), {\n  connector: () => new BehaviorSubject(0),\n  resetOnDisconnect: false\n});\n```\n\nAnd if [refCount](/api/operators/refCount) is being applied to the result of [publishBehavior](/api/operators/publishBehavior), you can use the [share](/api/operators/share) operator - with a [BehaviorSubject](api/index/class/BehaviorSubject) connector - to replace both.\n\n<!-- prettier-ignore -->\n```ts\nimport { timer, publishBehavior, refCount } from 'rxjs';\n\n// deprecated\nconst tick$ = timer(1_000).pipe(\n  publishBehavior(0),\n  refCount()\n);\n```\n\n<!-- prettier-ignore -->\n```ts\nimport { timer, share, BehaviorSubject } from 'rxjs';\n\n// suggested refactor\nconst tick$ = timer(1_000).pipe(\n  share({\n    connector: () => new BehaviorSubject(0),\n    resetOnError: false,\n    resetOnComplete: false,\n    resetOnRefCountZero: false\n  })\n);\n```\n\n### publishLast\n\nIf you're using [publishLast](/api/operators/publishLast) to create a [ConnectableObservable](/api/index/class/ConnectableObservable), you can use [connectable](/api/index/function/connectable) and an [AsyncSubject](api/index/class/AsyncSubject) instead.\n\n<!-- prettier-ignore -->\n```ts\nimport { timer, publishLast, ConnectableObservable } from 'rxjs';\n\n// deprecated\nconst tick$ = timer(1_000).pipe(\n  publishLast()\n) as ConnectableObservable<number>;\n```\n\n<!-- prettier-ignore -->\n```ts\nimport { connectable, timer, AsyncSubject } from 'rxjs';\n\n// suggested refactor\nconst tick$ = connectable(timer(1_000), {\n  connector: () => new AsyncSubject<number>(),\n  resetOnDisconnect: false\n});\n```\n\nAnd if [refCount](/api/operators/refCount) is being applied to the result of [publishLast](/api/operators/publishLast), you can use the [share](/api/operators/share) operator - with an [AsyncSubject](api/index/class/AsyncSubject) connector - to replace both.\n\n<!-- prettier-ignore -->\n```ts\nimport { timer, publishLast, refCount } from 'rxjs';\n\n// deprecated\nconst tick$ = timer(1_000).pipe(\n  publishLast(),\n  refCount()\n);\n```\n\n<!-- prettier-ignore -->\n```ts\nimport { timer, share, AsyncSubject } from 'rxjs';\n\n// suggested refactor\nconst tick$ = timer(1_000).pipe(\n  share({\n    connector: () => new AsyncSubject(),\n    resetOnError: false,\n    resetOnComplete: false,\n    resetOnRefCountZero: false\n  })\n);\n```\n\n### publishReplay\n\nIf you're using [publishReplay](/api/operators/publishReplay) to create a [ConnectableObservable](/api/index/class/ConnectableObservable), you can use [connectable](/api/index/function/connectable) and a [ReplaySubject](api/index/class/ReplaySubject) instead.\n\n<!-- prettier-ignore -->\n```ts\nimport { timer, publishReplay, ConnectableObservable } from 'rxjs';\n\n// deprecated\nconst tick$ = timer(1_000).pipe(\n  publishReplay(1)\n) as ConnectableObservable<number>;\n```\n\n<!-- prettier-ignore -->\n```ts\nimport { connectable, timer, ReplaySubject } from 'rxjs';\n\n// suggested refactor\nconst tick$ = connectable(timer(1_000), {\n  connector: () => new ReplaySubject<number>(1),\n  resetOnDisconnect: false\n});\n```\n\nAnd if [refCount](/api/operators/refCount) is being applied to the result of [publishReplay](/api/operators/publishReplay), you can use the [share](/api/operators/share) operator - with a [ReplaySubject](api/index/class/ReplaySubject) connector - to replace both.\n\n<!-- prettier-ignore -->\n```ts\nimport { timer, publishReplay, refCount } from 'rxjs';\n\n// deprecated\nconst tick$ = timer(1_000).pipe(\n  publishReplay(1),\n  refCount()\n);\n```\n\n<!-- prettier-ignore -->\n```ts\nimport { timer, share, ReplaySubject } from 'rxjs';\n\n// suggested refactor\nconst tick$ = timer(1_000).pipe(\n  share({\n    connector: () => new ReplaySubject(1),\n    resetOnError: false,\n    resetOnComplete: false,\n    resetOnRefCountZero: false\n  })\n);\n```\n\nIf [publishReplay](/api/operators/publishReplay) is being called with a selector, you can use the [connect](/api/operators/connect) operator - with a [ReplaySubject](api/index/class/ReplaySubject) connector - instead.\n\n<!-- prettier-ignore -->\n```ts\nimport { timer, publishReplay, combineLatest } from 'rxjs';\n\n// deprecated\nconst tick$ = timer(1_000).pipe(\n  publishReplay(1, undefined, (source) => combineLatest([source, source]))\n);\n```\n\n<!-- prettier-ignore -->\n```ts\nimport { timer, connect, combineLatest, ReplaySubject } from 'rxjs';\n\n// suggested refactor\nconst tick$ = timer(1_000).pipe(\n  connect((source) => combineLatest([source, source]), {\n    connector: () => new ReplaySubject(1)\n  })\n);\n```\n\n### refCount\n\nInstead of applying the [refCount](/api/operators/refCount) operator to the [ConnectableObservable](/api/index/class/ConnectableObservable) obtained from a [multicast](/api/operators/multicast)\nor [publish](/api/operators/publish) operator, use the [share](/api/operators/share) operator to replace both.\n\nThe properties passed to [share](/api/operators/share) will depend upon the operators that are being replaced. The refactors for using [refCount](/api/operators/refCount) with [multicast](/api/operators/multicast), [publish](/api/operators/publish), [publishBehavior](/api/operators/publishBehavior), [publishLast](/api/operators/publishLast) and [publishReplay](/api/operators/publishReplay) are detailed above.\n"
  },
  {
    "path": "apps/rxjs.dev/content/deprecations/resultSelector.md",
    "content": "# ResultSelector Parameter\n\nSome operator supported a resultSelector argument that acted as mapping function on the result of that operator.\nThe same behavior can be reproduced with the `map` operator, therefore this argument became deprecated.\n\n<div class=\"alert is-important\">\n    <span>\n        This deprecation was introduced in RxJS 6.0 and will become breaking with RxJS 8.\n    </span>\n</div>\n\nThere were two reasons for actually deprecating those parameters:\n\n1. It increases the bundle size of every operator\n2. In some scenarios values had to be retained in memory causing a general memory pressure\n\n## Operators affected by this Change\n\n- [concatMap](/api/operators/concatMap)\n- [concatMapTo](/api/operators/concatMapTo)\n- [exhaustMap](/api/operators/exhaustMap)\n- [mergeMap](/api/operators/mergeMap)\n- [mergeMapTo](/api/operators/mergeMapTo)\n- [switchMap](/api/operators/switchMap)\n- [switchMapTo](/api/operators/switchMapTo)\n\n## How to Refactor\n\nInstead of using the `resultSelector` Argument, you can leverage the [`map`](/api/operators/map) operator on the inner Observable:\n\n<!-- prettier-ignore -->\n```ts\nimport { fromEvent, switchMap, interval, map } from 'rxjs';\n\n// deprecated\nfromEvent(document, 'click').pipe(\n  switchMap((x) => interval(1000), (_, x) => x + 1)\n);\n// suggested change\nfromEvent(document, 'click').pipe(\n  switchMap((x) => interval(1000).pipe(map((x) => x + 1)))\n);\n```\n"
  },
  {
    "path": "apps/rxjs.dev/content/deprecations/scheduler-argument.md",
    "content": "# Scheduler Argument\n\nTo limit the API surface of some operators, but also prepare for a [major refactoring in V8](https://github.com/ReactiveX/rxjs/pull/4583), we\nagreed on deprecating the `scheduler` argument from many operators. It solely deprecates those methods where this argument is rarely used. So `time` related\noperators, like [`interval`](https://rxjs.dev/api/index/function/interval) are not affected by this deprecation.\n\nTo support this transition the [scheduled creation function](/api/index/function/scheduled) was added.\n\n<div class=\"alert is-important\">\n    <span>\n        This deprecation was introduced in RxJS 6.5 and will become breaking with RxJS 8.\n    </span>\n</div>\n\n## Operators affected by this Change\n\n- [from](/api/index/function/from)\n- [of](/api/index/function/of)\n- [merge](/api/index/function/merge)\n- [concat](/api/index/function/concat)\n- [startWith](/api/operators/startWith)\n- [endWith](/api/operators/endWith)\n- [combineLatest](/api/index/function/combineLatest)\n\n## How to Refactor\n\nIf you use any operator from the above list and you're passing the `scheduler` argument, you have three potential refactoring options.\n\n### Refactoring of `of` and `from`\n\n`scheduled` is kinda copying the behavior of `from`. Therefore if you used `from` with a `scheduler` argument, you can just replace them.\n\nFor the `of` creation function you need to replace this Observable with `scheduled` and instead of passing the `scheduler` argument to `of` pass it to `scheduled`.\nFollowing code example demonstrate this process.\n\n```ts\nimport { of, asyncScheduler, scheduled } from 'rxjs';\n\n// Deprecated approach\nof(1, 2, 3, asyncScheduler).subscribe((x) => console.log(x));\n// suggested approach\nscheduled([1, 2, 3], asyncScheduler).subscribe((x) => console.log(x));\n```\n\n### Refactoring of `merge`, `concat`, `combineLatest`, `startWith` and `endWith`\n\nIn case you used to pass a scheduler argument to one of these operators you probably had code like this:\n\n```ts\nimport { concat, of, asyncScheduler } from 'rxjs';\n\nconcat(of('hello '), of('World'), asyncScheduler).subscribe((x) => console.log(x));\n```\n\nTo work around this deprecation you can leverage the [`scheduled`](/api/index/function/scheduled) function.\n\n```ts\nimport { scheduled, of, asyncScheduler, concatAll } from 'rxjs';\n\nscheduled([of('hello '), of('World')], asyncScheduler)\n  .pipe(concatAll())\n  .subscribe((x) => console.log(x));\n```\n\nYou can apply this pattern to refactor deprecated usage of `concat`, `startWith` and `endWith` but do notice that you will want to use [mergeAll](/api/operators/mergeAll) to refactor the deprecated usage of `merge`.\n\nWith `combineLatest`, you will want to use [combineLatestAll](/api/operators/combineLatestAll)\n\nE.g. code that used to look like this:\n\n```ts\nimport { combineLatest, of, asyncScheduler } from 'rxjs';\n\ncombineLatest(of('hello '), of('World'), asyncScheduler).subscribe(console.log);\n```\n\nwould become:\n\n```ts\nimport { scheduled, of, asyncScheduler, combineLatestAll } from 'rxjs';\n\nscheduled([of('hello '), of('World')], asyncScheduler)\n  .pipe(combineLatestAll())\n  .subscribe((x) => console.log(x));\n```\n"
  },
  {
    "path": "apps/rxjs.dev/content/deprecations/subscribe-arguments.md",
    "content": "# Subscribe Arguments\n\nYou might have seen that we deprecated some signatures of the `subscribe` method, which might have caused some confusion.\nThe `subscribe` method itself is not deprecated. This deprecation also affects the [`tap` operator](../../api/operators/tap), as tap supports the same signature as the `subscribe` method.\n\nThis is to get ready for a future where we may allow configuration of `subscribe` via the second argument, for things like `AbortSignal` or the like (imagine `source$.subscribe(fn, { signal })`, etc). This deprecation is also because 2-3 function arguments can contribute to harder-to-read code. For example someone could name functions poorly and confuse the next reader: `source$.subscribe(doSomething, doSomethingElse, lol)` With that signature, you have to know unapparent details about `subscribe`, where using a partial observer solves that neatly: `source$.subscribe({ next: doSomething, error: doSomethingElse, complete: lol })`.\n\n<div class=\"alert is-important\">\n    <span>\n        This deprecation was introduced in RxJS 6.4.\n    </span>\n</div>\n\nIn short we deprecated all signatures where you specified an anonymous `error` or `complete` callback and passed an empty function to one of the callbacks before. \n\n## What Signature is affected\n\n**We have deprecated all signatures of `subscribe` that take more than 1 argument.** \n\nWe deprecated signatures for just passing the `complete` callback.\n\n```ts\nimport { of } from 'rxjs';\n\n// deprecated\nof([1,2,3]).subscribe(null, null, console.info); // difficult to read\n// suggested change\nof([1,2,3]).subscribe({complete: console.info});\n```\n\nSimilarly, we also deprecated signatures for solely passing the `error` callback.\n\n```ts\nimport { throwError } from 'rxjs';\n\n// deprecated \nthrowError('I am an error').subscribe(null, console.error);\n// suggested change\nthrowError('I am an error').subscribe({error: console.error});\n```\n\nDo notice, in general it is recommended only to use the anonymous function if you only specify the `next` callback otherwise\nwe recommend to pass an `Observer`\n\n```ts\nimport { of } from 'rxjs';\n\n// recommended \nof([1,2,3]).subscribe((v) => console.info(v));\n// also recommended\nof([1,2,3]).subscribe({\n    next: (v) => console.log(v),\n    error: (e) => console.error(e),\n    complete: () => console.info('complete') \n})\n```\n"
  },
  {
    "path": "apps/rxjs.dev/content/deprecations/to-promise.md",
    "content": "# Conversion to Promises\n\nThe similarity between Observables and Promises is that both [collections](/guide/observable) may produce values over\ntime, but the difference is that Observables may produce none or more than one value, while Promises produce only one\nvalue when resolved successfully.\n\n## Issues\n\nFor this reason, in RxJS 7, the return type of the Observable's [`toPromise()`](/api/index/class/Observable#toPromise)\nmethod has been fixed to better reflect the fact that Observables can yield zero values. This may be a **breaking\nchange** to some projects as the return type was changed from `Promise<T>` to `Promise<T | undefined>`.\n\nAlso, `toPromise()` method name was never indicating what emitted value a Promise will resolve with because Observables\ncan produce multiple values over time. When converting to a Promise, you might want to choose which value to pick -\neither the first value that has arrived or the last one. To fix all these issues, we decided to deprecate `toPromise()`,\nand to introduce the two new helper functions for conversion to Promises.\n\n## Use one of the two new functions\n\nAs a replacement to the deprecated `toPromise()` method, you should use one of the two built in static conversion\nfunctions {@link firstValueFrom} or {@link lastValueFrom}.\n\n### `lastValueFrom`\n\nThe `lastValueFrom` is almost exactly the same as `toPromise()` meaning that it will resolve with the last value that has\narrived when the Observable completes, but with the difference in behavior when Observable completes without emitting a\nsingle value. When Observable completes without emitting, `toPromise()` will successfully resolve with `undefined` (thus\nthe return type change), while the `lastValueFrom` will reject with the {@link EmptyError}. Thus, the return type of the\n`lastValueFrom` is `Promise<T>`, just like `toPromise()` had in RxJS 6.\n\n#### Example\n\n```ts\nimport { interval, take, lastValueFrom } from 'rxjs';\n\nasync function execute() {\n  const source$ = interval(2000).pipe(take(10));\n  const finalNumber = await lastValueFrom(source$);\n  console.log(`The final number is ${finalNumber}`);\n}\n\nexecute();\n\n// Expected output:\n// \"The final number is 9\"\n```\n\n### `firstValueFrom`\n\nHowever, you might want to take the first value as it arrives without waiting an Observable to complete, thus you can\nuse `firstValueFrom`. The `firstValueFrom` will resolve a Promise with the first value that was emitted from the\nObservable and will immediately unsubscribe to retain resources. The `firstValueFrom` will also reject with an\n{@link EmptyError} if the Observable completes with no values emitted.\n\n#### Example\n\n```ts\nimport { interval, firstValueFrom } from 'rxjs';\n\nasync function execute() {\n  const source$ = interval(2000);\n  const firstNumber = await firstValueFrom(source$);\n  console.log(`The first number is ${firstNumber}`);\n}\n\nexecute();\n\n// Expected output:\n// \"The first number is 0\"\n```\n\n<span class=\"informal\">Both functions will return a Promise that rejects if the source Observable errors. The Promise\nwill reject with the same error that the Observable has errored with.</span>\n\n## Use default value\n\nIf you don't want Promises created by `lastValueFrom` or `firstValueFrom` to reject with {@link EmptyError} if there\nwere no emissions before completion, you can use the second parameter. The second parameter is expected to be an object\nwith `defaultValue` parameter. The value in the `defaultValue` will be used to resolve a Promise when source Observable\ncompletes without emitted values.\n\n```ts\nimport { firstValueFrom, EMPTY } from 'rxjs';\n\nconst result = await firstValueFrom(EMPTY, { defaultValue: 0 });\nconsole.log(result);\n\n// Expected output:\n// 0\n```\n\n## Warning\n\nOnly use `lastValueFrom` function if you _know_ an Observable will eventually complete. The `firstValueFrom` function should\nbe used if you _know_ an Observable will emit at least one value _or_ will eventually complete. If the source Observable\ndoes not complete or emit, you will end up with a Promise that is hung up, and potentially all of the state of an async\nfunction hanging out in memory. To avoid this situation, look into adding something like {@link timeout}, {@link take},\n{@link takeWhile}, or {@link takeUntil} amongst others.\n"
  },
  {
    "path": "apps/rxjs.dev/content/file-not-found.md",
    "content": "@description\n\n<div class=\"nf-container l-flex-wrap flex-center\">\n    <img src=\"assets/images/support/rxjs-404.png\" width=\"300\" height=\"300\"/>\n    <div class=\"nf-response l-flex-wrap\">\n        <h1 class=\"no-toc\">Page Not Found</h1>\n        <p>We're sorry. The page you are looking for cannot be found.</p>\n    </div>\n</div>\n"
  },
  {
    "path": "apps/rxjs.dev/content/guide/core-semantics.md",
    "content": "# RxJS Core Semantics\n\nStarting in version 8, all RxJS operators that are provided in the core library MUST meet the following semantics. In the current version, version 7, all operators SHOULD meet the following semantics (as guidelines). If they do not, we need to track the issue on [GitHub](https://github.com/ReactiveX/rxjs/issues).\n\n## Purpose\n\nThe purpose of these semantics is provide predictable behavior for the users of our library, and to ensure consistent behavior between our many different operators. It should be noted that at the time of this writing, we don't always adhere to these semantic guidelines. This document is to serve as a goalpost for upcoming changes and work as much as it is to help describe the library. This is also a \"living document\" and is subject to change.\n\n## General Design Guidelines\n\n**Functions such as operators, constructors, and creation functions, should use named parameters in cases where there is more than 1 argument, and arguments after the first are non-obvious.** The primary use case should be streamlined to work without configuration. For example, `fakeFlattenMap(n => of(n))` is fine, but `fakeFlattenMap(n => of(n), 1)` is less readable than `fakeFlattenMap(n => of(n), { maxConcurrent: 1 })`. Other things, like `of(1, 2, 3)` are obvious enough that named parameters don't make sense.\n\n## Operators\n\n- MUST be a function that returns an [operator function](https://rxjs.dev/api/index/interface/OperatorFunction). That is `(source: Observable<In>) => Observable<Out>`.\n- The returned operator function MUST be [referentially transparent](https://en.wikipedia.org/wiki/Referential_transparency). That is to say, that if you capture the return value of the operator (e.g. `const double => map(x => x + x)`), you can use that value to operate on any many observables as you like without changing any underlying state in the operator reference. (e.g. `a$.pipe(double)` and `b$.pipe(double)`).\n- The observable returned by the operator function MUST subscribe to the source.\n- If the operation performed by the operator can tell it not change anything about the output of the source, it MUST return the reference to the source. For example `take(Infinity)` or `skip(0)`.\n- Operators that accept a \"notifier\", that is another observable source that is used to trigger some behavior, must accept any type that can be converted to an `Observable` with `from`. For example `takeUntil`.\n- Operators that accept \"notifiers\" (as described above), MUST ONLY recognized next values from the notifier as \"notifications\". Emitted completions may not be used a source of notification.\n- \"Notifiers\" provided directly to the operator MUST be subscribed to _before_ the source is subscribed to. \"Notifiers\" created via factory function provided to the operator SHOULD be subscribed to at the earliest possible moment.\n- The observable returned by the operator function is considered to be the \"consumer\" of the source. As such, the consumer MUST unsubscribe from the source as soon as it knows it no longer needs values before proceeding to do _any_ action.\n- Events that happen after the completion of a source SHOULD happen after the source finalizes. This is to ensure that finalization always happens in a predictable time frame relative to the event.\n- `Error` objects MUST NOT be retained longer than necessary. This is a possible source of memory pressure.\n- `Promise` references MUST NOT be retained longer than necessary. This is a possible source of memory pressure.\n- IF they perform a related operation to a creation function, they SHOULD share the creation function's name only with the suffix `With`. (e.g. `concat` and `concatWith`).\n- SHOULD NOT have \"result selectors\". This is a secondary argument that provides the ability to \"map\" values after performing the primary operation of the operator.\n\n## Creation Functions\n\n- Names MUST NOT end in `With`. That is reserved for the operator counter parts of creation functions.\n- MAY have \"result selectors\". This is a secondary argument that provides the ability to \"map\" values before they're emitted from the resulting observable.\n- IF the creation function accepts a \"result selector\", it must not accept \"n-arguments\" ahead of that result selector. Instead, it should accept an array or possibly an object. (bad: `combineThings(sourceA$, sourceB$, (a, b) => a + b)`, good: `combineThings([sourceA$, sourceB$], (a, b) => a + b)`. In this case, it may be okay to provide the result selector as a second argument, rather than as a named parameter, as the use should be fairly obvious.\n"
  },
  {
    "path": "apps/rxjs.dev/content/guide/glossary-and-semantics.md",
    "content": "# RxJS: Glossary And Semantics\n\nWhen discussing and documenting observables, it's important to have a common language and a known set of rules around what is going on. This document is an attempt to standardize these things so we can try to control the language in our docs, and hopefully other publications about RxJS, so we can discuss reactive programming with RxJS on consistent terms.\n\nWhile not all of the documentation for RxJS reflects this terminology, it is a goal of the team to ensure it does, and to ensure the language and names around the library use this document as a source of truth and unified language.\n\n## Major Entities\n\nThere are high level entities that are frequently discussed. It's important to define them separately from other lower-level concepts, because they relate to the nature of observable.\n\n### Consumer\n\nThe code that is subscribing to the observable. This is whoever is being _notified_ of [nexted](#next) values, and [errors](#error) or [completions](#complete).\n\n### Producer\n\nAny system or thing that is the source of values that are being pushed out of the observable subscription to the consumer. This can be a wide variety of things, from a `WebSocket` to a simple iteration over an `Array`. The producer is most often created during the [subscribe](#subscribe) action, and therefor \"owned\" by a [subscription](#subscription) in a 1:1 way, but that is not always the case. A producer may be shared between many subscriptions, if it is created outside of the [subscribe](#subscribe) action, in which case it is one-to-many, resulting in a [multicast](#multicast).\n\n### Subscription\n\nA contract where a [consumer](#consumer) is [observing](#observation) values pushed by a [producer](#producer). The subscription (not to be confused with the `Subscription` class or type), is an ongoing process that amounts to the function of the observable from the Consumer's perspective. Subscription starts the moment a [subscribe](#subscribe) action is initiated, even before the [subscribe](#subscribe) action is finished.\n\n### Observable\n\nThe primary type in RxJS. At its highest level, an observable represents a template for connecting an [Observer](#observer), as a [consumer](#consumer), to a [producer](#producer), via a [subscribe](#subscribe) action, resulting in a [subscription](#subscription).\n\n### Observer\n\nThe manifestation of a [consumer](#consumer). A type that may have some (or all) handlers for each type of [notification](#notification): [next](#next), [error](#error), and [complete](#complete). Having all three types of handlers generally gets this to be called an \"observer\", where if it is missing any of the notification handlers, it may be called a [\"partial observer\"](#partial-observer).\n\n## Major Actions\n\nThere are specific actions and events that occur between major entities in RxJS that need to be defined. These major actions are the highest level events that occur within various parts in RxJS.\n\n### Subscribe\n\nThe act of a [consumer](#consumer) requesting from an Observable to set up a [subscription](#subscription) so that it may [observe](#observation) a [producer](#producer). A subscribe action can occur with an observable via many different mechanisms. The primary mechanism is the [`subscribe` method](/api/index/class/Observable#subscribe) on the [Observable class](/api/index/class/Observable). Other mechanisms include the [`forEach` method](/api/index/class/Observable#forEach), functions like [`lastValueFrom`](/api/index/function/lastValueFrom), and [`firstValueFrom`](/api/index/function/firstValueFrom), and the deprecated [`toPromise` method](/api/index/class/Observable#forEach).\n\n### Finalization\n\nThe act of cleaning up resources used by a producer. This is guaranteed to happen on `error`, `complete`, or if unsubscription occurs. This is not to be confused with [unsubscription](#unsubscription), but it does always happen during unsubscription.\n\n### Unsubscription\n\nThe act of a [consumer](#consumer) telling a [producer](#producer) is no longer interested in receiving values. Causes [Finalization](#finalization)\n\n### Observation\n\nA [consumer](#consumer) reacting to [next](#next), [error](#error), or [complete](#complete) [notifications](#notification). This can only happen _during_ [subscription](#subscription).\n\n### Observation Chain\n\nWhen an [observable](#observable) uses another [observable](#observable) as a [producer](#producer), an \"observation chain\" is set up. That is a chain of [observation](#observation) such that multiple [observers](#observer) are [notifying](#notification) each other in a unidirectional way toward the final [consumer](#consumer).\n\n### Next\n\nA value has been pushed to the [consumer](#consumer) to be [observed](#observation). Will only happen during [subscription](#subscription), and cannot happen after [error](#error), [complete](#error), or [unsubscription](#unsubscription). Logically, this also means it cannot happen after [finalization](#finalization).\n\n### Error\n\nThe [producer](#producer) has encountered a problem and is notifying the [consumer](#consumer). This is a notification that the [producer](#producer) will no longer send values and will [finalize](#finalization). This cannot occur after [complete](#complete), any other [error](#error), or [unsubscription](#unsubscription). Logically, this also means it cannot happen after [finalization](#finalization).\n\n### Complete\n\nThe [producer](#producer) is notifying the [consumer](#consumer) that it is done [nexting](#Next) values, without error, will send no more values, and it will [finalize](#finalization). [Completion](#complete) cannot occur after an [error](#error), or [unsubscribe](#unsubscription). [Complete](#complete) cannot be called twice. [Complete](#complete), if it occurs, will always happen before [finalization](#finalization).\n\n### Notification\n\nThe act of a [producer](#producer) pushing [nexted](#next) values, [errors](#error) or [completions](#complete) to a [consumer](#consumer) to be [observed](#observation). Not to be confused with the [`Notification` type](/api/index/class/Notification), which is notification manifested as a JavaScript object.\n\n## Major Concepts\n\nSome of what we discuss is conceptual. These are mostly common traits of behaviors that can manifest in observables or in push-based reactive systems.\n\n### Multicast\n\nThe act of one [producer](#producer) being [observed](#observation) by **many** [consumers](#consumer).\n\n### Unicast\n\nThe act of one [producer](#producer) being [observed](#observation) by **only one** [consumer](#consumer). An observable is \"unicast\" when it only connects one [producer](#producer) to one [consumer](#consumer). Unicast doesn't necessarily mean [\"cold\"](#cold).\n\n### Cold\n\nAn observable is \"cold\" when it creates a new [producer](#producer) during [subscribe](#subscribe) for every new [subscription](#subscription). As a result, \"cold\" observables are _always_ [unicast](#unicast), being one [producer](#producer) [observed](#observation) by one [consumer](#consumer). Cold observables can be made [hot](#hot) but not the other way around.\n\n### Hot\n\nAn observable is \"hot\", when its [producer](#producer) was created outside of the context of the [subscribe](#subscribe) action. This means that the \"hot\" observable is almost always [multicast](#multicast). It is possible that a \"hot\" observable is still _technically_ unicast, if it is engineered to only allow one [subscription](#subscription) at a time, however, there is no straightforward mechanism for this in RxJS, and the scenario is an unlikely one. For the purposes of discussion, all \"hot\" observables can be assumed to be [multicast](#multicast). Hot observables cannot be made [cold](#cold).\n\n### Push\n\n[Observables](#observable) are a push-based type. That means rather than having the [consumer](#consumer) call a function or perform some other action to get a value, the [consumer](#consumer) receives values as soon as the [producer](#producer) has produced them, via a registered [next](#next) handler.\n\n### Pull\n\nPull-based systems are the opposite of [push](#push)-based. In a pull-based type or system, the [consumer](#consumer) must request each value the [producer](#producer) has produced manually, perhaps long after the [producer](#producer) has actually done so. Examples of such systems are [Functions](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function) and [Iterators](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Iteration_protocols)\n\n## Minor Entities\n\n### Operator\n\nA factory function that creates an [operator function](#operator-function). Examples of this in rxjs are functions like [`map`](/api/operators/map) and [`mergeMap`](/api/operators/mergeMap), which are generally passed to [`pipe`](/api/index/class/Observable#pipe). The result of calling many operators, and passing their resulting [operator functions](#operator-function) into pipe on an observable [source](#source) will be another [observable](#observable), and will generally not result in [subscription](#subscription).\n\n### Operator Function\n\nA function that takes an [observable](#observable), and maps it to a new [observable](#observable). Nothing more, nothing less. Operator functions are created by [operators](#operator). If you were to call an rxjs operator like [map](/api/operators/map) and put the return value in a variable, the returned value would be an operator function.\n\n### Operation\n\nAn action taken while handling a [notification](#notification), as set up by an [operator](#operator) and/or [operator function](#operator-function). In RxJS, a developer can chain several [operator functions](#operator-function) together by calling [operators](#operator) and passing the created [operator functions](#operator-function) to the [`pipe`](/api/index/class/Observable#pipe) method of [`Observable`](/api/index/class/Observable), which results in a new [observable](#observable). During [subscription](#subscription) to that observable, operations are performed in an order dictated by the [observation chain](#observation-chain).\n\n### Stream\n\nA \"stream\" or \"streaming\" in the case of observables, refers to the collection of [operations](#operation), as they are processed during a [subscription](#subscription). This is not to be confused with node [Streams](https://nodejs.org/api/stream.html), and the word \"stream\", on its own, should be used _sparingly_ in documentation and articles. Instead, prefer [observation chain](#observation-chain), [operations](#operation), or [subscription](#subscription). \"Streaming\" is less ambiguous, and is fine to use given this defined meaning.\n\n### Source\n\nAn [observable](#observable) or [valid observable input](#observable-inputs) having been converted to an observable, that will supply values to another [observable](#observable), either as the result of an [operator](#operator) or other function that creates one observable as another. This [source](#source), will be the [producer](#producer) for the resulting [observable](#observable) and all of its [subscriptions](#subscriptions). Sources may generally be any type of observable.\n\n### Observable Inputs\n\nAn \"observable input\" ([defined as a type here](/api/index/type-alias/ObservableInput)), is any type that can be easily converted to an [Observable](#observable). Observable Inputs may sometimes be referred to as \"valid observable sources\".\n\n### Notifier\n\nAn [observable](#observable) that is being used to notify another [observable](#observable) that it needs to perform some action. The action should only occur on a [next notification](#next), and never on [error](#error) or [complete](#complete). Generally, notifiers are used with specific operators, such as [`takeUntil`](/api/operators/takeUntil), [`buffer`](/api/operators/buffer), or [`delayWhen`](/api/operators/delayWhen). A notifier may be passed directly, or it may be returned by a callback.\n\n### Inner Source\n\nOne, of possibly many [sources](#source), which are [subscribed](#subscribe) to automatically within a single [subscription](#subscription) to another observable. Examples of an \"inner source\" include the [observable inputs](#observable-inputs) returned by the mapping function in a [mergeMap](/api/operators/mergeMap) [operator](#operator). (e.g. `source.pipe(mergeMap(value => createInnerSource(value)))`, where `createInnerSource` returns any valid [observable input](#observable-inputs)).\n\n### Partial Observer\n\nAn [observer](#observer) that lacks all necessary [notification](#notification) handlers. Generally these are supplied by user-land [consumer](#consumer) code. A \"full observer\" or \"observer\" would simply be an observer that has all [notification](#notification) handlers.\n\n## Other Concepts\n\n### Unhandled Errors\n\nAn \"unhandled error\" is any [error](#error) that is not handled by a [consumer](#consumer)-provided function, which is generally provided during the [subscribe](#subscribe) action. If no error handler was provided, RxJS will assume the error is \"unhandled\" and rethrow the error on a new callstack to prevent [\"producer interference\"](#producer-interference).\n\n### Producer Interference\n\n[Producer](#producer) interference happens when an error is allowed to unwind the RxJS callstack during [notification](#notification). When this happens, the error could break things like for-loops in [upstream](#upstream-and-downstream) [sources](#source) that are [notifying](#notification) [consumers](#consumer) during a [multicast](#multicast). That would cause the other [consumers](#consumer) in that [multicast](#multicast) to suddenly stop receiving values without logical explanation. As of version 6, RxJS goes out of its way to prevent producer interference by ensuring that all unhandled errors are thrown on a separate callstack.\n\n### Upstream And Downstream\n\nThe order in which [notifications](#notification) are processed by [operations](#operation) in a [stream](#stream) have a directionality to them. \"Upstream\" refers to an [operation](#operation) that was already processed before the current [operation](#operation), and \"downstream\" refers to an [operation](#operation) that _will_ be processed _after_ the current [operation](#operation). See also: [Streaming](#stream).\n"
  },
  {
    "path": "apps/rxjs.dev/content/guide/higher-order-observables.md",
    "content": "# Higher-order Observables\n\nObservables most commonly emit ordinary values like strings and numbers, but surprisingly often, it is necessary to handle Observables *of* Observables, so-called higher-order Observables. For example, imagine you have an Observable emitting strings that are the URLs of files you want to fetch. The code might look like this:\n\n```ts\nconst fileObservable = urlObservable.pipe(\n   map(url => http.get(url)),\n);\n```\n\n`http.get()` returns an Observable for each URL. Now you have an Observable *of* Observables, a higher-order Observable.\n\nBut how do you work with a higher-order Observable? Typically, by _flattening_: by converting a higher-order Observable into an ordinary Observable. For example:\n\n```ts\nconst fileObservable = urlObservable.pipe(\n   concatMap(url => http.get(url)),\n);\n```\n\nThe Observable returned in the `concatMap` function is usually referred to as a so-called \"inner\" Observable, while in this context the `urlObservable` is the so-called \"outer\" Observable.\n\nThe [`concatMap()`](/api/operators/concatMap) operator subscribes to each \"inner\" Observable, buffers all further emissions of the \"outer\" Observable, and copies all the emitted values until the inner Observable completes, and continues processing the values of the \"outer Observable\". All of the values are in that way concatenated.  Other useful flattening operators are\n\n* [`mergeMap()`](/api/operators/mergeMap) — subscribes to each inner Observable as it arrives, then emits each value as it arrives\n* [`switchMap()`](/api/operators/switchMap) — subscribes to the first inner Observable when it arrives, and emits each value as it arrives, but when the next inner Observable arrives, unsubscribes to the previous one, and subscribes to the new one.\n* [`exhaustMap()`](/api/operators/exhaustMap) — subscribes to the first inner Observable when it arrives, and emits each value as it arrives, discarding all newly arriving inner Observables until that first one completes, then waits for the next inner Observable.\n\n"
  },
  {
    "path": "apps/rxjs.dev/content/guide/importing.md",
    "content": "# Importing instructions\n\nThere are different ways you can {@link guide/installation install} RxJS. Using/importing RxJS depends on\nthe used RxJS version, but also depends on the used installation method.\n\n[Pipeable operators](https://v6.rxjs.dev/guide/v6/pipeable-operators) were introduced in RxJS version\n5.5. This enabled all operators to be exported from a single place. This new export site was introduced\nwith RxJS version 6 where all pipeable operators could have been imported from `'rxjs/operators'`. For\nexample, `import { map } from 'rxjs/operators'`.\n\n## New in RxJS v7.2.0\n\n<span class=\"informal\">**With RxJS v7.2.0, most operators have been moved to `{@link api#index 'rxjs'}`\nexport site. This means that the preferred way to import operators is from `'rxjs'`, while\n`'rxjs/operators'` export site has been deprecated.**</span>\n\nFor example, instead of using:\n\n```ts\nimport { map } from 'rxjs/operators';\n```\n\n**the preferred way** is to use:\n\n```ts\nimport { map } from 'rxjs';\n```\n\nAlthough the old way of importing operators is still active, it will be removed in one of the next major\nversions.\n\nClick {@link #how-to-migrate here to see} how to migrate.\n\n## Export sites\n\nRxJS v7 exports 6 different locations out of which you can import what you need. Those are:\n\n- `{@link api#index 'rxjs'}` - for example: `import { of } from 'rxjs';`\n- `{@link api#operators 'rxjs/operators'}` - for example: `import { map } from 'rxjs/operators';`\n- `{@link api#ajax 'rxjs/ajax'}` - for example: `import { ajax } from 'rxjs/ajax';`\n- `{@link api#fetch 'rxjs/fetch'}` - for example: `import { fromFetch } from 'rxjs/fetch';`\n- `{@link api#webSocket 'rxjs/webSocket'}` - for example: `import { webSocket } from 'rxjs/webSocket';`\n- `{@link api#testing 'rxjs/testing'}` - for example: `import { TestScheduler } from 'rxjs/testing';`\n\n### How to migrate?\n\nWhile nothing has been removed from `'rxjs/operators'`, it is strongly recommended doing the operator\nimports from `'rxjs'`. Almost all operator function exports have been moved to `'rxjs'`, but only a\ncouple of old and deprecated operators have stayed in the `'rxjs/operators'`. Those operator functions\nare now mostly deprecated and most of them have their either static operator substitution or are kept as\noperators, but have a new name so that they are different to their static creation counter-part (usually\nending with `With`). Those are:\n\n| `'rxjs/operators'` Operator                             | Replace With Static Creation Operator | Replace With New Operator Name |\n| ------------------------------------------------------- | ------------------------------------- | ------------------------------ |\n| [`combineLatest`](/api/operators/combineLatest)         | {@link combineLatest}                 | {@link combineLatestWith}      |\n| [`concat`](/api/operators/concat)                       | {@link concat}                        | {@link concatWith}             |\n| [`merge`](/api/operators/merge)                         | {@link merge}                         | {@link mergeWith}              |\n| [`onErrorResumeNext`](/api/operators/onErrorResumeNext) | {@link onErrorResumeNext}             | {@link onErrorResumeNextWith}  |\n| [`race`](/api/operators/race)                           | {@link race}                          | {@link raceWith}               |\n| [`zip`](/api/operators/zip)                             | {@link zip}                           | {@link zipWith}                |\n\n`partition`, the operator, is a special case, as it is deprecated and you should be using the `partition` creation function exported from `'rxjs'` instead.\n\nFor example, the old and deprecated way of using [`merge`](/api/operators/merge) from `'rxjs/operators'`\nis:\n\n```ts\nimport { merge } from 'rxjs/operators';\n\na$.pipe(merge(b$)).subscribe();\n```\n\nBut this should be avoided and replaced with one of the next two examples.\n\nFor example, this could be replaced by using a static creation {@link merge} function:\n\n```ts\nimport { merge } from 'rxjs';\n\nmerge(a$, b$).subscribe();\n```\n\nOr it could be written using a pipeable {@link mergeWith} operator:\n\n```ts\nimport { mergeWith } from 'rxjs';\n\na$.pipe(mergeWith(b$)).subscribe();\n```\n\nDepending on the preferred style, you can choose which one to follow, they are completely equal.\n\nSince a new way of importing operators is introduced with RxJS v7.2.0, instructions will be split to\nprior and after this version.\n\n### ES6 via npm\n\nIf you've installed RxJS using {@link guide/installation#es6-via-npm ES6 via npm} and installed version\nis:\n\n#### v7.2.0 or later\n\nImport only what you need:\n\n```ts\nimport { of, map } from 'rxjs';\n\nof(1, 2, 3).pipe(map((x) => x + '!!!')); // etc\n```\n\nTo import the entire set of functionality:\n\n```ts\nimport * as rxjs from 'rxjs';\n\nrxjs.of(1, 2, 3).pipe(rxjs.map((x) => x + '!!!')); // etc;\n```\n\nTo use with a globally imported bundle:\n\n```js\nconst { of, map } = rxjs;\n\nof(1, 2, 3).pipe(map((x) => x + '!!!')); // etc\n```\n\nIf you installed RxJS version:\n\n#### v7.1.0 or older\n\nImport only what you need:\n\n```ts\nimport { of } from 'rxjs';\nimport { map } from 'rxjs/operators';\n\nof(1, 2, 3).pipe(map((x) => x + '!!!')); // etc\n```\n\nTo import the entire set of functionality:\n\n```ts\nimport * as rxjs from 'rxjs';\nimport * as operators from 'rxjs';\n\nrxjs.of(1, 2, 3).pipe(operators.map((x) => x + '!!!')); // etc;\n```\n\nTo use with a globally imported bundle:\n\n```js\nconst { of } = rxjs;\nconst { map } = rxjs.operators;\n\nof(1, 2, 3).pipe(map((x) => x + '!!!')); // etc\n```\n\n### CDN\n\nIf you installed a library {@link guide/installation#cdn using CDN}, the global namespace for rxjs is\n`rxjs`.\n\n#### v7.2.0 or later\n\n```js\nconst { range, filter, map } = rxjs;\n\nrange(1, 200)\n  .pipe(\n    filter((x) => x % 2 === 1),\n    map((x) => x + x)\n  )\n  .subscribe((x) => console.log(x));\n```\n\n#### v7.1.0 or older\n\n```js\nconst { range } = rxjs;\nconst { filter, map } = rxjs.operators;\n\nrange(1, 200)\n  .pipe(\n    filter((x) => x % 2 === 1),\n    map((x) => x + x)\n  )\n  .subscribe((x) => console.log(x));\n```\n"
  },
  {
    "path": "apps/rxjs.dev/content/guide/installation.md",
    "content": "# Installation Instructions\n\nHere are different ways you can install RxJS:\n\n## ES2015 via npm\n\n```shell\nnpm install rxjs\n```\n\nBy default, RxJS 7.x will provide different variants of the code based on the consumer:\n\n- When RxJS 7.x is used on Node.js regardless of whether it is consumed via `require` or `import`, CommonJS code targeting ES5 will be provided for execution.\n- When RxJS 7.4+ is used via a bundler targeting a browser (or other non-Node.js platform) ES module code targeting ES5 will be provided by default with the option to use ES2015 code.\n  7.x versions prior to 7.4.0 will only provide ES5 code.\n\nIf the target browsers for a project support ES2015+ or the bundle process supports down-leveling to ES5 then the bundler can optionally be configured to allow the ES2015 RxJS code to be used instead.\nYou can enable support for using the ES2015 RxJS code by configuring a bundler to use the `es2015` custom export condition during module resolution.\nConfiguring a bundler to use the `es2015` custom export condition is specific to each bundler.\nIf you are interested in using this option, please consult the documentation of your bundler for additional information.\nHowever, some general information can be found here:\n\n- https://webpack.js.org/guides/package-exports/#conditions-custom\n- https://github.com/rollup/plugins/blob/node-resolve-v11.0.0/packages/node-resolve/README.md#exportconditions\n\nTo import only what you need, please {@link guide/importing#es6-via-npm check out this} guide.\n\n## CommonJS via npm\n\nIf you receive an error like error TS2304: Cannot find name 'Promise' or error TS2304: Cannot find name\n'Iterable' when using RxJS you may need to install a supplemental set of typings.\n\n1.  For typings users:\n\n```shell\ntypings install es6-shim --ambient\n```\n\n2.  If you're not using typings the interfaces can be copied from /es6-shim/es6-shim.d.ts.\n\n3.  Add type definition file included in tsconfig.json or CLI argument.\n\n## All Module Types (CJS/ES6/AMD/TypeScript) via npm\n\nTo install this library via npm version 3, use the following command:\n\n```shell\nnpm install @reactivex/rxjs\n```\n\nIf you are using npm version 2, you need to specify the library version explicitly:\n\n```shell\nnpm install @reactivex/rxjs@7.3.0\n```\n"
  },
  {
    "path": "apps/rxjs.dev/content/guide/observable.md",
    "content": "# Observable\n\nObservables are lazy Push collections of multiple values. They fill the missing spot in the following table:\n\n|          | Single                                                                                                | Multiple                                                                                            |\n| -------- | ----------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------- |\n| **Pull** | [`Function`](https://developer.mozilla.org/en-US/docs/Glossary/Function)                              | [`Iterator`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Iteration_protocols) |\n| **Push** | [`Promise`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise) | [`Observable`](/api/index/class/Observable)                                                         |\n\n**Example.** The following is an Observable that pushes the values `1`, `2`, `3` immediately (synchronously) when subscribed, and the value `4` after one second has passed since the subscribe call, then completes:\n\n```ts\nimport { Observable } from 'rxjs';\n\nconst observable = new Observable((subscriber) => {\n  subscriber.next(1);\n  subscriber.next(2);\n  subscriber.next(3);\n  setTimeout(() => {\n    subscriber.next(4);\n    subscriber.complete();\n  }, 1000);\n});\n```\n\nTo invoke the Observable and see these values, we need to _subscribe_ to it:\n\n```ts\nimport { Observable } from 'rxjs';\n\nconst observable = new Observable((subscriber) => {\n  subscriber.next(1);\n  subscriber.next(2);\n  subscriber.next(3);\n  setTimeout(() => {\n    subscriber.next(4);\n    subscriber.complete();\n  }, 1000);\n});\n\nconsole.log('just before subscribe');\nobservable.subscribe({\n  next(x) {\n    console.log('got value ' + x);\n  },\n  error(err) {\n    console.error('something wrong occurred: ' + err);\n  },\n  complete() {\n    console.log('done');\n  },\n});\nconsole.log('just after subscribe');\n```\n\nWhich executes as such on the console:\n\n```none\njust before subscribe\ngot value 1\ngot value 2\ngot value 3\njust after subscribe\ngot value 4\ndone\n```\n\n## Pull versus Push\n\n_Pull_ and _Push_ are two different protocols that describe how a data _Producer_ can communicate with a data _Consumer_.\n\n**What is Pull?** In Pull systems, the Consumer determines when it receives data from the data Producer. The Producer itself is unaware of when the data will be delivered to the Consumer.\n\nEvery JavaScript Function is a Pull system. The function is a Producer of data, and the code that calls the function is consuming it by \"pulling\" out a _single_ return value from its call.\n\nES2015 introduced [generator functions and iterators](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function*) (`function*`), another type of Pull system. Code that calls `iterator.next()` is the Consumer, \"pulling\" out _multiple_ values from the iterator (the Producer).\n\n|          | Producer                                   | Consumer                                    |\n| -------- | ------------------------------------------ | ------------------------------------------- |\n| **Pull** | **Passive:** produces data when requested. | **Active:** decides when data is requested. |\n| **Push** | **Active:** produces data at its own pace. | **Passive:** reacts to received data.       |\n\n**What is Push?** In Push systems, the Producer determines when to send data to the Consumer. The Consumer is unaware of when it will receive that data.\n\nPromises are the most common type of Push system in JavaScript today. A Promise (the Producer) delivers a resolved value to registered callbacks (the Consumers), but unlike functions, it is the Promise which is in charge of determining precisely when that value is \"pushed\" to the callbacks.\n\nRxJS introduces Observables, a new Push system for JavaScript. An Observable is a Producer of multiple values, \"pushing\" them to Observers (Consumers).\n\n- A **Function** is a lazily evaluated computation that synchronously returns a single value on invocation.\n- A **generator** is a lazily evaluated computation that synchronously returns zero to (potentially) infinite values on iteration.\n- A **Promise** is a computation that may (or may not) eventually return a single value.\n- An **Observable** is a lazily evaluated computation that can synchronously or asynchronously return zero to (potentially) infinite values from the time it's invoked onwards.\n\n<span class=\"informal\">For more info about what to use when converting Observables to Promises, please refer to [this guide](/deprecations/to-promise).</span>\n\n## Observables as generalizations of functions\n\nContrary to popular claims, Observables are not like EventEmitters nor are they like Promises for multiple values. Observables _may act_ like EventEmitters in some cases, namely when they are multicasted using RxJS Subjects, but usually they don't act like EventEmitters.\n\n<span class=\"informal\">Observables are like functions with zero arguments, but generalize those to allow multiple values.</span>\n\nConsider the following:\n\n```ts\nfunction foo() {\n  console.log('Hello');\n  return 42;\n}\n\nconst x = foo.call(); // same as foo()\nconsole.log(x);\nconst y = foo.call(); // same as foo()\nconsole.log(y);\n```\n\nWe expect to see as output:\n\n```none\n\"Hello\"\n42\n\"Hello\"\n42\n```\n\nYou can write the same behavior above, but with Observables:\n\n```ts\nimport { Observable } from 'rxjs';\n\nconst foo = new Observable((subscriber) => {\n  console.log('Hello');\n  subscriber.next(42);\n});\n\nfoo.subscribe((x) => {\n  console.log(x);\n});\nfoo.subscribe((y) => {\n  console.log(y);\n});\n```\n\nAnd the output is the same:\n\n```none\n\"Hello\"\n42\n\"Hello\"\n42\n```\n\nThis happens because both functions and Observables are lazy computations. If you don't call the function, the `console.log('Hello')` won't happen. Also with Observables, if you don't \"call\" it (with `subscribe`), the `console.log('Hello')` won't happen. Plus, \"calling\" or \"subscribing\" is an isolated operation: two function calls trigger two separate side effects, and two Observable subscribes trigger two separate side effects. As opposed to EventEmitters which share the side effects and have eager execution regardless of the existence of subscribers, Observables have no shared execution and are lazy.\n\n<span class=\"informal\">Subscribing to an Observable is analogous to calling a Function.</span>\n\nSome people claim that Observables are asynchronous. That is not true. If you surround a function call with logs, like this:\n\n```ts\nconsole.log('before');\nconsole.log(foo.call());\nconsole.log('after');\n```\n\nYou will see the output:\n\n```none\n\"before\"\n\"Hello\"\n42\n\"after\"\n```\n\nAnd this is the same behavior with Observables:\n\n```ts\nconsole.log('before');\nfoo.subscribe((x) => {\n  console.log(x);\n});\nconsole.log('after');\n```\n\nAnd the output is:\n\n```none\n\"before\"\n\"Hello\"\n42\n\"after\"\n```\n\nWhich proves the subscription of `foo` was entirely synchronous, just like a function.\n\n<span class=\"informal\">Observables are able to deliver values either synchronously or asynchronously.</span>\n\nWhat is the difference between an Observable and a function? **Observables can \"return\" multiple values over time**, something which functions cannot. You can't do this:\n\n```ts\nfunction foo() {\n  console.log('Hello');\n  return 42;\n  return 100; // dead code. will never happen\n}\n```\n\nFunctions can only return one value. Observables, however, can do this:\n\n```ts\nimport { Observable } from 'rxjs';\n\nconst foo = new Observable((subscriber) => {\n  console.log('Hello');\n  subscriber.next(42);\n  subscriber.next(100); // \"return\" another value\n  subscriber.next(200); // \"return\" yet another\n});\n\nconsole.log('before');\nfoo.subscribe((x) => {\n  console.log(x);\n});\nconsole.log('after');\n```\n\nWith synchronous output:\n\n```none\n\"before\"\n\"Hello\"\n42\n100\n200\n\"after\"\n```\n\nBut you can also \"return\" values asynchronously:\n\n```ts\nimport { Observable } from 'rxjs';\n\nconst foo = new Observable((subscriber) => {\n  console.log('Hello');\n  subscriber.next(42);\n  subscriber.next(100);\n  subscriber.next(200);\n  setTimeout(() => {\n    subscriber.next(300); // happens asynchronously\n  }, 1000);\n});\n\nconsole.log('before');\nfoo.subscribe((x) => {\n  console.log(x);\n});\nconsole.log('after');\n```\n\nWith output:\n\n```none\n\"before\"\n\"Hello\"\n42\n100\n200\n\"after\"\n300\n```\n\nConclusion:\n\n- `func.call()` means \"_give me one value synchronously_\"\n- `observable.subscribe()` means \"_give me any amount of values, either synchronously or asynchronously_\"\n\n## Anatomy of an Observable\n\nObservables are **created** using `new Observable` or a creation operator, are **subscribed** to with an Observer, **execute** to deliver `next` / `error` / `complete` notifications to the Observer, and their execution may be **disposed**. These four aspects are all encoded in an Observable instance, but some of these aspects are related to other types, like Observer and Subscription.\n\nCore Observable concerns:\n\n- **Creating** Observables\n- **Subscribing** to Observables\n- **Executing** the Observable\n- **Disposing** Observables\n\n### Creating Observables\n\nThe `Observable` constructor takes one argument: the `subscribe` function.\n\nThe following example creates an Observable to emit the string `'hi'` every second to a subscriber.\n\n```ts\nimport { Observable } from 'rxjs';\n\nconst observable = new Observable(function subscribe(subscriber) {\n  const id = setInterval(() => {\n    subscriber.next('hi');\n  }, 1000);\n});\n```\n\n<span class=\"informal\">Observables can be created with `new Observable`. Most commonly, observables are created using creation functions, like `of`, `from`, `interval`, etc.</span>\n\nIn the example above, the `subscribe` function is the most important piece to describe the Observable. Let's look at what subscribing means.\n\n### Subscribing to Observables\n\nThe Observable `observable` in the example can be _subscribed_ to, like this:\n\n```ts\nobservable.subscribe((x) => console.log(x));\n```\n\nIt is not a coincidence that `observable.subscribe` and `subscribe` in `new Observable(function subscribe(subscriber) {...})` have the same name. In the library, they are different, but for practical purposes you can consider them conceptually equal.\n\nThis shows how `subscribe` calls are not shared among multiple Observers of the same Observable. When calling `observable.subscribe` with an Observer, the function `subscribe` in `new Observable(function subscribe(subscriber) {...})` is run for that given subscriber. Each call to `observable.subscribe` triggers its own independent setup for that given subscriber.\n\n<span class=\"informal\">Subscribing to an Observable is like calling a function, providing callbacks where the data will be delivered to.</span>\n\nThis is drastically different to event handler APIs like `addEventListener` / `removeEventListener`. With `observable.subscribe`, the given Observer is not registered as a listener in the Observable. The Observable does not even maintain a list of attached Observers.\n\nA `subscribe` call is simply a way to start an \"Observable execution\" and deliver values or events to an Observer of that execution.\n\n### Executing Observables\n\nThe code inside `new Observable(function subscribe(subscriber) {...})` represents an \"Observable execution\", a lazy computation that only happens for each Observer that subscribes. The execution produces multiple values over time, either synchronously or asynchronously.\n\nThere are three types of values an Observable Execution can deliver:\n\n- \"Next\" notification: sends a value such as a Number, a String, an Object, etc.\n- \"Error\" notification: sends a JavaScript Error or exception.\n- \"Complete\" notification: does not send a value.\n\n\"Next\" notifications are the most important and most common type: they represent actual data being delivered to a subscriber. \"Error\" and \"Complete\" notifications may happen only once during the Observable Execution, and there can only be either one of them.\n\nThese constraints are expressed best in the so-called _Observable Grammar_ or _Contract_, written as a regular expression:\n\n```none\nnext*(error|complete)?\n```\n\n<span class=\"informal\">In an Observable Execution, zero to infinite Next notifications may be delivered. If either an Error or Complete notification is delivered, then nothing else can be delivered afterwards.</span>\n\nThe following is an example of an Observable execution that delivers three Next notifications, then completes:\n\n```ts\nimport { Observable } from 'rxjs';\n\nconst observable = new Observable(function subscribe(subscriber) {\n  subscriber.next(1);\n  subscriber.next(2);\n  subscriber.next(3);\n  subscriber.complete();\n});\n```\n\nObservables strictly adhere to the Observable Contract, so the following code would not deliver the Next notification `4`:\n\n```ts\nimport { Observable } from 'rxjs';\n\nconst observable = new Observable(function subscribe(subscriber) {\n  subscriber.next(1);\n  subscriber.next(2);\n  subscriber.next(3);\n  subscriber.complete();\n  subscriber.next(4); // Is not delivered because it would violate the contract\n});\n```\n\nIt is a good idea to wrap any code in `subscribe` with `try`/`catch` block that will deliver an Error notification if it catches an exception:\n\n```ts\nimport { Observable } from 'rxjs';\n\nconst observable = new Observable(function subscribe(subscriber) {\n  try {\n    subscriber.next(1);\n    subscriber.next(2);\n    subscriber.next(3);\n    subscriber.complete();\n  } catch (err) {\n    subscriber.error(err); // delivers an error if it caught one\n  }\n});\n```\n\n### Disposing Observable Executions\n\nBecause Observable Executions may be infinite, and it's common for an Observer to want to abort execution in finite time, we need an API for canceling an execution. Since each execution is exclusive to one Observer only, once the Observer is done receiving values, it has to have a way to stop the execution, in order to avoid wasting computation power or memory resources.\n\nWhen `observable.subscribe` is called, the Observer gets attached to the newly created Observable execution. This call also returns an object, the `Subscription`:\n\n```ts\nconst subscription = observable.subscribe((x) => console.log(x));\n```\n\nThe Subscription represents the ongoing execution, and has a minimal API which allows you to cancel that execution. Read more about the [`Subscription` type here](./guide/subscription). With `subscription.unsubscribe()` you can cancel the ongoing execution:\n\n```ts\nimport { from } from 'rxjs';\n\nconst observable = from([10, 20, 30]);\nconst subscription = observable.subscribe((x) => console.log(x));\n// Later:\nsubscription.unsubscribe();\n```\n\n<span class=\"informal\">When you subscribe, you get back a Subscription, which represents the ongoing execution. Just call `unsubscribe()` to cancel the execution.</span>\n\nEach Observable must define how to dispose resources of that execution when we create the Observable using `create()`. You can do that by returning a custom `unsubscribe` function from within `function subscribe()`.\n\nFor instance, this is how we clear an interval execution set with `setInterval`:\n\n```ts\nimport { Observable } from 'rxjs';\n\nconst observable = new Observable(function subscribe(subscriber) {\n  // Keep track of the interval resource\n  const intervalId = setInterval(() => {\n    subscriber.next('hi');\n  }, 1000);\n\n  // Provide a way of canceling and disposing the interval resource\n  return function unsubscribe() {\n    clearInterval(intervalId);\n  };\n});\n```\n\nJust like `observable.subscribe` resembles `new Observable(function subscribe() {...})`, the `unsubscribe` we return from `subscribe` is conceptually equal to `subscription.unsubscribe`. In fact, if we remove the ReactiveX types surrounding these concepts, we're left with rather straightforward JavaScript.\n\n```ts\nfunction subscribe(subscriber) {\n  const intervalId = setInterval(() => {\n    subscriber.next('hi');\n  }, 1000);\n\n  return function unsubscribe() {\n    clearInterval(intervalId);\n  };\n}\n\nconst unsubscribe = subscribe({ next: (x) => console.log(x) });\n\n// Later:\nunsubscribe(); // dispose the resources\n```\n\nThe reason why we use Rx types like Observable, Observer, and Subscription is to get safety (such as the Observable Contract) and composability with Operators.\n"
  },
  {
    "path": "apps/rxjs.dev/content/guide/observer.md",
    "content": "# Observer\n\n**What is an Observer?** An Observer is a consumer of values delivered by an Observable. Observers are simply a set of callbacks, one for each type of notification delivered by the Observable: `next`, `error`, and `complete`. The following is an example of a typical Observer object:\n\n```ts\nconst observer = {\n  next: x => console.log('Observer got a next value: ' + x),\n  error: err => console.error('Observer got an error: ' + err),\n  complete: () => console.log('Observer got a complete notification'),\n};\n```\n\nTo use the Observer, provide it to the `subscribe` of an Observable:\n\n```ts\nobservable.subscribe(observer);\n```\n\n<span class=\"informal\">Observers are just objects with three callbacks, one for each type of notification that an Observable may deliver.</span>\n\nObservers in RxJS may also be *partial*. If you don't provide one of the callbacks, the execution of the Observable will still happen normally, except some types of notifications will be ignored, because they don't have a corresponding callback in the Observer.\n\nThe example below is an `Observer` without the `complete` callback:\n\n```ts\nconst observer = {\n  next: x => console.log('Observer got a next value: ' + x),\n  error: err => console.error('Observer got an error: ' + err),\n};\n```\n\nWhen subscribing to an `Observable`, you may also just provide the next callback as an argument, without being attached to an `Observer` object, for instance like this:\n\n```ts\nobservable.subscribe(x => console.log('Observer got a next value: ' + x));\n```\n\nInternally in `observable.subscribe`, it will create an `Observer` object using the callback argument as the `next` handler.\n"
  },
  {
    "path": "apps/rxjs.dev/content/guide/operators.md",
    "content": "# RxJS Operators\n\nRxJS is mostly useful for its _operators_, even though the Observable is the foundation. Operators are the essential pieces that allow complex asynchronous code to be easily composed in a declarative manner.\n\n## What are operators?\n\nOperators are **functions**. There are two kinds of operators:\n\n**Pipeable Operators** are the kind that can be piped to Observables using the syntax `observableInstance.pipe(operator)` or, more commonly, `observableInstance.pipe(operatorFactory())`. Operator factory functions include, [`filter(...)`](/api/operators/filter), and [`mergeMap(...)`](/api/operators/mergeMap).\n\nWhen Pipeable Operators are called, they do not _change_ the existing Observable instance. Instead, they return a _new_ Observable, whose subscription logic is based on the first Observable.\n\n<span class=\"informal\">A Pipeable Operator is a function that takes an Observable as its input and returns another Observable. It is a pure operation: the previous Observable stays unmodified.</span>\n\n<span class=\"informal\">A Pipeable Operator Factory is a function that can take parameters to set the context and return a Pipeable Operator. The factory’s arguments belong to the operator’s lexical scope.</span>\n\nA Pipeable Operator is essentially a pure function which takes one Observable as input and generates another Observable as output. Subscribing to the output Observable will also subscribe to the input Observable.\n\n**Creation Operators** are the other kind of operator, which can be called as standalone functions to create a new Observable. For example: `of(1, 2, 3)` creates an observable that will emit 1, 2, and 3, one right after another. Creation operators will be discussed in more detail in a later section.\n\nFor example, the operator called [`map`](/api/operators/map) is analogous to the Array method of the same name. Just as `[1, 2, 3].map(x => x * x)` will yield `[1, 4, 9]`, the Observable created like this:\n\n```ts\nimport { of, map } from 'rxjs';\n\nof(1, 2, 3)\n  .pipe(map((x) => x * x))\n  .subscribe((v) => console.log(`value: ${v}`));\n\n// Logs:\n// value: 1\n// value: 4\n// value: 9\n```\n\nwill emit `1`, `4`, `9`. Another useful operator is [`first`](/api/operators/first):\n\n```ts\nimport { of, first } from 'rxjs';\n\nof(1, 2, 3)\n  .pipe(first())\n  .subscribe((v) => console.log(`value: ${v}`));\n\n// Logs:\n// value: 1\n```\n\nNote that `map` logically must be constructed on the fly, since it must be given the mapping function to. By contrast, `first` could be a constant, but is nonetheless constructed on the fly. As a general practice, all operators are constructed, whether they need arguments or not.\n\n## Piping\n\nPipeable operators are functions, so they _could_ be used like ordinary functions: `op()(obs)` — but in practice, there tend to be many of them convolved together, and quickly become unreadable: `op4()(op3()(op2()(op1()(obs))))`. For that reason, Observables have a method called `.pipe()` that accomplishes the same thing while being much easier to read:\n\n```ts\nobs.pipe(op1(), op2(), op3(), op4());\n```\n\nAs a stylistic matter, `op()(obs)` is never used, even if there is only one operator; `obs.pipe(op())` is universally preferred.\n\n## Creation Operators\n\n**What are creation operators?** Distinct from pipeable operators, creation operators are functions that can be used to create an Observable with some common predefined behavior or by joining other Observables.\n\nA typical example of a creation operator would be the `interval` function. It takes a number (not an Observable) as input argument, and produces an Observable as output:\n\n```ts\nimport { interval } from 'rxjs';\n\nconst observable = interval(1000 /* number of milliseconds */);\n```\n\nSee the list of all static creation operators [here](#creation-operators-list).\n\n## Higher-order Observables\n\nObservables most commonly emit ordinary values like strings and numbers, but surprisingly often, it is necessary to handle Observables _of_ Observables, so-called higher-order Observables. For example, imagine you had an Observable emitting strings that were the URLs of files you wanted to see. The code might look like this:\n\n```ts\nconst fileObservable = urlObservable.pipe(map((url) => http.get(url)));\n```\n\n`http.get()` returns an Observable (of string or string arrays probably) for each individual URL. Now you have an Observable _of_ Observables, a higher-order Observable.\n\nBut how do you work with a higher-order Observable? Typically, by _flattening_: by (somehow) converting a higher-order Observable into an ordinary Observable. For example:\n\n```ts\nconst fileObservable = urlObservable.pipe(\n  map((url) => http.get(url)),\n  concatAll()\n);\n```\n\nThe [`concatAll()`](/api/operators/concatAll) operator subscribes to each \"inner\" Observable that comes out of the \"outer\" Observable, and copies all the emitted values until that Observable completes, and goes on to the next one. All of the values are in that way concatenated. Other useful flattening operators (called [_join operators_](#join-operators)) are\n\n- [`mergeAll()`](/api/operators/mergeAll) — subscribes to each inner Observable as it arrives, then emits each value as it arrives\n- [`switchAll()`](/api/operators/switchAll) — subscribes to the first inner Observable when it arrives, and emits each value as it arrives, but when the next inner Observable arrives, unsubscribes to the previous one, and subscribes to the new one.\n- [`exhaustAll()`](/api/operators/exhaustAll) — subscribes to the first inner Observable when it arrives, and emits each value as it arrives, discarding all newly arriving inner Observables until that first one completes, then waits for the next inner Observable.\n\nJust as many array libraries combine [`map()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map) and [`flat()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/flat) (or `flatten()`) into a single [`flatMap()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/flatMap), there are mapping equivalents of all the RxJS flattening operators [`concatMap()`](/api/operators/concatMap), [`mergeMap()`](/api/operators/mergeMap), [`switchMap()`](/api/operators/switchMap), and [`exhaustMap()`](/api/operators/exhaustMap).\n\n## Marble diagrams\n\nTo explain how operators work, textual descriptions are often not enough. Many operators are related to time, they may for instance delay, sample, throttle, or debounce value emissions in different ways. Diagrams are often a better tool for that. _Marble Diagrams_ are visual representations of how operators work, and include the input Observable(s), the operator and its parameters, and the output Observable.\n\n<span class=\"informal\">In a marble diagram, time flows to the right, and the diagram describes how values (\"marbles\") are emitted on the Observable execution.</span>\n\nBelow you can see the anatomy of a marble diagram.\n\n<img src=\"assets/images/guide/marble-diagram-anatomy.svg\">\n\nThroughout this documentation site, we extensively use marble diagrams to explain how operators work. They may be really useful in other contexts too, like on a whiteboard or even in our unit tests (as ASCII diagrams).\n\n## Categories of operators\n\nThere are operators for different purposes, and they may be categorized as: creation, transformation, filtering, joining, multicasting, error handling, utility, etc. In the following list you will find all the operators organized in categories.\n\nFor a complete overview, see the [references page](/api).\n\n### <a id=\"creation-operators-list\"></a>Creation Operators\n\n- [`ajax`](/api/ajax/ajax)\n- [`bindCallback`](/api/index/function/bindCallback)\n- [`bindNodeCallback`](/api/index/function/bindNodeCallback)\n- [`defer`](/api/index/function/defer)\n- [`EMPTY`](/api/index/const/EMPTY)\n- [`from`](/api/index/function/from)\n- [`fromEvent`](/api/index/function/fromEvent)\n- [`fromEventPattern`](/api/index/function/fromEventPattern)\n- [`generate`](/api/index/function/generate)\n- [`interval`](/api/index/function/interval)\n- [`of`](/api/index/function/of)\n- [`range`](/api/index/function/range)\n- [`throwError`](/api/index/function/throwError)\n- [`timer`](/api/index/function/timer)\n- [`iif`](/api/index/function/iif)\n\n### <a id=\"join-creation-operators\"></a>Join Creation Operators\n\nThese are Observable creation operators that also have join functionality -- emitting values of multiple source Observables.\n\n- [`combineLatest`](/api/index/function/combineLatest)\n- [`concat`](/api/index/function/concat)\n- [`forkJoin`](/api/index/function/forkJoin)\n- [`merge`](/api/index/function/merge)\n- [`partition`](/api/index/function/partition)\n- [`race`](/api/index/function/race)\n- [`zip`](/api/index/function/zip)\n\n### Transformation Operators\n\n- [`buffer`](/api/operators/buffer)\n- [`bufferCount`](/api/operators/bufferCount)\n- [`bufferTime`](/api/operators/bufferTime)\n- [`bufferToggle`](/api/operators/bufferToggle)\n- [`bufferWhen`](/api/operators/bufferWhen)\n- [`concatMap`](/api/operators/concatMap)\n- [`concatMapTo`](/api/operators/concatMapTo)\n- [`exhaustMap`](/api/operators/exhaustMap)\n- [`expand`](/api/operators/expand)\n- [`groupBy`](/api/operators/groupBy)\n- [`map`](/api/operators/map)\n- [`mapTo`](/api/operators/mapTo)\n- [`mergeMap`](/api/operators/mergeMap)\n- [`mergeMapTo`](/api/operators/mergeMapTo)\n- [`mergeScan`](/api/operators/mergeScan)\n- [`pairwise`](/api/operators/pairwise)\n- [`partition`](/api/operators/partition)\n- [`scan`](/api/operators/scan)\n- [`switchScan`](/api/operators/switchScan)\n- [`switchMap`](/api/operators/switchMap)\n- [`switchMapTo`](/api/operators/switchMapTo)\n- [`window`](/api/operators/window)\n- [`windowCount`](/api/operators/windowCount)\n- [`windowTime`](/api/operators/windowTime)\n- [`windowToggle`](/api/operators/windowToggle)\n- [`windowWhen`](/api/operators/windowWhen)\n\n### Filtering Operators\n\n- [`audit`](/api/operators/audit)\n- [`auditTime`](/api/operators/auditTime)\n- [`debounce`](/api/operators/debounce)\n- [`debounceTime`](/api/operators/debounceTime)\n- [`distinct`](/api/operators/distinct)\n- [`distinctUntilChanged`](/api/operators/distinctUntilChanged)\n- [`distinctUntilKeyChanged`](/api/operators/distinctUntilKeyChanged)\n- [`elementAt`](/api/operators/elementAt)\n- [`filter`](/api/operators/filter)\n- [`first`](/api/operators/first)\n- [`ignoreElements`](/api/operators/ignoreElements)\n- [`last`](/api/operators/last)\n- [`sample`](/api/operators/sample)\n- [`sampleTime`](/api/operators/sampleTime)\n- [`single`](/api/operators/single)\n- [`skip`](/api/operators/skip)\n- [`skipLast`](/api/operators/skipLast)\n- [`skipUntil`](/api/operators/skipUntil)\n- [`skipWhile`](/api/operators/skipWhile)\n- [`take`](/api/operators/take)\n- [`takeLast`](/api/operators/takeLast)\n- [`takeUntil`](/api/operators/takeUntil)\n- [`takeWhile`](/api/operators/takeWhile)\n- [`throttle`](/api/operators/throttle)\n- [`throttleTime`](/api/operators/throttleTime)\n\n### <a id=\"join-operators\"></a>Join Operators\n\nAlso see the [Join Creation Operators](#join-creation-operators) section above.\n\n- [`combineLatestAll`](/api/operators/combineLatestAll)\n- [`concatAll`](/api/operators/concatAll)\n- [`exhaustAll`](/api/operators/exhaustAll)\n- [`mergeAll`](/api/operators/mergeAll)\n- [`switchAll`](/api/operators/switchAll)\n- [`startWith`](/api/operators/startWith)\n- [`withLatestFrom`](/api/operators/withLatestFrom)\n\n### Multicasting Operators\n\n- [`share`](/api/operators/share)\n\n### Error Handling Operators\n\n- [`catchError`](/api/operators/catchError)\n- [`retry`](/api/operators/retry)\n- [`retryWhen`](/api/operators/retryWhen)\n\n### Utility Operators\n\n- [`tap`](/api/operators/tap)\n- [`delay`](/api/operators/delay)\n- [`delayWhen`](/api/operators/delayWhen)\n- [`dematerialize`](/api/operators/dematerialize)\n- [`materialize`](/api/operators/materialize)\n- [`observeOn`](/api/operators/observeOn)\n- [`subscribeOn`](/api/operators/subscribeOn)\n- [`timeInterval`](/api/operators/timeInterval)\n- [`timestamp`](/api/operators/timestamp)\n- [`timeout`](/api/operators/timeout)\n- [`timeoutWith`](/api/operators/timeoutWith)\n- [`toArray`](/api/operators/toArray)\n\n### Conditional and Boolean Operators\n\n- [`defaultIfEmpty`](/api/operators/defaultIfEmpty)\n- [`every`](/api/operators/every)\n- [`find`](/api/operators/find)\n- [`findIndex`](/api/operators/findIndex)\n- [`isEmpty`](/api/operators/isEmpty)\n\n### Mathematical and Aggregate Operators\n\n- [`count`](/api/operators/count)\n- [`max`](/api/operators/max)\n- [`min`](/api/operators/min)\n- [`reduce`](/api/operators/reduce)\n\n## Creating custom operators\n\n### Use the `pipe()` function to make new operators\n\nIf there is a commonly used sequence of operators in your code, use the `pipe()` function to extract the sequence into a new operator. Even if a sequence is not that common, breaking it out into a single operator can improve readability.\n\nFor example, you could make a function that discarded odd values and doubled even values like this:\n\n```ts\nimport { pipe, filter, map } from 'rxjs';\n\nfunction discardOddDoubleEven() {\n  return pipe(\n    filter((v) => !(v % 2)),\n    map((v) => v + v)\n  );\n}\n```\n\n(The `pipe()` function is analogous to, but not the same thing as, the `.pipe()` method on an Observable.)\n\n### Creating new operators from scratch\n\nIt is more complicated, but if you have to write an operator that cannot be made from a combination of existing operators (a rare occurrence), you can write an operator from scratch using the Observable constructor, like this:\n\n```ts\nimport { Observable, of } from 'rxjs';\n\nfunction delay<T>(delayInMillis: number) {\n  return (observable: Observable<T>) =>\n    new Observable<T>((subscriber) => {\n      // this function will be called each time this\n      // Observable is subscribed to.\n      const allTimerIDs = new Set();\n      let hasCompleted = false;\n      const subscription = observable.subscribe({\n        next(value) {\n          // Start a timer to delay the next value\n          // from being pushed.\n          const timerID = setTimeout(() => {\n            subscriber.next(value);\n            // after we push the value, we need to clean up the timer timerID\n            allTimerIDs.delete(timerID);\n            // If the source has completed, and there are no more timers running,\n            // we can complete the resulting observable.\n            if (hasCompleted && allTimerIDs.size === 0) {\n              subscriber.complete();\n            }\n          }, delayInMillis);\n\n          allTimerIDs.add(timerID);\n        },\n        error(err) {\n          // We need to make sure we're propagating our errors through.\n          subscriber.error(err);\n        },\n        complete() {\n          hasCompleted = true;\n          // If we still have timers running, we don't want to complete yet.\n          if (allTimerIDs.size === 0) {\n            subscriber.complete();\n          }\n        },\n      });\n\n      // Return the finalization logic. This will be invoked when\n      // the result errors, completes, or is unsubscribed.\n      return () => {\n        subscription.unsubscribe();\n        // Clean up our timers.\n        for (const timerID of allTimerIDs) {\n          clearTimeout(timerID);\n        }\n      };\n    });\n}\n\n// Try it out!\nof(1, 2, 3).pipe(delay(1000)).subscribe(console.log);\n```\n\nNote that you must\n\n1. implement all three Observer functions, `next()`, `error()`, and `complete()` when subscribing to the input Observable.\n2. implement a \"finalization\" function that cleans up when the Observable completes (in this case by unsubscribing and clearing any pending timeouts).\n3. return that finalization function from the function passed to the Observable constructor.\n\nOf course, this is only an example; the [`delay()`](/api/operators/delay) operator already exists.\n"
  },
  {
    "path": "apps/rxjs.dev/content/guide/overview.md",
    "content": "# Introduction\n\nRxJS is a library for composing asynchronous and event-based programs by using observable sequences. It provides one core type, the [Observable](./guide/observable), satellite types (Observer, Schedulers, Subjects) and operators inspired by `Array` methods (`map`, `filter`, `reduce`, `every`, etc) to allow handling asynchronous events as collections.\n\n<span class=\"informal\">Think of RxJS as Lodash for events.</span>\n\nReactiveX combines the [Observer pattern](https://en.wikipedia.org/wiki/Observer_pattern) with the [Iterator pattern](https://en.wikipedia.org/wiki/Iterator_pattern) and [functional programming with collections](http://martinfowler.com/articles/collection-pipeline/#NestedOperatorExpressions) to fill the need for an ideal way of managing sequences of events.\n\nThe essential concepts in RxJS which solve async event management are:\n\n- **Observable:** represents the idea of an invokable collection of future values or events.\n- **Observer:** is a collection of callbacks that knows how to listen to values delivered by the Observable.\n- **Subscription:** represents the execution of an Observable, is primarily useful for cancelling the execution.\n- **Operators:** are pure functions that enable a functional programming style of dealing with collections with operations like `map`, `filter`, `concat`, `reduce`, etc.\n- **Subject:** is equivalent to an EventEmitter, and the only way of multicasting a value or event to multiple Observers.\n- **Schedulers:** are centralized dispatchers to control concurrency, allowing us to coordinate when computation happens on e.g. `setTimeout` or `requestAnimationFrame` or others.\n\n## First examples\n\nNormally you register event listeners.\n\n```ts\ndocument.addEventListener('click', () => console.log('Clicked!'));\n```\n\nUsing RxJS you create an observable instead.\n\n```ts\nimport { fromEvent } from 'rxjs';\n\nfromEvent(document, 'click').subscribe(() => console.log('Clicked!'));\n```\n\n### Purity\n\nWhat makes RxJS powerful is its ability to produce values using pure functions. That means your code is less prone to errors.\n\nNormally you would create an impure function, where other\npieces of your code can mess up your state.\n\n```ts\nlet count = 0;\ndocument.addEventListener('click', () => console.log(`Clicked ${++count} times`));\n```\n\nUsing RxJS you isolate the state.\n\n```ts\nimport { fromEvent, scan } from 'rxjs';\n\nfromEvent(document, 'click')\n  .pipe(scan((count) => count + 1, 0))\n  .subscribe((count) => console.log(`Clicked ${count} times`));\n```\n\nThe **scan** operator works just like **reduce** for arrays. It takes a value which is exposed to a callback. The returned value of the callback will then become the next value exposed the next time the callback runs.\n\n### Flow\n\nRxJS has a whole range of operators that helps you control how the events flow through your observables.\n\nThis is how you would allow at most one click per second, with plain JavaScript:\n\n```ts\nlet count = 0;\nlet rate = 1000;\nlet lastClick = Date.now() - rate;\ndocument.addEventListener('click', () => {\n  if (Date.now() - lastClick >= rate) {\n    console.log(`Clicked ${++count} times`);\n    lastClick = Date.now();\n  }\n});\n```\n\nWith RxJS:\n\n```ts\nimport { fromEvent, throttleTime, scan } from 'rxjs';\n\nfromEvent(document, 'click')\n  .pipe(\n    throttleTime(1000),\n    scan((count) => count + 1, 0)\n  )\n  .subscribe((count) => console.log(`Clicked ${count} times`));\n```\n\nOther flow control operators are [**filter**](../api/operators/filter), [**delay**](../api/operators/delay), [**debounceTime**](../api/operators/debounceTime), [**take**](../api/operators/take), [**takeUntil**](../api/operators/takeUntil), [**distinct**](../api/operators/distinct), [**distinctUntilChanged**](../api/operators/distinctUntilChanged) etc.\n\n### Values\n\nYou can transform the values passed through your observables.\n\nHere's how you can add the current mouse x position for every click, in plain JavaScript:\n\n```ts\nlet count = 0;\nconst rate = 1000;\nlet lastClick = Date.now() - rate;\ndocument.addEventListener('click', (event) => {\n  if (Date.now() - lastClick >= rate) {\n    count += event.clientX;\n    console.log(count);\n    lastClick = Date.now();\n  }\n});\n```\n\nWith RxJS:\n\n```ts\nimport { fromEvent, throttleTime, map, scan } from 'rxjs';\n\nfromEvent(document, 'click')\n  .pipe(\n    throttleTime(1000),\n    map((event) => event.clientX),\n    scan((count, clientX) => count + clientX, 0)\n  )\n  .subscribe((count) => console.log(count));\n```\n\nOther value producing operators are [**pairwise**](../api/operators/pairwise), [**sample**](../api/operators/sample) etc.\n"
  },
  {
    "path": "apps/rxjs.dev/content/guide/scheduler.md",
    "content": "# Scheduler\n\n**What is a Scheduler?** A scheduler controls when a subscription starts and when notifications are delivered. It consists of three components.\n\n- **A Scheduler is a data structure.** It knows how to store and queue tasks based on priority or other criteria.\n- **A Scheduler is an execution context.** It denotes where and when the task is executed (e.g. immediately, or in another callback mechanism such as setTimeout or process.nextTick, or the animation frame).\n- **A Scheduler has a (virtual) clock.** It provides a notion of \"time\" by a getter method `now()` on the scheduler. Tasks being scheduled on a particular scheduler will adhere only to the time denoted by that clock.\n\n<span class=\"informal\">A Scheduler lets you define in what execution context will an Observable deliver notifications to its Observer.</span>\n\nIn the example below, we take the usual simple Observable that emits values `1`, `2`, `3` synchronously, and use the operator `observeOn` to specify the `asyncScheduler` scheduler to use for delivering those values.\n\n<!-- prettier-ignore -->\n```ts\nimport { Observable, observeOn, asyncScheduler } from 'rxjs';\n\nconst observable = new Observable((observer) => {\n  observer.next(1);\n  observer.next(2);\n  observer.next(3);\n  observer.complete();\n}).pipe(\n  observeOn(asyncScheduler)\n);\n\nconsole.log('just before subscribe');\nobservable.subscribe({\n  next(x) {\n    console.log('got value ' + x);\n  },\n  error(err) {\n    console.error('something wrong occurred: ' + err);\n  },\n  complete() {\n    console.log('done');\n  },\n});\nconsole.log('just after subscribe');\n```\n\nWhich executes with the output:\n\n```none\njust before subscribe\njust after subscribe\ngot value 1\ngot value 2\ngot value 3\ndone\n```\n\nNotice how the notifications `got value...` were delivered after `just after subscribe`, which is different to the default behavior we have seen so far. This is because `observeOn(asyncScheduler)` introduces a proxy Observer between `new Observable` and the final Observer. Let's rename some identifiers to make that distinction obvious in the example code:\n\n<!-- prettier-ignore -->\n```ts\nimport { Observable, observeOn, asyncScheduler } from 'rxjs';\n\nconst observable = new Observable((proxyObserver) => {\n  proxyObserver.next(1);\n  proxyObserver.next(2);\n  proxyObserver.next(3);\n  proxyObserver.complete();\n}).pipe(\n  observeOn(asyncScheduler)\n);\n\nconst finalObserver = {\n  next(x) {\n    console.log('got value ' + x);\n  },\n  error(err) {\n    console.error('something wrong occurred: ' + err);\n  },\n  complete() {\n    console.log('done');\n  },\n};\n\nconsole.log('just before subscribe');\nobservable.subscribe(finalObserver);\nconsole.log('just after subscribe');\n```\n\nThe `proxyObserver` is created in `observeOn(asyncScheduler)`, and its `next(val)` function is approximately the following:\n\n<!-- prettier-ignore -->\n```ts\nconst proxyObserver = {\n  next(val) {\n    asyncScheduler.schedule(\n      (x) => finalObserver.next(x),\n      0 /* delay */,\n      val /* will be the x for the function above */\n    );\n  },\n\n  // ...\n};\n```\n\nThe `asyncScheduler` Scheduler operates with a `setTimeout` or `setInterval`, even if the given `delay` was zero. As usual, in JavaScript, `setTimeout(fn, 0)` is known to run the function `fn` earliest on the next event loop iteration. This explains why `got value 1` is delivered to the `finalObserver` after `just after subscribe` happened.\n\nThe `schedule()` method of a Scheduler takes a `delay` argument, which refers to a quantity of time relative to the Scheduler's own internal clock. A Scheduler's clock need not have any relation to the actual wall-clock time. This is how temporal operators like `delay` operate not on actual time, but on time dictated by the Scheduler's clock. This is specially useful in testing, where a _virtual time Scheduler_ may be used to fake wall-clock time while in reality executing scheduled tasks synchronously.\n\n## Scheduler Types\n\nThe `asyncScheduler` Scheduler is one of the built-in schedulers provided by RxJS. Each of these can be created and returned by using static properties of the `Scheduler` object.\n\n| Scheduler                 | Purpose                                                                                                                                                                        |\n| ------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |\n| `null`                    | By not passing any scheduler, notifications are delivered synchronously and recursively. Use this for constant-time operations or tail recursive operations.                   |\n| `queueScheduler`          | Schedules on a queue in the current event frame (trampoline scheduler). Use this for iteration operations.                                                                     |\n| `asapScheduler`           | Schedules on the micro task queue, which is the same queue used for promises. Basically after the current job, but before the next job. Use this for asynchronous conversions. |\n| `asyncScheduler`          | Schedules work with `setInterval`. Use this for time-based operations.                                                                                                         |\n| `animationFrameScheduler` | Schedules task that will happen just before next browser content repaint. Can be used to create smooth browser animations.                                                     |\n\n## Using Schedulers\n\nYou may have already used schedulers in your RxJS code without explicitly stating the type of schedulers to be used. This is because all Observable operators that deal with concurrency have optional schedulers. If you do not provide the scheduler, RxJS will pick a default scheduler by using the principle of least concurrency. This means that the scheduler which introduces the least amount of concurrency that satisfies the needs of the operator is chosen. For example, for operators returning an observable with a finite and small number of messages, RxJS uses no Scheduler, i.e. `null` or `undefined`. For operators returning a potentially large or infinite number of messages, `queueScheduler` Scheduler is used. For operators which use timers, `asyncScheduler` is used.\n\nBecause RxJS uses the least concurrency scheduler, you can pick a different scheduler if you want to introduce concurrency for performance purpose. To specify a particular scheduler, you can use those operator methods that take a scheduler, e.g., `from([10, 20, 30], asyncScheduler)`.\n\n**Static creation operators usually take a Scheduler as argument.** For instance, `from(array, scheduler)` lets you specify the Scheduler to use when delivering each notification converted from the `array`. It is usually the last argument to the operator. The following static creation operators take a Scheduler argument:\n\n- `bindCallback`\n- `bindNodeCallback`\n- `combineLatest`\n- `concat`\n- `empty`\n- `from`\n- `fromPromise`\n- `interval`\n- `merge`\n- `of`\n- `range`\n- `throw`\n- `timer`\n\n**Use `subscribeOn` to schedule in what context will the `subscribe()` call happen.** By default, a `subscribe()` call on an Observable will happen synchronously and immediately. However, you may delay or schedule the actual subscription to happen on a given Scheduler, using the instance operator `subscribeOn(scheduler)`, where `scheduler` is an argument you provide.\n\n**Use `observeOn` to schedule in what context will notifications be delivered.** As we saw in the examples above, instance operator `observeOn(scheduler)` introduces a mediator Observer between the source Observable and the destination Observer, where the mediator schedules calls to the destination Observer using your given `scheduler`.\n\n**Instance operators may take a Scheduler as argument.**\n\nTime-related operators like `bufferTime`, `debounceTime`, `delay`, `auditTime`, `sampleTime`, `throttleTime`, `timeInterval`, `timeout`, `timeoutWith`, `windowTime` all take a Scheduler as the last argument, and otherwise operate by default on the `asyncScheduler`.\n\nOther instance operators that take a Scheduler as argument: `combineLatest`, `concat`, `expand`, `merge`, `startWith`.\n"
  },
  {
    "path": "apps/rxjs.dev/content/guide/subject.md",
    "content": "# Subject\n\n**What is a Subject?** An RxJS Subject is a special type of Observable that allows values to be multicasted to many Observers. While plain Observables are unicast (each subscribed Observer owns an independent execution of the Observable), Subjects are multicast.\n\n<span class=\"informal\">A Subject is like an Observable, but can multicast to many Observers. Subjects are like EventEmitters: they maintain a registry of many listeners.</span>\n\n**Every Subject is an Observable.** Given a Subject, you can `subscribe` to it, providing an Observer, which will start receiving values normally. From the perspective of the Observer, it cannot tell whether the Observable execution is coming from a plain unicast Observable or a Subject.\n\nInternally to the Subject, `subscribe` does not invoke a new execution that delivers values. It simply registers the given Observer in a list of Observers, similarly to how `addListener` usually works in other libraries and languages.\n\n**Every Subject is an Observer.** It is an object with the methods `next(v)`, `error(e)`, and `complete()`. To feed a new value to the Subject, just call `next(theValue)`, and it will be multicasted to the Observers registered to listen to the Subject.\n\nIn the example below, we have two Observers attached to a Subject, and we feed some values to the Subject:\n\n```ts\nimport { Subject } from 'rxjs';\n\nconst subject = new Subject<number>();\n\nsubject.subscribe({\n  next: (v) => console.log(`observerA: ${v}`),\n});\nsubject.subscribe({\n  next: (v) => console.log(`observerB: ${v}`),\n});\n\nsubject.next(1);\nsubject.next(2);\n\n// Logs:\n// observerA: 1\n// observerB: 1\n// observerA: 2\n// observerB: 2\n```\n\nSince a Subject is an Observer, this also means you may provide a Subject as the argument to the `subscribe` of any Observable, like the example below shows:\n\n```ts\nimport { Subject, from } from 'rxjs';\n\nconst subject = new Subject<number>();\n\nsubject.subscribe({\n  next: (v) => console.log(`observerA: ${v}`),\n});\nsubject.subscribe({\n  next: (v) => console.log(`observerB: ${v}`),\n});\n\nconst observable = from([1, 2, 3]);\n\nobservable.subscribe(subject); // You can subscribe providing a Subject\n\n// Logs:\n// observerA: 1\n// observerB: 1\n// observerA: 2\n// observerB: 2\n// observerA: 3\n// observerB: 3\n```\n\nWith the approach above, we essentially just converted a unicast Observable execution to multicast, through the Subject. This demonstrates how Subjects are the only way of making any Observable execution be shared to multiple Observers.\n\nThere are also a few specializations of the `Subject` type: `BehaviorSubject`, `ReplaySubject`, and `AsyncSubject`.\n\n## Multicasted Observables\n\nA \"multicasted Observable\" passes notifications through a Subject which may have many subscribers, whereas a plain \"unicast Observable\" only sends notifications to a single Observer.\n\n<span class=\"informal\">A multicasted Observable uses a Subject under the hood to make multiple Observers see the same Observable execution.</span>\n\nUnder the hood, this is how the `multicast` operator works: Observers subscribe to an underlying Subject, and the Subject subscribes to the source Observable. The following example is similar to the previous example which used `observable.subscribe(subject)`:\n\n```ts\nimport { from, Subject, multicast } from 'rxjs';\n\nconst source = from([1, 2, 3]);\nconst subject = new Subject();\nconst multicasted = source.pipe(multicast(subject));\n\n// These are, under the hood, `subject.subscribe({...})`:\nmulticasted.subscribe({\n  next: (v) => console.log(`observerA: ${v}`),\n});\nmulticasted.subscribe({\n  next: (v) => console.log(`observerB: ${v}`),\n});\n\n// This is, under the hood, `source.subscribe(subject)`:\nmulticasted.connect();\n```\n\n`multicast` returns an Observable that looks like a normal Observable, but works like a Subject when it comes to subscribing. `multicast` returns a `ConnectableObservable`, which is simply an Observable with the `connect()` method.\n\nThe `connect()` method is important to determine exactly when the shared Observable execution will start. Because `connect()` does `source.subscribe(subject)` under the hood, `connect()` returns a Subscription, which you can unsubscribe from in order to cancel the shared Observable execution.\n\n### Reference counting\n\nCalling `connect()` manually and handling the Subscription is often cumbersome. Usually, we want to _automatically_ connect when the first Observer arrives, and automatically cancel the shared execution when the last Observer unsubscribes.\n\nConsider the following example where subscriptions occur as outlined by this list:\n\n1. First Observer subscribes to the multicasted Observable\n2. **The multicasted Observable is connected**\n3. The `next` value `0` is delivered to the first Observer\n4. Second Observer subscribes to the multicasted Observable\n5. The `next` value `1` is delivered to the first Observer\n6. The `next` value `1` is delivered to the second Observer\n7. First Observer unsubscribes from the multicasted Observable\n8. The `next` value `2` is delivered to the second Observer\n9. Second Observer unsubscribes from the multicasted Observable\n10. **The connection to the multicasted Observable is unsubscribed**\n\nTo achieve that with explicit calls to `connect()`, we write the following code:\n\n```ts\nimport { interval, Subject, multicast } from 'rxjs';\n\nconst source = interval(500);\nconst subject = new Subject();\nconst multicasted = source.pipe(multicast(subject));\nlet subscription1, subscription2, subscriptionConnect;\n\nsubscription1 = multicasted.subscribe({\n  next: (v) => console.log(`observerA: ${v}`),\n});\n// We should call `connect()` here, because the first\n// subscriber to `multicasted` is interested in consuming values\nsubscriptionConnect = multicasted.connect();\n\nsetTimeout(() => {\n  subscription2 = multicasted.subscribe({\n    next: (v) => console.log(`observerB: ${v}`),\n  });\n}, 600);\n\nsetTimeout(() => {\n  subscription1.unsubscribe();\n}, 1200);\n\n// We should unsubscribe the shared Observable execution here,\n// because `multicasted` would have no more subscribers after this\nsetTimeout(() => {\n  subscription2.unsubscribe();\n  subscriptionConnect.unsubscribe(); // for the shared Observable execution\n}, 2000);\n```\n\nIf we wish to avoid explicit calls to `connect()`, we can use ConnectableObservable's `refCount()` method (reference counting), which returns an Observable that keeps track of how many subscribers it has. When the number of subscribers increases from `0` to `1`, it will call `connect()` for us, which starts the shared execution. Only when the number of subscribers decreases from `1` to `0` will it be fully unsubscribed, stopping further execution.\n\n<span class=\"informal\">`refCount` makes the multicasted Observable automatically start executing when the first subscriber arrives, and stop executing when the last subscriber leaves.</span>\n\nBelow is an example:\n\n```ts\nimport { interval, Subject, multicast, refCount } from 'rxjs';\n\nconst source = interval(500);\nconst subject = new Subject();\nconst refCounted = source.pipe(multicast(subject), refCount());\nlet subscription1, subscription2;\n\n// This calls `connect()`, because\n// it is the first subscriber to `refCounted`\nconsole.log('observerA subscribed');\nsubscription1 = refCounted.subscribe({\n  next: (v) => console.log(`observerA: ${v}`),\n});\n\nsetTimeout(() => {\n  console.log('observerB subscribed');\n  subscription2 = refCounted.subscribe({\n    next: (v) => console.log(`observerB: ${v}`),\n  });\n}, 600);\n\nsetTimeout(() => {\n  console.log('observerA unsubscribed');\n  subscription1.unsubscribe();\n}, 1200);\n\n// This is when the shared Observable execution will stop, because\n// `refCounted` would have no more subscribers after this\nsetTimeout(() => {\n  console.log('observerB unsubscribed');\n  subscription2.unsubscribe();\n}, 2000);\n\n// Logs\n// observerA subscribed\n// observerA: 0\n// observerB subscribed\n// observerA: 1\n// observerB: 1\n// observerA unsubscribed\n// observerB: 2\n// observerB unsubscribed\n```\n\nThe `refCount()` method only exists on ConnectableObservable, and it returns an `Observable`, not another ConnectableObservable.\n\n## BehaviorSubject\n\nOne of the variants of Subjects is the `BehaviorSubject`, which has a notion of \"the current value\". It stores the latest value emitted to its consumers, and whenever a new Observer subscribes, it will immediately receive the \"current value\" from the `BehaviorSubject`.\n\n<span class=\"informal\">BehaviorSubjects are useful for representing \"values over time\". For instance, an event stream of birthdays is a Subject, but the stream of a person's age would be a BehaviorSubject.</span>\n\nIn the following example, the BehaviorSubject is initialized with the value `0` which the first Observer receives when it subscribes. The second Observer receives the value `2` even though it subscribed after the value `2` was sent.\n\n```ts\nimport { BehaviorSubject } from 'rxjs';\nconst subject = new BehaviorSubject(0); // 0 is the initial value\n\nsubject.subscribe({\n  next: (v) => console.log(`observerA: ${v}`),\n});\n\nsubject.next(1);\nsubject.next(2);\n\nsubject.subscribe({\n  next: (v) => console.log(`observerB: ${v}`),\n});\n\nsubject.next(3);\n\n// Logs\n// observerA: 0\n// observerA: 1\n// observerA: 2\n// observerB: 2\n// observerA: 3\n// observerB: 3\n```\n\n## ReplaySubject\n\nA `ReplaySubject` is similar to a `BehaviorSubject` in that it can send old values to new subscribers, but it can also _record_ a part of the Observable execution.\n\n<span class=\"informal\">A `ReplaySubject` records multiple values from the Observable execution and replays them to new subscribers.</span>\n\nWhen creating a `ReplaySubject`, you can specify how many values to replay:\n\n```ts\nimport { ReplaySubject } from 'rxjs';\nconst subject = new ReplaySubject(3); // buffer 3 values for new subscribers\n\nsubject.subscribe({\n  next: (v) => console.log(`observerA: ${v}`),\n});\n\nsubject.next(1);\nsubject.next(2);\nsubject.next(3);\nsubject.next(4);\n\nsubject.subscribe({\n  next: (v) => console.log(`observerB: ${v}`),\n});\n\nsubject.next(5);\n\n// Logs:\n// observerA: 1\n// observerA: 2\n// observerA: 3\n// observerA: 4\n// observerB: 2\n// observerB: 3\n// observerB: 4\n// observerA: 5\n// observerB: 5\n```\n\nYou can also specify a _window time_ in milliseconds, besides of the buffer size, to determine how old the recorded values can be. In the following example we use a large buffer size of `100`, but a window time parameter of just `500` milliseconds.\n\n<!-- skip-example -->\n\n```ts\nimport { ReplaySubject } from 'rxjs';\nconst subject = new ReplaySubject(100, 500 /* windowTime */);\n\nsubject.subscribe({\n  next: (v) => console.log(`observerA: ${v}`),\n});\n\nlet i = 1;\nsetInterval(() => subject.next(i++), 200);\n\nsetTimeout(() => {\n  subject.subscribe({\n    next: (v) => console.log(`observerB: ${v}`),\n  });\n}, 1000);\n\n// Logs\n// observerA: 1\n// observerA: 2\n// observerA: 3\n// observerA: 4\n// observerA: 5\n// observerB: 3\n// observerB: 4\n// observerB: 5\n// observerA: 6\n// observerB: 6\n// ...\n```\n\n## AsyncSubject\n\nThe AsyncSubject is a variant where only the last value of the Observable execution is sent to its observers, and only when the execution completes.\n\n```js\nimport { AsyncSubject } from 'rxjs';\nconst subject = new AsyncSubject();\n\nsubject.subscribe({\n  next: (v) => console.log(`observerA: ${v}`),\n});\n\nsubject.next(1);\nsubject.next(2);\nsubject.next(3);\nsubject.next(4);\n\nsubject.subscribe({\n  next: (v) => console.log(`observerB: ${v}`),\n});\n\nsubject.next(5);\nsubject.complete();\n\n// Logs:\n// observerA: 5\n// observerB: 5\n```\n\nThe AsyncSubject is similar to the [`last()`](/api/operators/last) operator, in that it waits for the `complete` notification in order to deliver a single value.\n\n## Void subject\n\nSometimes the emitted value doesn't matter as much as the fact that a value was emitted.\n\nFor instance, the code below signals that one second has passed.\n\n```ts\nconst subject = new Subject<string>();\nsetTimeout(() => subject.next('dummy'), 1000);\n```\n\nPassing a dummy value this way is clumsy and can confuse users.\n\nBy declaring a _void subject_, you signal that the value is irrelevant. Only the event itself matters.\n\n```ts\nconst subject = new Subject<void>();\nsetTimeout(() => subject.next(), 1000);\n```\n\nA complete example with context is shown below:\n\n```ts\nimport { Subject } from 'rxjs';\n\nconst subject = new Subject(); // Shorthand for Subject<void>\n\nsubject.subscribe({\n  next: () => console.log('One second has passed'),\n});\n\nsetTimeout(() => subject.next(), 1000);\n```\n\n<span class=\"informal\">Before version 7, the default type of Subject values was `any`. `Subject<any>` disables type checking of the emitted values, whereas `Subject<void>` prevents accidental access to the emitted value. If you want the old behavior, then replace `Subject` with `Subject<any>`.</span>\n"
  },
  {
    "path": "apps/rxjs.dev/content/guide/subscription.md",
    "content": "# Subscription\n\n**What is a Subscription?** A Subscription is an object that represents a disposable resource, usually the execution of an Observable. A Subscription has one important method, `unsubscribe`, that takes no argument and just disposes the resource held by the subscription. In previous versions of RxJS, Subscription was called \"Disposable\".\n\n```ts\nimport { interval } from 'rxjs';\n\nconst observable = interval(1000);\nconst subscription = observable.subscribe(x => console.log(x));\n// Later:\n// This cancels the ongoing Observable execution which\n// was started by calling subscribe with an Observer.\nsubscription.unsubscribe(); \n```\n\n<span class=\"informal\">A Subscription essentially just has an `unsubscribe()` function to release resources or cancel Observable executions.</span>\n\nSubscriptions can also be put together, so that a call to an `unsubscribe()` of one Subscription may unsubscribe multiple Subscriptions. You can do this by \"adding\" one subscription into another:\n\n```ts\nimport { interval } from 'rxjs';\n\nconst observable1 = interval(400);\nconst observable2 = interval(300);\n\nconst subscription = observable1.subscribe(x => console.log('first: ' + x));\nconst childSubscription = observable2.subscribe(x => console.log('second: ' + x));\n\nsubscription.add(childSubscription);\n\nsetTimeout(() => {\n  // Unsubscribes BOTH subscription and childSubscription\n  subscription.unsubscribe();\n}, 1000);\n```\n\nWhen executed, we see in the console:\n```none\nsecond: 0\nfirst: 0\nsecond: 1\nfirst: 1\nsecond: 2\n```\n\nSubscriptions also have a `remove(otherSubscription)` method, in order to undo the addition of a child Subscription.\n"
  },
  {
    "path": "apps/rxjs.dev/content/guide/testing/marble-testing.md",
    "content": "# Testing RxJS Code with Marble Diagrams\n\n<div class=\"alert is-helpful\">\n  <span>This guide refers to usage of marble diagrams when using the new <code>testScheduler.run(callback)</code>. Some details here do not apply to using the TestScheduler manually, without using the <code>run()</code> helper.</span>\n</div>\n\nWe can test our _asynchronous_ RxJS code _synchronously_ and deterministically by virtualizing time using the TestScheduler. **Marble diagrams** provide a visual way for us to represent the behavior of an Observable. We can use them to assert that a particular Observable behaves as expected, as well as to create [hot and cold Observables](https://medium.com/@benlesh/hot-vs-cold-observables-f8094ed53339) we can use as mocks.\n\n> At this time, the TestScheduler can only be used to test code that uses RxJS schedulers - `AsyncScheduler`, etc. If the code consumes a Promise, for example, it cannot be reliably tested with `TestScheduler`, but instead should be tested more traditionally. See the [Known Issues](#known-issues) section for more details.\n\n```ts\nimport { TestScheduler } from 'rxjs/testing';\nimport { throttleTime } from 'rxjs';\n\nconst testScheduler = new TestScheduler((actual, expected) => {\n  // asserting the two objects are equal - required\n  // for TestScheduler assertions to work via your test framework\n  // e.g. using chai.\n  expect(actual).deep.equal(expected);\n});\n\n// This test runs synchronously.\nit('generates the stream correctly', () => {\n  testScheduler.run((helpers) => {\n    const { cold, time, expectObservable, expectSubscriptions } = helpers;\n    const e1 = cold(' -a--b--c---|');\n    const e1subs = '  ^----------!';\n    const t = time('   ---|       '); // t = 3\n    const expected = '-a-----c---|';\n\n    expectObservable(e1.pipe(throttleTime(t))).toBe(expected);\n    expectSubscriptions(e1.subscriptions).toBe(e1subs);\n  });\n});\n```\n\n## API\n\nThe callback function you provide to `testScheduler.run(callback)` is called with `helpers` object that contains functions you'll use to write your tests.\n\n<div class=\"alert is-helpful\">\n  <span>\n    When the code inside this callback is being executed, any operator that uses timers/AsyncScheduler (like delay, debounceTime, etc.,) will automatically use the TestScheduler instead, so that we have \"virtual time\". You do not need to pass the TestScheduler to them, like in the past.\n  </span>\n</div>\n\n```ts\ntestScheduler.run((helpers) => {\n  const { cold, hot, expectObservable, expectSubscriptions, flush, time, animate } = helpers;\n  // use them\n});\n```\n\nAlthough `run()` executes entirely synchronously, the helper functions inside your callback function do not! These functions **schedule assertions** that will execute either when your callback completes or when you explicitly call `flush()`. Be wary of calling synchronous assertions, for example `expect`, from your testing library of choice, from within the callback. See [Synchronous Assertion](#synchronous-assertion) for more information on how to do this.\n\n- `cold(marbleDiagram: string, values?: object, error?: any)` - creates a \"cold\" observable whose subscription starts when the test begins.\n- `hot(marbleDiagram: string, values?: object, error?: any)` - creates a \"hot\" observable (like a subject) that will behave as though it's already \"running\" when the test begins. An interesting difference is that `hot` marbles allow a `^` character to signal where the \"zero frame\" is. That is the point at which the subscription to observables being tested begins.\n- `expectObservable(actual: Observable<T>, subscriptionMarbles?: string).toBe(marbleDiagram: string, values?: object, error?: any)` - schedules an assertion for when the TestScheduler flushes. Give `subscriptionMarbles` as parameter to change the schedule of subscription and unsubscription. If you don't provide the `subscriptionMarbles` parameter it will subscribe at the beginning and never unsubscribe. Read below about subscription marble diagram.\n- `expectSubscriptions(actualSubscriptionLogs: SubscriptionLog[]).toBe(subscriptionMarbles: string)` - like `expectObservable` schedules an assertion for when the testScheduler flushes. Both `cold()` and `hot()` return an observable with a property `subscriptions` of type `SubscriptionLog[]`. Give `subscriptions` as parameter to `expectSubscriptions` to assert whether it matches the `subscriptionsMarbles` marble diagram given in `toBe()`. Subscription marble diagrams are slightly different than Observable marble diagrams. Read more below.\n- `flush()` - immediately starts virtual time. Not often used since `run()` will automatically flush for you when your callback returns, but in some cases you may wish to flush more than once or otherwise have more control.\n- `time()` - converts marbles into a number indicating number of frames. It can be used by operators expecting a specific timeout. It measures time based on the position of the complete (`|`) signal:\n\n  ```ts\n  testScheduler.run((helpers) => {\n    const { time, cold } = helpers;\n    const source = cold('---a--b--|');\n    const t = time('        --|    ');\n    //                         --|\n    const expected = '   -----a--b|';\n    const result = source.pipe(delay(t));\n    expectObservable(result).toBe(expected);\n  });\n  ```\n\n- `animate()` - specifies when requested animation frames will be 'painted'. `animate` accepts a marble diagram and each value emission in the diagram indicates when a 'paint' occurs - at which time, any queued `requestAnimationFrame` callbacks will be executed. Call `animate` at the beginning of your test and align the marble diagrams so that it's clear when the callbacks will be executed:\n\n  ```ts\n  testScheduler.run((helpers) => {\n    const { animate, cold } = helpers;\n    animate('              ---x---x---x---x');\n    const requests = cold('-r-------r------');\n    /* ... */\n    const expected = '     ---a-------b----';\n  });\n  ```\n\n## Marble syntax\n\nIn the context of TestScheduler, a marble diagram is a string containing special syntax representing events happening over virtual time. Time progresses by _frames_. The first character of any marble string always represents the _zero frame_, or the start of time. Inside of `testScheduler.run(callback)` the frameTimeFactor is set to 1, which means one frame is equal to one virtual millisecond.\n\nHow many virtual milliseconds one frame represents depends on the value of `TestScheduler.frameTimeFactor`. For legacy reasons the value of `frameTimeFactor` is 1 _only_ when your code inside the `testScheduler.run(callback)` callback is running. Outside of it, it's set to 10. This will likely change in a future version of RxJS so that it is always 1.\n\n> IMPORTANT: This syntax guide refers to usage of marble diagrams when using the new `testScheduler.run(callback)`. The semantics of marble diagrams when using the TestScheduler manually are different, and some features like the new time progression syntax are not supported.\n\n- `' '` whitespace: horizontal whitespace is ignored, and can be used to help vertically align multiple marble diagrams.\n- `'-'` frame: 1 \"frame\" of virtual time passing (see above description of frames).\n- `[0-9]+[ms|s|m]` time progression: the time progression syntax lets you progress virtual time by a specific amount. It's a number, followed by a time unit of `ms` (milliseconds), `s` (seconds), or `m` (minutes) without any space between them, e.g. `a 10ms b`. See [Time progression syntax](#time-progression-syntax) for more details.\n- `'|'` complete: The successful completion of an observable. This is the observable producer signaling `complete()`.\n- `'#'` error: An error terminating the observable. This is the observable producer signaling `error()`.\n- `[a-z0-9]` e.g. `'a'` any alphanumeric character: Represents a value being emitted by the producer signaling `next()`. Also consider that you could map this into an object or an array like this:\n\n<!-- prettier-ignore -->\n  ```ts\n  const expected = '400ms (a-b|)';\n  const values = {\n    a: 'value emitted',\n    b: 'another value emitted',\n  };\n\n  expectObservable(someStreamForTesting).toBe(expected, values);\n\n  // This would work also\n  const expected = '400ms (0-1|)';\n  const values = [\n    'value emitted',\n    'another value emitted'\n  ];\n\n  expectObservable(someStreamForTesting).toBe(expected, values);\n  ```\n\n- `'()'` sync groupings: When multiple events need to be in the same frame synchronously, parentheses are used to group those events. You can group next'd values, a completion, or an error in this manner. The position of the initial `(` determines the time at which its values are emitted. While it can be counter-intuitive at first, after all the values have synchronously emitted time will progress a number of frames equal to the number of ASCII characters in the group, including the parentheses. e.g. `'(abc)'` will emit the values of a, b, and c synchronously in the same frame and then advance virtual time by 5 frames, `'(abc)'.length === 5`. This is done because it often helps you vertically align your marble diagrams, but it's a known pain point in real-world testing. [Learn more about known issues](#known-issues).\n- `'^'` subscription point: (hot observables only) shows the point at which the tested observables will be subscribed to the hot observable. This is the \"zero frame\" for that observable, every frame before the `^` will be negative. Negative time might seem pointless, but there are in fact advanced cases where this is necessary, usually involving ReplaySubjects.\n\n### Time progression syntax\n\nThe new time progression syntax takes inspiration from the CSS duration syntax. It's a number (integer or floating point) immediately followed by a unit; ms (milliseconds), s (seconds), m (minutes). e.g. `100ms`, `1.4s`, `5.25m`.\n\nWhen it's not the first character of the diagram it must be padded a space before/after to disambiguate it from a series of marbles. e.g. `a 1ms b` needs the spaces because `a1msb` will be interpreted as `['a', '1', 'm', 's', 'b']` where each of these characters is a value that will be next()'d as-is.\n\n**NOTE**: You may have to subtract 1 millisecond from the time you want to progress because the alphanumeric marbles (representing an actual emitted value) _advance time 1 virtual frame_ themselves already, after they emit. This can be counter-intuitive and frustrating, but for now it is indeed correct.\n\n<!-- prettier-ignore -->\n```ts\nconst input = ' -a-b-c|';\nconst expected = '-- 9ms a 9ms b 9ms (c|)';\n\n// Depending on your personal preferences you could also\n// use frame dashes to keep vertical alignment with the input.\n// const input = ' -a-b-c|';\n// const expected = '------- 4ms a 9ms b 9ms (c|)';\n// or\n// const expected = '-----------a 9ms b 9ms (c|)';\n\nconst result = cold(input).pipe(\n  concatMap((d) => of(d).pipe(\n    delay(10)\n  ))\n);\n\nexpectObservable(result).toBe(expected);\n```\n\n### Examples\n\n`'-'` or `'------'`: Equivalent to {@link NEVER}, or an observable that never emits or errors or completes.\n\n`|`: Equivalent to {@link EMPTY}, or an observable that never emits and completes immediately.\n\n`#`: Equivalent to {@link throwError}, or an observable that never emits and errors immediately.\n\n`'--a--'`: An observable that waits 2 \"frames\", emits value `a` on frame 2 and then never completes.\n\n`'--a--b--|'`: On frame 2 emit `a`, on frame 5 emit `b`, and on frame 8, `complete`.\n\n`'--a--b--#'`: On frame 2 emit `a`, on frame 5 emit `b`, and on frame 8, `error`.\n\n`'-a-^-b--|'`: In a hot observable, on frame -2 emit `a`, then on frame 2 emit `b`, and on frame 5, `complete`.\n\n`'--(abc)-|'`: on frame 2 emit `a`, `b`, and `c`, then on frame 8, `complete`.\n\n`'-----(a|)'`: on frame 5 emit `a` and `complete`.\n\n`'a 9ms b 9s c|'`: on frame 0 emit `a`, on frame 10 emit `b`, on frame 9,011 emit `c`, then on frame 9,012 `complete`.\n\n`'--a 2.5m b'`: on frame 2 emit `a`, on frame 150,003 emit `b` and never complete.\n\n## Subscription marbles\n\nThe `expectSubscriptions` helper allows you to assert that a `cold()` or `hot()` Observable you created was subscribed/unsubscribed to at the correct point in time. The `subscriptionMarbles` parameter to `expectObservable` allows your test to defer subscription to a later virtual time, and/or unsubscribe even if the observable being tested has not yet completed.\n\nThe subscription marble syntax is slightly different to conventional marble syntax.\n\n- `'-'` time: 1 frame time passing.\n- `[0-9]+[ms|s|m]` time progression: the time progression syntax lets you progress virtual time by a specific amount. It's a number, followed by a time unit of `ms` (milliseconds), `s` (seconds), or `m` (minutes) without any space between them, e.g. `a 10ms b`. See [Time progression syntax](#time-progression-syntax) for more details.\n- `'^'` subscription point: shows the point in time at which a subscription happens.\n- `'!'` unsubscription point: shows the point in time at which a subscription is unsubscribed.\n\nThere should be **at most one** `^` point in a subscription marble diagram, and **at most one** `!` point. Other than that, the `-` character is the only one allowed in a subscription marble diagram.\n\n### Examples\n\n`'-'` or `'------'`: no subscription ever happened.\n\n`'--^--'`: a subscription happened after 2 \"frames\" of time passed, and the subscription was not unsubscribed.\n\n`'--^--!-'`: on frame 2 a subscription happened, and on frame 5 was unsubscribed.\n\n`'500ms ^ 1s !'`: on frame 500 a subscription happened, and on frame 1,501 was unsubscribed.\n\nGiven a hot source, test multiple subscribers that subscribe at different times:\n\n```ts\ntestScheduler.run(({ hot, expectObservable }) => {\n  const source = hot('--a--a--a--a--a--a--a--');\n  const sub1 = '      --^-----------!';\n  const sub2 = '      ---------^--------!';\n  const expect1 = '   --a--a--a--a--';\n  const expect2 = '   -----------a--a--a-';\n\n  expectObservable(source, sub1).toBe(expect1);\n  expectObservable(source, sub2).toBe(expect2);\n});\n```\n\nManually unsubscribe from a source that will never complete:\n\n```ts\nit('should repeat forever', () => {\n  const testScheduler = createScheduler();\n\n  testScheduler.run(({ expectObservable }) => {\n    const foreverStream$ = interval(1).pipe(mapTo('a'));\n\n    // Omitting this arg may crash the test suite.\n    const unsub = '------!';\n\n    expectObservable(foreverStream$, unsub).toBe('-aaaaa');\n  });\n});\n```\n\n## Synchronous Assertion\n\nSometimes, we need to assert changes in state _after_ an observable stream has completed - such as when a side effect like `tap` updates a variable. Outside of Marbles testing with TestScheduler, we might think of this as creating a delay or waiting before making our assertion.\n\nFor example:\n\n```ts\nlet eventCount = 0;\n\nconst s1 = cold('--a--b|', { a: 'x', b: 'y' });\n\n// side effect using 'tap' updates a variable\nconst result = s1.pipe(tap(() => eventCount++));\n\nexpectObservable(result).toBe('--a--b|', { a: 'x', b: 'y' });\n\n// flush - run 'virtual time' to complete all outstanding hot or cold observables\nflush();\n\nexpect(eventCount).toBe(2);\n```\n\nIn the above situation we need the observable stream to complete so that we can test the variable was set to the correct value. The TestScheduler runs in 'virtual time' (synchronously), but doesn't normally run (and complete) until the testScheduler callback returns. The flush() method manually triggers the virtual time so that we can test the local variable after the observable completes.\n\n---\n\n## Known issues\n\n### RxJS code that consumes Promises cannot be directly tested\n\nIf you have RxJS code that uses asynchronous scheduling - e.g. Promises, etc. - you can't reliably use marble diagrams _for that particular code_. This is because those other scheduling methods won't be virtualized or known to TestScheduler.\n\nThe solution is to test that code in isolation, with the traditional asynchronous testing methods of your testing framework. The specifics depend on your testing framework of choice, but here's a pseudo-code example:\n\n```ts\n// Some RxJS code that also consumes a Promise, so TestScheduler won't be able\n// to correctly virtualize and the test will always be really asynchronous.\nconst myAsyncCode = () => from(Promise.resolve('something'));\n\nit('has async code', (done) => {\n  myAsyncCode().subscribe((d) => {\n    assertEqual(d, 'something');\n    done();\n  });\n});\n```\n\nOn a related note, you also can't currently assert delays of zero, even with `AsyncScheduler`, e.g. `delay(0)` is like saying `setTimeout(work, 0)`. This schedules a new [\"task\" aka \"macrotask\"](https://jakearchibald.com/2015/tasks-microtasks-queues-and-schedules/), so it's asynchronous, but without an explicit passage of time.\n\n### Behavior is different outside of `testScheduler.run(callback)`\n\nThe `TestScheduler` has been around since v5, but was actually intended for testing RxJS itself by the maintainers, rather than for use in regular user apps. Because of this, some of the default behaviors and features of the TestScheduler did not work well (or at all) for users. In v6 we introduced the `testScheduler.run(callback)` method which allowed us to provide new defaults and features in a non-breaking way, but it's still possible to [use the TestScheduler outside](https://github.com/ReactiveX/rxjs/blob/7113ae4b451dd8463fae71b68edab96079d089df/docs_app/content/guide/testing/internal-marble-tests.md) of `testScheduler.run(callback)`. It's important to note that if you do so, there are some major differences in how it will behave.\n\n- `TestScheduler` helper methods have more verbose names, like `testScheduler.createColdObservable()` instead of `cold()`.\n- The testScheduler instance is _not_ automatically used by operators that use `AsyncScheduler`, e.g. `delay`, `debounceTime`, etc., so you have to explicitly pass it to them.\n- There is NO support for time progression syntax e.g. `-a 100ms b-|`.\n- 1 frame is 10 virtual milliseconds by default. i.e. `TestScheduler.frameTimeFactor = 10`.\n- Each whitespace `' '` equals 1 frame, same as a hyphen `'-'`.\n- There is a hard maximum number of frames set at 750 i.e. `maxFrames = 750`. After 750 they are silently ignored.\n- You must explicitly flush the scheduler.\n\nWhile at this time usage of the TestScheduler outside of `testScheduler.run(callback)` has not been officially deprecated, it is discouraged because it is likely to cause confusion.\n"
  },
  {
    "path": "apps/rxjs.dev/content/license.md",
    "content": "@title\n@description\nThe MIT License\n\nCopyright (c) 2014-2018 Google, Inc., RxJS Team Members and Contributors\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n"
  },
  {
    "path": "apps/rxjs.dev/content/maintainer-guidelines.md",
    "content": "# Maintainer Guidelines\n\nThese are guidelines for maintainers of this repository as (mostly) [gifted to us by](https://github.com/ReactiveX/RxJS/issues/121#issue-97747542)\nHis Beardliness, @jeffbcross. They are words to live by for those that are tasked with reviewing and merging pull requests and otherwise\nshepherding the community. As the roster of trusted maintainers grows, we'll expect these guidelines to stay pretty\nmuch the same (but suggestions are always welcome).\n\n### The ~~10~~ 6 Commandments\n\n- **[Code of Conduct](../../../CODE_OF_CONDUCT.md)**. We should be setting a good example and be welcoming to all. We should be listening\n  to all feedback from everyone in our community and respect their viewpoints and opinions.\n- **Be sure PRs meet [Contribution Guidelines](../../../CONTRIBUTING.md)**. It's important we keep our code base\n  and repository consistent. The best way to do this is to know and enforce the contribution guidelines.\n- **Clean, flat commit history**. We never click the green merge button on PRs, but instead we pull down\n  the PR branch and rebase it against master then replace master with the PR branch. See\n  [example gist](https://gist.github.com/jeffbcross/307c6da45d26e29030ef). This reduces noise in the commit\n  history, removing all of the merge commits, and keeps history flat. The flat history is beneficial\n  to tools/scripts that analyze commit ancestry.\n- **Always green master**. Failing master builds tend to cascade into other broken builds, and\n  frustration among other contributors who have rebased against a broken master. Much of our deployment\n  and other infrastructure is based on the assumption that master is always green, nothing should be\n  merged before Travis has confirmed that a PR is green, even for seemingly insignificant changes.\n  Nothing should be merged into a red master, and whomever broke it should drop everything and fix it\n  right away. Fixes should be submitted as a PR and verified as green instead of immediately merging\n  to master.\n- **No force pushes to master**. Only in rare circumstances should a force push to master be made,\n  and other maintainers should be notified beforehand. The most common situation for a justified force\n  push is when a commit has been pushed with an invalid message. The force push should be made as soon\n  as possible to reduce side effects.\n- **Small, logical commits**. A PR should be focused on a single problem, though that problem may be\n  reasonable to be broken into a few logical commits. For example, a global renaming may be best to be\n  broken into a single commit that renames all files, and then a commit that renames symbols within files.\n  This makes the review process simpler easier, so the diff of the meaty commit (where symbols are\n  renamed) can be easily understood than if both were done in the same commit, in which case github would\n  just show a deleted file and an added file.\n"
  },
  {
    "path": "apps/rxjs.dev/content/marketing/announcements.json",
    "content": "[\n  {\n    \"startDate\": \"2019-12-20\",\n    \"endDate\": \"2020-03-20\",\n    \"message\": \"<strong style=\\\"font-weight: 700\\\" class=\\\"text-headline\\\">RxJS Live Conference in London</strong><br/>March 19th-20th, 2020\",\n    \"imageUrl\": \"generated/images/marketing/home/rxjs-live-london.svg\",\n    \"linkUrl\": \"https://www.rxjs.live/london\"\n  }\n]"
  },
  {
    "path": "apps/rxjs.dev/content/marketing/api.html",
    "content": "<h1 class=\"no-toc\">API List</h1>\n<aio-api-list></aio-api-list>\n"
  },
  {
    "path": "apps/rxjs.dev/content/marketing/contributors.json",
    "content": "{\n  \"ben\": {\n    \"name\": \"Ben Lesh\",\n    \"role\": \"Developer\",\n    \"github\": \"https://github.com/benlesh\",\n    \"picture\": \"https://avatars2.githubusercontent.com/u/1540597\",\n    \"twitter\": \"https://twitter.com/BenLesh\",\n    \"website\": \"https://benlesh.com\",\n    \"group\": \"Core Team\"\n  },\n  \"paul\": {\n    \"name\": \"Paul Taylor\",\n    \"role\": \"Developer\",\n    \"github\": \"https://github.com/trxcllnt\",\n    \"picture\": \"https://avatars2.githubusercontent.com/u/178183\",\n    \"twitter\": \"https://twitter.com/trxcllnt\",\n    \"website\": \"http://graphistry.com\",\n    \"group\": \"Core Team\"\n  },\n  \"oj\": {\n    \"name\": \"OJ Kwon\",\n    \"role\": \"Developer\",\n    \"github\": \"https://github.com/kwonoj\",\n    \"picture\": \"https://avatars1.githubusercontent.com/u/1210596\",\n    \"twitter\": \"https://twitter.com/_ojkwon\",\n    \"group\": \"Core Team\"\n  },\n  \"david\": {\n    \"name\": \"David Driscoll\",\n    \"role\": \"Developer\",\n    \"github\": \"https://github.com/david-driscoll\",\n    \"picture\": \"https://avatars0.githubusercontent.com/u/1269157\",\n    \"twitter\": \"https://twitter.com/david_dotnet\",\n    \"website\": \"http://david-driscoll.github.io\",\n    \"group\": \"Core Team\"\n  },\n  \"tracy\": {\n    \"name\": \"Tracy Lee\",\n    \"role\": \"Developer\",\n    \"github\": \"https://github.com/ladyleet\",\n    \"picture\": \"https://avatars0.githubusercontent.com/u/8270563\",\n    \"twitter\": \"https://twitter.com/ladyleet\",\n    \"website\": \"http://thisdot.co\",\n    \"group\": \"Core Team\"\n  },\n  \"nic\": {\n    \"name\": \"Nicholas Jamieson\",\n    \"group\": \"Core Team\",\n    \"github\": \"https://github.com/cartant\",\n    \"picture\": \"https://avatars0.githubusercontent.com/u/3878593\",\n    \"twitter\": \"https://twitter.com/ncjamieson\",\n    \"website\": \"http://cartant.com\",\n    \"role\": \"Developer\"\n  },\n  \"tracy-lee\": {\n    \"name\": \"Tracy Lee\",\n    \"role\": \"Developer\",\n    \"github\": \"https://github.com/ladyleet\",\n    \"picture\": \"https://avatars0.githubusercontent.com/u/8270563\",\n    \"twitter\": \"https://twitter.com/ladyleet\",\n    \"website\": \"http://thisdot.co\",\n    \"group\": \"Learning Team\"\n  },\n  \"ashwin\": {\n    \"name\": \"Ashwin Sureshkumar\",\n    \"role\": \"Developer\",\n    \"github\": \"https://github.com/ashwin-sureshkumar\",\n    \"picture\": \"https://avatars0.githubusercontent.com/u/4744080\",\n    \"twitter\": \"https://twitter.com/Sureshkumar_Ash\",\n    \"website\": \"https://t.co/XduklnxpK3\",\n    \"group\": \"Learning Team\"\n  },\n  \"brian\": {\n    \"name\": \"Brian Troncone\",\n    \"role\": \"Developer\",\n    \"github\": \"https://github.com/btroncone\",\n    \"picture\": \"https://avatars3.githubusercontent.com/u/5085101\",\n    \"twitter\": \"http://twitter.com/btroncone\",\n    \"group\": \"Learning Team\"\n  },\n  \"sumit\": {\n    \"name\": \"Sumit Arora\",\n    \"role\": \"Developer\",\n    \"github\": \"https://github.com/sumitarora\",\n    \"picture\": \"https://avatars3.githubusercontent.com/u/198247\",\n    \"twitter\": \"https://twitter.com/arorasumit\",\n    \"website\": \"http://www.arorasumit.com/\",\n    \"group\": \"Learning Team\"\n  },\n  \"jen\": {\n    \"name\": \"Jen Luker\",\n    \"role\": \"Developer, A11y\",\n    \"github\": \"https://github.com/knitcodemonkey\",\n    \"picture\": \"https://avatars0.githubusercontent.com/u/1584489\",\n    \"twitter\": \"https://twitter.com/knitcodemonkey\",\n    \"website\": \"http://jenluker.com\",\n    \"group\": \"Learning Team\"\n  },\n  \"jan\": {\n    \"name\": \"Jan-Niklas Wortmann\",\n    \"role\": \"Developer\",\n    \"github\": \"https://github.com/JWO719\",\n    \"picture\": \"https://avatars3.githubusercontent.com/u/6104311\",\n    \"twitter\": \"https://twitter.com/niklas_wortmann\",\n    \"group\": \"Learning Team\"\n  },\n  \"matthew\": {\n    \"name\": \"Matthew Podwysocki\",\n    \"role\": \"Developer\",\n    \"github\": \"https://github.com/mattpodwysocki\",\n    \"picture\": \"https://avatars0.githubusercontent.com/u/49051\",\n    \"twitter\": \"https://twitter.com/mattpodwysocki\",\n    \"group\": \"Alumn\"\n  },\n  \"andre\": {\n    \"name\": \"André Staltz\",\n    \"role\": \"Developer\",\n    \"github\": \"https://github.com/staltz\",\n    \"picture\": \"https://avatars0.githubusercontent.com/u/90512\",\n    \"twitter\": \"https://twitter.com/andrestaltz\",\n    \"website\": \"http://staltz.com\",\n    \"group\": \"Alumn\"\n  },\n  \"jay\": {\n    \"name\": \"Jay Phelps\",\n    \"role\": \"Developer\",\n    \"github\": \"https://github.com/jayphelps\",\n    \"picture\": \"https://avatars0.githubusercontent.com/u/762949\",\n    \"twitter\": \"https://twitter.com/_jayphelps\",\n    \"website\": \"http://jayphelps.com\",\n    \"group\": \"Alumn\"\n  },\n  \"nat\": {\n    \"name\": \"Natalie Smith\",\n    \"role\": \"Developer\",\n    \"github\": \"https://github.com/natmegs\",\n    \"picture\": \"https://avatars0.githubusercontent.com/u/19582796\",\n    \"twitter\": \"https://twitter.com/natalie_megan\",\n    \"website\": \"http://nataliesmith.ca/\",\n    \"group\": \"Contributors\"\n  },\n  \"cedric\": {\n    \"name\": \"Cédric Soulas\",\n    \"role\": \"Developer\",\n    \"github\": \"https://github.com/cedricss\",\n    \"picture\": \"https://avatars0.githubusercontent.com/u/802010\",\n    \"twitter\": \"https://twitter.com/CedricSoulas\",\n    \"website\": \"http://reactive.how/\",\n    \"group\": \"Contributors\"\n  },\n  \"jason\": {\n    \"name\": \"Jason Aden\",\n    \"role\": \"Developer\",\n    \"github\": \"https://github.com/jasonaden\",\n    \"picture\": \"https://avatars1.githubusercontent.com/u/516168\",\n    \"twitter\": \"https://twitter.com/jasonaden1\",\n    \"group\": \"Contributors\"\n  },\n  \"jan-niklas\": {\n    \"name\": \"Jan-Niklas Wortmann\",\n    \"role\": \"Developer\",\n    \"github\": \"https://github.com/JWO719\",\n    \"picture\": \"https://avatars3.githubusercontent.com/u/6104311\",\n    \"twitter\": \"https://twitter.com/niklas_wortmann\",\n    \"group\": \"Core Team\"\n  },\n  \"mladen\": {\n    \"name\": \"Mladen Jakovljević\",\n    \"role\": \"Developer\",\n    \"github\": \"https://github.com/jakovljevic-mladen\",\n    \"picture\": \"https://avatars3.githubusercontent.com/u/28087049\",\n    \"twitter\": \"https://twitter.com/jakovljevicMla\",\n    \"group\": \"Core Team\"\n  }\n}\n"
  },
  {
    "path": "apps/rxjs.dev/content/marketing/index.html",
    "content": "<!-- FULL HEADER BLOCK -->\n<header>\n\n  <!-- BACKGROUND IMAGE -->\n  <div class=\"hero\"></div>\n\n  <!-- INTRO SECTION -->\n  <section id=\"intro\">\n\n    <!-- LOGO -->\n    <div class=\"hero-logo\">\n      <img src=\"generated/images/marketing/home/Rx_Logo-512-512.png\" alt=\"RxJS logo\"/>\n    </div>\n\n    <!-- CONTAINER -->\n    <div class=\"homepage-container\">\n      <div class=\"headline-container\">\n        <h2 class=\"hero-headline no-toc\">RxJS</h2>\n        <span class=\"hero-subheadline\">Reactive Extensions Library for JavaScript</span>\n      </div>\n      <a class=\"button hero-cta\" href=\"/guide/overview\">Get Started</a>\n      <a class=\"button hero-cta\" href=\"/api\">API Docs</a>\n    </div>\n\n  </section>\n\n</header>\n\n<!-- MAIN CONTENT -->\n<article>\n\n  <h1 class=\"no-anchor no-toc\" style=\"display: none\"></h1>\n\n  <div class=\"home-rows\">\n\n  <aio-announcement-bar></aio-announcement-bar>\n  <a href=\"/deprecations/breaking-changes\">\n  <div layout=\"row\" class=\"home-row homepage-container\">\n      <div class=\"card\">\n        <div class=\"promo-1-desc l-pad-top-2\">\n          <div class=\"text-headline\">Version 7 released!</div>\n          <p class=\"text\">Here are a some of the benefits of running on the latest version</p>\n          <ul class=\"text\">\n            <li>~50% smaller</li>\n            <li>Improved typings</li>\n            <li>More consistent APIs</li>\n            <li>and much more...</li>\n          </ul>\n          <p class=\"text\">If you want to know more about the breaking changes, click here...</p>\n        </div>\n      </div>\n    </div>\n  </a>\n  \n\n  <div layout=\"row\" layout-xs=\"column\" class=\"home-row homepage-container\">\n\n    <div class=\"text-container\">\n      <div class=\"text-block promo-1-desc l-pad-top-2\">\n       <div class=\"text-headline\">Reactive Extensions Library for JavaScript</div>\n        <p class=\"text-body\">\n          RxJS is a library for reactive programming using Observables, to make it easier to compose asynchronous or callback-based code. This project is a rewrite of Reactive-Extensions/RxJS with better performance, better modularity, better debuggable call stacks, while staying mostly backwards compatible, with some breaking changes that reduce the API surface\n        </p>\n      </div>\n    </div>\n  </div>\n  <hr>\n  <div layout=\"row\" layout-xs=\"column\" class=\"home-row homepage-container\">\n    <div layout=\"row\" layout-xs=\"column\" class=\"home-row\">\n      <a href=\"code-of-conduct\">\n        <div class=\"card\">\n          <div class=\"card-text-container\">\n            <p>When participating in our community, you must follow our</p>\n            <div class=\"text-headline\">Code of Conduct</div>\n          </div>\n        </div>\n      </a>\n    </div>\n  </div><!-- end of home rows -->\n\n</article>\n"
  },
  {
    "path": "apps/rxjs.dev/content/marketing/operator-decision-tree.html",
    "content": "<aio-operator-decision-tree></aio-operator-decision-tree>"
  },
  {
    "path": "apps/rxjs.dev/content/marketing/team.html",
    "content": "<aio-contributor-list></aio-contributor-list>\r\n"
  },
  {
    "path": "apps/rxjs.dev/content/navigation.json",
    "content": "{\n  \"TopBar\": [\n    {\n      \"url\": \"guide/overview\",\n      \"title\": \"Overview\"\n    },\n    {\n      \"url\": \"api\",\n      \"title\": \"Reference\"\n    },\n    {\n      \"url\": \"team\",\n      \"title\": \"Team\"\n    }\n  ],\n  \"TopBarNarrow\": [],\n  \"SideNav\": [\n    {\n      \"url\": \"guide/overview\",\n      \"title\": \"Overview\",\n      \"tooltip\": \"RxJS Overview\",\n      \"children\": [\n        {\n          \"url\": \"guide/observable\",\n          \"title\": \"Observables\"\n        },\n        {\n          \"url\": \"guide/observer\",\n          \"title\": \"Observer\"\n        },\n        {\n          \"url\": \"guide/operators\",\n          \"title\": \"Operators\"\n        },\n        {\n          \"url\": \"guide/subscription\",\n          \"title\": \"Subscription\"\n        },\n        {\n          \"url\": \"guide/subject\",\n          \"title\": \"Subjects\"\n        },\n        {\n          \"url\": \"guide/scheduler\",\n          \"title\": \"Scheduler\"\n        },\n        {\n          \"url\": \"guide/testing/marble-testing\",\n          \"title\": \"Marble Testing\"\n        }\n      ]\n    },\n    {\n      \"url\": \"guide/installation\",\n      \"title\": \"Installation\",\n      \"tooltip\": \"Installation\"\n    },\n    {\n      \"url\": \"guide/importing\",\n      \"title\": \"Importing\",\n      \"tooltip\": \"RxJS Importing\"\n    },\n    {\n      \"url\": \"api\",\n      \"title\": \"Reference\",\n      \"tooltip\": \"RxJS Reference\"\n    },\n    {\n      \"url\": \"guide/glossary-and-semantics\",\n      \"title\": \"Glossary\",\n      \"tooltip\": \"Glossary and Semantics\"\n    },\n    {\n      \"tooltip\": \"Operator Decision Tree\",\n      \"url\": \"operator-decision-tree\",\n      \"title\": \"Operator Decision Tree\"\n    },\n    {\n      \"title\": \"Deprecations & Breaking Changes\",\n      \"children\": [\n        {\n          \"url\": \"deprecations/breaking-changes\",\n          \"title\": \"Breaking Changes\"\n        },\n        {\n          \"url\": \"deprecations/scheduler-argument\",\n          \"title\": \"Scheduler Argument\"\n        },\n        {\n          \"url\": \"deprecations/subscribe-arguments\",\n          \"title\": \"Subscribe Arguments\"\n        },\n        {\n          \"url\": \"deprecations/resultSelector\",\n          \"title\": \"ResultSelector Arguments\"\n        },\n        {\n          \"url\": \"deprecations/array-argument\",\n          \"title\": \"Array Arguments\"\n        },\n        {\n          \"url\": \"deprecations/multicasting\",\n          \"title\": \"Multicasting\"\n        },\n        {\n          \"url\": \"deprecations/to-promise\",\n          \"title\": \"Conversion to Promises\"\n        }\n      ]\n    },\n    {\n      \"url\": \"6-to-7-change-summary\",\n      \"title\": \"Detailed Change List\",\n      \"tooltip\": \"Detailed Change List\"\n    },\n    {\n      \"url\": \"code-of-conduct\",\n      \"title\": \"Code of Conduct\",\n      \"tooltip\": \"Code of Conduct\"\n    }\n  ],\n  \"docVersions\": [\n    {\n      \"title\": \"next\",\n      \"url\": \"https://next.rxjs.dev/\"\n    },\n    {\n      \"title\": \"stable\",\n      \"url\": \"https://rxjs.dev/\"\n    },\n    {\n      \"title\": \"v6\",\n      \"url\": \"https://v6.rxjs.dev/\"\n    }\n  ]\n}\n"
  },
  {
    "path": "apps/rxjs.dev/content/operator-decision-tree.yml",
    "content": "- label: 'I have one existing Observable, and'\n  children:\n    - label: I want to change each emitted value\n      children:\n        - label: to be a constant value\n          children:\n            - label: mapTo\n        - label: to be a value calculated through a formula\n          children:\n            - label: map\n    - label: I want to pick a property off each emitted value\n      children:\n        - label: map\n    - label: I want to spy the values being emitted without affecting them\n      children:\n        - label: tap\n    - label: I want to allow some values to pass\n      children:\n        - label: based on custom logic\n          children:\n            - label: filter\n        - label: if they are at the start of the Observable\n          children:\n            - label: and only the first value\n              children:\n                - label: first\n            - label: based on a given amount\n              children:\n                - label: take\n            - label: based on custom logic\n              children:\n                - label: takeWhile\n        - label: if they are exactly the n-th emission\n          children:\n            - label: elementAt\n        - label: if they are at the end of the Observable\n          children:\n            - label: and only the last value\n              children:\n                - label: last\n            - label: based on a given amount\n              children:\n                - label: takeLast\n        - label: until another Observable emits a value\n          children:\n            - label: takeUntil\n    - label: I want to ignore values\n      children:\n        - label: altogether\n          children:\n            - label: ignoreElements\n        - label: from the start of the Observable\n          children:\n            - label: based on a given amount\n              children:\n                - label: skip\n            - label: based on custom logic\n              children:\n                - label: skipWhile\n        - label: from the end of the Observable\n          children:\n            - label: skipLast\n        - label: until another Observable emits a value\n          children:\n            - label: skipUntil\n        - label: that match some previous value\n          children:\n            - label: according to value equality\n              children:\n                - label: emitted just before the current value\n                  children:\n                    - label: distinctUntilChanged\n                - label: emitted some time in the past\n                  children:\n                    - label: distinct\n            - label: according to a key or object property\n              children:\n                - label: emitted just before the current value\n                  children:\n                    - label: distinctUntilKeyChanged\n        - label: that occur too frequently\n          children:\n            - label: by emitting the first value in each time window\n              children:\n                - label: where time windows are determined by another Observable's emissions\n                  children:\n                    - label: throttle\n                - label: where time windows are determined by a time duration\n                  children:\n                    - label: throttleTime\n            - label: by emitting the last value in each time window\n              children:\n                - label: where time windows are determined by another Observable's emissions\n                  children:\n                    - label: audit\n                - label: where time windows are determined by a time duration\n                  children:\n                    - label: auditTime\n            - label: by emitting the last value as soon as enough silence has occurred\n              children:\n                - label: where the silence duration threshold is determined by another Observable\n                  children:\n                    - label: debounce\n                - label: where the silence duration threshold is determined by a time duration\n                  children:\n                    - label: debounceTime\n    - label: I want to compute a formula using all values emitted\n      children:\n        - label: and only output the final computed value\n          children:\n            - label: reduce\n        - label: and output the computed values when the source emits a value\n          children:\n            - label: scan\n        - label: and output the computed values as a nested Observable when the source emits a value\n          children:\n            - label: mergeScan\n        - label: and output the computed values as a nested Observable when the source emits a value while unsubscribing from the previous nested Observable\n          children:\n            - label: switchScan\n    - label: I want to wrap its messages with metadata\n      children:\n        - label: that describes each notification (next, error, or complete)\n          children:\n            - label: materialize\n        - label: that includes the time past since the last emitted value\n          children:\n            - label: timeInterval\n    - label: after a period of inactivity\n      children:\n        - label: I want to throw an error\n          children:\n            - label: timeout\n        - label: I want to switch to another Observable\n          children:\n            - label: timeoutWith\n    - label: I want to ensure there is only one value\n      children:\n        - label: single\n    - label: I want to know how many values it emits\n      children:\n        - label: count\n    - label: I want to prepend one value\n      children:\n        - label: startWith\n    - label: I want to delay the emissions\n      children:\n        - label: based on a given amount of time\n          children:\n            - label: delay\n        - label: based on the emissions of another Observable\n          children:\n            - label: delayWhen\n    - label: I want to group the values\n      children:\n        - label: until the Observable completes\n          children:\n            - label: and convert to an array\n              children:\n                - label: toArray\n            - label: and convert to a Promise\n              children:\n                - label: Observable\n                  method: toPromise\n        - label: consecutively in pairs, as arrays\n          children:\n            - label: pairwise\n        - label: 'based on a criterion, and output two Observables: those that match the criterion and those that do not'\n          children:\n            - label: partition\n        - label: in batches of a particular size\n          children:\n            - label: and emit the group as an array\n              children:\n                - label: bufferCount\n            - label: and emit the group as a nested Observable\n              children:\n                - label: windowCount\n        - label: based on time\n          children:\n            - label: and emit the group as an array\n              children:\n                - label: bufferTime\n            - label: and emit the group as a nested Observable\n              children:\n                - label: windowTime\n        - label: until another Observable emits\n          children:\n            - label: and emit the group as an array\n              children:\n                - label: buffer\n            - label: and emit the group as a nested Observable\n              children:\n                - label: window\n        - label: based on the emissions of an Observable created on-demand\n          children:\n            - label: and emit the group as an array\n              children:\n                - label: bufferWhen\n            - label: and emit the group as a nested Observable\n              children:\n                - label: windowWhen\n        - label: based on another Observable for opening a group, and an Observable for closing a group\n          children:\n            - label: and emit the group as an array\n              children:\n                - label: bufferToggle\n            - label: and emit the group as a nested Observable\n              children:\n                - label: windowToggle\n        - label: based on a key calculated from the emitted values\n          children:\n            - label: groupBy\n    - label: I want to start a new Observable for each value\n      children:\n        - label: and emit the values from all nested Observables in parallel\n          children:\n            - label: where the nested Observable is the same for every value\n              children:\n                - label: mergeMapTo\n            - label: where the nested Observable is calculated for each value\n              children:\n                - label: mergeMap\n        - label: and emit the values from each nested Observable in order\n          children:\n            - label: where the nested Observable is the same for every value\n              children:\n                - label: concatMapTo\n            - label: where the nested Observable is calculated for each value\n              children:\n                - label: concatMap\n        - label: and cancel the previous nested Observable when a new value arrives\n          children:\n            - label: where the nested Observable is the same for every value\n              children:\n                - label: switchMapTo\n            - label: where the nested Observable is calculated for each value\n              children:\n                - label: switchMap\n        - label: and ignore incoming values while the current nested Observable has not yet completed\n          children:\n            - label: exhaustMap\n        - label: and recursively start a new Observable for each new value\n          children:\n            - label: expand\n    - label: I want to perform custom operations\n      children:\n        - label: pipe\n    - label: I want to share a subscription between multiple subscribers\n      children:\n        - label: using a conventional Subject\n          children:\n            - label: and start it as soon as the first subscriber arrives\n              children:\n                - label: share\n            - label: and start it manually or imperatively\n              children:\n                - label: connectable\n        - label: using a specific subject implementation\n          children:\n            - label: share\n    - label: when an error occurs\n      children:\n        - label: I want to start a new Observable\n          children:\n            - label: catchError\n        - label: I want to re-subscribe\n          children:\n            - label: immediately\n              children:\n                - label: retry\n            - label: when another Observable emits\n              children:\n                - label: retryWhen\n    - label: when it completes\n      children:\n        - label: I want to re-subscribe\n          children:\n            - label: immediately\n              children:\n                - label: repeat\n            - label: when another Observable emits\n              children:\n                - label: repeatWhen\n        - label: I want to start a new Observable\n          children:\n            - label: concat\n    - label: when it completes, errors or unsubscribes, I want to execute a function\n      children:\n        - label: finalize\n    - label: I want to change the scheduler\n      children:\n        - label: that routes calls to subscribe\n          children:\n            - label: subscribeOn\n        - label: that routes values to observers\n          children:\n            - label: observeOn\n    - label: I want to combine this Observable with others, and\n      children:\n        - label: I want to receive values only from the Observable that emits a value first\n          children:\n            - label: race\n        - label: I want to output the values from either of them\n          children:\n            - label: merge\n        - label: I want to output a value computed from values of the source Observables\n          children:\n            - label: using the latest value of each source whenever any source emits\n              children:\n                - label: combineLatest\n            - label: using the latest value of each source only when the primary Observable emits\n              children:\n                - label: withLatestFrom\n            - label: using each source value only once\n              children:\n                - label: zip\n- label: 'I have some Observables to combine together as one Observable, and'\n  children:\n    - label: I want to receive values only from the Observable that emits a value first\n      children:\n        - label: race\n    - label: I want to be notified when all of them have completed\n      children:\n        - label: forkJoin\n    - label: I want to output the values from either of them\n      children:\n        - label: merge\n    - label: I want to output a value computed from values of the source Observables\n      children:\n        - label: using the latest value of each source whenever any source emits\n          children:\n            - label: combineLatest\n        - label: using each source value only once\n          children:\n            - label: zip\n    - label: I want to subscribe to each in order\n      children:\n        - label: concat\n- label: 'I have no Observables yet, and'\n  children:\n    - label: I want to create a new Observable\n      children:\n        - label: using custom logic\n          children:\n            - label: Observable\n              method: create\n        - label: using a state machine similar to a for loop\n          children:\n            - label: generate\n        - label: that throws an error\n          children:\n            - label: throwError\n        - label: that just completes, without emitting values\n          children:\n            - label: EMPTY\n        - label: that never emits anything\n          children:\n            - label: NEVER\n        - label: from an existing source of events\n          children:\n            - label: coming from the DOM or Node.js or similar\n              children:\n                - label: fromEvent\n            - label: that uses an API to add and remove event handlers\n              children:\n                - label: fromEventPattern\n        - label: from a Promise or an event source\n          children:\n            - label: from\n        - label: that iterates\n          children:\n            - label: over the values in an array\n              children:\n                - label: from\n            - label: over values in a numeric range\n              children:\n                - label: range\n            - label: over prefined values given as arguments\n              children:\n                - label: of\n        - label: that emits values on a timer\n          children:\n            - label: regularly\n              children:\n                - label: interval\n            - label: with an optional initial delay\n              children:\n                - label: timer\n        - label: which is built on demand when subscribed\n          children:\n            - label: defer\n    - label: I want to convert a callback to an Observable\n      children:\n        - label: supporting a conventional callback API\n          children:\n            - label: bindCallback\n        - label: supporting Node.js callback style API\n          children:\n            - label: bindNodeCallback\n"
  },
  {
    "path": "apps/rxjs.dev/database.rules.json",
    "content": "{\n  \"rules\": {\n    \".read\": \"auth != null\",\n    \".write\": \"auth != null\"\n  }\n}\n"
  },
  {
    "path": "apps/rxjs.dev/firebase.json",
    "content": "{\n  \"database\": {\n    \"rules\": \"database.rules.json\"\n  },\n  \"hosting\": {\n    \"public\": \"dist\",\n    \"target\": \"stable\",\n    \"cleanUrls\": true,\n    \"redirects\": [\n      //////////////////////////////////////////////////////////////////////////////////////////////\n      // README:\n      //   Redirects must also be handled by the ServiceWorker. If you add a redirect rule here,\n      //   make sure it is compatible with the configuration in `ngsw-config.json`.\n      //////////////////////////////////////////////////////////////////////////////////////////////\n\n      // Strip off the `.html` extension, because Firebase will not do this automatically any more\n      // (unless the new URL points to an existing file, which is not necessarily the case here).\n      { \"type\": 301, \"source\": \"/:somePath*/:file.html\", \"destination\": \"/:somePath*/:file\" },\n      { \"type\": 301, \"source\": \"/:topLevelFile.html\", \"destination\": \"/:topLevelFile\" },\n      { \"type\": 301, \"source\": \"/guide/v6/migration\", \"destination\": \"https://v6.rxjs.dev/guide/v6/migration\" },\n      { \"type\": 301, \"source\": \"/guide/v6/pipeable-operators\", \"destination\": \"https://v6.rxjs.dev/guide/v6/pipeable-operators\" }\n    ],\n    \"rewrites\": [\n      {\n        \"source\": \"**/!(*.*)\",\n        \"destination\": \"/index.html\"\n      }\n    ],\n    \"headers\": [\n      {\n        \"source\": \"/\",\n        \"headers\": [\n          {\n            \"key\": \"Link\",\n            \"value\": \"</generated/navigation.json>;rel=preload;as=fetch,</generated/docs/index.json>;rel=preload;as=fetch\"\n          }\n        ]\n      }\n    ]\n  }\n}\n"
  },
  {
    "path": "apps/rxjs.dev/ngsw-config.json",
    "content": "{\n  \"index\": \"/index.html\",\n  \"assetGroups\": [\n    {\n      \"name\": \"app-shell\",\n      \"installMode\": \"prefetch\",\n      \"updateMode\": \"prefetch\",\n      \"resources\": {\n        \"files\": [\n          \"/index.html\",\n          \"/pwa-manifest.json\",\n          \"/app/search/search-worker.js\",\n          \"/assets/images/favicons/favicon.ico\",\n          \"/assets/js/*.js\",\n          \"/*.css\",\n          \"/*.js\"\n        ],\n        \"urls\": [\n          \"https://fonts.googleapis.com/**\",\n          \"https://fonts.gstatic.com/s/**\",\n          \"https://maxcdn.bootstrapcdn.com/**\"\n        ]\n      }\n    }, {\n      \"name\": \"assets-eager\",\n      \"installMode\": \"prefetch\",\n      \"updateMode\": \"prefetch\",\n      \"resources\": {\n        \"files\": [\n          \"/assets/images/**\",\n          \"/generated/images/marketing/**\",\n          \"!/assets/images/favicons/**\",\n          \"!/**/_unused/**\",\n          \"!/assets/images/marble-diagrams/**\"\n        ]\n      }\n    }, {\n      \"name\": \"assets-lazy\",\n      \"installMode\": \"lazy\",\n      \"updateMode\": \"prefetch\",\n      \"resources\": {\n        \"files\": [\n          \"/assets/images/favicons/**\",\n          \"!/**/_unused/**\"\n        ]\n      }\n    }, {\n      \"name\": \"docs-index\",\n      \"installMode\": \"prefetch\",\n      \"updateMode\": \"prefetch\",\n      \"resources\": {\n        \"files\": [\n          \"/generated/*.json\",\n          \"/generated/docs/*.json\",\n          \"/generated/docs/api/api-list.json\",\n          \"/generated/docs/app/search-data.json\"\n        ]\n      }\n    }, {\n      \"name\": \"docs-lazy\",\n      \"installMode\": \"lazy\",\n      \"updateMode\": \"lazy\",\n      \"resources\": {\n        \"files\": [\n          \"/generated/docs/**/*.json\",\n          \"/generated/images/**\",\n          \"!/**/_unused/**\"\n        ]\n      }\n    }, {\n      \"name\": \"marble-diagrams\",\n      \"installMode\": \"lazy\",\n      \"updateMode\": \"lazy\",\n      \"resources\": {\n        \"files\": [\n          \"/assets/images/marble-diagrams/**\"\n        ]\n      }\n    }\n  ]\n}\n"
  },
  {
    "path": "apps/rxjs.dev/package.json",
    "content": "{\n  \"name\": \"rxjs.dev\",\n  \"version\": \"1.0.0\",\n  \"main\": \"index.js\",\n  \"repository\": \"git@github.com:ReactiveX/rxjs.git\",\n  \"author\": \"RxJS\",\n  \"license\": \"MIT\",\n  \"scripts\": {\n    \"ng\": \"ng\",\n    \"firebase\": \"firebase\",\n    \"start\": \"ng serve --configuration=fast\",\n    \"start:docker\": \"ng serve --configuration=stable --host 0.0.0.0\",\n    \"setup\": \"yarn ~~clean-generated && yarn docs\",\n    \"prebuild\": \"yarn setup\",\n    \"build\": \"yarn ~~build\",\n    \"lint\": \"yarn docs-lint && ng lint && yarn tools-lint\",\n    \"test\": \"ng test\",\n    \"pree2e\": \"yarn update-webdriver\",\n    \"e2e\": \"ng e2e --no-webdriver-update\",\n    \"e2e-prod\": \"yarn e2e --environment=dev --target=production\",\n    \"http-server\": \"http-server\",\n    \"test-pwa-score-localhost\": \"concurrently --kill-others --success first \\\"http-server dist -p 4200 --silent\\\" \\\"yarn test-pwa-score http://localhost:4200 90\\\"\",\n    \"test-pwa-score\": \"node scripts/test-pwa-score\",\n    \"deploy-production\": \"scripts/deploy-to-firebase.sh\",\n    \"payload-size\": \"scripts/payload.sh\",\n    \"docs\": \"npx ts-node -P tsconfig.docs.json ../../node_modules/dgeni/lib/gen-docs.js ./tools/transforms/angular.io-package\",\n    \"docs-watch\": \"npx ts-node -P tsconfig.docs.json tools/transforms/authors-package/watchr.js\",\n    \"docs-lint\": \"eslint --ignore-path=\\\"tools/transforms/.eslintignore\\\" tools/transforms\",\n    \"docs-test\": \"npx ts-node -P tsconfig.docs.json tools/transforms/test.js\",\n    \"firebase-utils-test\": \"jasmine-ts tools/firebase-test-utils/*.spec.ts\",\n    \"tools-lint\": \"eslint tools/firebase-test-utils\",\n    \"tools-test\": \"./scripts/deploy-to-firebase.test.sh && yarn docs-test && yarn firebase-utils-test\",\n    \"preserve-and-sync\": \"yarn docs\",\n    \"serve-and-sync\": \"concurrently --kill-others \\\"yarn docs-watch --watch-only\\\" \\\"yarn start\\\"\",\n    \"update-webdriver\": \"webdriver-manager update --standalone false --gecko false $CHROMEDRIVER_VERSION_ARG\",\n    \"~~build\": \"ng build --configuration=stable --source-map\",\n    \"~~clean-generated\": \"node --eval \\\"require('shelljs').rm('-rf', 'src/generated')\\\"\",\n    \"build:marbles\": \"ts-node -P ./tools/marbles/tsconfig.marbles.json ./tools/marbles/scripts/index.ts\"\n  },\n  \"engines\": {\n    \"node\": \">=10.9\"\n  },\n  \"private\": true,\n  \"dependencies\": {\n    \"@angular/animations\": \"^13.1.1\",\n    \"@angular/cdk\": \"^13.1.1\",\n    \"@angular/common\": \"^13.1.1\",\n    \"@angular/compiler\": \"^13.1.1\",\n    \"@angular/core\": \"^13.1.1\",\n    \"@angular/elements\": \"^13.1.1\",\n    \"@angular/forms\": \"^13.1.1\",\n    \"@angular/material\": \"^13.1.1\",\n    \"@angular/platform-browser\": \"^13.1.1\",\n    \"@angular/platform-browser-dynamic\": \"^13.1.1\",\n    \"@angular/router\": \"^13.1.1\",\n    \"@angular/service-worker\": \"^13.1.1\",\n    \"@stackblitz/sdk\": \"^1.5.3\",\n    \"@webcomponents/custom-elements\": \"^1.5.0\",\n    \"core-js\": \"^3.33.3\",\n    \"eyes.selenium\": \"^3.7.0\",\n    \"rxjs\": \"^7.5.1\",\n    \"tslib\": \"^2.3.1\",\n    \"zone.js\": \"~0.11.4\"\n  },\n  \"devDependencies\": {\n    \"@angular-devkit/build-angular\": \"~13.1.2\",\n    \"@angular-eslint/builder\": \"^13.0.0\",\n    \"@angular-eslint/eslint-plugin\": \"^13.0.0\",\n    \"@angular-eslint/eslint-plugin-template\": \"^13.0.0\",\n    \"@angular-eslint/template-parser\": \"^13.0.0\",\n    \"@angular/cli\": \"^13.1.2\",\n    \"@angular/compiler-cli\": \"^13.1.1\",\n    \"@jsdevtools/rehype-inline-svg\": \"^1.1.1\",\n    \"@swirly/parser\": \"^0.18.1\",\n    \"@swirly/renderer-node\": \"^0.18.2\",\n    \"@swirly/types\": \"^0.18.1\",\n    \"@types/jasmine\": \"~3.6.0\",\n    \"@types/jasminewd2\": \"^2.0.3\",\n    \"@types/lunr\": \"^2.3.3\",\n    \"@types/node\": \"^20.11.0\",\n    \"@types/svgo\": \"^1.3.3\",\n    \"@types/trusted-types\": \"^2.0.7\",\n    \"@types/yamljs\": \"^0.2.34\",\n    \"@typescript-eslint/eslint-plugin\": \"^6.9.0\",\n    \"@typescript-eslint/parser\": \"^6.9.1\",\n    \"archiver\": \"^3.0.0\",\n    \"canonical-path\": \"^1.0.0\",\n    \"chalk\": \"^2.1.0\",\n    \"cjson\": \"^0.5.0\",\n    \"concurrently\": \"^5.3.0\",\n    \"cross-spawn\": \"^6.0.5\",\n    \"css-selector-parser\": \"^1.3.0\",\n    \"dgeni\": \"^0.4.14\",\n    \"dgeni-packages\": \"^0.30.0\",\n    \"eslint\": \"^8.0.0\",\n    \"eslint-plugin-import\": \"^2.23.4\",\n    \"eslint-plugin-jasmine\": \"^4.1.2\",\n    \"eslint-plugin-jsdoc\": \"^46.8.2\",\n    \"eslint-plugin-prefer-arrow\": \"^1.2.3\",\n    \"firebase-tools\": \"^9.3.0\",\n    \"fs-extra\": \"^8.0.1\",\n    \"globby\": \"^9.2.0\",\n    \"hast-util-is-element\": \"^1.0.3\",\n    \"hast-util-to-string\": \"^1.0.2\",\n    \"html\": \"^1.0.0\",\n    \"http-server\": \"^0.12.3\",\n    \"ignore\": \"^5.1.2\",\n    \"image-size\": \"^0.7.4\",\n    \"jasmine\": \"^4.1.0\",\n    \"jasmine-core\": \"~4.1.0\",\n    \"jasmine-marbles\": \"^0.9.2\",\n    \"jasmine-spec-reporter\": \"~7.0.0\",\n    \"jasmine-ts\": \"^0.4.0\",\n    \"jsdom\": \"^15.1.1\",\n    \"karma\": \"~6.3.16\",\n    \"karma-chrome-launcher\": \"~3.1.0\",\n    \"karma-cli\": \"^2.0.0\",\n    \"karma-coverage-istanbul-reporter\": \"~3.0.2\",\n    \"karma-jasmine\": \"~4.0.0\",\n    \"karma-jasmine-html-reporter\": \"^1.5.0\",\n    \"lighthouse\": \"^7.0.1\",\n    \"lodash\": \"^4.17.20\",\n    \"lunr\": \"^2.1.0\",\n    \"protractor\": \"~7.0.0\",\n    \"rehype-slug\": \"^2.0.3\",\n    \"remark\": \"^12.0.1\",\n    \"remark-html\": \"^13.0.2\",\n    \"rimraf\": \"^2.6.1\",\n    \"semver\": \"^6.1.1\",\n    \"shelljs\": \"^0.8.3\",\n    \"stemmer\": \"^2.0.0\",\n    \"svgo\": \"^1.3.2\",\n    \"svgson\": \"^4.1.0\",\n    \"tree-kill\": \"^1.2.2\",\n    \"ts-node\": \"^8.2.0\",\n    \"typescript\": \"4.5.4\",\n    \"unist-util-filter\": \"^1.0.2\",\n    \"unist-util-source\": \"^1.0.5\",\n    \"unist-util-visit\": \"^1.4.1\",\n    \"unist-util-visit-parents\": \"^2.1.2\",\n    \"watchr\": \"^4.1.0\",\n    \"xregexp\": \"^4.0.0\",\n    \"yamljs\": \"^0.3.0\",\n    \"yargs\": \"^13.2.4\"\n  },\n  \"nx\": {\n    \"implicitDependencies\": [\n      \"rxjs\"\n    ]\n  }\n}\n"
  },
  {
    "path": "apps/rxjs.dev/scripts/_payload-limits.json",
    "content": "{\n  \"aio\": {\n    \"master\": {\n      \"uncompressed\": {\n        \"inline\": 1971,\n        \"main\": 567849,\n        \"polyfills\": 40272,\n        \"prettify\": 14886\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "apps/rxjs.dev/scripts/deploy-to-firebase.sh",
    "content": "#!/usr/bin/env bash\n\n# WARNING: FIREBASE_TOKEN should NOT be printed.\nset +x -eu -o pipefail\n\n## Only deploy if this not a PR. PRs are deployed early in `build.sh`.\n\nif [[ $TRAVIS_PULL_REQUEST != \"false\" ]]; then\n  echo \"Skipping deploy because this is a PR build.\"\n  exit 0\nfi\n\n# Do not deploy if the current commit is not the latest on its branch.\n\nreadonly LATEST_COMMIT=$(git ls-remote origin $TRAVIS_BRANCH | cut -c1-40)\nif [[ $TRAVIS_COMMIT != $LATEST_COMMIT ]]; then\n  echo \"Skipping deploy because $TRAVIS_COMMIT is not the latest commit ($LATEST_COMMIT).\"\n  exit 0\nfi\n\n# The deployment mode is computed based on the branch we are building\nif [[ $TRAVIS_BRANCH == master ]]; then\n  readonly deployEnv=next\n#elif [[ $TRAVIS_BRANCH == $STABLE_BRANCH ]]; then\n#    readonly deployEnv=stable\n#else\n#  # Extract the major versions from the branches, e.g. the 4 from 4.3.x\n#  readonly majorVersion=${TRAVIS_BRANCH%%.*}\n#  readonly majorVersionStable=${STABLE_BRANCH%%.*}\n#\n#  # Do not deploy if the major version is not less than the stable branch major version\n#  if [[ !( \"$majorVersion\" < \"$majorVersionStable\" ) ]]; then\n#    echo \"Skipping deploy of branch \\\"${TRAVIS_BRANCH}\\\" to firebase.\"\n#    echo \"We only deploy archive branches with the major version less than the stable branch: \\\"${STABLE_BRANCH}\\\"\"\n#    exit 0\n#  fi\n#\n#  # Find the branch that has highest minor version for the given `$majorVersion`\n#  readonly mostRecentMinorVersion=$(\n#    # List the branches that start with the major version\n#    git ls-remote origin refs/heads/${majorVersion}.*.x |\n#    # Extract the version number\n#    awk -F'/' '{print $3}' |\n#    # Sort by the minor version\n#    sort -t. -k 2,2n |\n#    # Get the highest version\n#    tail -n1\n#  )\n#\n#  # Do not deploy as it is not the latest branch for the given major version\n#  if [[ $TRAVIS_BRANCH != $mostRecentMinorVersion ]]; then\n#    echo \"Skipping deploy of branch \\\"${TRAVIS_BRANCH}\\\" to firebase.\"\n#    echo \"There is a more recent branch with the same major version: \\\"${mostRecentMinorVersion}\\\"\"\n#    exit 0\n#  fi\n#\n#  readonly deployEnv=archive\nfi\n\ncase $deployEnv in\n  next)\n    readonly projectId=rxjs-dev\n    readonly deployedUrl=https://rxjs.dev\n    readonly firebaseToken=$FIREBASE_TOKEN\n    ;;\n#  stable)\n#    readonly projectId=beta-rxjsdocs\n#    readonly deployedUrl=https://beta-rxjsdocs.firebaseapp.com/\n#    readonly firebaseToken=$FIREBASE_TOKEN\n#    ;;\n  # archive)\n  #   readonly projectId=angular-io-${majorVersion}\n  #   readonly deployedUrl=https://v${majorVersion}.angular.io/\n  #   readonly firebaseToken=$FIREBASE_TOKEN\n  #   ;;\nesac\n\necho \"Git branch        : $TRAVIS_BRANCH\"\necho \"Build/deploy mode : $deployEnv\"\necho \"Firebase project  : $projectId\"\necho \"Deployment URL    : $deployedUrl\"\n\nif [[ ${1:-} == \"--dry-run\" ]]; then\n  exit 0\nfi\n\n# Deploy\n(\n  cd \"`dirname $0`/..\"\n\n  # Build the app\n  yarn build --env=$deployEnv\n\n  # Include any mode-specific files\n  cp -rf src/extra-files/$deployEnv/. dist/\n\n  # Check payload size\n  # yarn payload-size\n\n  # Deploy to Firebase\n  firebase use \"$projectId\" --token \"$firebaseToken\"\n  firebase deploy --message \"Commit: $TRAVIS_COMMIT\" --non-interactive --token \"$firebaseToken\"\n\n  # Run PWA-score tests\n  # yarn test-pwa-score \"$deployedUrl\" \"$MIN_PWA_SCORE\"\n)\n"
  },
  {
    "path": "apps/rxjs.dev/scripts/deploy-to-firebase.test.sh",
    "content": "#!/usr/bin/env bash\nset +x -eu -o pipefail\n\nfunction check {\n  if [[ $1 == $2 ]]; then\n    echo Pass\n    exit 0\n  fi\n  echo Fail\n  echo ---- Expected ----\n  echo \"$2\"\n  echo ---- Actual   ----\n  echo \"$1\"\n  exit 1\n}\n\n(\n  echo ===== master - skip deploy - pull request\n  actual=$(\n    export TRAVIS_PULL_REQUEST=true\n    `dirname $0`/deploy-to-firebase.sh --dry-run\n  )\n  expected=\"Skipping deploy because this is a PR build.\"\n  check \"$actual\" \"$expected\"\n)\n\n(\n  echo ===== master - deploy success\n  actual=$(\n    export TRAVIS_PULL_REQUEST=false\n    export TRAVIS_BRANCH=master\n    export TRAVIS_COMMIT=$(git ls-remote origin master | cut -c-40)\n    export FIREBASE_TOKEN=XXXXX\n    `dirname $0`/deploy-to-firebase.sh --dry-run\n  )\n  expected=\"Git branch        : master\nBuild/deploy mode : next\nFirebase project  : aio-staging\nDeployment URL    : https://next.angular.io/\"\n  check \"$actual\" \"$expected\"\n)\n\n(\n  echo ===== master - skip deploy - commit not HEAD\n  actual=$(\n    export TRAVIS_PULL_REQUEST=false\n    export TRAVIS_BRANCH=master\n    export TRAVIS_COMMIT=DUMMY_TEST_COMMIT\n    `dirname $0`/deploy-to-firebase.sh --dry-run\n  )\n  expected=\"Skipping deploy because DUMMY_TEST_COMMIT is not the latest commit ($(git ls-remote origin master | cut -c1-40)).\"\n  check \"$actual\" \"$expected\"\n)\n\n(\n  echo ===== stable - deploy success\n  actual=$(\n    export TRAVIS_PULL_REQUEST=false\n    export TRAVIS_BRANCH=4.3.x\n    export STABLE_BRANCH=4.3.x\n    export TRAVIS_COMMIT=$(git ls-remote origin 4.3.x | cut -c-40)\n    export FIREBASE_TOKEN=XXXXX\n    `dirname $0`/deploy-to-firebase.sh --dry-run\n  )\n  expected=\"Git branch        : 4.3.x\nBuild/deploy mode : stable\nFirebase project  : angular-io\nDeployment URL    : https://angular.io/\"\n  check \"$actual\" \"$expected\"\n)\n\n(\n  echo ===== stable - skip deploy - commit not HEAD\n  actual=$(\n    export TRAVIS_PULL_REQUEST=false\n    export TRAVIS_BRANCH=4.3.x\n    export STABLE_BRANCH=4.3.x\n    export TRAVIS_COMMIT=DUMMY_TEST_COMMIT\n    `dirname $0`/deploy-to-firebase.sh --dry-run\n  )\n  expected=\"Skipping deploy because DUMMY_TEST_COMMIT is not the latest commit ($(git ls-remote origin 4.3.x | cut -c1-40)).\"\n  check \"$actual\" \"$expected\"\n)\n\n(\n  echo ===== archive - deploy success\n  actual=$(\n    export TRAVIS_PULL_REQUEST=false\n    export TRAVIS_BRANCH=2.4.x\n    export STABLE_BRANCH=4.3.x\n    export TRAVIS_COMMIT=$(git ls-remote origin 2.4.x | cut -c-40)\n    export FIREBASE_TOKEN=XXXXX\n    `dirname $0`/deploy-to-firebase.sh --dry-run\n  )\n  expected=\"Git branch        : 2.4.x\nBuild/deploy mode : archive\nFirebase project  : angular-io-2\nDeployment URL    : https://v2.angular.io/\"\n  check \"$actual\" \"$expected\"\n)\n\n(\n  echo ===== archive - skip deploy - commit not HEAD\n  actual=$(\n    export TRAVIS_PULL_REQUEST=false\n    export TRAVIS_BRANCH=2.4.x\n    export STABLE_BRANCH=4.3.x\n    export TRAVIS_COMMIT=DUMMY_TEST_COMMIT\n    export FIREBASE_TOKEN=XXXXX\n    `dirname $0`/deploy-to-firebase.sh --dry-run\n  )\n  expected=\"Skipping deploy because DUMMY_TEST_COMMIT is not the latest commit ($(git ls-remote origin 2.4.x | cut -c1-40)).\"\n  check \"$actual\" \"$expected\"\n)\n\n(\n  echo ===== archive - skip deploy - major version too high, lower minor\n  actual=$(\n    export TRAVIS_PULL_REQUEST=false\n    export TRAVIS_BRANCH=2.1.x\n    export STABLE_BRANCH=2.2.x\n    export TRAVIS_COMMIT=$(git ls-remote origin 2.1.x | cut -c-40)\n    export FIREBASE_TOKEN=XXXXX\n    `dirname $0`/deploy-to-firebase.sh --dry-run\n  )\n  expected=\"Skipping deploy of branch \\\"2.1.x\\\" to firebase.\nWe only deploy archive branches with the major version less than the stable branch: \\\"2.2.x\\\"\"\n  check \"$actual\" \"$expected\"\n)\n\n(\n  echo ===== archive - skip deploy - major version too high, higher minor\n  actual=$(\n    export TRAVIS_PULL_REQUEST=false\n    export TRAVIS_BRANCH=2.4.x\n    export STABLE_BRANCH=2.2.x\n    export TRAVIS_COMMIT=$(git ls-remote origin 2.4.x | cut -c-40)\n    export FIREBASE_TOKEN=XXXXX\n    `dirname $0`/deploy-to-firebase.sh --dry-run\n  )\n  expected=\"Skipping deploy of branch \\\"2.4.x\\\" to firebase.\nWe only deploy archive branches with the major version less than the stable branch: \\\"2.2.x\\\"\"\n  check \"$actual\" \"$expected\"\n)\n\n(\n  echo ===== archive - skip deploy - minor version too low\n  actual=$(\n    export TRAVIS_PULL_REQUEST=false\n    export TRAVIS_BRANCH=2.1.x\n    export STABLE_BRANCH=4.3.x\n    export TRAVIS_COMMIT=$(git ls-remote origin 2.1.x | cut -c-40)\n    export FIREBASE_TOKEN=XXXXX\n    `dirname $0`/deploy-to-firebase.sh --dry-run\n  )\n  expected=\"Skipping deploy of branch \\\"2.1.x\\\" to firebase.\nThere is a more recent branch with the same major version: \\\"2.4.x\\\"\"\n  check \"$actual\" \"$expected\"\n)\n"
  },
  {
    "path": "apps/rxjs.dev/scripts/payload.sh",
    "content": "#!/usr/bin/env bash\n\nset -eu -o pipefail\n\nreadonly thisDir=$(cd $(dirname $0); pwd)\nreadonly parentDir=$(dirname $thisDir)\n\n# Track payload size functions\nsource ../scripts/ci/payload-size.sh\n\ntrackPayloadSize \"aio\" \"dist/*.js\" true true \"${thisDir}/_payload-limits.json\"\n\n"
  },
  {
    "path": "apps/rxjs.dev/scripts/publish-docs.sh",
    "content": "#!/usr/bin/env bash\n\nreadonly projectId=rxjs-dev\nreadonly deployedUrl=https://rxjs-dev.firebaseapp.com\nreadonly firebaseToken=$FIREBASE_TOKEN\n\n# Deploy\n(\n  cd \"`dirname $0`/..\"\n\n  # Build the app\n  yarn build --env=stable\n\n  # Include any mode-specific files\n  cp -rf src/extra-files/$deployEnv/. dist/\n\n  # Deploy to Firebase\n  yarn firebase -- login\n  yarn firebase -- use \"$projectId\"\n  yarn firebase -- deploy --message \"Deploy docs automatically\" --non-interactive\n  yarn firebase -- logout\n)\n"
  },
  {
    "path": "apps/rxjs.dev/scripts/test-pwa-score.js",
    "content": "#!/bin/env node\n\n/**\n * Usage:\n *   node scripts/test-pwa-score <url> <min-score> [<log-file>]\n *\n * Fails if the score is below `<min-score>`.\n * If `<log-file>` is defined, the full results will be logged there.\n *\n * (Skips HTTPS-related audits, when run for HTTP URL.)\n */\n\n// Imports\nconst lighthouse = require('lighthouse');\nconst chromeLauncher = require('lighthouse/chrome-launcher');\nconst printer = require('lighthouse/lighthouse-cli/printer');\nconst config = require('lighthouse/lighthouse-core/config/default.js');\n\n// Constants\nconst CHROME_LAUNCH_OPTS = {};\nconst SKIPPED_HTTPS_AUDITS = ['redirects-http'];\nconst VIEWER_URL = 'https://googlechrome.github.io/lighthouse/viewer/';\n\n\n// Specify the path and flags for Chrome on Travis\nif (process.env.TRAVIS) {\n  process.env.LIGHTHOUSE_CHROMIUM_PATH = process.env.CHROME_BIN;\n  CHROME_LAUNCH_OPTS.chromeFlags = ['--no-sandbox'];\n}\n\n// Run\n_main(process.argv.slice(2));\n\n// Functions - Definitions\nfunction _main(args) {\n  const {url, minScore, logFile} = parseInput(args);\n  const isOnHttp = /^http:/.test(url);\n\n  console.log(`Running PWA audit for '${url}'...`);\n\n  if (isOnHttp) {\n    skipHttpsAudits(config);\n  }\n\n  launchChromeAndRunLighthouse(url, {}, config).\n    then(results => processResults(results, logFile)).\n    then(score => evaluateScore(minScore, score)).\n    catch(onError);\n}\n\nfunction evaluateScore(expectedScore, actualScore) {\n  console.log('Lighthouse PWA score:');\n  console.log(`  - Expected: ${expectedScore} / 100 (or higher)`);\n  console.log(`  - Actual:   ${actualScore} / 100`);\n\n  if (actualScore < expectedScore) {\n    throw new Error(`PWA score is too low. (${actualScore} < ${expectedScore})`);\n  }\n}\n\nfunction launchChromeAndRunLighthouse(url, flags, config) {\n  return chromeLauncher.launch(CHROME_LAUNCH_OPTS).then(chrome => {\n    flags.port = chrome.port;\n    return lighthouse(url, flags, config).\n      then(results => chrome.kill().then(() => results)).\n      catch(err => chrome.kill().then(() => { throw err; }, () => { throw err; }));\n  });\n}\n\nfunction onError(err) {\n  console.error(err);\n  process.exit(1);\n}\n\nfunction parseInput(args) {\n  const url = args[0];\n  const minScore = Number(args[1]);\n  const logFile = args[2];\n\n  if (!url) {\n    onError('Invalid arguments: <URL> not specified.');\n  } else if (isNaN(minScore)) {\n    onError('Invalid arguments: <MIN_SCORE> not specified or not a number.');\n  }\n\n  return {url, minScore, logFile};\n}\n\nfunction processResults(results, logFile) {\n  let promise = Promise.resolve();\n\n  if (logFile) {\n    console.log(`Saving results in '${logFile}'...`);\n    console.log(`(LightHouse viewer: ${VIEWER_URL})`);\n\n    // Remove the artifacts, which are not necessary for the report.\n    // (Saves ~1,500,000 lines of formatted JSON output \\o/)\n    results.artifacts = undefined;\n\n    promise = printer.write(results, 'json', logFile);\n  }\n\n  return promise.then(() => Math.round(results.score));\n}\n\nfunction skipHttpsAudits(config) {\n  console.info(`Skipping HTTPS-related audits (${SKIPPED_HTTPS_AUDITS.join(', ')})...`);\n  config.settings.skipAudits = SKIPPED_HTTPS_AUDITS;\n}\n"
  },
  {
    "path": "apps/rxjs.dev/src/app/app.component.ts",
    "content": "import { Component, ElementRef, HostBinding, HostListener, OnInit, QueryList, ViewChild, ViewChildren } from '@angular/core';\nimport { MatSidenav } from '@angular/material/sidenav';\n\nimport { CurrentNodes, NavigationService, NavigationNode, VersionInfo } from 'app/navigation/navigation.service';\nimport { DocumentService, DocumentContents } from 'app/documents/document.service';\nimport { Deployment } from 'app/shared/deployment.service';\nimport { LocationService } from 'app/shared/location.service';\nimport { NotificationComponent } from 'app/layout/notification/notification.component';\nimport { ScrollService } from 'app/shared/scroll.service';\nimport { SearchBoxComponent } from 'app/search/search-box/search-box.component';\nimport { SearchResults } from 'app/search/interfaces';\nimport { SearchService } from 'app/search/search.service';\nimport { TocService } from 'app/shared/toc.service';\n\nimport { BehaviorSubject, combineLatest, Observable } from 'rxjs';\nimport { first, map } from 'rxjs/operators';\nimport { Inject } from '@angular/core';\nimport { DOCUMENT } from '@angular/common';\n\nconst sideNavView = 'SideNav';\n\n@Component({\n  selector: 'aio-shell',\n  template: `<div id=\"top-of-page\"></div>\n\n    <div *ngIf=\"isFetching\" class=\"progress-bar-container\">\n      <mat-progress-bar mode=\"indeterminate\" color=\"warn\"></mat-progress-bar>\n    </div>\n\n    <mat-toolbar color=\"primary\" class=\"app-toolbar no-print\" [class.transitioning]=\"isTransitioning\">\n      <mat-toolbar-row class=\"notification-container\">\n        <aio-notification\n          notificationId=\"blm-2020\"\n          expirationDate=\"2022-04-15\"\n          [dismissOnContentClick]=\"false\"\n          (dismissed)=\"notificationDismissed()\"\n        >\n          <a href=\"/blackLivesMatter\">#BlackLivesMatter</a>\n        </aio-notification>\n      </mat-toolbar-row>\n      <mat-toolbar-row>\n        <button mat-button class=\"hamburger\" [class.starting]=\"isStarting\" (click)=\"sidenav.toggle()\" title=\"Docs menu\">\n          <mat-icon svgIcon=\"menu\"></mat-icon>\n        </button>\n        <a class=\"nav-link home\" href=\"/\" [ngSwitch]=\"isSideBySide\">\n          <img *ngSwitchCase=\"true\" src=\"assets/images/logos/logo.png\" width=\"150\" height=\"40\" title=\"Home\" alt=\"Home\" />\n          <img *ngSwitchDefault src=\"assets/images/logos/Rx_Logo_S.png\" width=\"37\" height=\"40\" title=\"Home\" alt=\"Home\" />\n        </a>\n        <aio-top-menu *ngIf=\"isSideBySide\" [nodes]=\"topMenuNodes\"></aio-top-menu>\n        <aio-search-box class=\"search-container\" #searchBox (onSearch)=\"doSearch($event)\" (onFocus)=\"doSearch($event)\"></aio-search-box>\n        <div class=\"toolbar-external-icons-container\">\n          <a href=\"https://github.com/ReactiveX/rxjs\" title=\"GitHub\" target=\"_blank\">\n            <img src=\"assets/images/logos/github-icon.svg\" alt=\"View on GitHub\"\n          /></a>\n        </div>\n      </mat-toolbar-row>\n    </mat-toolbar>\n\n    <aio-search-results\n      #searchResultsView\n      *ngIf=\"showSearchResults\"\n      [searchResults]=\"searchResults | async\"\n      (resultSelected)=\"hideSearchResults()\"\n    ></aio-search-results>\n\n    <mat-sidenav-container class=\"sidenav-container\" [class.starting]=\"isStarting\" [class.has-floating-toc]=\"hasFloatingToc\">\n      <mat-sidenav\n        [ngClass]=\"{ collapsed: !isSideBySide }\"\n        #sidenav\n        class=\"sidenav\"\n        [mode]=\"mode\"\n        [opened]=\"isOpened\"\n        (openedChange)=\"updateHostClasses()\"\n      >\n        <aio-nav-menu\n          *ngIf=\"!isSideBySide\"\n          [nodes]=\"topMenuNarrowNodes\"\n          [currentNode]=\"currentNodes?.TopBarNarrow\"\n          [isWide]=\"false\"\n        ></aio-nav-menu>\n        <aio-nav-menu [nodes]=\"sideNavNodes\" [currentNode]=\"currentNodes?.SideNav\" [isWide]=\"isSideBySide\"></aio-nav-menu>\n\n        <div class=\"doc-version\">\n          <aio-select (change)=\"onDocVersionChange($event.index)\" [options]=\"docVersions\" [selected]=\"currentDocVersion\"></aio-select>\n        </div>\n      </mat-sidenav>\n\n      <section class=\"sidenav-content\" [id]=\"pageId\" role=\"main\">\n        <aio-mode-banner [mode]=\"deployment.mode\" [version]=\"versionInfo\"></aio-mode-banner>\n        <aio-doc-viewer\n          [class.no-animations]=\"isStarting\"\n          [doc]=\"currentDocument\"\n          (docReady)=\"onDocReady()\"\n          (docRemoved)=\"onDocRemoved()\"\n          (docInserted)=\"onDocInserted()\"\n          (docRendered)=\"onDocRendered()\"\n        >\n        </aio-doc-viewer>\n        <aio-dt *ngIf=\"dtOn\" [(doc)]=\"currentDocument\"></aio-dt>\n      </section>\n    </mat-sidenav-container>\n\n    <div *ngIf=\"hasFloatingToc\" class=\"toc-container no-print\" [style.max-height.px]=\"tocMaxHeight\" (wheel)=\"restrainScrolling($event)\">\n      <aio-lazy-ce selector=\"aio-toc\"></aio-lazy-ce>\n    </div>\n\n    <footer class=\"no-print\">\n      <aio-footer [nodes]=\"footerNodes\" [versionInfo]=\"versionInfo\"></aio-footer>\n    </footer> `,\n})\nexport class AppComponent implements OnInit {\n  currentDocument: DocumentContents;\n  currentDocVersion: NavigationNode;\n  currentNodes: CurrentNodes = {};\n  currentPath: string;\n  docVersions: NavigationNode[];\n  dtOn = false;\n  footerNodes: NavigationNode[];\n\n  /**\n   * An HTML friendly identifier for the currently displayed page.\n   * This is computed from the `currentDocument.id` by replacing `/` with `-`\n   */\n  pageId: string;\n  /**\n   * An HTML friendly identifer for the \"folder\" of the currently displayed page.\n   * This is computed by taking everything up to the first `/` in the `currentDocument.id`\n   */\n  folderId: string;\n  /**\n   * These CSS classes are computed from the current state of the application\n   * (e.g. what document is being viewed) to allow for fine grain control over\n   * the styling of individual pages.\n   * You will get three classes:\n   *\n   * * `page-...`: computed from the current document id (e.g. events, guide-security, tutorial-toh-pt2)\n   * * `folder-...`: computed from the top level folder for an id (e.g. guide, tutorial, etc)\n   * * `view-...`: computed from the navigation view (e.g. SideNav, TopBar, etc)\n   */\n  @HostBinding('class')\n  hostClasses = '';\n\n  // Disable all Angular animations for the initial render.\n  @HostBinding('@.disabled')\n  isStarting = true;\n  isTransitioning = true;\n  isFetching = false;\n  isSideBySide = false;\n  private isFetchingTimeout: any;\n  private isSideNavDoc = false;\n\n  private sideBySideWidth = 992;\n  sideNavNodes: NavigationNode[];\n  topMenuNodes: NavigationNode[];\n  topMenuNarrowNodes: NavigationNode[];\n\n  hasFloatingToc = false;\n  private showFloatingToc = new BehaviorSubject(false);\n  private showFloatingTocWidth = 800;\n  tocMaxHeight: string;\n  private tocMaxHeightOffset = 0;\n\n  versionInfo: VersionInfo;\n\n  get isOpened() {\n    return this.isSideBySide && this.isSideNavDoc;\n  }\n  get mode() {\n    return this.isSideBySide ? 'side' : 'over';\n  }\n\n  // Search related properties\n  showSearchResults = false;\n  searchResults: Observable<SearchResults>;\n  @ViewChildren('searchBox, searchResultsView', { read: ElementRef })\n  searchElements: QueryList<ElementRef>;\n  @ViewChild(SearchBoxComponent, { static: true })\n  searchBox: SearchBoxComponent;\n\n  @ViewChild(MatSidenav, { static: true })\n  sidenav: MatSidenav;\n\n  @ViewChild(NotificationComponent, { static: true })\n  notification: NotificationComponent;\n  notificationAnimating = false;\n\n  constructor(\n    public deployment: Deployment,\n    private documentService: DocumentService,\n    private hostElement: ElementRef,\n    private locationService: LocationService,\n    private navigationService: NavigationService,\n    private scrollService: ScrollService,\n    private searchService: SearchService,\n    private tocService: TocService,\n    @Inject(DOCUMENT) private dom: Document\n  ) {}\n\n  ngOnInit() {\n    // Do not initialize the search on browsers that lack web worker support\n    if ('Worker' in window) {\n      // Delay initialization by up to 2 seconds\n      this.searchService.initWorker(2000);\n    }\n\n    this.onResize(window.innerWidth);\n\n    /* No need to unsubscribe because this root component never dies */\n\n    this.documentService.currentDocument.subscribe((doc) => (this.currentDocument = doc));\n\n    this.locationService.currentPath.subscribe((path) => {\n      if (path === this.currentPath) {\n        // scroll only if on same page (most likely a change to the hash)\n        this.scrollService.scroll();\n      } else {\n        // don't scroll; leave that to `onDocRendered`\n        this.currentPath = path;\n\n        // Start progress bar if doc not rendered within brief time\n        clearTimeout(this.isFetchingTimeout);\n        this.isFetchingTimeout = setTimeout(() => (this.isFetching = true), 200);\n      }\n    });\n\n    this.navigationService.currentNodes.subscribe((currentNodes) => {\n      this.currentNodes = currentNodes;\n    });\n\n    // Compute the version picker list from the current version and the versions in the navigation map\n    combineLatest(\n      this.navigationService.versionInfo,\n      this.navigationService.navigationViews.pipe(map((views) => views.docVersions))\n    ).subscribe(([versionInfo, versions]) => {\n      this.docVersions = [...versions];\n\n      // Find the current version - either title matches the current deployment mode\n      // or its title matches the major version of the current version info\n      this.currentDocVersion = this.docVersions.find(\n        (version) => version.title === this.deployment.mode || version.title === `v${versionInfo.major}`\n      )!;\n      this.currentDocVersion.title += ` (v${versionInfo.raw})`;\n    });\n\n    this.navigationService.navigationViews.subscribe((views) => {\n      this.footerNodes = views.Footer || [];\n      this.sideNavNodes = views.SideNav || [];\n      this.topMenuNodes = views.TopBar || [];\n      this.topMenuNarrowNodes = views.TopBarNarrow || this.topMenuNodes;\n    });\n\n    this.navigationService.versionInfo.subscribe((vi) => (this.versionInfo = vi));\n\n    const hasNonEmptyToc = this.tocService.tocList.pipe(map((tocList) => tocList.length > 0));\n    combineLatest(hasNonEmptyToc, this.showFloatingToc).subscribe(\n      ([hasToc, showFloatingToc]) => (this.hasFloatingToc = hasToc && showFloatingToc)\n    );\n\n    // Generally, we want to delay updating the shell (e.g. host classes, sidenav state) for the new\n    // document, until after the leaving document has been removed (to avoid having the styles for\n    // the new document applied prematurely).\n    // For the first document, though, (when we know there is no previous document), we want to\n    // ensure the styles are applied as soon as possible to avoid flicker.\n    combineLatest(\n      this.documentService.currentDocument, // ...needed to determine host classes\n      this.navigationService.currentNodes\n    ) // ...needed to determine `sidenav` state\n      .pipe(first())\n      .subscribe(() => this.updateShell());\n  }\n\n  onDocReady() {\n    // About to transition to new view.\n    this.isTransitioning = true;\n\n    // Stop fetching timeout (which, when render is fast, means progress bar never shown)\n    clearTimeout(this.isFetchingTimeout);\n\n    // If progress bar has been shown, keep it for at least 500ms (to avoid flashing).\n    setTimeout(() => (this.isFetching = false), 500);\n  }\n\n  onDocRemoved() {\n    this.scrollService.removeStoredScrollPosition();\n  }\n\n  onDocInserted() {\n    // Update the shell (host classes, sidenav state) to match the new document.\n    // This may be called as a result of actions initiated by view updates.\n    // In order to avoid errors (e.g. `ExpressionChangedAfterItHasBeenChecked`), updating the view\n    // (e.g. sidenav, host classes) needs to happen asynchronously.\n    setTimeout(() => this.updateShell());\n\n    // Scroll the good position depending on the context\n    this.scrollService.scrollAfterRender(500);\n  }\n\n  onDocRendered() {\n    if (this.isStarting) {\n      // In order to ensure that the initial sidenav-content left margin\n      // adjustment happens without animation, we need to ensure that\n      // `isStarting` remains `true` until the margin change is triggered.\n      // (Apparently, this happens with a slight delay.)\n      setTimeout(() => (this.isStarting = false), 100);\n    }\n\n    const head = this.dom.getElementsByTagName('head')[0];\n    let element: HTMLLinkElement | null = this.dom.querySelector('link[rel=\\'canonical\\']') || null;\n    if (element === null) {\n      element = this.dom.createElement('link') as HTMLLinkElement;\n      head.appendChild(element);\n    }\n    element.setAttribute('rel', 'canonical');\n    element.setAttribute('href', `https://rxjs.dev/${this.currentPath}`);\n    this.isTransitioning = false;\n  }\n\n  onDocVersionChange(versionIndex: number) {\n    const version = this.docVersions[versionIndex];\n    if (version.url) {\n      this.locationService.go(version.url);\n    }\n  }\n\n  @HostListener('window:resize', ['$event.target.innerWidth'])\n  onResize(width: number) {\n    this.isSideBySide = width >= this.sideBySideWidth;\n    this.showFloatingToc.next(width > this.showFloatingTocWidth);\n\n    if (this.isSideBySide && !this.isSideNavDoc) {\n      // If this is a non-sidenav doc and the screen is wide enough so that we can display menu\n      // items in the top-bar, ensure the sidenav is closed.\n      // (This condition can only be met when the resize event changes the value of `isSideBySide`\n      //  from `false` to `true` while on a non-sidenav doc.)\n      this.sidenav.toggle(false);\n    }\n  }\n\n  @HostListener('click', ['$event.target', '$event.button', '$event.ctrlKey', '$event.metaKey', '$event.altKey'])\n  onClick(eventTarget: HTMLElement, button: number, ctrlKey: boolean, metaKey: boolean, altKey: boolean): boolean {\n    // Hide the search results if we clicked outside both the \"search box\" and the \"search results\"\n    if (!this.searchElements.some((element) => element.nativeElement.contains(eventTarget))) {\n      this.hideSearchResults();\n    }\n\n    // Show developer source view if the footer is clicked while holding the meta and alt keys\n    if (eventTarget.tagName === 'FOOTER' && metaKey && altKey) {\n      this.dtOn = !this.dtOn;\n      return false;\n    }\n\n    // Deal with anchor clicks; climb DOM tree until anchor found (or null)\n    let target: HTMLElement | null = eventTarget;\n    while (target && !(target instanceof HTMLAnchorElement)) {\n      target = target.parentElement;\n    }\n    if (target instanceof HTMLAnchorElement) {\n      return this.locationService.handleAnchorClick(target, button, ctrlKey, metaKey);\n    }\n\n    // Allow the click to pass through\n    return true;\n  }\n\n  setPageId(id: string) {\n    // Special case the home page\n    this.pageId = id === 'index' ? 'home' : id.replace('/', '-');\n  }\n\n  setFolderId(id: string) {\n    // Special case the home page\n    this.folderId = id === 'index' ? 'home' : id.split('/', 1)[0];\n  }\n\n  notificationDismissed() {\n    this.notificationAnimating = true;\n    // this should be kept in sync with the animation durations in:\n    // - aio/src/styles/2-modules/_notification.scss\n    // - aio/src/app/layout/notification/notification.component.ts\n    setTimeout(() => (this.notificationAnimating = false), 250);\n    this.updateHostClasses();\n  }\n\n  updateHostClasses() {\n    const mode = `mode-${this.deployment.mode}`;\n    const sideNavOpen = `sidenav-${this.sidenav.opened ? 'open' : 'closed'}`;\n    const pageClass = `page-${this.pageId}`;\n    const folderClass = `folder-${this.folderId}`;\n    const viewClasses = Object.keys(this.currentNodes)\n      .map((view) => `view-${view}`)\n      .join(' ');\n    const notificationClass = `aio-notification-${this.notification.showNotification}`;\n    const notificationAnimatingClass = this.notificationAnimating ? 'aio-notification-animating' : '';\n\n    this.hostClasses = [mode, sideNavOpen, pageClass, folderClass, viewClasses, notificationClass, notificationAnimatingClass].join(' ');\n  }\n\n  updateShell() {\n    // Update the SideNav state (if necessary).\n    this.updateSideNav();\n\n    // Update the host classes.\n    this.setPageId(this.currentDocument.id);\n    this.setFolderId(this.currentDocument.id);\n    this.updateHostClasses();\n  }\n\n  updateSideNav() {\n    // Preserve current sidenav open state by default.\n    let openSideNav = this.sidenav.opened;\n    const isSideNavDoc = !!this.currentNodes[sideNavView];\n\n    if (this.isSideNavDoc !== isSideNavDoc) {\n      // View type changed. Is it now a sidenav view (e.g, guide or tutorial)?\n      // Open if changed to a sidenav doc; close if changed to a marketing doc.\n      openSideNav = this.isSideNavDoc = isSideNavDoc;\n    }\n\n    // May be open or closed when wide; always closed when narrow.\n    this.sidenav.toggle(this.isSideBySide && openSideNav);\n  }\n\n  // Dynamically change height of table of contents container\n  @HostListener('window:scroll')\n  onScroll() {\n    if (!this.tocMaxHeightOffset) {\n      // Must wait until `mat-toolbar` is measurable.\n      const el = this.hostElement.nativeElement as Element;\n      const headerEl = el.querySelector('.app-toolbar');\n      const footerEl = el.querySelector('footer');\n\n      if (headerEl && footerEl) {\n        this.tocMaxHeightOffset = headerEl.clientHeight + footerEl.clientHeight + 24; //  fudge margin\n      }\n    }\n\n    this.tocMaxHeight = (document.body.scrollHeight - window.pageYOffset - this.tocMaxHeightOffset).toFixed(2);\n  }\n\n  // Restrain scrolling inside an element, when the cursor is over it\n  restrainScrolling(evt: WheelEvent) {\n    const elem = evt.currentTarget as Element;\n    const scrollTop = elem.scrollTop;\n\n    if (evt.deltaY < 0) {\n      // Trying to scroll up: Prevent scrolling if already at the top.\n      if (scrollTop < 1) {\n        evt.preventDefault();\n      }\n    } else {\n      // Trying to scroll down: Prevent scrolling if already at the bottom.\n      const maxScrollTop = elem.scrollHeight - elem.clientHeight;\n      if (maxScrollTop - scrollTop < 1) {\n        evt.preventDefault();\n      }\n    }\n  }\n\n  // Search related methods and handlers\n\n  hideSearchResults() {\n    this.showSearchResults = false;\n    const oldSearch = this.locationService.search();\n    if (oldSearch.search !== undefined) {\n      this.locationService.setSearch('', { ...oldSearch, search: undefined });\n    }\n  }\n\n  focusSearchBox() {\n    if (this.searchBox) {\n      this.searchBox.focus();\n    }\n  }\n\n  doSearch(query: string) {\n    this.searchResults = this.searchService.search(query);\n    this.showSearchResults = !!query;\n  }\n\n  @HostListener('document:keyup', ['$event.key', '$event.which'])\n  onKeyUp(key: string, keyCode: number) {\n    // forward slash \"/\"\n    if (key === '/' || keyCode === 191) {\n      this.focusSearchBox();\n    }\n    if (key === 'Escape' || keyCode === 27) {\n      // escape key\n      if (this.showSearchResults) {\n        this.hideSearchResults();\n        this.focusSearchBox();\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "apps/rxjs.dev/src/app/app.module.ts",
    "content": "import { BrowserModule } from '@angular/platform-browser';\nimport { ErrorHandler, NgModule } from '@angular/core';\nimport { HttpClientModule } from '@angular/common/http';\nimport { BrowserAnimationsModule } from '@angular/platform-browser/animations';\nimport { ServiceWorkerModule } from '@angular/service-worker';\n\nimport { Location, LocationStrategy, PathLocationStrategy } from '@angular/common';\n\nimport { MatButtonModule } from '@angular/material/button';\nimport { MatIconModule, MatIconRegistry } from '@angular/material/icon';\nimport { MatProgressBarModule } from '@angular/material/progress-bar';\nimport { MatSidenavModule } from '@angular/material/sidenav';\nimport { MatToolbarModule } from '@angular/material/toolbar';\n\nimport { AppComponent } from 'app/app.component';\nimport { CustomIconRegistry, SVG_ICONS } from 'app/shared/custom-icon-registry';\nimport { Deployment } from 'app/shared/deployment.service';\nimport { DocViewerComponent } from 'app/layout/doc-viewer/doc-viewer.component';\nimport { DtComponent } from 'app/layout/doc-viewer/dt.component';\nimport { ModeBannerComponent } from 'app/layout/mode-banner/mode-banner.component';\nimport { GaService } from 'app/shared/ga.service';\nimport { Logger } from 'app/shared/logger.service';\nimport { LocationService } from 'app/shared/location.service';\nimport { NavigationService } from 'app/navigation/navigation.service';\nimport { DocumentService } from 'app/documents/document.service';\nimport { SearchService } from 'app/search/search.service';\nimport { TopMenuComponent } from 'app/layout/top-menu/top-menu.component';\nimport { FooterComponent } from 'app/layout/footer/footer.component';\nimport { NavMenuComponent } from 'app/layout/nav-menu/nav-menu.component';\nimport { NavItemComponent } from 'app/layout/nav-item/nav-item.component';\nimport { ReportingErrorHandler } from 'app/shared/reporting-error-handler';\nimport { ScrollService } from 'app/shared/scroll.service';\nimport { ScrollSpyService } from 'app/shared/scroll-spy.service';\nimport { SearchBoxComponent } from 'app/search/search-box/search-box.component';\nimport { NotificationComponent } from 'app/layout/notification/notification.component';\nimport { TocService } from 'app/shared/toc.service';\nimport { CurrentDateToken, currentDateProvider } from 'app/shared/current-date';\nimport { WindowToken, windowProvider } from 'app/shared/window';\n\nimport { CustomElementsModule } from 'app/custom-elements/custom-elements.module';\nimport { SharedModule } from 'app/shared/shared.module';\nimport { SwUpdatesModule } from 'app/sw-updates/sw-updates.module';\n\nimport {environment} from '../environments/environment';\n\n// These are the hardcoded inline svg sources to be used by the `<mat-icon>` component.\nexport const svgIconProviders = [\n  {\n    provide: SVG_ICONS,\n    useValue: {\n      name: 'close',\n      svgSource:\n        '<svg fill=\"#ffffff\" focusable=\"false\" viewBox=\"0 0 24 24\" xmlns=\"http://www.w3.org/2000/svg\">' +\n          '<path d=\"M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z\" />' +\n          '<path d=\"M0 0h24v24H0z\" fill=\"none\" />' +\n        '</svg>',\n    },\n    multi: true,\n  },\n  {\n    provide: SVG_ICONS,\n    useValue: {\n      name: 'error_outline',\n      svgSource:\n        '<svg focusable=\"false\" viewBox=\"0 0 24 24\" xmlns=\"http://www.w3.org/2000/svg\">' +\n          '<path d=\"M0 0h24v24H0V0z\" fill=\"none\" />' +\n          // eslint-disable-next-line max-len\n          '<path d=\"M11 15h2v2h-2zm0-8h2v6h-2zm.99-5C6.47 2 2 6.48 2 12s4.47 10 9.99 10C17.52 22 22 17.52 22 12S17.52 2 11.99 2zM12 20c-4.42 0-8-3.58-8-8s3.58-8 8-8 8 3.58 8 8-3.58 8-8 8z\" />' +\n        '</svg>',\n    },\n    multi: true,\n  },\n  {\n    provide: SVG_ICONS,\n    useValue: {\n      name: 'insert_comment',\n      svgSource:\n        '<svg fill=\"#ffffff\" focusable=\"false\" viewBox=\"0 0 24 24\" xmlns=\"http://www.w3.org/2000/svg\">' +\n          '<path d=\"M20 2H4c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h14l4 4V4c0-1.1-.9-2-2-2zm-2 12H6v-2h12v2zm0-3H6V9h12v2zm0-3H6V6h12v2z\" />' +\n          '<path d=\"M0 0h24v24H0z\" fill=\"none\" />' +\n        '</svg>',\n    },\n    multi: true,\n  },\n  {\n    provide: SVG_ICONS,\n    useValue: {\n      name: 'keyboard_arrow_right',\n      svgSource:\n        '<svg focusable=\"false\" viewBox=\"0 0 24 24\" xmlns=\"http://www.w3.org/2000/svg\">' +\n          '<path d=\"M8.59 16.34l4.58-4.59-4.58-4.59L10 5.75l6 6-6 6z\" />' +\n        '</svg>',\n    },\n    multi: true,\n  },\n  {\n    provide: SVG_ICONS,\n    useValue: {\n      name: 'menu',\n      svgSource:\n        '<svg focusable=\"false\" viewBox=\"0 0 24 24\" xmlns=\"http://www.w3.org/2000/svg\">' +\n          '<path d=\"M3 18h18v-2H3v2zm0-5h18v-2H3v2zm0-7v2h18V6H3z\" />' +\n        '</svg>',\n    },\n    multi: true,\n  },\n];\n\n@NgModule({\n  imports: [\n    BrowserModule,\n    BrowserAnimationsModule,\n    CustomElementsModule,\n    HttpClientModule,\n    MatButtonModule,\n    MatIconModule,\n    MatProgressBarModule,\n    MatSidenavModule,\n    MatToolbarModule,\n    SwUpdatesModule,\n    SharedModule,\n    ServiceWorkerModule.register('/ngsw-worker.js', {enabled: environment.production}),\n  ],\n  declarations: [\n    AppComponent,\n    DocViewerComponent,\n    DtComponent,\n    FooterComponent,\n    ModeBannerComponent,\n    NavMenuComponent,\n    NavItemComponent,\n    SearchBoxComponent,\n    NotificationComponent,\n    TopMenuComponent,\n  ],\n  providers: [\n    Deployment,\n    DocumentService,\n    { provide: ErrorHandler, useClass: ReportingErrorHandler },\n    GaService,\n    Logger,\n    Location,\n    { provide: LocationStrategy, useClass: PathLocationStrategy },\n    LocationService,\n    { provide: MatIconRegistry, useClass: CustomIconRegistry },\n    NavigationService,\n    ScrollService,\n    ScrollSpyService,\n    SearchService,\n    svgIconProviders,\n    TocService,\n    { provide: CurrentDateToken, useFactory: currentDateProvider },\n    { provide: WindowToken, useFactory: windowProvider },\n  ],\n  bootstrap: [ AppComponent ]\n})\nexport class AppModule { }\n"
  },
  {
    "path": "apps/rxjs.dev/src/app/custom-elements/announcement-bar/announcement-bar.component.spec.ts",
    "content": "import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing';\nimport { ComponentFixture, TestBed } from '@angular/core/testing';\nimport { Logger } from 'app/shared/logger.service';\nimport { MockLogger } from 'testing/logger.service';\nimport { AnnouncementBarComponent } from './announcement-bar.component';\n\nconst today = new Date();\nconst lastWeek = changeDays(today, -7);\nconst yesterday = changeDays(today, -1);\nconst tomorrow = changeDays(today, 1);\nconst nextWeek = changeDays(today, 7);\n\ndescribe('AnnouncementBarComponent', () => {\n\n  let element: HTMLElement;\n  let fixture: ComponentFixture<AnnouncementBarComponent>;\n  let component: AnnouncementBarComponent;\n  let httpMock: HttpTestingController;\n  let mockLogger: MockLogger;\n\n  beforeEach(() => {\n    const injector = TestBed.configureTestingModule({\n      imports: [HttpClientTestingModule],\n      declarations: [AnnouncementBarComponent],\n      providers: [{ provide: Logger, useClass: MockLogger }]\n    });\n\n    httpMock = injector.get(HttpTestingController);\n    mockLogger = injector.get(Logger);\n    fixture = TestBed.createComponent(AnnouncementBarComponent);\n    component = fixture.componentInstance;\n    element = fixture.nativeElement;\n  });\n\n  it('should have no announcement when first created', () => {\n    expect(component.announcement).toBeUndefined();\n  });\n\n  describe('ngOnInit', () => {\n    it('should make a single request to the server', () => {\n      component.ngOnInit();\n      httpMock.expectOne('generated/announcements.json');\n    });\n\n    it('should set the announcement to the first \"live\" one in the list loaded from `announcements.json`', () => {\n      component.ngOnInit();\n      const request = httpMock.expectOne('generated/announcements.json');\n      request.flush([\n        { startDate: lastWeek, endDate: yesterday, message: 'Test Announcement 0' },\n        { startDate: tomorrow, endDate: nextWeek, message: 'Test Announcement 1' },\n        { startDate: yesterday, endDate: tomorrow, message: 'Test Announcement 2' },\n        { startDate: yesterday, endDate: tomorrow, message: 'Test Announcement 3' }\n      ]);\n      expect(component.announcement.message).toEqual('Test Announcement 2');\n    });\n\n    it('should set the announcement to `undefined` if there are no announcements in `announcements.json`', () => {\n      component.ngOnInit();\n      const request = httpMock.expectOne('generated/announcements.json');\n      request.flush([]);\n      expect(component.announcement).toBeUndefined();\n    });\n\n    it('should handle invalid data in `announcements.json`', () => {\n      component.ngOnInit();\n      const request = httpMock.expectOne('generated/announcements.json');\n      request.flush('some random response');\n      expect(component.announcement).toBeUndefined();\n      expect(mockLogger.output.error).toEqual([\n        [jasmine.any(Error)]\n      ]);\n      expect(mockLogger.output.error[0][0].message).toMatch(/^generated\\/announcements\\.json contains invalid data:/);\n    });\n\n    it('should handle a failed request for `announcements.json`', () => {\n      component.ngOnInit();\n      const request = httpMock.expectOne('generated/announcements.json');\n      request.error(new ErrorEvent('404'));\n      expect(component.announcement).toBeUndefined();\n      expect(mockLogger.output.error).toEqual([\n        [jasmine.any(Error)]\n      ]);\n      expect(mockLogger.output.error[0][0].message).toMatch(/^generated\\/announcements\\.json request failed:/);\n    });\n  });\n\n  describe('rendering', () => {\n    beforeEach(() => {\n      component.announcement = {\n        imageUrl: 'link/to/image',\n        linkUrl: 'link/to/website',\n        message: 'this is an <b>important</b> message',\n        endDate: '2018-03-01',\n        startDate: '2018-02-01'\n      };\n      fixture.detectChanges();\n    });\n\n    it('should display the message as HTML', () => {\n      expect(element.innerHTML).toContain('this is an <b>important</b> message');\n    });\n\n    it('should display an image', () => {\n      expect(element.querySelector('img')!.src).toContain('link/to/image');\n    });\n\n    it('should display a link', () => {\n      expect(element.querySelector('a')!.href).toContain('link/to/website');\n    });\n  });\n});\n\nfunction changeDays(initial: Date, days: number) {\n  return (new Date(initial.valueOf()).setDate(initial.getDate() + days));\n}\n"
  },
  {
    "path": "apps/rxjs.dev/src/app/custom-elements/announcement-bar/announcement-bar.component.ts",
    "content": "import { Component, OnInit } from '@angular/core';\nimport { HttpClient } from '@angular/common/http';\nimport { catchError, map } from 'rxjs/operators';\nimport { Logger } from 'app/shared/logger.service';\nimport { CONTENT_URL_PREFIX } from 'app/documents/document.service';\nconst announcementsPath = CONTENT_URL_PREFIX + 'announcements.json';\n\nexport interface Announcement {\n  imageUrl: string;\n  message: string;\n  linkUrl: string;\n  startDate: string;\n  endDate: string;\n}\n\n/**\n * Display the latest live announcement. This is used on the homepage.\n *\n * The data for the announcements is kept in `aio/content/marketing/announcements.json`.\n *\n * The format for that data file looks like:\n *\n * ```\n * [\n *   {\n *     \"startDate\": \"2018-02-01\",\n *     \"endDate\": \"2018-03-01\",\n *     \"message\": \"This is an <b>important</b> announcement\",\n *     \"imageUrl\": \"url/to/image\",\n *     \"linkUrl\": \"url/to/website\"\n *   },\n *   ...\n * ]\n * ```\n *\n * Only one announcement will be shown at any time. This is determined as the first \"live\"\n * announcement in the file, where \"live\" means that its start date is before today, and its\n * end date is after today.\n *\n * **Security Note:**\n * The `message` field can contain unsanitized HTML but this field should only updated by\n * verified members of the Angular team.\n */\n@Component({\n  selector: 'aio-announcement-bar',\n  template: `\n  <div class=\"homepage-container\" *ngIf=\"announcement\">\n    <div class=\"announcement-bar\">\n      <!-- eslint-disable-next-line @angular-eslint/template/accessibility-alt-text -->\n      <img [src]=\"announcement.imageUrl\">\n      <p [innerHTML]=\"announcement.message\"></p>\n      <a class=\"button\" [href]=\"announcement.linkUrl\">Learn More</a>\n    </div>\n  </div>`\n})\nexport class AnnouncementBarComponent implements OnInit {\n  announcement: Announcement;\n\n  constructor(private http: HttpClient, private logger: Logger) {}\n\n  ngOnInit() {\n    this.http.get<Announcement[]>(announcementsPath)\n      .pipe(\n        catchError(error => {\n          this.logger.error(new Error(`${announcementsPath} request failed: ${error.message}`));\n          return [];\n        }),\n        map(announcements => this.findCurrentAnnouncement(announcements)),\n        catchError(error => {\n          this.logger.error(new Error(`${announcementsPath} contains invalid data: ${error.message}`));\n          return [];\n        }),\n      )\n      .subscribe(announcement => this.announcement = announcement);\n  }\n\n  /**\n   * Get the first date in the list that is \"live\" now\n   */\n  private findCurrentAnnouncement(announcements: Announcement[]) {\n    return announcements\n      .filter(announcement => new Date(announcement.startDate).valueOf() < Date.now())\n      .filter(announcement => new Date(announcement.endDate).valueOf() > Date.now())\n      [0];\n  }\n}\n"
  },
  {
    "path": "apps/rxjs.dev/src/app/custom-elements/announcement-bar/announcement-bar.module.ts",
    "content": "import { NgModule, Type } from '@angular/core';\nimport { CommonModule } from '@angular/common';\nimport { HttpClientModule } from '@angular/common/http';\nimport { SharedModule } from '../../shared/shared.module';\nimport { AnnouncementBarComponent } from './announcement-bar.component';\nimport { WithCustomElementComponent } from '../element-registry';\n\n@NgModule({\n  imports: [ CommonModule, SharedModule, HttpClientModule ],\n  declarations: [ AnnouncementBarComponent ]\n})\nexport class AnnouncementBarModule implements WithCustomElementComponent {\n  customElementComponent: Type<any> = AnnouncementBarComponent;\n}\n"
  },
  {
    "path": "apps/rxjs.dev/src/app/custom-elements/api/api-list.component.spec.ts",
    "content": "import { ComponentFixture, TestBed } from '@angular/core/testing';\nimport { BehaviorSubject } from 'rxjs';\n\nimport { ApiListComponent } from './api-list.component';\nimport { ApiItem, ApiSection, ApiService } from './api.service';\nimport { LocationService } from 'app/shared/location.service';\nimport { Logger } from 'app/shared/logger.service';\nimport { MockLogger } from 'testing/logger.service';\nimport { ApiListModule } from './api-list.module';\n\ndescribe('ApiListComponent', () => {\n  let component: ApiListComponent;\n  let fixture: ComponentFixture<ApiListComponent>;\n  let sections: ApiSection[];\n\n  beforeEach(() => {\n    TestBed.configureTestingModule({\n      imports: [ ApiListModule ],\n      providers: [\n        { provide: ApiService, useClass: TestApiService },\n        { provide: Logger, useClass: MockLogger },\n        { provide: LocationService, useClass: TestLocationService }\n      ]\n    });\n\n    fixture = TestBed.createComponent(ApiListComponent);\n    component = fixture.componentInstance;\n    sections = getApiSections();\n  });\n\n  /**\n   * Expectation Utility: Assert that filteredSections has the expected result for this test\n   *\n   * @param itemTest - return true if the item passes the match test\n   *\n   * Subscribes to `filteredSections` and performs expectation within subscription callback.\n   */\n  function expectFilteredResult(label: string, itemTest: (item: ApiItem) => boolean) {\n    component.filteredSections.subscribe(filtered => {\n      filtered = filtered.filter(section => section.items);\n      expect(filtered.length).toBeGreaterThan(0, 'expected something');\n      expect(filtered.every(section => section.items!.every(itemTest))).toBe(true, label);\n    });\n  }\n\n\n  describe('#filteredSections', () => {\n\n    beforeEach(() => {\n      fixture.detectChanges();\n    });\n\n    it('should return all complete sections when no criteria', () => {\n      let filtered: ApiSection[]|undefined;\n      component.filteredSections.subscribe(f => filtered = f);\n      expect(filtered).toEqual(sections);\n    });\n\n    it('item.show should be true for all queried items', () => {\n      component.setQuery('class');\n      expectFilteredResult('query: class', item => /class/.test(item.name));\n    });\n\n    it('items should be an array for every item in section when query matches section name', () => {\n      component.setQuery('core');\n      component.filteredSections.subscribe(filtered => {\n        filtered = filtered.filter(section => Array.isArray(section.items));\n        expect(filtered.length).toBe(1, 'only one section');\n        expect(filtered[0].name).toBe('core');\n        expect(filtered[0].items).toEqual(sections.find(section => section.name === 'core')!.items);\n      });\n    });\n\n    describe('section.items', () => {\n      it('should null if there are no matching items and the section itself does not match', () => {\n        component.setQuery('core');\n        component.filteredSections.subscribe(filtered => {\n          const commonSection = filtered.find(section => section.name === 'common')!;\n          expect(commonSection.items).toBe(null);\n        });\n      });\n\n      it('should be visible if they have the selected stability status', () => {\n        component.setStatus({value: 'stable', title: 'Stable'});\n        expectFilteredResult('status: stable', item => item.stability === 'stable');\n      });\n\n      it('should be visible if they have the selected security status', () => {\n        component.setStatus({value: 'security-risk', title: 'Security Risk'});\n        expectFilteredResult('status: security-risk', item => item.securityRisk);\n      });\n\n      it('should be visible if they match the selected API type', () => {\n        component.setType({value: 'class', title: 'Class'});\n        expectFilteredResult('type: class', item => item.docType === 'class');\n      });\n    });\n\n    it('should have no sections and no items visible when there is no match', () => {\n      component.setQuery('fizzbuzz');\n      component.filteredSections.subscribe(filtered => {\n        expect(filtered.some(section => !!section.items)).toBeFalsy();\n      });\n    });\n  });\n\n  describe('initial criteria from location', () => {\n    let locationService: TestLocationService;\n\n    beforeEach(() => {\n      locationService = fixture.componentRef.injector.get<any>(LocationService);\n    });\n\n    function expectOneItem(name: string, section: string, type: string, stability: string) {\n      fixture.detectChanges();\n\n      component.filteredSections.subscribe(filtered => {\n        filtered = filtered.filter(s => s.items);\n        expect(filtered.length).toBe(1, 'sections');\n        expect(filtered[0].name).toBe(section, 'section name');\n        const items = filtered[0].items!;\n        expect(items.length).toBe(1, 'items');\n\n        const item = items[0];\n        const badItem = 'Wrong item: ' + JSON.stringify(item, null, 2);\n\n        expect(item.docType).toBe(type, badItem);\n        expect(item.stability).toBe(stability, badItem);\n        expect(item.name).toBe(name, badItem);\n      });\n    }\n\n    it('should filter as expected for ?query', () => {\n      locationService.query = {query: '_3'};\n      expectOneItem('class_3', 'core', 'class', 'experimental');\n    });\n\n    it('should filter as expected for ?status', () => {\n      locationService.query = {status: 'deprecated'};\n      expectOneItem('function_1', 'core', 'function', 'deprecated');\n    });\n\n    it('should filter as expected when status is security-risk', () => {\n      locationService.query = {status: 'security-risk'};\n      fixture.detectChanges();\n      expectFilteredResult('security-risk', item => item.securityRisk);\n    });\n\n\n    it('should filter as expected for ?query&status&type', () => {\n      locationService.query = {\n        query: 's_1',\n        status: 'experimental',\n        type: 'class'\n      };\n      fixture.detectChanges();\n      expectOneItem('class_1', 'common', 'class', 'experimental');\n    });\n\n    it('should ignore case for ?query&status&type', () => {\n      locationService.query = {\n        query: 'S_1',\n        status: 'ExperiMental',\n        type: 'CLASS'\n      };\n      fixture.detectChanges();\n      expectOneItem('class_1', 'common', 'class', 'experimental');\n    });\n  });\n\n  describe('location path after criteria change', () => {\n    let locationService: TestLocationService;\n\n    beforeEach(() => {\n      locationService = fixture.componentRef.injector.get<any>(LocationService);\n    });\n\n    it('should have query', () => {\n      component.setQuery('foo');\n\n      // `setSearch` 2nd param is a query/search params object\n      const search = locationService.setSearch.calls.mostRecent().args[1];\n      expect(search.query).toBe('foo');\n    });\n\n    it('should keep last of multiple query settings (in lowercase)', () => {\n      component.setQuery('foo');\n      component.setQuery('fooBar');\n\n      const search = locationService.setSearch.calls.mostRecent().args[1];\n      expect(search.query).toBe('foobar');\n    });\n\n    it('should have query, status, and type', () => {\n      component.setQuery('foo');\n      component.setStatus({value: 'stable', title: 'Stable'});\n      component.setType({value: 'class', title: 'Class'});\n\n      const search = locationService.setSearch.calls.mostRecent().args[1];\n      expect(search.query).toBe('foo');\n      expect(search.status).toBe('stable');\n      expect(search.type).toBe('class');\n    });\n  });\n});\n\n////// Helpers ////////\n\nclass TestLocationService {\n  query: {[index: string]: string } = {};\n  setSearch = jasmine.createSpy('setSearch');\n  search() { return this.query; }\n}\n\nclass TestApiService {\n  sectionsSubject = new BehaviorSubject(getApiSections());\n  sections = this.sectionsSubject.asObservable();\n}\n\nconst apiSections: ApiSection[] = [\n  {\n    name: 'common',\n    title: 'common',\n    path: 'api/common',\n    deprecated: false,\n    items: [\n      {\n        name: 'class_1',\n        title: 'Class 1',\n        path: 'api/common/class_1',\n        docType: 'class',\n        stability: 'experimental',\n        securityRisk: false,\n      },\n      {\n        name: 'class_2',\n        title: 'Class 2',\n        path: 'api/common/class_2',\n        docType: 'class',\n        stability: 'stable',\n        securityRisk: false,\n      },\n      {\n        name: 'directive_1',\n        title: 'Directive 1',\n        path: 'api/common/directive_1',\n        docType: 'directive',\n        stability: 'stable',\n        securityRisk: true,\n      }\n    ]\n  },\n  {\n    name: 'core',\n    title: 'core',\n    path: 'api/core',\n    deprecated: false,\n    items: [\n      {\n        name: 'class_3',\n        title: 'Class 3',\n        path: 'api/core/class_3',\n        docType: 'class',\n        stability: 'experimental',\n        securityRisk: false,\n      },\n      {\n        name: 'function_1',\n        title: 'Function 1',\n        path: 'api/core/function 1',\n        docType: 'function',\n        stability: 'deprecated',\n        securityRisk: true,\n      },\n      {\n        name: 'const_1',\n        title: 'Const 1',\n        path: 'api/core/const_1',\n        docType: 'const',\n        stability: 'stable',\n        securityRisk: false,\n      }\n    ]\n  }\n];\n\nfunction getApiSections() { return apiSections; }\n"
  },
  {
    "path": "apps/rxjs.dev/src/app/custom-elements/api/api-list.component.ts",
    "content": "/*\n * API List & Filter Component\n *\n * A page that displays a formatted list of the public Angular API entities.\n * Clicking on a list item triggers navigation to the corresponding API entity document.\n * Can add/remove API entity links based on filter settings.\n */\n\nimport { Component, ElementRef, OnInit, ViewChild } from '@angular/core';\n\nimport { combineLatest, Observable, ReplaySubject } from 'rxjs';\n\nimport { LocationService } from 'app/shared/location.service';\nimport { ApiSection, ApiService } from './api.service';\n\nimport { Option } from 'app/shared/select/select.component';\nimport { map } from 'rxjs/operators';\n\nclass SearchCriteria {\n  query? = '';\n  status? = 'all';\n  type? = 'all';\n}\n\n@Component({\n  selector: 'aio-api-list',\n  template: `<div class=\"l-flex-wrap api-filter\">\n      <aio-select (change)=\"setType($event.option)\" [options]=\"types\" [selected]=\"type\" [showSymbol]=\"true\" label=\"Type:\"> </aio-select>\n\n      <div class=\"form-search\">\n        <input #filter placeholder=\"Filter\" aria-label=\"Filter\" (input)=\"setQuery(filter.value)\" />\n        <i class=\"material-icons\">search</i>\n      </div>\n    </div>\n\n    <article class=\"api-list-container l-content-small docs-content\">\n      <div *ngFor=\"let section of filteredSections | async\">\n        <h2 [id]=\"section.title\" *ngIf=\"section.items\">{{ section.title }}</h2>\n        <ul class=\"api-list\" *ngIf=\"section.items?.length\">\n          <ng-container *ngFor=\"let item of section.items\">\n            <li class=\"api-item\">\n              <a [href]=\"item.path\">\n                <span class=\"symbol {{ item.docType }}\"></span>\n                <span class=\"stability {{ item.stability }}\"\n                  >{{ item.title }} {{ !item.stability || item.stability === 'stable' ? '' : '(' + item.stability + ')' }}</span\n                >\n              </a>\n            </li>\n          </ng-container>\n        </ul>\n      </div>\n    </article> `,\n})\nexport class ApiListComponent implements OnInit {\n  filteredSections: Observable<ApiSection[]>;\n\n  showStatusMenu = false;\n  showTypeMenu = false;\n\n  private criteriaSubject = new ReplaySubject<SearchCriteria>(1);\n  private searchCriteria = new SearchCriteria();\n\n  status: Option;\n  type: Option;\n\n  // API types\n  types: Option[] = [\n    { value: 'all', title: 'All' },\n    { value: 'class', title: 'Class' },\n    { value: 'const', title: 'Const' },\n    { value: 'enum', title: 'Enum' },\n    { value: 'function', title: 'Function' },\n    { value: 'interface', title: 'Interface' },\n    { value: 'type-alias', title: 'Type alias' },\n  ];\n\n  statuses: Option[] = [\n    { value: 'all', title: 'All' },\n    { value: 'deprecated', title: 'Deprecated' },\n    { value: 'security-risk', title: 'Security Risk' },\n  ];\n\n  @ViewChild('filter', { static: true }) queryEl: ElementRef;\n\n  constructor(private apiService: ApiService, private locationService: LocationService) {}\n\n  ngOnInit() {\n    this.filteredSections = combineLatest(this.apiService.sections, this.criteriaSubject).pipe(\n      map((results) => ({ sections: results[0], criteria: results[1] })),\n      map((results) => results.sections.map((section) => ({ ...section, items: this.filterSection(section, results.criteria) })))\n    );\n\n    this.initializeSearchCriteria();\n  }\n\n  // TODO: may need to debounce as the original did\n  // although there shouldn't be any perf consequences if we don't\n  setQuery(query: string) {\n    this.setSearchCriteria({ query: (query || '').toLowerCase().trim() });\n  }\n\n  setStatus(status: Option) {\n    this.toggleStatusMenu();\n    this.status = status;\n    this.setSearchCriteria({ status: status.value });\n  }\n\n  setType(type: Option) {\n    this.toggleTypeMenu();\n    this.type = type;\n    this.setSearchCriteria({ type: type.value });\n  }\n\n  toggleStatusMenu() {\n    this.showStatusMenu = !this.showStatusMenu;\n  }\n\n  toggleTypeMenu() {\n    this.showTypeMenu = !this.showTypeMenu;\n  }\n\n  //////// Private //////////\n\n  private filterSection(section: ApiSection, { query, status, type }: SearchCriteria) {\n    const items = section.items!.filter((item) => {\n      return matchesType() && matchesStatus() && matchesQuery();\n\n      function matchesQuery() {\n        return !query || section.name.indexOf(query) !== -1 || item.name.indexOf(query) !== -1;\n      }\n\n      function matchesStatus() {\n        return status === 'all' || status === item.stability || (status === 'security-risk' && item.securityRisk);\n      }\n\n      function matchesType() {\n        return type === 'all' || type === item.docType;\n      }\n    });\n\n    // If there are no items we still return an empty array if the section name matches and the type is 'package'\n    return items.length ? items : type === 'package' && (!query || section.name.indexOf(query) !== -1) ? [] : null;\n  }\n\n  // Get initial search criteria from URL search params\n  private initializeSearchCriteria() {\n    const { query, status, type } = this.locationService.search();\n\n    const q = (query || '').toLowerCase();\n    // Hack: can't bind to query because input cursor always forced to end-of-line.\n    this.queryEl.nativeElement.value = q;\n\n    this.status = this.statuses.find((x) => x.value === status) || this.statuses[0];\n    this.type = this.types.find((x) => x.value === type) || this.types[0];\n\n    this.searchCriteria = {\n      query: q,\n      status: this.status.value,\n      type: this.type.value,\n    };\n\n    this.criteriaSubject.next(this.searchCriteria);\n  }\n\n  private setLocationSearch() {\n    const { query, status, type } = this.searchCriteria;\n    const params = {\n      query: query ? query : undefined,\n      status: status !== 'all' ? status : undefined,\n      type: type !== 'all' ? type : undefined,\n    };\n\n    this.locationService.setSearch('API Search', params);\n  }\n\n  private setSearchCriteria(criteria: SearchCriteria) {\n    this.criteriaSubject.next(Object.assign(this.searchCriteria, criteria));\n    this.setLocationSearch();\n  }\n}\n"
  },
  {
    "path": "apps/rxjs.dev/src/app/custom-elements/api/api-list.module.ts",
    "content": "import { NgModule, Type } from '@angular/core';\nimport { CommonModule } from '@angular/common';\nimport { HttpClientModule } from '@angular/common/http';\nimport { SharedModule } from '../../shared/shared.module';\nimport { ApiListComponent } from './api-list.component';\nimport { ApiService } from './api.service';\nimport { WithCustomElementComponent } from '../element-registry';\n\n@NgModule({\n  imports: [ CommonModule, SharedModule, HttpClientModule ],\n  declarations: [ ApiListComponent ],\n  providers: [ ApiService ]\n})\nexport class ApiListModule implements WithCustomElementComponent {\n  customElementComponent: Type<any> = ApiListComponent;\n}\n"
  },
  {
    "path": "apps/rxjs.dev/src/app/custom-elements/api/api.service.spec.ts",
    "content": "import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing';\nimport { Injector } from '@angular/core';\nimport { TestBed } from '@angular/core/testing';\n\nimport { Logger } from 'app/shared/logger.service';\n\nimport { ApiService } from './api.service';\n\ndescribe('ApiService', () => {\n\n  let injector: Injector;\n  let service: ApiService;\n  let httpMock: HttpTestingController;\n\n  beforeEach(() => {\n    injector = TestBed.configureTestingModule({\n      imports: [HttpClientTestingModule],\n      providers: [\n        ApiService,\n        { provide: Logger, useClass: TestLogger }\n      ]\n    });\n\n    service = injector.get<ApiService>(ApiService);\n    httpMock = injector.get(HttpTestingController);\n  });\n\n  afterEach(() => httpMock.verify());\n\n  it('should not immediately connect to the server', () => {\n    httpMock.expectNone({});\n  });\n\n  it('subscribers should be completed/unsubscribed when service destroyed', () => {\n      let completed = false;\n\n      service.sections.subscribe(\n        undefined,\n        undefined,\n        () => completed = true\n      );\n\n      service.ngOnDestroy();\n      expect(completed).toBe(true);\n\n      // Stop `httpMock.verify()` from complaining.\n      httpMock.expectOne({});\n  });\n\n  describe('#sections', () => {\n\n    it('first subscriber should fetch sections', done => {\n      const data = [\n        {name: 'a', title: 'A', path: '', items: [], deprecated: false},\n        {name: 'b', title: 'B', path: '', items: [], deprecated: false},\n      ];\n\n      service.sections.subscribe(sections => {\n        expect(sections).toEqual(data);\n        done();\n      });\n\n      httpMock.expectOne({}).flush(data);\n    });\n\n    it('second subscriber should get previous sections and NOT trigger refetch', done => {\n      const data = [\n        {name: 'a', title: 'A', path: '', items: [], deprecated: false},\n        {name: 'b', title: 'B', path: '', items: [], deprecated: false},\n      ];\n      let subscriptions = 0;\n\n      service.sections.subscribe(sections => {\n        subscriptions++;\n        expect(sections).toEqual(data);\n      });\n\n      service.sections.subscribe(sections => {\n        subscriptions++;\n        expect(sections).toEqual(data);\n        expect(subscriptions).toBe(2);\n        done();\n      });\n\n      httpMock.expectOne({}).flush(data);\n    });\n  });\n\n  describe('#fetchSections', () => {\n\n    it('should connect to the server w/ expected URL', () => {\n      service.fetchSections();\n      httpMock.expectOne('generated/docs/api/api-list.json');\n    });\n\n    it('should refresh the #sections observable w/ new content on second call', () => {\n\n      let call = 0;\n\n      let data = [\n        {name: 'a', title: 'A', path: '', items: [], deprecated: false},\n        {name: 'b', title: 'B', path: '', items: [], deprecated: false},\n      ];\n\n      service.sections.subscribe(sections => {\n        // called twice during this test\n        // (1) during subscribe\n        // (2) after refresh\n        expect(sections).toEqual(data, 'call ' + call++);\n      });\n\n      httpMock.expectOne({}).flush(data);\n\n      // refresh/refetch\n      data = [{name: 'c', title: 'C', path: '', items: [], deprecated: false}];\n      service.fetchSections();\n      httpMock.expectOne({}).flush(data);\n\n      expect(call).toBe(2, 'should be called twice');\n    });\n  });\n});\n\nclass TestLogger {\n  log = jasmine.createSpy('log');\n  error = jasmine.createSpy('error');\n}\n"
  },
  {
    "path": "apps/rxjs.dev/src/app/custom-elements/api/api.service.ts",
    "content": "import { Injectable, OnDestroy } from '@angular/core';\nimport { HttpClient, HttpErrorResponse } from '@angular/common/http';\n\nimport { ReplaySubject, Subject } from 'rxjs';\nimport { takeUntil, tap } from 'rxjs/operators';\n\nimport { Logger } from 'app/shared/logger.service';\nimport { DOC_CONTENT_URL_PREFIX } from 'app/documents/document.service';\n\nexport interface ApiItem {\n  name: string;\n  title: string;\n  path: string;\n  docType: string;\n  stability: string;\n  securityRisk: boolean;\n}\n\nexport interface ApiSection {\n  path: string;\n  name: string;\n  title: string;\n  deprecated: boolean;\n  items: ApiItem[]|null;\n}\n\n@Injectable()\nexport class ApiService implements OnDestroy {\n\n  private apiBase = DOC_CONTENT_URL_PREFIX + 'api/';\n  private apiListJsonDefault = 'api-list.json';\n  private firstTime = true;\n  private onDestroy = new Subject();\n  private sectionsSubject = new ReplaySubject<ApiSection[]>(1);\n  private _sections = this.sectionsSubject.pipe(takeUntil(this.onDestroy));\n\n  /**\n   * Return a cached observable of API sections from a JSON file.\n   * API sections is an array of Angular top modules and metadata about their API documents (items).\n   */\n  get sections() {\n\n    if (this.firstTime) {\n      this.firstTime = false;\n      this.fetchSections(); // TODO: get URL for fetchSections by configuration?\n\n      // makes sectionsSubject hot; subscribe ensures stays alive (always refCount > 0);\n      this._sections.subscribe(() => this.logger.log('ApiService got API sections') );\n    }\n\n    return this._sections.pipe(tap(sections => {\n      sections.forEach(section => {\n        section.deprecated = !!section.items &&\n            section.items.every(item => item.stability === 'deprecated');\n      });\n    }));\n  }\n\n  constructor(private http: HttpClient, private logger: Logger) { }\n\n  ngOnDestroy() {\n    this.onDestroy.next(null);\n  }\n\n /**\n  * Fetch API sections from a JSON file.\n  * API sections is an array of Angular top modules and metadata about their API documents (items).\n  * Updates `sections` observable\n  *\n  * @param src Name of the api list JSON file\n  */\n  fetchSections(src?: string) {\n    // TODO: get URL by configuration?\n    const url = this.apiBase + (src || this.apiListJsonDefault);\n    this.http.get<ApiSection[]>(url)\n      .pipe(\n        takeUntil(this.onDestroy),\n        tap(() => this.logger.log(`Got API sections from ${url}`)),\n      )\n      .subscribe(\n        sections => this.sectionsSubject.next(sections),\n        (err: HttpErrorResponse) => {\n          // TODO: handle error\n          this.logger.error(err);\n          throw err; // rethrow for now.\n        }\n      );\n  }\n}\n"
  },
  {
    "path": "apps/rxjs.dev/src/app/custom-elements/code/code-example.component.spec.ts",
    "content": "import { Component, ViewChild } from '@angular/core';\nimport { ComponentFixture, TestBed } from '@angular/core/testing';\n\nimport { CodeExampleComponent } from './code-example.component';\nimport { CodeExampleModule } from './code-example.module';\nimport { Logger } from 'app/shared/logger.service';\nimport { MockLogger } from 'testing/logger.service';\n\ndescribe('CodeExampleComponent', () => {\n  let hostComponent: HostComponent;\n  let codeExampleComponent: CodeExampleComponent;\n  let fixture: ComponentFixture<HostComponent>;\n\n  beforeEach(() => {\n    TestBed.configureTestingModule({\n      imports: [ CodeExampleModule ],\n      declarations: [\n        HostComponent,\n      ],\n      providers: [\n        { provide: Logger, useClass: MockLogger },\n      ]\n    });\n\n    fixture = TestBed.createComponent(HostComponent);\n    fixture.detectChanges();\n\n    hostComponent = fixture.componentInstance;\n    codeExampleComponent = hostComponent.codeExampleComponent;\n  });\n\n  it('should be able to capture the code snippet provided in content', () => {\n    expect(codeExampleComponent.aioCode.code.trim()).toBe('const foo = \"bar\";');\n  });\n\n  it('should change aio-code classes based on header presence', () => {\n    expect(codeExampleComponent.header).toBe('Great Example');\n    expect(fixture.nativeElement.querySelector('header')).toBeTruthy();\n    expect(codeExampleComponent.classes).toEqual({\n      'headed-code': true,\n      'simple-code': false\n    });\n\n    codeExampleComponent.header = '';\n    fixture.detectChanges();\n\n    expect(codeExampleComponent.header).toBe('');\n    expect(fixture.nativeElement.querySelector('header')).toBeFalsy();\n    expect(codeExampleComponent.classes).toEqual({\n      'headed-code': false,\n      'simple-code': true\n    });\n  });\n\n  it('should set avoidFile class if path has .avoid.', () => {\n    const codeExampleComponentElement: HTMLElement =\n        fixture.nativeElement.querySelector('code-example');\n\n    expect(codeExampleComponent.path).toBe('code-path');\n    expect(codeExampleComponentElement.className.indexOf('avoidFile') === -1).toBe(true);\n\n    codeExampleComponent.path = 'code-path.avoid.';\n    fixture.detectChanges();\n\n    expect(codeExampleComponentElement.className.indexOf('avoidFile') === -1).toBe(false);\n  });\n\n  it('should coerce hidecopy', () => {\n    expect(codeExampleComponent.hidecopy).toBe(false);\n\n    hostComponent.hidecopy = true;\n    fixture.detectChanges();\n    expect(codeExampleComponent.hidecopy).toBe(true);\n\n    hostComponent.hidecopy = 'false';\n    fixture.detectChanges();\n    expect(codeExampleComponent.hidecopy).toBe(false);\n\n    hostComponent.hidecopy = 'true';\n    fixture.detectChanges();\n    expect(codeExampleComponent.hidecopy).toBe(true);\n  });\n});\n\n@Component({\n  selector: 'aio-host-comp',\n  template: `\n    <code-example [header]=\"header\" [path]=\"path\" [hidecopy]=\"hidecopy\">\n      {{code}}\n    </code-example>\n  `\n})\nclass HostComponent {\n  code = 'const foo = \"bar\";';\n  header = 'Great Example';\n  path = 'code-path';\n  hidecopy: boolean | string = false;\n\n  @ViewChild(CodeExampleComponent, {static: true}) codeExampleComponent: CodeExampleComponent;\n}\n"
  },
  {
    "path": "apps/rxjs.dev/src/app/custom-elements/code/code-example.component.ts",
    "content": "/* tslint:disable component-selector */\nimport { Component, HostBinding, ElementRef, ViewChild, Input, AfterViewInit } from '@angular/core';\nimport { CodeComponent } from './code.component';\n\n/**\n * An embeddable code block that displays nicely formatted code.\n * Example usage:\n *\n * ```\n * <code-example language=\"ts\" linenums=\"2\" class=\"special\" header=\"Do Stuff\">\n * // a code block\n * console.log('do stuff');\n * </code-example>\n * ```\n */\n@Component({\n  // eslint-disable-next-line @angular-eslint/component-selector\n  selector: 'code-example',\n  template: `\n    <!-- Content projection is used to get the content HTML provided to this component -->\n    <div #content style=\"display: none\"><ng-content></ng-content></div>\n    <header *ngIf=\"header\">{{header}}</header>\n    <aio-code [ngClass]=\"classes\"\n              [language]=\"language\"\n              [linenums]=\"linenums\"\n              [path]=\"path\"\n              [region]=\"region\"\n              [hideCopy]=\"hidecopy\"\n              [header]=\"header\">\n    </aio-code>\n  `,\n})\nexport class CodeExampleComponent implements AfterViewInit {\n  classes: Record<string, boolean>;\n\n  @Input() language: string;\n\n  @Input() linenums: string;\n\n  @Input() region: string;\n\n  @Input()\n  set header(header: string) {\n    this._header = header;\n    this.classes = {\n      'headed-code': !!this.header,\n      'simple-code': !this.header,\n    };\n  }\n  get header(): string { return this._header; }\n  private _header: string;\n\n  @Input()\n  set path(path: string) {\n    this._path = path;\n    this.isAvoid = this.path.indexOf('.avoid.') !== -1;\n  }\n  get path(): string { return this._path; }\n  private _path = '';\n\n  @Input()\n  set hidecopy(hidecopy: boolean) {\n    // Coerce the boolean value.\n    this._hidecopy = hidecopy != null && `${hidecopy}` !== 'false';\n  }\n  get hidecopy(): boolean { return this._hidecopy; }\n  private _hidecopy: boolean;\n\n  // eslint-disable-next-line @angular-eslint/no-input-rename\n  @Input('hide-copy')\n  set hyphenatedHideCopy(hidecopy: boolean) {\n    this.hidecopy = hidecopy;\n  }\n\n  // eslint-disable-next-line @angular-eslint/no-input-rename\n  @Input('hideCopy')\n  set capitalizedHideCopy(hidecopy: boolean) {\n    this.hidecopy = hidecopy;\n  }\n\n  @HostBinding('class.avoidFile') isAvoid = false;\n\n  @ViewChild('content', { static: true }) content: ElementRef;\n\n  @ViewChild(CodeComponent, { static: true }) aioCode: CodeComponent;\n\n  ngAfterViewInit() {\n    this.aioCode.code = this.content.nativeElement.innerHTML;\n  }\n}\n"
  },
  {
    "path": "apps/rxjs.dev/src/app/custom-elements/code/code-example.module.ts",
    "content": "import { NgModule, Type } from '@angular/core';\nimport { CommonModule } from '@angular/common';\nimport { CodeExampleComponent } from './code-example.component';\nimport { CodeModule } from './code.module';\nimport { WithCustomElementComponent } from '../element-registry';\n\n@NgModule({\n  imports: [ CommonModule, CodeModule ],\n  declarations: [ CodeExampleComponent ],\n  exports: [ CodeExampleComponent ]\n})\nexport class CodeExampleModule implements WithCustomElementComponent {\n  customElementComponent: Type<any> = CodeExampleComponent;\n}\n"
  },
  {
    "path": "apps/rxjs.dev/src/app/custom-elements/code/code-tabs.component.spec.ts",
    "content": "import { Component, ViewChild, NO_ERRORS_SCHEMA } from '@angular/core';\nimport { ComponentFixture, TestBed } from '@angular/core/testing';\nimport { Logger } from 'app/shared/logger.service';\nimport { MockLogger } from 'testing/logger.service';\nimport { NoopAnimationsModule } from '@angular/platform-browser/animations';\n\nimport { CodeTabsComponent } from './code-tabs.component';\nimport { CodeTabsModule } from './code-tabs.module';\n\n@Component({\n  selector: 'aio-host-comp',\n  template: `\n    <code-tabs linenums=\"default-linenums\">\n      <code-pane class=\"class-A\" language=\"language-A\" linenums=\"linenums-A\" path=\"path-A\" region=\"region-A\" header=\"header-A\">\n        Code example 1\n      </code-pane>\n      <code-pane class=\"class-B\" language=\"language-B\" path=\"path-B\" region=\"region-B\" header=\"header-B\">\n        Code example 2\n      </code-pane>\n    </code-tabs>\n  `,\n})\nclass HostComponent {\n  @ViewChild(CodeTabsComponent, { static: true }) codeTabsComponent: CodeTabsComponent;\n}\n\ndescribe('CodeTabsComponent', () => {\n  let fixture: ComponentFixture<HostComponent>;\n  let hostComponent: HostComponent;\n  let codeTabsComponent: CodeTabsComponent;\n\n  beforeEach(() => {\n    TestBed.configureTestingModule({\n      declarations: [HostComponent],\n      imports: [CodeTabsModule, NoopAnimationsModule],\n      schemas: [NO_ERRORS_SCHEMA],\n      providers: [{ provide: Logger, useClass: MockLogger }],\n    });\n\n    fixture = TestBed.createComponent(HostComponent);\n    fixture.detectChanges();\n\n    hostComponent = fixture.componentInstance;\n    codeTabsComponent = hostComponent.codeTabsComponent;\n  });\n\n  it('should get correct tab info', () => {\n    const tabs = codeTabsComponent.tabs;\n    expect(tabs.length).toBe(2);\n\n    // First code pane expectations\n    expect(tabs[0].class).toBe('class-A');\n    expect(tabs[0].language).toBe('language-A');\n    expect(tabs[0].linenums).toBe('linenums-A');\n    expect(tabs[0].path).toBe('path-A');\n    expect(tabs[0].region).toBe('region-A');\n    expect(tabs[0].header).toBe('header-A');\n    expect(tabs[0].code.trim()).toBe('Code example 1');\n\n    // Second code pane expectations\n    expect(tabs[1].class).toBe('class-B');\n    expect(tabs[1].language).toBe('language-B');\n    expect(tabs[1].linenums).toBe('default-linenums', 'Default linenums should have been used');\n    expect(tabs[1].path).toBe('path-B');\n    expect(tabs[1].region).toBe('region-B');\n    expect(tabs[1].header).toBe('header-B');\n    expect(tabs[1].code.trim()).toBe('Code example 2');\n  });\n\n  it('should create the right number of tabs with the right labels and classes', () => {\n    const matTabs = fixture.nativeElement.querySelectorAll('.mat-tab-label');\n    expect(matTabs.length).toBe(2);\n\n    expect(matTabs[0].textContent.trim()).toBe('header-A');\n    expect(matTabs[0].querySelector('.class-A')).toBeTruthy();\n\n    expect(matTabs[1].textContent.trim()).toBe('header-B');\n    expect(matTabs[1].querySelector('.class-B')).toBeTruthy();\n  });\n\n  it('should show the first tab with the right code', () => {\n    const codeContent = fixture.nativeElement.querySelector('aio-code').textContent;\n    expect(codeContent.indexOf('Code example 1') !== -1).toBeTruthy();\n  });\n});\n"
  },
  {
    "path": "apps/rxjs.dev/src/app/custom-elements/code/code-tabs.component.ts",
    "content": "/* tslint:disable component-selector */\nimport { AfterViewInit, Component, ElementRef, Input, OnInit, QueryList, ViewChild, ViewChildren } from '@angular/core';\nimport { CodeComponent } from './code.component';\n\nexport interface TabInfo {\n  class: string | null;\n  code: string;\n  language: string | null;\n  linenums: any;\n  path: string;\n  region: string;\n  header: string | null;\n}\n\n/**\n * Renders a set of tab group of code snippets.\n *\n * The innerHTML of the `<code-tabs>` component should contain `<code-pane>` elements.\n * Each `<code-pane>` has the same interface as the embedded `<code-example>` component.\n * The optional `linenums` attribute is the default `linenums` for each code pane.\n */\n@Component({\n  // eslint-disable-next-line @angular-eslint/component-selector\n  selector: 'code-tabs',\n  template: `\n    <!-- Use content projection so that the provided HTML's code-panes can be split into tabs -->\n    <div #content style=\"display: none\"><ng-content></ng-content></div>\n    <mat-card>\n      <mat-tab-group class=\"code-tab-group\" disableRipple>\n        <mat-tab style=\"overflow-y: hidden;\" *ngFor=\"let tab of tabs\">\n          <ng-template mat-tab-label>\n            <span class=\"{{ tab.class }}\">{{ tab.header }}</span>\n          </ng-template>\n          <aio-code\n            class=\"{{ tab.class }}\"\n            [language]=\"tab.language\"\n            [linenums]=\"tab.linenums\"\n            [path]=\"tab.path\"\n            [region]=\"tab.region\"\n            [header]=\"tab.header\"\n          >\n          </aio-code>\n        </mat-tab>\n      </mat-tab-group>\n    </mat-card>\n  `,\n})\nexport class CodeTabsComponent implements OnInit, AfterViewInit {\n  tabs: TabInfo[];\n\n  @Input() linenums: string;\n\n  @ViewChild('content', { static: true }) content: ElementRef<HTMLDivElement>;\n\n  @ViewChildren(CodeComponent) codeComponents: QueryList<CodeComponent>;\n\n  ngOnInit() {\n    this.tabs = [];\n    const codeExamples = Array.from(this.content.nativeElement.querySelectorAll('code-pane'));\n\n    for (const tabContent of codeExamples) {\n      this.tabs.push(this.getTabInfo(tabContent));\n    }\n  }\n\n  ngAfterViewInit() {\n    this.codeComponents.toArray().forEach((codeComponent, i) => {\n      codeComponent.code = this.tabs[i].code;\n    });\n  }\n\n  /** Gets the extracted TabInfo data from the provided code-pane element. */\n  private getTabInfo(tabContent: Element): TabInfo {\n    return {\n      class: tabContent.getAttribute('class'),\n      code: tabContent.innerHTML,\n      language: tabContent.getAttribute('language'),\n      linenums: tabContent.getAttribute('linenums') || this.linenums,\n      path: tabContent.getAttribute('path') || '',\n      region: tabContent.getAttribute('region') || '',\n      header: tabContent.getAttribute('header'),\n    };\n  }\n}\n"
  },
  {
    "path": "apps/rxjs.dev/src/app/custom-elements/code/code-tabs.module.ts",
    "content": "import { NgModule, Type } from '@angular/core';\nimport { CommonModule } from '@angular/common';\nimport { CodeTabsComponent } from './code-tabs.component';\nimport { MatCardModule } from '@angular/material/card';\nimport { MatTabsModule } from '@angular/material/tabs';\nimport { CodeModule } from './code.module';\nimport { WithCustomElementComponent } from '../element-registry';\n\n@NgModule({\n  imports: [ CommonModule, MatCardModule, MatTabsModule, CodeModule ],\n  declarations: [ CodeTabsComponent ],\n  exports: [ CodeTabsComponent ]\n})\nexport class CodeTabsModule implements WithCustomElementComponent {\n  customElementComponent: Type<any> = CodeTabsComponent;\n}\n"
  },
  {
    "path": "apps/rxjs.dev/src/app/custom-elements/code/code.component.spec.ts",
    "content": "import { Component, ViewChild, NO_ERRORS_SCHEMA } from '@angular/core';\nimport { ComponentFixture, TestBed } from '@angular/core/testing';\nimport { Logger } from 'app/shared/logger.service';\nimport { MockLogger } from 'testing/logger.service';\nimport { NoopAnimationsModule } from '@angular/platform-browser/animations';\n\nimport { CodeTabsComponent } from './code-tabs.component';\nimport { CodeTabsModule } from './code-tabs.module';\n\ndescribe('CodeTabsComponent', () => {\n  let fixture: ComponentFixture<HostComponent>;\n  let hostComponent: HostComponent;\n  let codeTabsComponent: CodeTabsComponent;\n\n  beforeEach(() => {\n    TestBed.configureTestingModule({\n      declarations: [ HostComponent ],\n      imports: [ CodeTabsModule, NoopAnimationsModule ],\n      schemas: [ NO_ERRORS_SCHEMA ],\n      providers: [\n       { provide: Logger, useClass: MockLogger },\n      ]\n    });\n\n    fixture = TestBed.createComponent(HostComponent);\n    fixture.detectChanges();\n\n    hostComponent = fixture.componentInstance;\n    codeTabsComponent = hostComponent.codeTabsComponent;\n  });\n\n  it('should get correct tab info', () => {\n    const tabs = codeTabsComponent.tabs;\n    expect(tabs.length).toBe(2);\n\n    // First code pane expectations\n    expect(tabs[0].class).toBe('class-A');\n    expect(tabs[0].language).toBe('language-A');\n    expect(tabs[0].linenums).toBe('linenums-A');\n    expect(tabs[0].path).toBe('path-A');\n    expect(tabs[0].region).toBe('region-A');\n    expect(tabs[0].header).toBe('header-A');\n    expect(tabs[0].code.trim()).toBe('Code example 1');\n\n    // Second code pane expectations\n    expect(tabs[1].class).toBe('class-B');\n    expect(tabs[1].language).toBe('language-B');\n    expect(tabs[1].linenums).toBe('default-linenums', 'Default linenums should have been used');\n    expect(tabs[1].path).toBe('path-B');\n    expect(tabs[1].region).toBe('region-B');\n    expect(tabs[1].header).toBe('header-B');\n    expect(tabs[1].code.trim()).toBe('Code example 2');\n  });\n\n  it('should create the right number of tabs with the right labels and classes', () => {\n    const matTabs = fixture.nativeElement.querySelectorAll('.mat-tab-label');\n    expect(matTabs.length).toBe(2);\n\n    expect(matTabs[0].textContent.trim()).toBe('header-A');\n    expect(matTabs[0].querySelector('.class-A')).toBeTruthy();\n\n    expect(matTabs[1].textContent.trim()).toBe('header-B');\n    expect(matTabs[1].querySelector('.class-B')).toBeTruthy();\n  });\n\n  it('should show the first tab with the right code', () => {\n    const codeContent = fixture.nativeElement.querySelector('aio-code').textContent;\n    expect(codeContent.indexOf('Code example 1') !== -1).toBeTruthy();\n  });\n});\n\n@Component({\n  selector: 'aio-host-comp',\n  template: `\n    <code-tabs linenums=\"default-linenums\">\n      <code-pane class=\"class-A\"\n                 language=\"language-A\"\n                 linenums=\"linenums-A\"\n                 path=\"path-A\"\n                 region=\"region-A\"\n                 header=\"header-A\">\n        Code example 1\n      </code-pane>\n      <code-pane class=\"class-B\"\n                 language=\"language-B\"\n                 path=\"path-B\"\n                 region=\"region-B\"\n                 header=\"header-B\">\n        Code example 2\n      </code-pane>\n    </code-tabs>\n  `\n})\nclass HostComponent {\n  @ViewChild(CodeTabsComponent, {static: true}) codeTabsComponent: CodeTabsComponent;\n}\n"
  },
  {
    "path": "apps/rxjs.dev/src/app/custom-elements/code/code.component.ts",
    "content": "import { Component, ElementRef, EventEmitter, Input, OnChanges, Output, ViewChild } from '@angular/core';\nimport { Logger } from 'app/shared/logger.service';\nimport { PrettyPrinter } from './pretty-printer.service';\nimport { CopierService } from 'app/shared/copier.service';\nimport { MatSnackBar } from '@angular/material/snack-bar';\nimport { tap } from 'rxjs/operators';\nimport { StackblitzService } from 'app/shared/stackblitz.service';\n// @ts-expect-error\nimport version from '../../../../tools/stackblitz/rxjs.version';\n\n/**\n * If linenums is not set, this is the default maximum number of lines that\n * an example can display without line numbers.\n */\nconst DEFAULT_LINE_NUMS_COUNT = 10;\n\n/**\n * Formatted Code Block\n *\n * Pretty renders a code block, used in the docs and API reference by the code-example and\n * code-tabs embedded components.\n * It includes a \"copy\" button that will send the content to the clipboard when clicked\n *\n * Example usage:\n *\n * ```\n * <aio-code\n *   [language]=\"ts\"\n *   [linenums]=\"true\"\n *   [path]=\"router/src/app/app.module.ts\"\n *   [region]=\"animations-module\">\n * </aio-code>\n * ```\n *\n *\n * Renders code provided through the `updateCode` method.\n */\n@Component({\n  selector: 'aio-code',\n  template: `\n    <pre class=\"prettyprint lang-{{ language }}\">\n      <button *ngIf=\"!hideCopy\" class=\"material-icons copy-button no-print\"\n        title=\"Copy code snippet\"\n        [attr.aria-label]=\"ariaLabelCopy\"\n        (click)=\"doCopy()\">\n        <span aria-hidden=\"true\">content_copy</span>\n      </button>\n      <button *ngIf=\"!hideCopy\" class=\"material-icons edit-button no-print\"\n        title=\"Edit in StackBlitz\"\n        [attr.aria-label]=\"ariaLabelEdit\"\n        (click)=\"editInStackBlitz()\">\n        <span aria-hidden=\"true\">open_in_new</span>\n      </button>\n      <code class=\"animated fadeIn\" #codeContainer></code>\n    </pre>\n  `,\n})\nexport class CodeComponent implements OnChanges {\n  ariaLabelCopy = '';\n  ariaLabelEdit = '';\n\n  /** The code to be copied when clicking the copy button, this should not be HTML encoded */\n  private codeText: string;\n\n  /** Code that should be formatted with current inputs and displayed in the view. */\n  set code(code: string) {\n    this._code = code;\n\n    if (!this._code || !this._code.trim()) {\n      this.showMissingCodeMessage();\n    } else {\n      this.formatDisplayedCode();\n    }\n  }\n  get code(): string {\n    return this._code;\n  }\n  _code: string;\n\n  /** Whether the copy button should be shown. */\n  @Input() hideCopy: boolean;\n\n  /** Language to render the code (e.g. javascript, dart, typescript). */\n  @Input() language: string | null;\n\n  /**\n   * Whether to display line numbers:\n   *  - If false: hide\n   *  - If true: show\n   *  - If number: show but start at that number\n   */\n  @Input() linenums: boolean | number | string;\n\n  /** Path to the source of the code. */\n  @Input() path: string;\n\n  /** Region of the source of the code being displayed. */\n  @Input() region: string;\n\n  /** Optional header to be displayed above the code. */\n  @Input()\n  set header(header: string | null) {\n    this._header = header;\n    this.ariaLabelCopy = this.header ? `Copy code snippet from ${this.header}` : '';\n    this.ariaLabelEdit = this.header ? `Edit code snippet from ${this.header} in StackBlitz` : '';\n  }\n  get header(): string | null {\n    return this._header;\n  }\n  private _header: string | null;\n\n  @Output() codeFormatted = new EventEmitter<void>();\n\n  /** The element in the template that will display the formatted code. */\n  @ViewChild('codeContainer', { static: true }) codeContainer: ElementRef;\n\n  constructor(\n    private snackbar: MatSnackBar,\n    private pretty: PrettyPrinter,\n    private copier: CopierService,\n    private logger: Logger,\n    private stackblitz: StackblitzService\n  ) {}\n\n  ngOnChanges() {\n    // If some inputs have changed and there is code displayed, update the view with the latest\n    // formatted code.\n    if (this.code) {\n      this.formatDisplayedCode();\n    }\n  }\n\n  private formatDisplayedCode() {\n    const leftAlignedCode = leftAlign(this.code);\n    this.setCodeHtml(leftAlignedCode); // start with unformatted code\n    this.codeText = this.getCodeText(); // store the unformatted code as text (for copying)\n\n    this.pretty\n      .formatCode(leftAlignedCode, this.language ?? '', this.getLinenums(leftAlignedCode))\n      .pipe(tap(() => this.codeFormatted.emit()))\n      .subscribe(\n        (c) => this.setCodeHtml(c),\n        () => {\n          /* ignore failure to format */\n        }\n      );\n  }\n\n  /** Sets the message showing that the code could not be found. */\n  private showMissingCodeMessage() {\n    const src = this.path ? this.path + (this.region ? '#' + this.region : '') : '';\n    const srcMsg = src ? ` for\\n${src}` : '.';\n    this.setCodeHtml(`<p class=\"code-missing\">The code sample is missing${srcMsg}</p>`);\n  }\n\n  /** Sets the innerHTML of the code container to the provided code string. */\n  private setCodeHtml(formattedCode: string) {\n    // **Security:** Code example content is provided by docs authors and as such its considered to\n    // be safe for innerHTML purposes.\n    this.codeContainer.nativeElement.innerHTML = formattedCode;\n  }\n\n  /** Gets the textContent of the displayed code element. */\n  private getCodeText() {\n    // `prettify` may remove newlines, e.g. when `linenums` are on. Retrieve the content of the\n    // container as text, before prettifying it.\n    // We take the textContent because we don't want it to be HTML encoded.\n    return this.codeContainer.nativeElement.textContent;\n  }\n\n  /** Extracts html placed in the `// html: ` comment in the code.  */\n  private getHtmlFromCode(code: string): string {\n    const pattern = new RegExp('// html: (.*)');\n    const matches = code.match(pattern);\n\n    return matches ? matches[1] : '';\n  }\n\n  /** Copies the code snippet to the user's clipboard. */\n  doCopy() {\n    const code = this.codeText;\n    const successfullyCopied = this.copier.copyText(code);\n\n    if (successfullyCopied) {\n      this.logger.log('Copied code to clipboard:', code);\n      this.snackbar.open('Code Copied', '', { duration: 800 });\n    } else {\n      this.logger.error(new Error(`ERROR copying code to clipboard: \"${code}\"`));\n      this.snackbar.open('Copy failed. Please try again!', '', { duration: 800 });\n    }\n  }\n\n  editInStackBlitz() {\n    this.stackblitz.openProject({\n      code: this.codeText,\n      language: this.language ?? '',\n      dependencies: {\n        rxjs: version,\n      },\n      html: this.getHtmlFromCode(this.codeText),\n    });\n  }\n\n  /** Gets the calculated value of linenums (boolean/number). */\n  getLinenums(code: string) {\n    const linenums =\n      typeof this.linenums === 'boolean'\n        ? this.linenums\n        : this.linenums === 'true'\n        ? true\n        : this.linenums === 'false'\n        ? false\n        : typeof this.linenums === 'string'\n        ? parseInt(this.linenums, 10)\n        : this.linenums;\n\n    // if no linenums, enable line numbers if more than one line\n    return linenums == null || isNaN(linenums as number) ? (code.match(/\\n/g) || []).length > DEFAULT_LINE_NUMS_COUNT : linenums;\n  }\n}\n\nfunction leftAlign(text: string): string {\n  let indent = Number.MAX_VALUE;\n\n  const lines = text.split('\\n');\n  lines.forEach((line) => {\n    const lineIndent = line.search(/\\S/);\n    if (lineIndent !== -1) {\n      indent = Math.min(lineIndent, indent);\n    }\n  });\n\n  return lines\n    .map((line) => line.substr(indent))\n    .join('\\n')\n    .trim();\n}\n"
  },
  {
    "path": "apps/rxjs.dev/src/app/custom-elements/code/code.module.ts",
    "content": "import { NgModule } from '@angular/core';\nimport { CommonModule } from '@angular/common';\nimport { CodeComponent } from './code.component';\nimport { MatSnackBarModule } from '@angular/material/snack-bar';\nimport { PrettyPrinter } from './pretty-printer.service';\nimport { CopierService } from 'app/shared/copier.service';\n\n@NgModule({\n  imports: [ CommonModule, MatSnackBarModule ],\n  declarations: [ CodeComponent ],\n  exports: [ CodeComponent ],\n  providers: [ PrettyPrinter, CopierService ]\n})\nexport class CodeModule { }\n"
  },
  {
    "path": "apps/rxjs.dev/src/app/custom-elements/code/pretty-printer.service.ts",
    "content": "import { Injectable } from '@angular/core';\n\nimport { from as fromPromise, Observable } from 'rxjs';\nimport { first, map, share } from 'rxjs/operators';\n\nimport { Logger } from 'app/shared/logger.service';\n\ntype PrettyPrintOne = (code: string, language?: string, linenums?: number | boolean) => string;\n\n/**\n * Wrapper around the prettify.js library\n */\n@Injectable()\nexport class PrettyPrinter {\n\n  private prettyPrintOne: Observable<PrettyPrintOne>;\n\n  constructor(private logger: Logger) {\n    this.prettyPrintOne = fromPromise(this.getPrettyPrintOne()).pipe(share());\n  }\n\n  private getPrettyPrintOne(): Promise<PrettyPrintOne> {\n    const ppo = (window as any).prettyPrintOne;\n    return ppo ? Promise.resolve(ppo) :\n      // `prettyPrintOne` is not on `window`, which means `prettify.js` has not been loaded yet.\n      // Import it; as a side-effect it will add `prettyPrintOne` on `window`.\n      import('assets/js/prettify.js' as any)\n        .then(\n          () => (window as any).prettyPrintOne,\n          err => {\n            const msg = `Cannot get prettify.js from server: ${err.message}`;\n            this.logger.error(new Error(msg));\n            // return a pretty print fn that always fails.\n            return () => { throw new Error(msg); };\n          });\n  }\n\n  /**\n   * Format code snippet as HTML\n   *\n   * @param code the code snippet to format; should already be HTML encoded\n   * @param language The language of the code to render (could be javascript, html, typescript, etc)\n   * @param linenums Whether to display line numbers:\n   *  - false: don't display\n   *  - true: do display\n   *  - number: do display but start at the given number\n   * @returns Observable of formatted code\n   */\n  formatCode(code: string, language?: string, linenums?: number | boolean) {\n    return this.prettyPrintOne.pipe(\n      map(ppo => {\n        try {\n          return ppo(code, language, linenums);\n        } catch (err) {\n          const msg = `Could not format code that begins '${code.substr(0, 50)}...'.`;\n          console.error(msg, err);\n          throw new Error(msg);\n        }\n      }),\n      first(),  // complete immediately\n    );\n  }\n}\n"
  },
  {
    "path": "apps/rxjs.dev/src/app/custom-elements/contributor/contributor-list.component.spec.ts",
    "content": "import { ReflectiveInjector } from '@angular/core';\n\nimport { of } from 'rxjs';\n\nimport { ContributorGroup } from './contributors.model';\nimport { ContributorListComponent } from './contributor-list.component';\nimport { ContributorService } from './contributor.service';\nimport { LocationService } from 'app/shared/location.service';\n\n// Testing the component class behaviors, independent of its template\n// Let e2e tests verify how it displays.\ndescribe('ContributorListComponent', () => {\n\n  let component: ContributorListComponent;\n  let injector: ReflectiveInjector;\n  let contributorService: TestContributorService;\n  let locationService: TestLocationService;\n  let contributorGroups: ContributorGroup[];\n\n  beforeEach(() => {\n    injector = ReflectiveInjector.resolveAndCreate([\n      ContributorListComponent,\n      {provide: ContributorService, useClass: TestContributorService },\n      {provide: LocationService, useClass: TestLocationService }\n    ]);\n\n    locationService = injector.get(LocationService);\n    contributorService = injector.get(ContributorService);\n    contributorGroups = contributorService.testContributors;\n  });\n\n  it('should select the first group when no query string', () => {\n    component = getComponent();\n    expect(component.selectedGroup).toBe(contributorGroups[0]);\n  });\n\n  it('should select the first group when query string w/o \"group\" property', () => {\n    locationService.searchResult = { foo: 'GDE' };\n    component = getComponent();\n    expect(component.selectedGroup).toBe(contributorGroups[0]);\n  });\n\n  it('should select the first group when query group not found', () => {\n    locationService.searchResult = { group: 'foo' };\n    component = getComponent();\n    expect(component.selectedGroup).toBe(contributorGroups[0]);\n  });\n\n  it('should select the GDE group when query group is \"GDE\"', () => {\n    locationService.searchResult = { group: 'GDE' };\n    component = getComponent();\n    expect(component.selectedGroup).toBe(contributorGroups[1]);\n  });\n\n  it('should select the GDE group when query group is \"gde\" (case insensitive)', () => {\n    locationService.searchResult = { group: 'gde' };\n    component = getComponent();\n    expect(component.selectedGroup).toBe(contributorGroups[1]);\n  });\n\n  it('should set the query to the \"GDE\" group when user selects \"GDE\"', () => {\n    component = getComponent();\n    component.selectGroup('GDE');\n    expect(locationService.searchResult.group).toBe('GDE');\n  });\n\n  it('should set the query to the first group when user selects unknown name', () => {\n    component = getComponent();\n    component.selectGroup('GDE'); // a legit group that isn't the first\n\n    component.selectGroup('foo'); // not a legit group name\n    expect(locationService.searchResult.group).toBe('Angular');\n  });\n\n  //// Test Helpers ////\n  function  getComponent(): ContributorListComponent {\n    const comp = injector.get(ContributorListComponent);\n    comp.ngOnInit();\n    return comp;\n  }\n\n  interface SearchResult { [index: string]: string };\n\n  class TestLocationService {\n    searchResult: SearchResult = {};\n    search = jasmine.createSpy('search').and.callFake(() => this.searchResult);\n    setSearch = jasmine.createSpy('setSearch')\n      .and.callFake((label: string, result: SearchResult) => {\n        this.searchResult = result;\n      });\n  }\n\n  class TestContributorService {\n    testContributors = getTestData();\n    contributors = of(this.testContributors);\n  }\n\n  function getTestData(): ContributorGroup[] {\n    return [\n      // Not interested in the contributors data in these tests\n      { name: 'Angular', order: 0, contributors: [] },\n      { name: 'GDE', order: 1, contributors: [] },\n    ];\n  }\n});\n"
  },
  {
    "path": "apps/rxjs.dev/src/app/custom-elements/contributor/contributor-list.component.ts",
    "content": "import { Component, OnInit } from '@angular/core';\nimport { ContributorGroup } from './contributors.model';\nimport { ContributorService } from './contributor.service';\nimport { LocationService } from 'app/shared/location.service';\n\n@Component({\n  selector: 'aio-contributor-list',\n  template: `\n  <div class=\"flex-center group-buttons\">\n  <!-- eslint-disable-next-line @angular-eslint/template/click-events-have-key-events -->\n    <a *ngFor=\"let name of groupNames\"\n       [class.selected]=\"name == selectedGroup.name\"\n       class=\"button mat-button filter-button\"\n       (click)=\"selectGroup(name)\">{{name}}</a>\n  </div>\n  <section *ngIf=\"selectedGroup\" class=\"grid-fluid\">\n    <div class=\"contributor-group\">\n      <aio-contributor *ngFor=\"let person of selectedGroup.contributors\" [person]=\"person\"></aio-contributor>\n    </div>\n  </section>`\n})\nexport class ContributorListComponent implements OnInit {\n  private groups: ContributorGroup[];\n  groupNames: string[];\n  selectedGroup: ContributorGroup;\n\n  constructor(\n    private contributorService: ContributorService,\n    private locationService: LocationService) { }\n\n  ngOnInit() {\n    const groupName =  this.locationService.search().group || '';\n    // no need to unsubscribe because `contributors` completes\n    this.contributorService.contributors\n      .subscribe(grps => {\n        this.groups = grps;\n        this.groupNames = grps.map(g => g.name);\n        this.selectGroup(groupName);\n      });\n  }\n\n  selectGroup(name: string) {\n    name = name.toLowerCase();\n    this.selectedGroup = this.groups.find(g => g.name.toLowerCase() === name) || this.groups[0];\n    this.locationService.setSearch('', {group: this.selectedGroup.name});\n  }\n}\n"
  },
  {
    "path": "apps/rxjs.dev/src/app/custom-elements/contributor/contributor-list.module.ts",
    "content": "import { NgModule, Type } from '@angular/core';\nimport { CommonModule } from '@angular/common';\nimport { ContributorListComponent } from './contributor-list.component';\nimport { ContributorService } from './contributor.service';\nimport { ContributorComponent } from './contributor.component';\nimport { WithCustomElementComponent } from '../element-registry';\n\n@NgModule({\n  imports: [CommonModule],\n  declarations: [ContributorListComponent, ContributorComponent],\n  providers: [ContributorService],\n})\nexport class ContributorListModule implements WithCustomElementComponent {\n  customElementComponent: Type<any> = ContributorListComponent;\n}\n"
  },
  {
    "path": "apps/rxjs.dev/src/app/custom-elements/contributor/contributor.component.ts",
    "content": "import { Component, Input } from '@angular/core';\n\nimport { Contributor } from './contributors.model';\nimport { CONTENT_URL_PREFIX } from 'app/documents/document.service';\n\n@Component({\n  selector: 'aio-contributor',\n  template: `\n    <div [ngClass]=\"{ 'flipped': person.isFlipped }\" class=\"contributor-card\">\n\n        <div class=\"card-front\">\n            <h3>{{person.name}}</h3>\n\n            <div class=\"contributor-image\" [style.background-image]=\"'url('+(person.picture || noPicture)+')'\">\n                <div class=\"contributor-info\">\n                    <a *ngIf=\"person.bio\" mat-button>\n                        View Bio\n                    </a>\n                    <a *ngIf=\"person.twitter\" mat-button class=\"icon\"\n                        href=\"{{person.twitter}}\" target=\"_blank\" (click)=\"$event.stopPropagation()\">\n                        <span class=\"fa fa-twitter fa-2x\" aria-hidden=\"true\"></span>\n                        <span class=\"sr-only\">Twitter {{person.name}}</span>\n                    </a>\n                    <a *ngIf=\"person.github\" mat-button class=\"icon\"\n                        href=\"{{person.github}}\" target=\"_blank\" (click)=\"$event.stopPropagation()\">\n                        <span class=\"fa fa-github fa-2x\" aria-hidden=\"true\"></span>\n                        <span class=\"sr-only\">GitHub {{person.name}}</span>\n                    </a>\n                    <a *ngIf=\"person.website\" mat-button class=\"icon\"\n                        href=\"{{person.website}}\" target=\"_blank\" (click)=\"$event.stopPropagation()\">\n                        <span class=\"fa fa-link fa-2x\" aria-hidden=\"true\"></span>\n                        <span class=\"sr-only\">Personal website {{person.name}}</span>\n                    </a>\n                </div>\n            </div>\n        </div>\n\n        <!-- eslint-disable-next-line @angular-eslint/template/click-events-have-key-events -->\n        <div class=\"card-back\" *ngIf=\"person.isFlipped\" (click)=\"flipCard(person)\">\n            <h3>{{person.name}}</h3>\n            <p class=\"contributor-bio\">{{person.bio}}</p>\n        </div>\n    </div>\n  `,\n})\nexport class ContributorComponent {\n  @Input() person: Contributor;\n  noPicture = '_no-one.png';\n  pictureBase = CONTENT_URL_PREFIX + 'images/bios/';\n\n  flipCard(person: Contributor) {\n    person.isFlipped = !person.isFlipped;\n  }\n}\n"
  },
  {
    "path": "apps/rxjs.dev/src/app/custom-elements/contributor/contributor.service.spec.ts",
    "content": "import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing';\nimport { Injector } from '@angular/core';\nimport { TestBed } from '@angular/core/testing';\n\nimport { ContributorService } from './contributor.service';\nimport { ContributorGroup } from './contributors.model';\n\ndescribe('ContributorService', () => {\n\n  let injector: Injector;\n  let contribService: ContributorService;\n  let httpMock: HttpTestingController;\n\n  beforeEach(() => {\n    injector = TestBed.configureTestingModule({\n      imports: [HttpClientTestingModule],\n      providers: [\n        ContributorService\n      ]\n    });\n\n    contribService = injector.get(ContributorService);\n    httpMock = injector.get(HttpTestingController);\n  });\n\n  afterEach(() => httpMock.verify());\n\n  it('should make a single connection to the server', () => {\n    const req = httpMock.expectOne({});\n    expect(req.request.url).toBe('generated/contributors.json');\n  });\n\n  describe('#contributors', () => {\n\n    let contribs: ContributorGroup[];\n    let testData: any;\n\n    beforeEach(() => {\n      testData = getTestContribs();\n      httpMock.expectOne({}).flush(testData);\n      contribService.contributors.subscribe(results => contribs = results);\n    });\n\n    it('contributors observable should complete', () => {\n      let completed = false;\n      contribService.contributors.subscribe(undefined, undefined, () => completed = true);\n      expect(completed).toBe(true, 'observable completed');\n    });\n\n    it('should reshape the contributor json to expected result', () => {\n      const groupNames = contribs.map(g => g.name).join(',');\n      expect(groupNames).toEqual('Angular,GDE');\n    });\n\n    it('should have expected \"GDE\" contribs in order', () => {\n      const gde = contribs[1];\n      const actualAngularNames = gde.contributors.map(l => l.name).join(',');\n      const expectedAngularNames = [testData.jeffcross, testData.kapunahelewong].map(l => l.name).join(',');\n      expect(actualAngularNames).toEqual(expectedAngularNames);\n    });\n  });\n\n  it('should do WHAT(?) if the request fails');\n});\n\nfunction getTestContribs() {\n  return {\n    kapunahelewong: {\n      name: 'Kapunahele Wong',\n      picture: 'kapunahelewong.jpg',\n      website: 'https://github.com/kapunahelewong',\n      twitter: 'kapunahele',\n      bio: 'Kapunahele is a front-end developer and contributor to angular.io',\n      group: 'GDE'\n    },\n    misko: {\n      name: 'Miško Hevery',\n      picture: 'misko.jpg',\n      twitter: 'mhevery',\n      website: 'http://misko.hevery.com',\n      bio: 'Miško Hevery is the creator of AngularJS framework.',\n      group: 'Angular'\n    },\n    igor: {\n      name: 'Igor Minar',\n      picture: 'igor-minar.jpg',\n      twitter: 'IgorMinar',\n      website: 'https://google.com/+IgorMinar',\n      bio: 'Igor is a software engineer at Angular.',\n      group: 'Angular'\n    },\n    kara: {\n      name: 'Kara Erickson',\n      picture: 'kara-erickson.jpg',\n      twitter: 'karaforthewin',\n      website: 'https://github.com/kara',\n      bio: 'Kara is a software engineer on the Angular team at Angular and a co-organizer of the Angular-SF Meetup. ',\n      group: 'Angular'\n    },\n    jeffcross: {\n      name: 'Jeff Cross',\n      picture: 'jeff-cross.jpg',\n      twitter: 'jeffbcross',\n      website: 'https://twitter.com/jeffbcross',\n      bio: 'Jeff was one of the earliest core team members on AngularJS.',\n      group: 'GDE'\n    },\n    naomi: {\n      name: 'Naomi Black',\n      picture: 'naomi.jpg',\n      twitter: 'naomitraveller',\n      website: 'http://google.com/+NaomiBlack',\n      bio: 'Naomi is Angular\\'s TPM generalist and jack-of-all-trades.',\n      group: 'Angular'\n    }\n };\n}\n"
  },
  {
    "path": "apps/rxjs.dev/src/app/custom-elements/contributor/contributor.service.ts",
    "content": "import { Injectable } from '@angular/core';\nimport { HttpClient } from '@angular/common/http';\n\nimport { ConnectableObservable, Observable } from 'rxjs';\nimport { map, publishLast } from 'rxjs/operators';\n\nimport { Contributor, ContributorGroup } from './contributors.model';\n\n// TODO(andrewjs): Look into changing this so that we don't import the service just to get the const\nimport { CONTENT_URL_PREFIX } from 'app/documents/document.service';\n\nconst contributorsPath = CONTENT_URL_PREFIX + 'contributors.json';\nconst knownGroups = ['Core Team', 'Learning Team', 'Alumn', 'Contributors'];\n\n@Injectable()\nexport class ContributorService {\n  contributors: Observable<ContributorGroup[]>;\n\n  constructor(private http: HttpClient) {\n    this.contributors = this.getContributors();\n  }\n\n  private getContributors() {\n    const contributors = this.http.get<{[key: string]: Contributor}>(contributorsPath).pipe(\n      // Create group map\n      map(contribs => {\n        const contribMap: { [name: string]: Contributor[]} = {};\n        Object.keys(contribs).forEach(key => {\n          const contributor = contribs[key];\n          const group = contributor.group;\n          const contribGroup = contribMap[group];\n          if (contribGroup) {\n            contribGroup.push(contributor);\n          } else {\n            contribMap[group] = [contributor];\n          }\n        });\n\n        return contribMap;\n      }),\n\n      // Flatten group map into sorted group array of sorted contributors\n      map(cmap => Object.keys(cmap).map(key => {\n          const order = knownGroups.indexOf(key);\n          return {\n            name: key,\n            order: order === -1 ? knownGroups.length : order,\n            contributors: cmap[key].sort(compareContributors)\n          } as ContributorGroup;\n        })\n        .sort(compareGroups)),\n\n      publishLast(),\n    );\n\n    (contributors as ConnectableObservable<ContributorGroup[]>).connect();\n    return contributors;\n  }\n}\n\nfunction compareContributors(l: Contributor, r: Contributor) {\n return l.name.toUpperCase() > r.name.toUpperCase() ? 1 : -1;\n}\n\nfunction compareGroups(l: ContributorGroup, r: ContributorGroup) {\n  return l.order === r.order ?\n    (l.name > r.name ? 1 : -1) :\n     l.order > r.order ? 1 : -1;\n}\n"
  },
  {
    "path": "apps/rxjs.dev/src/app/custom-elements/contributor/contributors.model.ts",
    "content": "export class ContributorGroup {\n  name: string;\n  order: number;\n  contributors: Contributor[];\n}\n\nexport class Contributor {\n  group: string;\n  name: string;\n  picture?: string;\n  website?: string;\n  twitter?: string;\n  github?: string;\n  bio?: string;\n  isFlipped ? = false;\n}\n"
  },
  {
    "path": "apps/rxjs.dev/src/app/custom-elements/current-location/current-location.component.spec.ts",
    "content": "import { ComponentFixture, TestBed } from '@angular/core/testing';\nimport { LocationService } from 'app/shared/location.service';\nimport { MockLocationService } from 'testing/location.service';\nimport { CurrentLocationComponent } from './current-location.component';\n\n\ndescribe('CurrentLocationComponent', () => {\n  let element: HTMLElement;\n  let fixture: ComponentFixture<CurrentLocationComponent>;\n  let locationService: MockLocationService;\n\n  beforeEach(() => {\n    locationService = new MockLocationService('initial/url');\n\n    TestBed.configureTestingModule({\n      declarations: [ CurrentLocationComponent ],\n      providers: [\n        { provide: LocationService, useValue: locationService }\n      ]\n    });\n\n    fixture = TestBed.createComponent(CurrentLocationComponent);\n    element = fixture.nativeElement;\n  });\n\n  it('should render the current location', () => {\n    fixture.detectChanges();\n    expect(element.textContent).toEqual('initial/url');\n\n    locationService.urlSubject.next('next/url');\n\n    fixture.detectChanges();\n    expect(element.textContent).toEqual('next/url');\n  });\n});\n"
  },
  {
    "path": "apps/rxjs.dev/src/app/custom-elements/current-location/current-location.component.ts",
    "content": "/* tslint:disable component-selector */\nimport { Component } from '@angular/core';\nimport { LocationService } from 'app/shared/location.service';\n\n/** Renders the current location path. */\n@Component({\n  // eslint-disable-next-line @angular-eslint/component-selector\n  selector: 'current-location',\n  template: '{{ location.currentPath | async }}'\n})\nexport class CurrentLocationComponent {\n  constructor(public location: LocationService) { }\n}\n"
  },
  {
    "path": "apps/rxjs.dev/src/app/custom-elements/current-location/current-location.module.ts",
    "content": "import { NgModule, Type } from '@angular/core';\nimport { CommonModule } from '@angular/common';\nimport { CurrentLocationComponent } from './current-location.component';\nimport { WithCustomElementComponent } from '../element-registry';\n\n@NgModule({\n  imports: [ CommonModule ],\n  declarations: [ CurrentLocationComponent ]\n})\nexport class CurrentLocationModule implements WithCustomElementComponent {\n  customElementComponent: Type<any> = CurrentLocationComponent;\n}\n"
  },
  {
    "path": "apps/rxjs.dev/src/app/custom-elements/custom-elements.module.ts",
    "content": "import { NgModule } from '@angular/core';\nimport { ROUTES} from '@angular/router';\nimport { ElementsLoader } from './elements-loader';\nimport {\n  ELEMENT_MODULE_LOAD_CALLBACKS,\n  ELEMENT_MODULE_LOAD_CALLBACKS_AS_ROUTES,\n  ELEMENT_MODULE_LOAD_CALLBACKS_TOKEN\n} from './element-registry';\nimport { LazyCustomElementComponent } from './lazy-custom-element.component';\n\n@NgModule({\n  declarations: [ LazyCustomElementComponent ],\n  exports: [ LazyCustomElementComponent ],\n  providers: [\n    ElementsLoader,\n    { provide: ELEMENT_MODULE_LOAD_CALLBACKS_TOKEN, useValue: ELEMENT_MODULE_LOAD_CALLBACKS },\n\n    // Providing these routes as a signal to the build system that these modules should be\n    // registered as lazy-loadable.\n    // TODO(andrewjs): Provide first-class support for providing this.\n    { provide: ROUTES, useValue: ELEMENT_MODULE_LOAD_CALLBACKS_AS_ROUTES, multi: true },\n  ],\n})\nexport class CustomElementsModule { }\n"
  },
  {
    "path": "apps/rxjs.dev/src/app/custom-elements/element-registry.ts",
    "content": "import { InjectionToken, Type } from '@angular/core';\nimport { LoadChildrenCallback } from '@angular/router';\n\n// Modules containing custom elements must be set up as lazy-loaded routes (loadChildren)\n// TODO(andrewjs): This is a hack, Angular should have first-class support for preparing a module\n// that contains custom elements.\nexport const ELEMENT_MODULE_LOAD_CALLBACKS_AS_ROUTES = [\n  {\n    selector: 'aio-announcement-bar',\n    loadChildren: () => import('./announcement-bar/announcement-bar.module').then(m => m.AnnouncementBarModule)\n  },\n  {\n    selector: 'aio-api-list',\n    loadChildren: () => import('./api/api-list.module').then(m => m.ApiListModule)\n  },\n  {\n    selector: 'aio-contributor-list',\n    loadChildren: () => import('./contributor/contributor-list.module').then(m => m.ContributorListModule)\n  },\n  {\n    selector: 'aio-file-not-found-search',\n    loadChildren: () => import('./search/file-not-found-search.module').then(m => m.FileNotFoundSearchModule)\n  },\n  {\n    selector: 'aio-resource-list',\n    loadChildren: () => import('./resource/resource-list.module').then(m => m.ResourceListModule)\n  },\n  {\n    selector: 'aio-toc',\n    loadChildren: () => import('./toc/toc.module').then(m => m.TocModule)\n  },\n  {\n    selector: 'code-example',\n    loadChildren: () => import('./code/code-example.module').then(m => m.CodeExampleModule)\n  },\n  {\n    selector: 'code-tabs',\n    loadChildren: () => import('./code/code-tabs.module').then(m => m.CodeTabsModule)\n  },\n  {\n    selector: 'current-location',\n    loadChildren: () => import('./current-location/current-location.module').then(m => m.CurrentLocationModule)\n  },\n  {\n    selector: 'expandable-section',\n    loadChildren: () => import('./expandable-section/expandable-section.module').then(m => m.ExpandableSectionModule)\n  },\n  {\n    selector: 'live-example',\n    loadChildren: () => import('./live-example/live-example.module').then(m => m.LiveExampleModule)\n  },\n  {\n    selector: 'aio-operator-decision-tree',\n    loadChildren: () => import('./operator-decision-tree/operator-decision-tree.module').then(m => m.OperatorDecisionTreeModule)\n  }\n];\n\n/**\n * Interface expected to be implemented by all modules that declare a component that can be used as\n * a custom element.\n */\nexport interface WithCustomElementComponent {\n  customElementComponent: Type<any>;\n}\n\n/** Injection token to provide the element path modules. */\n// export const ELEMENT_MODULE_PATHS_TOKEN = new InjectionToken('aio/elements-map');\n\n/** Map of possible custom element selectors to their lazy-loadable module paths. */\n// export const ELEMENT_MODULE_PATHS = new Map<string, () => Promise<any>>();\n// ELEMENT_MODULE_PATHS_AS_ROUTES.forEach(route => {\n//   ELEMENT_MODULE_PATHS.set(route.selector, route.loadChildren);\n// });\n\n/** Injection token to provide the element path modules. */\nexport const ELEMENT_MODULE_LOAD_CALLBACKS_TOKEN = new InjectionToken<Map<string, LoadChildrenCallback>>('aio/elements-map');\n\n/** Map of possible custom element selectors to their lazy-loadable module paths. */\nexport const ELEMENT_MODULE_LOAD_CALLBACKS = new Map<string, LoadChildrenCallback>();\nELEMENT_MODULE_LOAD_CALLBACKS_AS_ROUTES.forEach(route => {\n  ELEMENT_MODULE_LOAD_CALLBACKS.set(route.selector, route.loadChildren);\n});\n"
  },
  {
    "path": "apps/rxjs.dev/src/app/custom-elements/elements-loader.spec.ts",
    "content": "import {\n  Compiler,\n  ComponentFactory,\n  ComponentFactoryResolver, ComponentRef, Injector, NgModuleFactory,\n  NgModuleRef,\n  Type,\n} from '@angular/core';\nimport { TestBed, fakeAsync, flushMicrotasks } from '@angular/core/testing';\n\nimport { ElementsLoader } from './elements-loader';\nimport { ELEMENT_MODULE_LOAD_CALLBACKS_TOKEN, WithCustomElementComponent } from './element-registry';\n\n\ninterface Deferred {\n  resolve(): void;\n  reject(err: any): void;\n}\n\ndescribe('ElementsLoader', () => {\n  let elementsLoader: ElementsLoader;\n  let compiler: Compiler;\n\n  beforeEach(() => {\n    const injector = TestBed.configureTestingModule({\n      providers: [\n        ElementsLoader,\n        {\n          provide: ELEMENT_MODULE_LOAD_CALLBACKS_TOKEN, useValue: new Map<\n            string, () => Promise<NgModuleFactory<WithCustomElementComponent> | Type<WithCustomElementComponent>>\n          >([\n          ['element-a-selector', () => Promise.resolve(new FakeModuleFactory('element-a-module'))],\n          ['element-b-selector', () => Promise.resolve(new FakeModuleFactory('element-b-module'))],\n          ['element-c-selector', () => Promise.resolve(FakeCustomElementModule)]\n        ])},\n      ]\n    });\n\n    elementsLoader = injector.get(ElementsLoader);\n    compiler = injector.get(Compiler);\n  });\n\n  describe('loadContainedCustomElements()', () => {\n    let loadCustomElementSpy: jasmine.Spy;\n\n    beforeEach(() => loadCustomElementSpy = spyOn(elementsLoader, 'loadCustomElement'));\n\n    it('should attempt to load and register all contained elements', fakeAsync(() => {\n      expect(loadCustomElementSpy).not.toHaveBeenCalled();\n\n      const hostEl = document.createElement('div');\n      hostEl.innerHTML = `\n        <element-a-selector></element-a-selector>\n        <element-b-selector></element-b-selector>\n      `;\n\n      elementsLoader.loadContainedCustomElements(hostEl);\n      flushMicrotasks();\n\n      expect(loadCustomElementSpy).toHaveBeenCalledTimes(2);\n      expect(loadCustomElementSpy).toHaveBeenCalledWith('element-a-selector');\n      expect(loadCustomElementSpy).toHaveBeenCalledWith('element-b-selector');\n    }));\n\n    it('should attempt to load and register only contained elements', fakeAsync(() => {\n      expect(loadCustomElementSpy).not.toHaveBeenCalled();\n\n      const hostEl = document.createElement('div');\n      hostEl.innerHTML = `\n        <element-b-selector></element-b-selector>\n      `;\n\n      elementsLoader.loadContainedCustomElements(hostEl);\n      flushMicrotasks();\n\n      expect(loadCustomElementSpy).toHaveBeenCalledTimes(1);\n      expect(loadCustomElementSpy).toHaveBeenCalledWith('element-b-selector');\n    }));\n\n    it('should wait for all contained elements to load and register', fakeAsync(() => {\n      const deferreds = returnPromisesFromSpy(loadCustomElementSpy);\n\n      const hostEl = document.createElement('div');\n      hostEl.innerHTML = `\n        <element-a-selector></element-a-selector>\n        <element-b-selector></element-b-selector>\n      `;\n\n      const log: any[] = [];\n      elementsLoader.loadContainedCustomElements(hostEl).subscribe(\n        v => log.push(`emitted: ${v}`),\n        e => log.push(`errored: ${e}`),\n        () => log.push('completed'),\n      );\n\n      flushMicrotasks();\n      expect(log).toEqual([]);\n\n      deferreds[0].resolve();\n      flushMicrotasks();\n      expect(log).toEqual([]);\n\n      deferreds[1].resolve();\n      flushMicrotasks();\n      expect(log).toEqual(['emitted: undefined', 'completed']);\n    }));\n\n    it('should fail if any of the contained elements fails to load and register', fakeAsync(() => {\n      const deferreds = returnPromisesFromSpy(loadCustomElementSpy);\n\n      const hostEl = document.createElement('div');\n      hostEl.innerHTML = `\n        <element-a-selector></element-a-selector>\n        <element-b-selector></element-b-selector>\n      `;\n\n      const log: any[] = [];\n      elementsLoader.loadContainedCustomElements(hostEl).subscribe(\n        v => log.push(`emitted: ${v}`),\n        e => log.push(`errored: ${e}`),\n        () => log.push('completed'),\n      );\n\n      flushMicrotasks();\n      expect(log).toEqual([]);\n\n      deferreds[0].resolve();\n      flushMicrotasks();\n      expect(log).toEqual([]);\n\n      deferreds[1].reject('foo');\n      flushMicrotasks();\n      expect(log).toEqual(['errored: foo']);\n    }));\n  });\n\n  describe('loadCustomElement()', () => {\n    let definedSpy: jasmine.Spy;\n    let whenDefinedSpy: jasmine.Spy;\n    let whenDefinedDeferreds: Deferred[];\n\n    beforeEach(() => {\n      // `loadCustomElement()` uses the `window.customElements` API. Provide mocks for these tests.\n      definedSpy = spyOn(window.customElements, 'define');\n      whenDefinedSpy = spyOn(window.customElements, 'whenDefined');\n      whenDefinedDeferreds = returnPromisesFromSpy(whenDefinedSpy);\n    });\n\n    it('should be able to load and register an element', fakeAsync(() => {\n      elementsLoader.loadCustomElement('element-a-selector');\n      flushMicrotasks();\n\n      expect(definedSpy).toHaveBeenCalledTimes(1);\n      expect(definedSpy).toHaveBeenCalledWith('element-a-selector', jasmine.any(Function));\n\n      // Verify the right component was loaded/registered.\n      const Ctor = definedSpy.calls.argsFor(0)[1];\n      expect(Ctor.observedAttributes).toEqual(['element-a-module']);\n    }));\n\n    it('should wait until the element is defined', fakeAsync(() => {\n      let state = 'pending';\n      elementsLoader.loadCustomElement('element-b-selector').then(() => state = 'resolved');\n      flushMicrotasks();\n\n      expect(state).toBe('pending');\n      expect(whenDefinedSpy).toHaveBeenCalledTimes(1);\n      expect(whenDefinedSpy).toHaveBeenCalledWith('element-b-selector');\n\n      whenDefinedDeferreds[0].resolve();\n      flushMicrotasks();\n      expect(state).toBe('resolved');\n    }));\n\n    it('should not load and register the same element more than once', fakeAsync(() => {\n      elementsLoader.loadCustomElement('element-a-selector');\n      flushMicrotasks();\n      expect(definedSpy).toHaveBeenCalledTimes(1);\n\n      definedSpy.calls.reset();\n\n      // While loading/registering is still in progress:\n      elementsLoader.loadCustomElement('element-a-selector');\n      flushMicrotasks();\n      expect(definedSpy).not.toHaveBeenCalled();\n\n      definedSpy.calls.reset();\n      whenDefinedDeferreds[0].resolve();\n\n      // Once loading/registering is already completed:\n      let state = 'pending';\n      elementsLoader.loadCustomElement('element-a-selector').then(() => state = 'resolved');\n      flushMicrotasks();\n      expect(state).toBe('resolved');\n      expect(definedSpy).not.toHaveBeenCalled();\n    }));\n\n    it('should fail if defining the custom element fails', fakeAsync(() => {\n      let state = 'pending';\n      elementsLoader.loadCustomElement('element-b-selector').catch(e => state = `rejected: ${e}`);\n      flushMicrotasks();\n      expect(state).toBe('pending');\n\n      whenDefinedDeferreds[0].reject('foo');\n      flushMicrotasks();\n      expect(state).toBe('rejected: foo');\n    }));\n\n    it('should be able to load and register an element again if previous attempt failed',\n      fakeAsync(() => {\n        elementsLoader.loadCustomElement('element-a-selector');\n        flushMicrotasks();\n        expect(definedSpy).toHaveBeenCalledTimes(1);\n\n        definedSpy.calls.reset();\n\n        // While loading/registering is still in progress:\n        elementsLoader.loadCustomElement('element-a-selector').catch(() => undefined);\n        flushMicrotasks();\n        expect(definedSpy).not.toHaveBeenCalled();\n\n        whenDefinedDeferreds[0].reject('foo');\n        flushMicrotasks();\n        expect(definedSpy).not.toHaveBeenCalled();\n\n        // Once loading/registering has already failed:\n        elementsLoader.loadCustomElement('element-a-selector');\n        flushMicrotasks();\n        expect(definedSpy).toHaveBeenCalledTimes(1);\n      })\n    );\n\n    it('should be able to load and register an element after compiling its NgModule', fakeAsync(() => {\n      const compilerSpy = spyOn(compiler, 'compileModuleAsync')\n        .and.returnValue(Promise.resolve(new FakeModuleFactory('element-c-module')));\n\n      elementsLoader.loadCustomElement('element-c-selector');\n      flushMicrotasks();\n\n      expect(definedSpy).toHaveBeenCalledTimes(1);\n      expect(definedSpy).toHaveBeenCalledWith('element-c-selector', jasmine.any(Function));\n\n      expect(compilerSpy).toHaveBeenCalledTimes(1);\n      expect(compilerSpy).toHaveBeenCalledWith(FakeCustomElementModule);\n    }));\n  });\n});\n\n// TEST CLASSES/HELPERS\n\nclass FakeCustomElementModule implements WithCustomElementComponent {\n  customElementComponent: Type<any>;\n}\n\nclass FakeComponentFactory extends ComponentFactory<any> {\n  selector: string;\n  componentType: Type<any>;\n  ngContentSelectors: string[];\n  inputs = [{propName: this.identifyingInput, templateName: this.identifyingInput}];\n  outputs = [];\n\n  constructor(private identifyingInput: string) { super(); }\n\n  create(injector: Injector,\n         projectableNodes?: any[][],\n         rootSelectorOrNode?: string | any,\n         ngModule?: NgModuleRef<any>): ComponentRef<any> {\n    return jasmine.createSpy('ComponentRef') as any;\n  }\n}\n\nclass FakeComponentFactoryResolver extends ComponentFactoryResolver {\n  constructor(private modulePath: string) { super(); }\n\n  resolveComponentFactory(component: Type<any>): ComponentFactory<any> {\n    return new FakeComponentFactory(this.modulePath);\n  }\n}\n\nclass FakeModuleRef extends NgModuleRef<WithCustomElementComponent> {\n  injector = jasmine.createSpyObj('injector', ['get']);\n  componentFactoryResolver = new FakeComponentFactoryResolver(this.modulePath);\n  instance: WithCustomElementComponent = new FakeCustomElementModule();\n\n  constructor(private modulePath: string) {\n    super();\n\n    this.injector.get.and.returnValue(this.componentFactoryResolver);\n  }\n\n  destroy() {}\n  onDestroy(callback: () => void) {}\n}\n\nclass FakeModuleFactory extends NgModuleFactory<any> {\n  moduleType: Type<any>;\n  moduleRefToCreate = new FakeModuleRef(this.modulePath);\n\n  constructor(private modulePath: string) { super(); }\n\n  create(parentInjector: Injector | null): NgModuleRef<any> {\n    return this.moduleRefToCreate;\n  }\n}\n\nfunction returnPromisesFromSpy(spy: jasmine.Spy): Deferred[] {\n  const deferreds: Deferred[] = [];\n  spy.and.callFake(() => new Promise((resolve: any, reject) => deferreds.push({resolve, reject})));\n  return deferreds;\n}\n"
  },
  {
    "path": "apps/rxjs.dev/src/app/custom-elements/elements-loader.ts",
    "content": "import {\n  Compiler,\n  Inject,\n  Injectable,\n  NgModuleFactory,\n  NgModuleRef,\n  Type,\n} from '@angular/core';\nimport { ELEMENT_MODULE_LOAD_CALLBACKS_TOKEN, WithCustomElementComponent } from './element-registry';\nimport { from, Observable, of } from 'rxjs';\nimport { createCustomElement } from '@angular/elements';\nimport { LoadChildrenCallback } from '@angular/router';\n\n\n@Injectable()\nexport class ElementsLoader {\n  /** Map of unregistered custom elements and their respective module paths to load. */\n  private elementsToLoad: Map<string, LoadChildrenCallback>;\n  /** Map of custom elements that are in the process of being loaded and registered. */\n  private elementsLoading = new Map<string, Promise<void>>();\n\n  constructor(private moduleRef: NgModuleRef<any>,\n              @Inject(ELEMENT_MODULE_LOAD_CALLBACKS_TOKEN) elementModulePaths: Map<string, LoadChildrenCallback>,\n              private compiler: Compiler) {\n    this.elementsToLoad = new Map(elementModulePaths);\n  }\n\n  /**\n   * Queries the provided element for any custom elements that have not yet been registered with\n   * the browser. Custom elements that are registered will be removed from the list of unregistered\n   * elements so that they will not be queried in subsequent calls.\n   */\n  loadContainedCustomElements(element: HTMLElement): Observable<void> {\n    const unregisteredSelectors = Array.from(this.elementsToLoad.keys())\n        .filter(s => element.querySelector(s));\n\n    if (!unregisteredSelectors.length) { return of(undefined); }\n\n    // Returns observable that completes when all discovered elements have been registered.\n    const allRegistered = Promise.all(unregisteredSelectors.map(s => this.loadCustomElement(s)));\n    return from(allRegistered.then(() => undefined));\n  }\n\n  /** Loads and registers the custom element defined on the `WithCustomElement` module factory. */\n  loadCustomElement(selector: string): Promise<void> {\n    if (this.elementsLoading.has(selector)) {\n      // The custom element is in the process of being loaded and registered.\n      return this.elementsLoading.get(selector)!;\n    }\n\n    if (this.elementsToLoad.has(selector)) {\n      // Load and register the custom element (for the first time).\n      const modulePathLoader = this.elementsToLoad.get(selector)!;\n      const loadedAndRegistered =\n          (modulePathLoader() as Promise<NgModuleFactory<WithCustomElementComponent> | Type<WithCustomElementComponent>>)\n          .then(elementModuleOrFactory => {\n            /**\n             * With View Engine, the NgModule factory is created and provided when loaded.\n             * With Ivy, only the NgModule class is provided loaded and must be compiled.\n             * This uses the same mechanism as the deprecated `SystemJsNgModuleLoader` in\n             * in `packages/core/src/linker/system_js_ng_module_factory_loader.ts`\n             * to pass on the NgModuleFactory, or compile the NgModule and return its NgModuleFactory.\n             */\n            if (elementModuleOrFactory instanceof NgModuleFactory) {\n              return elementModuleOrFactory;\n            } else {\n              return this.compiler.compileModuleAsync(elementModuleOrFactory);\n            }\n          })\n          .then(elementModuleFactory => {\n            const elementModuleRef = elementModuleFactory.create(this.moduleRef.injector);\n            const injector = elementModuleRef.injector;\n            const CustomElementComponent = elementModuleRef.instance.customElementComponent;\n            const CustomElement = createCustomElement(CustomElementComponent, {injector});\n\n            customElements!.define(selector, CustomElement);\n            return customElements.whenDefined(selector);\n          })\n          .then(() => {\n            // The custom element has been successfully loaded and registered.\n            // Remove from `elementsLoading` and `elementsToLoad`.\n            this.elementsLoading.delete(selector);\n            this.elementsToLoad.delete(selector);\n          })\n          .catch(err => {\n            // The custom element has failed to load and register.\n            // Remove from `elementsLoading`.\n            // (Do not remove from `elementsToLoad` in case it was a temporary error.)\n            this.elementsLoading.delete(selector);\n            return Promise.reject(err);\n          });\n\n      this.elementsLoading.set(selector, loadedAndRegistered);\n      return loadedAndRegistered;\n    }\n\n    // The custom element has already been loaded and registered.\n    return Promise.resolve();\n  }\n}\n"
  },
  {
    "path": "apps/rxjs.dev/src/app/custom-elements/expandable-section/expandable-section.component.ts",
    "content": "/* tslint:disable component-selector */\nimport { Component, Input } from '@angular/core';\n\n/** Custom element wrapper for the material expansion panel with a title input. */\n@Component({\n  selector: 'aio-expandable-section',\n  template: `<mat-expansion-panel style=\"background: inherit\">\n    <mat-expansion-panel-header>\n      {{ title }}\n    </mat-expansion-panel-header>\n\n    <ng-content></ng-content>\n  </mat-expansion-panel> `,\n})\nexport class ExpandableSectionComponent {\n  @Input() title: string;\n}\n"
  },
  {
    "path": "apps/rxjs.dev/src/app/custom-elements/expandable-section/expandable-section.module.ts",
    "content": "import { NgModule, Type } from '@angular/core';\nimport { ExpandableSectionComponent } from './expandable-section.component';\nimport { WithCustomElementComponent } from '../element-registry';\nimport { MatExpansionModule } from '@angular/material/expansion';\n\n@NgModule({\n  imports: [ MatExpansionModule ],\n  declarations: [ ExpandableSectionComponent, ]\n})\nexport class ExpandableSectionModule implements WithCustomElementComponent {\n  customElementComponent: Type<any> = ExpandableSectionComponent;\n}\n"
  },
  {
    "path": "apps/rxjs.dev/src/app/custom-elements/lazy-custom-element.component.spec.ts",
    "content": "import { ComponentFixture, TestBed } from '@angular/core/testing';\nimport { Logger } from 'app/shared/logger.service';\nimport { MockLogger } from 'testing/logger.service';\nimport { LazyCustomElementComponent } from './lazy-custom-element.component';\nimport { ElementsLoader } from './elements-loader';\n\ndescribe('LazyCustomElementComponent', () => {\n  let mockElementsLoader: jasmine.SpyObj<ElementsLoader>;\n  let mockLogger: MockLogger;\n  let fixture: ComponentFixture<LazyCustomElementComponent>;\n\n  beforeEach(() => {\n    mockElementsLoader = jasmine.createSpyObj<ElementsLoader>('ElementsLoader', [\n      'loadContainedCustomElements',\n      'loadCustomElement',\n    ]);\n\n    const injector = TestBed.configureTestingModule({\n      declarations: [ LazyCustomElementComponent ],\n      providers: [\n        { provide: ElementsLoader, useValue: mockElementsLoader },\n        { provide: Logger, useClass: MockLogger },\n      ],\n    });\n\n    mockLogger = injector.get(Logger);\n    fixture = TestBed.createComponent(LazyCustomElementComponent);\n  });\n\n  it('should set the HTML content based on the selector', () => {\n    const elem = fixture.nativeElement;\n\n    expect(elem.innerHTML).toBe('');\n\n    fixture.componentInstance.selector = 'foo-bar';\n    fixture.detectChanges();\n\n    expect(elem.innerHTML).toBe('<foo-bar></foo-bar>');\n  });\n\n  it('should load the specified custom element', () => {\n    expect(mockElementsLoader.loadCustomElement).not.toHaveBeenCalled();\n\n    fixture.componentInstance.selector = 'foo-bar';\n    fixture.detectChanges();\n\n    expect(mockElementsLoader.loadCustomElement).toHaveBeenCalledWith('foo-bar');\n  });\n\n  it('should log an error (and abort) if the selector is empty', () => {\n    fixture.detectChanges();\n\n    expect(mockElementsLoader.loadCustomElement).not.toHaveBeenCalled();\n    expect(mockLogger.output.error).toEqual([[jasmine.any(Error)]]);\n    expect(mockLogger.output.error[0][0].message).toBe('Invalid selector for \\'aio-lazy-ce\\': ');\n  });\n\n  it('should log an error (and abort) if the selector is invalid', () => {\n    fixture.componentInstance.selector = 'foo-bar><script></script><foo-bar';\n    fixture.detectChanges();\n\n    expect(mockElementsLoader.loadCustomElement).not.toHaveBeenCalled();\n    expect(mockLogger.output.error).toEqual([[jasmine.any(Error)]]);\n    expect(mockLogger.output.error[0][0].message).toBe(\n        'Invalid selector for \\'aio-lazy-ce\\': foo-bar><script></script><foo-bar');\n  });\n});\n"
  },
  {
    "path": "apps/rxjs.dev/src/app/custom-elements/lazy-custom-element.component.ts",
    "content": "import { Component, ElementRef, Input, OnInit } from '@angular/core';\nimport { Logger } from 'app/shared/logger.service';\nimport { ElementsLoader } from './elements-loader';\n\n@Component({\n  selector: 'aio-lazy-ce',\n  template: '',\n})\nexport class LazyCustomElementComponent implements OnInit {\n  @Input() selector = '';\n\n  constructor(\n    private elementRef: ElementRef,\n    private elementsLoader: ElementsLoader,\n    private logger: Logger,\n  ) {}\n\n  ngOnInit() {\n    if (!this.selector || /[^\\w-]/.test(this.selector)) {\n      this.logger.error(new Error(`Invalid selector for 'aio-lazy-ce': ${this.selector}`));\n      return;\n    }\n\n    this.elementRef.nativeElement.innerHTML = `<${this.selector}></${this.selector}>`;\n    this.elementsLoader.loadCustomElement(this.selector);\n  }\n}\n"
  },
  {
    "path": "apps/rxjs.dev/src/app/custom-elements/live-example/live-example.component.spec.ts",
    "content": "import { ComponentFixture, TestBed } from '@angular/core/testing';\nimport { By } from '@angular/platform-browser';\nimport { Component, DebugElement } from '@angular/core';\nimport { Location } from '@angular/common';\n\nimport { LiveExampleComponent, EmbeddedStackblitzComponent } from './live-example.component';\n\nconst defaultTestPath = '/test';\n\ndescribe('LiveExampleComponent', () => {\n  let liveExampleDe: DebugElement;\n  let liveExampleComponent: LiveExampleComponent;\n  let fixture: ComponentFixture<HostComponent>;\n  let testPath: string;\n\n  //////// test helpers ////////\n\n  @Component({\n    selector: 'aio-host-comp',\n    template: '<live-example></live-example>'\n  })\n  class HostComponent { }\n\n  class TestLocation {\n    path() { return testPath; }\n  }\n\n  function getAnchors() {\n    return liveExampleDe.queryAll(By.css('a')).map(de => de.nativeElement as HTMLAnchorElement);\n  }\n\n  function getHrefs() { return getAnchors().map(a => a.href); }\n\n  function setHostTemplate(template: string) {\n    TestBed.overrideComponent(HostComponent, {set: {template}});\n  }\n\n  function testComponent(testFn: () => void) {\n    fixture = TestBed.createComponent(HostComponent);\n    liveExampleDe = fixture.debugElement.children[0];\n    liveExampleComponent = liveExampleDe.componentInstance;\n\n    // Trigger `ngAfterContentInit()`.\n    fixture.detectChanges();\n\n    testFn();\n  }\n\n  //////// tests ////////\n  beforeEach(() => {\n    TestBed.configureTestingModule({\n      declarations: [ HostComponent, LiveExampleComponent, EmbeddedStackblitzComponent ],\n      providers: [\n        { provide: Location, useClass: TestLocation }\n      ]\n    })\n    // Disable the <iframe> within the EmbeddedStackblitzComponent\n    .overrideComponent(EmbeddedStackblitzComponent, {set: {template: 'NO IFRAME'}});\n\n    testPath = defaultTestPath;\n  });\n\n  describe('when not embedded', () => {\n    function getLiveExampleAnchor() { return getAnchors()[0]; }\n\n    it('should create LiveExampleComponent', () => {\n      testComponent(() => {\n        expect(liveExampleComponent).toBeTruthy('LiveExampleComponent');\n      });\n    });\n\n    it('should have expected stackblitz & download hrefs', () => {\n      testPath = '/tutorial/toh-pt1';\n      testComponent(() => {\n        const hrefs = getHrefs();\n        expect(hrefs[0]).toContain('/toh-pt1/stackblitz.html');\n        expect(hrefs[1]).toContain('/toh-pt1/toh-pt1.zip');\n      });\n    });\n\n    it('should have expected stackblitz & download hrefs even when path has # frag', () => {\n      testPath = '/tutorial/toh-pt1#somewhere';\n      testComponent(() => {\n        const hrefs = getHrefs();\n        expect(hrefs[0]).toContain('/toh-pt1/stackblitz.html');\n        expect(hrefs[1]).toContain('/toh-pt1/toh-pt1.zip');\n      });\n    });\n\n    it('should have expected stackblitz & download hrefs even when path has ? params', () => {\n      testPath = '/tutorial/toh-pt1?foo=1&bar=\"bar\"';\n      testComponent(() => {\n        const hrefs = getHrefs();\n        expect(hrefs[0]).toContain('/toh-pt1/stackblitz.html');\n        expect(hrefs[1]).toContain('/toh-pt1/toh-pt1.zip');\n      });\n    });\n\n    it('should have expected stackblitz & download hrefs when has example directory (name)', () => {\n      testPath = '/guide/somewhere';\n      setHostTemplate('<live-example name=\"toh-pt1\"></live-example>');\n      testComponent(() => {\n        const hrefs = getHrefs();\n        expect(hrefs[0]).toContain('/toh-pt1/stackblitz.html');\n        expect(hrefs[1]).toContain('/toh-pt1/toh-pt1.zip');\n      });\n    });\n\n    it('should have expected stackblitz & download hrefs when has `stackblitz`', () => {\n      testPath = '/testing';\n      setHostTemplate('<live-example stackblitz=\"app-specs\"></live-example>');\n      testComponent(() => {\n        const hrefs = getHrefs();\n        expect(hrefs[0]).toContain('/testing/app-specs.stackblitz.html');\n        expect(hrefs[1]).toContain('/testing/app-specs.testing.zip');\n      });\n    });\n\n    it('should have expected stackblitz & download hrefs when has `name` & `stackblitz`', () => {\n      testPath = '/guide/somewhere';\n      setHostTemplate('<live-example name=\"testing\" stackblitz=\"app-specs\"></live-example>');\n      testComponent(() => {\n        const hrefs = getHrefs();\n        expect(hrefs[0]).toContain('/testing/app-specs.stackblitz.html');\n        expect(hrefs[1]).toContain('/testing/app-specs.testing.zip');\n      });\n    });\n\n    it('should be embedded style by default', () => {\n      setHostTemplate('<live-example></live-example>');\n      testComponent(() => {\n        const hrefs = getHrefs();\n        expect(hrefs[0]).toContain(defaultTestPath + '/stackblitz.html');\n      });\n    });\n\n    it('should not have a download link when `noDownload` attr present', () => {\n      setHostTemplate('<live-example noDownload></live-example>');\n      testComponent(() => {\n        const hrefs = getHrefs();\n        expect(hrefs.length).toBe(1, 'only the stackblitz live-example anchor');\n        expect(hrefs[0]).toContain('stackblitz.html');\n      });\n    });\n\n    it('should only have a download link when `downloadOnly` attr present', () => {\n      setHostTemplate('<live-example downloadOnly>download this</live-example>');\n      testComponent(() => {\n        const hrefs = getHrefs();\n        expect(hrefs.length).toBe(1, 'only the zip anchor');\n        expect(hrefs[0]).toContain('.zip');      });\n    });\n\n    it('should have default title when no title attribute or content', () => {\n      setHostTemplate('<live-example></live-example>');\n      testComponent(() => {\n        const expectedTitle = 'live example';\n        const anchor = getLiveExampleAnchor();\n        expect(anchor.textContent).toBe(expectedTitle, 'anchor content');\n        expect(anchor.getAttribute('title')).toBe(expectedTitle, 'title');\n      });\n    });\n\n    it('should add title when set `title` attribute', () => {\n      const expectedTitle = 'Great Example';\n      setHostTemplate(`<live-example title=\"${expectedTitle}\"></live-example>`);\n      testComponent(() => {\n        const anchor = getLiveExampleAnchor();\n        expect(anchor.textContent).toBe(expectedTitle, 'anchor content');\n        expect(anchor.getAttribute('title')).toBe(expectedTitle, 'title');\n      });\n    });\n\n    it('should add title from <live-example> body', () => {\n      const expectedTitle = 'The Greatest Example';\n      setHostTemplate(`<live-example title=\"ignore this title\">${expectedTitle}</live-example>`);\n      testComponent(() => {\n        const anchor = getLiveExampleAnchor();\n        expect(anchor.textContent).toBe(expectedTitle, 'anchor content');\n        expect(anchor.getAttribute('title')).toBe(expectedTitle, 'title');\n      });\n    });\n\n    it('should not duplicate the exampleDir on a zip when there is a / on the name', () => {\n      setHostTemplate('<live-example name=\"testing/ts\"></live-example>');\n      testComponent(() => {\n        const hrefs = getHrefs();\n        expect(hrefs[0]).toContain('/testing/ts/stackblitz.html');\n        expect(hrefs[1]).toContain('/testing/ts/testing.zip');\n      });\n    });\n  });\n\n  describe('when embedded', () => {\n\n    function getDownloadAnchor() {\n      const anchor = liveExampleDe.query(By.css('p > a'));\n      return anchor && anchor.nativeElement as HTMLAnchorElement;\n    }\n\n    function getEmbeddedStackblitzComponent() {\n      const compDe = liveExampleDe.query(By.directive(EmbeddedStackblitzComponent));\n      return compDe && compDe.componentInstance as EmbeddedStackblitzComponent;\n    }\n\n    it('should have hidden, embedded stackblitz', () => {\n      setHostTemplate('<live-example embedded></live-example>');\n      testComponent(() => {\n        expect(liveExampleComponent.mode).toBe('embedded', 'component is embedded');\n        expect(getEmbeddedStackblitzComponent()).toBeTruthy('EmbeddedStackblitzComponent');\n      });\n    });\n\n    it('should have download paragraph with expected anchor href', () => {\n      testPath = '/tutorial/toh-pt1';\n      setHostTemplate('<live-example embedded></live-example>');\n      testComponent(() => {\n        expect(getDownloadAnchor().href).toContain('/toh-pt1/toh-pt1.zip');\n      });\n    });\n\n    it('should not have download paragraph when has `nodownload`', () => {\n      testPath = '/tutorial/toh-pt1';\n      setHostTemplate('<live-example embedded nodownload></live-example>');\n      testComponent(() => {\n        expect(getDownloadAnchor()).toBeNull();\n      });\n    });\n  });\n});\n"
  },
  {
    "path": "apps/rxjs.dev/src/app/custom-elements/live-example/live-example.component.ts",
    "content": "/* tslint:disable component-selector */\nimport { AfterContentInit, AfterViewInit, Component, ElementRef, Input, ViewChild } from '@angular/core';\nimport { Location } from '@angular/common';\nimport { CONTENT_URL_PREFIX } from 'app/documents/document.service';\nimport { AttrMap, boolFromValue, getAttrs, getAttrValue } from 'app/shared/attribute-utils';\n\nconst LIVE_EXAMPLE_BASE = CONTENT_URL_PREFIX + 'live-examples/';\nconst ZIP_BASE = CONTENT_URL_PREFIX + 'zips/';\n\n/**\n * Angular.io Live Example Embedded Component\n *\n * Renders a link to a live/host example of the doc page.\n *\n * All attributes and the text content are optional\n *\n * Usage:\n *   <live-example\n *      [name=\"...\"]        // name of the example directory\n *      [stackblitz=\"...\"\"] // name of the stackblitz file (becomes part of zip file name as well)\n *      [embedded]          // embed the stackblitz in the doc page, else display in new browser tab (default)\n *      [noDownload]        // no downloadable zip option\n *      [downloadOnly]      // just the zip\n *      [title=\"...\"]>      // text for live example link and tooltip\n *        text              // higher precedence way to specify text for live example link and tooltip\n *  </live-example>\n * Example:\n *   <p>Run <live-example>Try the live example</live-example></p>.\n *   // ~/resources/live-examples/{page}/stackblitz.json\n *\n *   <p>Run <live-example name=\"toh-pt1\">this example</live-example></p>.\n *   // ~/resources/live-examples/toh-pt1/stackblitz.json\n *\n *   // Link to the default stackblitz in the toh-pt1 sample\n *   // The title overrides default (\"live example\") with \"Tour of Heroes - Part 1\"\n *   <p>Run <live-example name=\"toh-pt1\" title=\"Tour of Heroes - Part 1\"></live-example></p>.\n *   // ~/resources/live-examples/toh-pt1/stackblitz.json\n *\n *   <p>Run <live-example stackblitz=\"minimal\"></live-example></p>.\n *   // ~/resources/live-examples/{page}/minimal.stackblitz.json\n *\n *   // Embed the current page's default stackblitz\n *   // Text within tag is \"live example\"\n *   // No title (no tooltip)\n *   <live-example embedded title=\"\"></live-example>\n *   // ~/resources/live-examples/{page}/stackblitz.json\n *\n *   // Displays within the document page as an embedded style stackblitz editor\n *   <live-example name=\"toh-pt1\" embedded stackblitz=\"minimal\">Tour of Heroes - Part 1</live-example>\n *   // ~/resources/live-examples/toh-pt1/minimal.stackblitz.json\n */\n@Component({\n  // eslint-disable-next-line @angular-eslint/component-selector\n  selector: 'live-example',\n  template: `\n    <!-- Content projection is used to get the content HTML provided to the component. -->\n    <span #content style=\"display: none\"><ng-content></ng-content></span>\n\n    <span [ngSwitch]=\"mode\">\n      <span *ngSwitchCase=\"'embedded'\">\n        <div title=\"{{ title }}\">\n          <aio-embedded-stackblitz [src]=\"stackblitz\"></aio-embedded-stackblitz>\n        </div>\n        <p *ngIf=\"enableDownload\">You can also <a [href]=\"zip\" download title=\"Download example\">download this example</a>.</p>\n      </span>\n      <span *ngSwitchCase=\"'downloadOnly'\">\n        <a [href]=\"zip\" download title=\"{{ title }}\">{{ title }}</a>\n      </span>\n      <span *ngSwitchDefault>\n        <a [href]=\"stackblitz\" target=\"_blank\" title=\"{{ title }}\">{{ title }}</a>\n        <span *ngIf=\"enableDownload\"> / <a [href]=\"zip\" download title=\"Download example\">download example</a> </span>\n      </span>\n    </span>\n  `,\n})\nexport class LiveExampleComponent implements AfterContentInit {\n  readonly mode: 'default' | 'embedded' | 'downloadOnly';\n  readonly enableDownload: boolean;\n  readonly stackblitz: string;\n  readonly zip: string;\n  title: string;\n\n  @ViewChild('content', { static: true })\n  private content: ElementRef;\n\n  constructor(elementRef: ElementRef, location: Location) {\n    const attrs = getAttrs(elementRef);\n    const exampleDir = this.getExampleDir(attrs, location.path(false));\n    const stackblitzName = this.getStackblitzName(attrs);\n\n    this.mode = this.getMode(attrs);\n    this.enableDownload = this.getEnableDownload(attrs);\n    this.stackblitz = this.getStackblitz(exampleDir, stackblitzName, this.mode === 'embedded');\n    this.zip = this.getZip(exampleDir, stackblitzName);\n    this.title = this.getTitle(attrs);\n  }\n\n  ngAfterContentInit() {\n    // Angular will sanitize this title when displayed, so it should be plain text.\n    const textContent = this.content.nativeElement.textContent.trim();\n    if (textContent) {\n      this.title = textContent;\n    }\n  }\n\n  private getEnableDownload(attrs: AttrMap) {\n    const downloadDisabled = boolFromValue(getAttrValue(attrs, 'noDownload'));\n    return !downloadDisabled;\n  }\n\n  private getExampleDir(attrs: AttrMap, path: string) {\n    let exampleDir = getAttrValue(attrs, 'name');\n    if (!exampleDir) {\n      // Take the last path segment, excluding query params and hash fragment.\n      const match = path.match(/[^/?#]+(?=\\/?(?:\\?|#|$))/);\n      exampleDir = match ? match[0] : 'index';\n    }\n    return exampleDir.trim();\n  }\n\n  private getMode(this: LiveExampleComponent, attrs: AttrMap): typeof this.mode {\n    const downloadOnly = boolFromValue(getAttrValue(attrs, 'downloadOnly'));\n    const isEmbedded = boolFromValue(getAttrValue(attrs, 'embedded'));\n\n    return downloadOnly ? 'downloadOnly' : isEmbedded ? 'embedded' : 'default';\n  }\n\n  private getStackblitz(exampleDir: string, stackblitzName: string, isEmbedded: boolean) {\n    const urlQuery = isEmbedded ? '?ctl=1' : '';\n    return `${LIVE_EXAMPLE_BASE}${exampleDir}/${stackblitzName}stackblitz.html${urlQuery}`;\n  }\n\n  private getStackblitzName(attrs: AttrMap) {\n    const attrValue = (getAttrValue(attrs, 'stackblitz') || '').trim();\n    return attrValue && `${attrValue}.`;\n  }\n\n  private getTitle(attrs: AttrMap) {\n    return (getAttrValue(attrs, 'title') || 'live example').trim();\n  }\n\n  private getZip(exampleDir: string, stackblitzName: string) {\n    const zipName = exampleDir.split('/')[0];\n    return `${ZIP_BASE}${exampleDir}/${stackblitzName}${zipName}.zip`;\n  }\n}\n\n///// EmbeddedStackblitzComponent ///\n/**\n * Hides the <iframe> so we can test LiveExampleComponent without actually triggering\n * a call to stackblitz to load the iframe\n */\n@Component({\n  selector: 'aio-embedded-stackblitz',\n  template: '<iframe #iframe frameborder=\"0\" width=\"100%\" height=\"100%\"></iframe>',\n  styles: ['iframe { min-height: 400px; }'],\n})\nexport class EmbeddedStackblitzComponent implements AfterViewInit {\n  @Input() src: string;\n\n  @ViewChild('iframe', { static: true }) iframe: ElementRef;\n\n  ngAfterViewInit() {\n    // DEVELOPMENT TESTING ONLY\n    // this.src = 'https://angular.io/resources/live-examples/quickstart/ts/stackblitz.json';\n\n    if (this.iframe) {\n      // security: the `src` is always authored by the documentation team\n      // and is considered to be safe\n      this.iframe.nativeElement.src = this.src;\n    }\n  }\n}\n"
  },
  {
    "path": "apps/rxjs.dev/src/app/custom-elements/live-example/live-example.module.ts",
    "content": "import { NgModule, Type } from '@angular/core';\nimport { CommonModule } from '@angular/common';\nimport { EmbeddedStackblitzComponent, LiveExampleComponent } from './live-example.component';\nimport { WithCustomElementComponent } from '../element-registry';\n\n@NgModule({\n  imports: [ CommonModule ],\n  declarations: [ LiveExampleComponent, EmbeddedStackblitzComponent ]\n})\nexport class LiveExampleModule implements WithCustomElementComponent {\n  customElementComponent: Type<any> = LiveExampleComponent;\n}\n"
  },
  {
    "path": "apps/rxjs.dev/src/app/custom-elements/operator-decision-tree/README.md",
    "content": "The `operator-decision-tree` module requires `decision-tree-data.json`, which is hosted at `/generated/app`.\n\nThe JSON is generated via `apps/rxjs.dev/content/operator-decision-tree.yml`.\n\n# TODO\n\n- Consider placing the widget on the home page - or a link on the home page, “Decision Tree”\n- Manual focus calls when navigating the tree (example: after making a selection, focus on the current sentence)\n- Drop jasmine-marbles for just the TestScheduler\n"
  },
  {
    "path": "apps/rxjs.dev/src/app/custom-elements/operator-decision-tree/fixtures.ts",
    "content": "import {\n  OperatorDecisionTree,\n  OperatorTreeNode,\n  OperatorTreeNodeWithOptions\n} from './interfaces';\n\nexport const treeNodeStubWithOptionsA: OperatorTreeNodeWithOptions = {\n  id: 'treeNodeStubWithOptionsA',\n  label: 'someLabelA',\n  options: ['treeNodeStubWithOptionsB']\n};\n\nexport const treeNodeStubWithOptionsB: OperatorTreeNodeWithOptions = {\n  id: 'treeNodeStubWithOptionsB',\n  label: 'someLabelB',\n  options: ['treeNodeStubNoOptions']\n};\n\nexport const treeNodeStubNoOptions: OperatorTreeNode = {\n  id: 'treeNodeStubNoOptions',\n  label: 'somelabelNoOptions',\n  path: 'some/path/NoOptions',\n  docType: 'someDocTypeNoOptions'\n};\n\nexport const treeNodeInitialStub = {\n  initial: {\n    id: 'initial',\n    options: ['treeNodeStubWithOptionsA']\n  }\n};\n\nexport const treeStub: OperatorDecisionTree = {\n  [treeNodeStubWithOptionsA.id]: treeNodeStubWithOptionsA,\n  [treeNodeStubWithOptionsB.id]: treeNodeStubWithOptionsB,\n  [treeNodeStubNoOptions.id]: treeNodeStubNoOptions,\n  ...treeNodeInitialStub\n};\n"
  },
  {
    "path": "apps/rxjs.dev/src/app/custom-elements/operator-decision-tree/interfaces.ts",
    "content": "export interface OperatorTreeNode {\n  id: string;\n  label?: string;\n  options?: string[];\n  path?: string;\n  docType?: string;\n  method?: string;\n}\n\nexport interface OperatorTreeNodeWithOptions extends OperatorTreeNode {\n  options: string[];\n}\n\nexport interface OperatorDecisionTree {\n  [key: string]: OperatorTreeNode;\n  initial: Required<Pick<OperatorTreeNode, 'id' | 'options'>>;\n  error?: any;\n}\n\nexport interface State {\n  previousBranchIds: string[];\n  currentBranchId: string;\n}\n"
  },
  {
    "path": "apps/rxjs.dev/src/app/custom-elements/operator-decision-tree/operator-decision-tree-data.service.spec.ts",
    "content": "import { TestBed } from '@angular/core/testing';\nimport { OperatorDecisionTreeDataService } from './operator-decision-tree-data.service';\nimport { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing';\nimport { treeStub } from './fixtures';\n\ndescribe('OperatorDecisionTreeDataService', () => {\n  let service: OperatorDecisionTreeDataService;\n  let httpTestingController: HttpTestingController;\n\n  beforeEach(() => {\n    TestBed.configureTestingModule({\n      imports: [HttpClientTestingModule],\n      providers: [OperatorDecisionTreeDataService]\n    });\n\n    httpTestingController = TestBed.inject(HttpTestingController);\n    service = TestBed.inject(OperatorDecisionTreeDataService);\n  });\n\n  describe('getDecisionTree$', () => {\n    it('should get the decision-tree-data.json', () => {\n      service.getDecisionTree$().subscribe(\n        data => expect(data).toBe(treeStub)\n      );\n      const req = httpTestingController.expectOne('/generated/docs/app/decision-tree-data.json');\n      expect(req.request.method).toEqual('GET');\n\n      req.flush(treeStub);\n      httpTestingController.verify();\n    });\n  });\n});\n"
  },
  {
    "path": "apps/rxjs.dev/src/app/custom-elements/operator-decision-tree/operator-decision-tree-data.service.ts",
    "content": "import { HttpClient } from '@angular/common/http';\nimport { Injectable } from '@angular/core';\nimport { Observable } from 'rxjs';\nimport { OperatorDecisionTree } from './interfaces';\n\n@Injectable()\nexport class OperatorDecisionTreeDataService {\n  constructor(private http: HttpClient) {}\n\n  getDecisionTree$(): Observable<OperatorDecisionTree> {\n    return this.http.get<OperatorDecisionTree>(\n      '/generated/docs/app/decision-tree-data.json'\n    );\n  }\n}\n"
  },
  {
    "path": "apps/rxjs.dev/src/app/custom-elements/operator-decision-tree/operator-decision-tree.component.scss",
    "content": "@use '@angular/material' as mat;\n@import '../../../styles/constants';\n\nh2 {\n  max-width: 700px;\n}\n\nbutton.option {\n  @include mat.elevation-transition;\n  border-radius: 34px;\n  border: 0;\n  cursor: pointer;\n  display: block;\n  margin-bottom: 12px;\n  padding: 0;\n  text-align: left;\n\n  &:active, &:hover, &:focus {\n    @include mat.elevation(8);\n    mat-card {\n      background-color: $pink;\n      color: $white;\n    }\n  }\n\n}\n\nmat-card {\n  border-radius: 34px;\n  padding: 12px 24px;\n  transition: all 250ms;\n}\n\nsection {\n  margin-bottom: 16px;\n}\n\n"
  },
  {
    "path": "apps/rxjs.dev/src/app/custom-elements/operator-decision-tree/operator-decision-tree.component.spec.ts",
    "content": "import { CommonModule, Location } from '@angular/common';\nimport { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';\nimport { MatButtonModule } from '@angular/material/button';\nimport { MatCardModule } from '@angular/material/card';\nimport { MatRippleModule } from '@angular/material/core';\nimport { By } from '@angular/platform-browser';\nimport { NoopAnimationsModule } from '@angular/platform-browser/animations';\nimport { ScrollService } from 'app/shared/scroll.service';\nimport { BehaviorSubject } from 'rxjs';\nimport { treeNodeStubNoOptions, treeNodeStubWithOptionsA } from './fixtures';\nimport { OperatorDecisionTreeComponent } from './operator-decision-tree.component';\nimport { OperatorDecisionTreeService } from './operator-decision-tree.service';\n\nconst operatorDecisionTreeServiceStub = {\n  currentSentence$: new BehaviorSubject('Conditioner is better'),\n  options$: new BehaviorSubject([treeNodeStubWithOptionsA]),\n  isBeyondInitialQuestion$: new BehaviorSubject(false),\n  hasError$: new BehaviorSubject(false),\n  selectOption: jasmine.createSpy(),\n  back: jasmine.createSpy(),\n  startOver: jasmine.createSpy()\n};\n\ndescribe('OperatorDecisionTreeComponent', () => {\n  let component: OperatorDecisionTreeComponent;\n  let fixture: ComponentFixture<OperatorDecisionTreeComponent>;\n  let operatorDecisionTreeService: OperatorDecisionTreeService;\n  let scrollService: ScrollService;\n  let locationService: jasmine.SpyObj<Location>;\n\n  beforeEach(waitForAsync(() => {\n    locationService = jasmine.createSpyObj(['subscribe']);\n    TestBed.configureTestingModule({\n      imports: [\n        CommonModule,\n        MatButtonModule,\n        MatCardModule,\n        MatRippleModule,\n        NoopAnimationsModule\n      ],\n      declarations: [OperatorDecisionTreeComponent],\n      providers: [\n        {\n          provide: OperatorDecisionTreeService,\n          useValue: operatorDecisionTreeServiceStub\n        },\n        ScrollService,\n        {provide: Location, useValue: locationService }\n      ]\n    }).compileComponents();\n  }));\n\n  beforeEach(() => {\n    fixture = TestBed.createComponent(OperatorDecisionTreeComponent);\n    component = fixture.componentInstance;\n    operatorDecisionTreeService = TestBed.inject(OperatorDecisionTreeService);\n    scrollService = TestBed.inject(ScrollService);\n    fixture.detectChanges();\n  });\n\n  afterEach(() => {\n    operatorDecisionTreeServiceStub.currentSentence$.next(\n      'Conditioner is better'\n    );\n    operatorDecisionTreeServiceStub.options$.next([treeNodeStubWithOptionsA]);\n    operatorDecisionTreeServiceStub.isBeyondInitialQuestion$.next(false);\n    operatorDecisionTreeServiceStub.hasError$.next(false);\n  });\n\n  it('should create', () => {\n    expect(component).toBeTruthy();\n  });\n\n  describe('in the template', () => {\n    describe('when the OperatorDecisionTreeService.currentSentence$ emits a signal', () => {\n      it('should update what is being displayed as the current sentence', () => {\n        expect(\n          fixture.debugElement.query(By.css('h2')).nativeElement.textContent\n        ).toContain('Conditioner is better');\n\n        operatorDecisionTreeServiceStub.currentSentence$.next(\n          'Shampoo is better'\n        );\n        fixture.detectChanges();\n\n        expect(\n          fixture.debugElement.query(By.css('h2')).nativeElement.textContent\n        ).toContain('Shampoo is better');\n      });\n    });\n\n    describe('when there are options to choose', () => {\n      it('should have option buttons', () => {\n        expect(\n          fixture.debugElement.queryAll(By.css('button.option')).length\n        ).toBeTruthy();\n      });\n    });\n\n    describe('when there are no more options to choose', () => {\n      it('should have no option buttons', () => {\n        operatorDecisionTreeServiceStub.options$.next([\n          treeNodeStubNoOptions as any\n        ]);\n        fixture.detectChanges();\n\n        expect(\n          fixture.debugElement.queryAll(By.css('button.option')).length\n        ).toBeFalsy();\n      });\n\n      describe('when there is a method associated with the operator', () => {\n        it('should display a method, docType, label, and a link to the operator path', () => {\n          const node = {\n            ...treeNodeStubNoOptions,\n            method: 'someMethod'\n          };\n          operatorDecisionTreeServiceStub.options$.next([node as any]);\n          fixture.detectChanges();\n\n          const sentence: HTMLParagraphElement = fixture.debugElement.query(\n            By.css('p')\n          ).nativeElement;\n          const link: HTMLAnchorElement = fixture.debugElement\n            .query(By.css('a'))\n            .nativeElement.getAttribute('href');\n\n          expect(sentence.textContent).toContain(\n            `You want the ${node.method} of the ${node.docType} ${node.label}.`\n          );\n          expect(link).toContain(`${node.path}#${node.method}`);\n        });\n      });\n\n      describe('when there is no method associated with the operator', () => {\n        it('should display a docType, label, and a link to the operator path', () => {\n          operatorDecisionTreeServiceStub.options$.next([\n            treeNodeStubNoOptions as any\n          ]);\n          fixture.detectChanges();\n\n          const sentence: HTMLParagraphElement = fixture.debugElement.query(\n            By.css('p')\n          ).nativeElement;\n          const link: HTMLAnchorElement = fixture.debugElement\n            .query(By.css('a'))\n            .nativeElement.getAttribute('href');\n\n          expect(sentence.textContent).toContain(\n            `You want the ${treeNodeStubNoOptions.docType} ${\n              treeNodeStubNoOptions.label\n            }.`\n          );\n          expect(link).toContain(treeNodeStubNoOptions.path);\n        });\n      });\n    });\n\n    describe('when there are no errors', () => {\n      it('should not display the error template', () => {\n        expect(fixture.debugElement.query(By.css('div.error'))).toBeNull();\n      });\n    });\n\n    describe('when there is an error', () => {\n      it('should display the error template', () => {\n        operatorDecisionTreeServiceStub.hasError$.next(true);\n        fixture.detectChanges();\n        expect(fixture.debugElement.query(By.css('div.error'))).toBeTruthy();\n      });\n    });\n  });\n\n  describe('selectOption', () => {\n    describe('when an option is clicked', () => {\n      it('should call the selectOption method', () => {\n        spyOn(component, 'selectOption');\n        fixture.debugElement\n          .query(By.css('button.option'))\n          .triggerEventHandler('click', null);\n        expect(component.selectOption).toHaveBeenCalled();\n      });\n    });\n\n    describe('when fired', () => {\n      it('should call the selectOption method on the operatorDecisionTreeService', () => {\n        component.selectOption(treeNodeStubWithOptionsA.id);\n        expect(operatorDecisionTreeService.selectOption).toHaveBeenCalledWith(\n          treeNodeStubWithOptionsA.id\n        );\n      });\n      it('should call the scrollToTop method of the scrollService', () => {\n        spyOn(scrollService, 'scrollToTop');\n        component.selectOption(treeNodeStubWithOptionsA.id);\n        expect(scrollService.scrollToTop).toHaveBeenCalled();\n      });\n    });\n  });\n\n  describe('back', () => {\n    describe('when the back button is pressed', () => {\n      it('should should call the back method', () => {\n        spyOn(component, 'back');\n        operatorDecisionTreeServiceStub.isBeyondInitialQuestion$.next(true);\n        fixture.detectChanges();\n        fixture.debugElement\n          .query(By.css('button.back'))\n          .triggerEventHandler('click', null);\n        expect(component.back).toHaveBeenCalled();\n      });\n    });\n\n    describe('when fired', () => {\n      it('should call the back method on the operatorDecisionTreeService', () => {\n        component.back();\n        expect(operatorDecisionTreeService.back).toHaveBeenCalled();\n      });\n    });\n  });\n\n  describe('startOver', () => {\n    describe('when the start-over button is pressed', () => {\n      it('should should call the startOver method', () => {\n        spyOn(component, 'startOver');\n        operatorDecisionTreeServiceStub.isBeyondInitialQuestion$.next(true);\n        fixture.detectChanges();\n        fixture.debugElement\n          .query(By.css('button.start-over'))\n          .triggerEventHandler('click', null);\n        expect(component.startOver).toHaveBeenCalled();\n      });\n    });\n\n    describe('when fired', () => {\n      it('should call the startOver method on the operatorDecisionTreeService', () => {\n        component.startOver();\n        expect(operatorDecisionTreeService.startOver).toHaveBeenCalled();\n      });\n    });\n  });\n\n  describe('ngOnDestroy', () => {\n    it('should call the startOver method', () => {\n      spyOn(component, 'startOver');\n      component.ngOnDestroy();\n      expect(component.startOver).toHaveBeenCalled();\n    });\n  });\n});\n"
  },
  {
    "path": "apps/rxjs.dev/src/app/custom-elements/operator-decision-tree/operator-decision-tree.component.ts",
    "content": "import { animate, state, style, transition, trigger } from '@angular/animations';\nimport { Component, OnDestroy } from '@angular/core';\nimport { ScrollService } from 'app/shared/scroll.service';\nimport { Observable } from 'rxjs';\nimport { OperatorTreeNode } from './interfaces';\nimport { OperatorDecisionTreeService } from './operator-decision-tree.service';\n\n@Component({\n  selector: 'aio-operator-decision-tree',\n  template: `\n    <h1 class=\"mat-heading\" tabindex=\"0\">Operator Decision Tree</h1>\n    <ng-container *ngIf=\"(hasError$ | async) === false; else hasErrorTemplate\">\n      <h2 class=\"mat-subheading-2\" tabindex=\"0\">\n        {{ currentSentence$ | async }}\n      </h2>\n      <ng-container *ngIf=\"isBeyondInitialQuestion$ | async\">\n        <section>\n          <button (click)=\"back()\" mat-button class=\"back\">Back</button>\n          <button (click)=\"startOver()\" mat-button color=\"warn\" class=\"start-over\">Start Over</button>\n        </section>\n      </ng-container>\n      <div>\n        <ng-container *ngFor=\"let option of options$ | async\">\n          <ng-container *ngIf=\"option.options; else operatorTemplate\">\n            <button class=\"option mat-body-1\" (click)=\"selectOption(option.id)\" [@flyIn]>\n              <mat-card matRipple>\n                {{ option.label }}\n              </mat-card>\n            </button>\n          </ng-container>\n          <ng-template #operatorTemplate>\n            <p *ngIf=\"option.method\" class=\"mat-body-1\">\n              You want the {{ option.method }} of the {{ option.docType }}\n              <a href=\"{{ option.path }}#{{ option.method }}\">{{ option.label }}</a\n              >.\n            </p>\n            <p *ngIf=\"!option.method\" class=\"mat-body-1\">\n              You want the {{ option.docType }} <a href=\"{{ option.path }}\">{{ option.label }}</a\n              >.\n            </p>\n          </ng-template>\n        </ng-container>\n      </div>\n    </ng-container>\n\n    <ng-template #hasErrorTemplate>\n      <div class=\"mat-body-1 error\">\n        <p>Oops! There was an issue loading the decision tree.. we're real sorry about that. Please try reloading the page.</p>\n        <p>\n          You can also try\n          <a href=\"https://github.com/ReactiveX/rxjs/issues/new?template=documentation.md\" target=\"_blank\">submitting an issue on GitHub</a\n          >.\n        </p>\n      </div>\n    </ng-template>\n  `,\n  styleUrls: ['./operator-decision-tree.component.scss'],\n  animations: [\n    trigger('flyIn', [\n      state('in', style({ transform: 'translateX(0)' })),\n      transition(':enter', [style({ transform: 'translateX(-100%)' }), animate(250)]),\n    ]),\n  ],\n})\nexport class OperatorDecisionTreeComponent implements OnDestroy {\n  currentSentence$: Observable<string> = this.operatorDecisionTreeService.currentSentence$;\n  options$: Observable<OperatorTreeNode[]> = this.operatorDecisionTreeService.options$;\n  isBeyondInitialQuestion$: Observable<boolean> = this.operatorDecisionTreeService.isBeyondInitialQuestion$;\n  hasError$: Observable<boolean> = this.operatorDecisionTreeService.hasError$;\n\n  constructor(private operatorDecisionTreeService: OperatorDecisionTreeService, private scrollService: ScrollService) {}\n\n  selectOption(optionId: string): void {\n    this.operatorDecisionTreeService.selectOption(optionId);\n    this.scrollService.scrollToTop();\n  }\n\n  back(): void {\n    this.operatorDecisionTreeService.back();\n  }\n\n  startOver(): void {\n    this.operatorDecisionTreeService.startOver();\n  }\n\n  ngOnDestroy(): void {\n    this.startOver();\n  }\n}\n"
  },
  {
    "path": "apps/rxjs.dev/src/app/custom-elements/operator-decision-tree/operator-decision-tree.module.spec.ts",
    "content": "import { OperatorDecisionTreeModule } from './operator-decision-tree.module';\n\ndescribe('OperatorDecisionTreeModule', () => {\n  let chooseYourOwnOperatorModule: OperatorDecisionTreeModule;\n\n  beforeEach(() => {\n    chooseYourOwnOperatorModule = new OperatorDecisionTreeModule();\n  });\n\n  it('should create an instance', () => {\n    expect(chooseYourOwnOperatorModule).toBeTruthy();\n  });\n});\n"
  },
  {
    "path": "apps/rxjs.dev/src/app/custom-elements/operator-decision-tree/operator-decision-tree.module.ts",
    "content": "import { CommonModule } from '@angular/common';\nimport { NgModule, Type } from '@angular/core';\nimport { MatButtonModule } from '@angular/material/button';\nimport { MatCardModule } from '@angular/material/card';\nimport { MatRippleModule } from '@angular/material/core';\nimport { ScrollService } from 'app/shared/scroll.service';\nimport { WithCustomElementComponent } from '../element-registry';\nimport { OperatorDecisionTreeDataService } from './operator-decision-tree-data.service';\nimport { OperatorDecisionTreeComponent } from './operator-decision-tree.component';\nimport { OperatorDecisionTreeService } from './operator-decision-tree.service';\n\n@NgModule({\n  imports: [CommonModule, MatButtonModule, MatCardModule, MatRippleModule],\n  declarations: [OperatorDecisionTreeComponent],\n  providers: [\n    OperatorDecisionTreeDataService,\n    OperatorDecisionTreeService,\n    ScrollService\n  ]\n})\nexport class OperatorDecisionTreeModule implements WithCustomElementComponent {\n  customElementComponent: Type<\n    OperatorDecisionTreeComponent\n  > = OperatorDecisionTreeComponent;\n}\n"
  },
  {
    "path": "apps/rxjs.dev/src/app/custom-elements/operator-decision-tree/operator-decision-tree.service.spec.ts",
    "content": "import { TestBed } from '@angular/core/testing';\nimport { cold, initTestScheduler, addMatchers } from 'jasmine-marbles';\nimport {\n  treeNodeInitialStub,\n  treeNodeStubNoOptions,\n  treeNodeStubWithOptionsA,\n  treeNodeStubWithOptionsB,\n  treeStub\n} from './fixtures';\nimport { OperatorDecisionTreeDataService } from './operator-decision-tree-data.service';\nimport { OperatorDecisionTreeService } from './operator-decision-tree.service';\n\ndescribe('OperatorDecisionTreeService', () => {\n  let service: OperatorDecisionTreeService;\n  const dataServiceStub = {\n    getDecisionTree$: jasmine.createSpy()\n  };\n\n  beforeEach(() => {\n    addMatchers();\n    initTestScheduler();\n    TestBed.configureTestingModule({\n      providers: [\n        OperatorDecisionTreeService,\n        {\n          provide: OperatorDecisionTreeDataService,\n          useValue: dataServiceStub\n        }\n      ]\n    });\n  });\n\n  describe('currentSentence$', () => {\n    const initialSentence = 'Start by choosing an option from the list below.';\n\n    beforeEach(() => {\n      dataServiceStub.getDecisionTree$.and.returnValue(\n        cold('x', { x: treeStub })\n      );\n      service = TestBed.inject(OperatorDecisionTreeService);\n    });\n\n    describe('when it is the initial sequence', () => {\n      it('should emit an initial sentence', () => {\n        spyOn(service, 'selectOption');\n        expect(service.currentSentence$).toBeObservable(\n          cold('x', { x: initialSentence })\n        );\n        expect(service.selectOption).not.toHaveBeenCalled();\n      });\n    });\n\n    describe('when an option is selected', () => {\n      it('should emit a sentence based on previous chosen labels', () => {\n        service.selectOption(treeNodeStubWithOptionsA.id);\n        expect(service.currentSentence$).toBeObservable(\n          cold('x', { x: `${treeNodeStubWithOptionsA.label}...` })\n        );\n\n        service.selectOption(treeNodeStubWithOptionsB.id);\n        expect(service.currentSentence$).toBeObservable(\n          cold('x', {\n            x: `${treeNodeStubWithOptionsA.label} ${\n              treeNodeStubWithOptionsB.label\n            }...`\n          })\n        );\n      });\n\n      describe('and the back method is called', () => {\n        it('should emit the previous sentence', () => {\n          service.selectOption(treeNodeStubWithOptionsA.id);\n          service.selectOption(treeNodeStubWithOptionsB.id);\n          service.back();\n          expect(service.currentSentence$).toBeObservable(\n            cold('x', { x: `${treeNodeStubWithOptionsA.label}...` })\n          );\n        });\n      });\n\n      describe('and the startOver method is called', () => {\n        it('should emit the initial sentence', () => {\n          service.selectOption(treeNodeStubWithOptionsA.id);\n          service.startOver();\n          expect(service.currentSentence$).toBeObservable(\n            cold('x', { x: initialSentence })\n          );\n        });\n      });\n    });\n  });\n\n  describe('options$', () => {\n    describe('signals do not get past the filter,', () => {\n      describe('when the tree has an error', () => {\n        it('should never emit', () => {\n          dataServiceStub.getDecisionTree$.and.returnValue(cold('#'));\n          service = TestBed.inject(OperatorDecisionTreeService);\n          expect(service.options$).toBeObservable(cold('-'));\n        });\n      });\n\n      describe('when the current branch has no options', () => {\n        it('should never emit', () => {\n          dataServiceStub.getDecisionTree$.and.returnValue(\n            cold('x', {\n              x: { [treeNodeStubNoOptions.id]: treeNodeStubNoOptions }\n            })\n          );\n          service = TestBed.inject(OperatorDecisionTreeService);\n          expect(service.options$).toBeObservable(cold('-'));\n        });\n      });\n\n      describe('when the currentBranchId does not exist in the tree', () => {\n        it('should never emit', () => {\n          dataServiceStub.getDecisionTree$.and.returnValue(\n            cold('x', {\n              x: { foo: treeNodeStubNoOptions }\n            })\n          );\n          service = TestBed.inject(OperatorDecisionTreeService);\n          expect(service.options$).toBeObservable(cold('-'));\n        });\n      });\n    });\n\n    describe('when signals get past the filter', () => {\n      beforeEach(() => {\n        dataServiceStub.getDecisionTree$.and.returnValue(\n          cold('x', { x: treeStub })\n        );\n        service = TestBed.inject(OperatorDecisionTreeService);\n      });\n\n      describe('when it is the initial sequence', () => {\n        it('should be an array of the tree nodes from the initial options', () => {\n          expect(service.options$).toBeObservable(\n            cold('a', { a: [treeStub[treeNodeInitialStub.initial.options[0]]] })\n          );\n        });\n      });\n\n      describe('when an option is selected', () => {\n        describe('and there are additional options', () => {\n          it('should be an array of the new option nodes', () => {\n            service.selectOption(treeNodeStubWithOptionsA.id);\n            expect(service.options$).toBeObservable(\n              cold('a', { a: [treeNodeStubWithOptionsB] })\n            );\n          });\n        });\n\n        describe('and there are no additional options', () => {\n          it('should not emit', () => {\n            service.selectOption(treeNodeStubNoOptions.id);\n            expect(service.options$).toBeObservable(cold('-'));\n          });\n        });\n      });\n    });\n  });\n\n  describe('isBeyondInitialQuestion$', () => {\n    beforeEach(() => {\n      dataServiceStub.getDecisionTree$.and.returnValue(\n        cold('x', { x: treeStub })\n      );\n      service = TestBed.inject(OperatorDecisionTreeService);\n    });\n\n    describe('when not beyond the initial question', () => {\n      it('should be false', () => {\n        spyOn(service, 'selectOption');\n        expect(service.isBeyondInitialQuestion$).toBeObservable(\n          cold('a', { a: false })\n        );\n        expect(service.selectOption).not.toHaveBeenCalled();\n      });\n    });\n\n    describe('when beyond the initial question', () => {\n      it('should be true', () => {\n        service.selectOption(treeNodeStubWithOptionsA.id);\n        expect(service.isBeyondInitialQuestion$).toBeObservable(\n          cold('a', { a: true })\n        );\n      });\n    });\n  });\n\n  describe('hasError$', () => {\n    describe('when the tree has no error', () => {\n      it('should not emit', () => {\n        dataServiceStub.getDecisionTree$.and.returnValue(\n          cold('x', { x: treeStub })\n        );\n        service = TestBed.inject(OperatorDecisionTreeService);\n        expect(service.hasError$).toBeObservable(cold('-'));\n      });\n    });\n  });\n});\n"
  },
  {
    "path": "apps/rxjs.dev/src/app/custom-elements/operator-decision-tree/operator-decision-tree.service.ts",
    "content": "import { Injectable } from '@angular/core';\nimport { BehaviorSubject, combineLatest, Observable, of } from 'rxjs';\nimport { filter, map, mapTo, shareReplay, catchError } from 'rxjs/operators';\nimport { OperatorDecisionTree, OperatorTreeNode, State } from './interfaces';\nimport { OperatorDecisionTreeDataService } from './operator-decision-tree-data.service';\nimport { isInitialDecision, nodeHasOptions, treeIsErrorFree } from './utils';\n\n@Injectable()\nexport class OperatorDecisionTreeService {\n  private initialState: State = {\n    previousBranchIds: ['initial'],\n    currentBranchId: 'initial'\n  };\n  private state$ = new BehaviorSubject<State>(this.initialState);\n  private tree$: Observable<\n    OperatorDecisionTree\n  > = this.dataService.getDecisionTree$().pipe(\n    catchError(error => of(error)), // This helps if the JSON for some reason fails to get fetched\n    shareReplay()\n  );\n\n  currentSentence$: Observable<string> = combineLatest(\n    this.tree$,\n    this.state$\n  ).pipe(\n    filter(([tree]) => treeIsErrorFree(tree)),\n    map(([tree, { previousBranchIds }]) =>\n      isInitialDecision(previousBranchIds)\n        ? 'Start by choosing an option from the list below.'\n        : `${previousBranchIds\n            .map(entityId => tree[entityId].label)\n            .join(' ')}...`.trim()\n    )\n  );\n\n  options$: Observable<(OperatorTreeNode)[]> = combineLatest(\n    this.tree$,\n    this.state$\n  ).pipe(\n    filter(([tree, state]) => (\n        treeIsErrorFree(tree) &&\n        !!tree[state.currentBranchId] &&\n        !!tree[state.currentBranchId].options\n      )),\n    map(([tree, state]) => {\n      // Project is currently using TypeScript 2.9.2\n      // With TS 3.1+ this can be done better if we map to [tree, node] and typeguard with a tuple in a filter\n      // filter((a): a is [OperatorDecisionTree, OperatorTreeNodeWithOptions] => !a[0].error && !!a[1].options)\n      const node = tree[state.currentBranchId];\n      return nodeHasOptions(node)\n        ? node.options.map(option => tree[option])\n        : tree.initial.options.map(option => tree[option]);\n    })\n  );\n\n  isBeyondInitialQuestion$: Observable<boolean> = this.state$.pipe(\n    map(({ currentBranchId }) => currentBranchId !== 'initial')\n  );\n\n  // This helps if the JSON for some reason fails to get fetched\n  hasError$ = this.tree$.pipe(\n    filter(tree => !!tree.error),\n    mapTo(true)\n  );\n\n  constructor(private dataService: OperatorDecisionTreeDataService) {}\n\n  private get snapShot(): State {\n    return this.state$.getValue();\n  }\n\n  selectOption(optionId: string): void {\n    this.state$.next({\n      previousBranchIds: [...this.snapShot.previousBranchIds, optionId],\n      currentBranchId: optionId\n    });\n  }\n\n  back(): void {\n    const previousOptionId = this.snapShot.previousBranchIds[\n      this.snapShot.previousBranchIds.length - 2\n    ];\n\n    if (previousOptionId) {\n      this.state$.next({\n        previousBranchIds: [\n          ...this.snapShot.previousBranchIds.slice(\n            0,\n            this.snapShot.previousBranchIds.length - 1\n          )\n        ],\n        currentBranchId: previousOptionId\n      });\n    }\n  }\n\n  startOver(): void {\n    this.state$.next(this.initialState);\n  }\n}\n"
  },
  {
    "path": "apps/rxjs.dev/src/app/custom-elements/operator-decision-tree/utils.spec.ts",
    "content": "import { isInitialDecision, treeIsErrorFree, nodeHasOptions } from './utils';\n\ndescribe('isInitialDecision', () => {\n  describe('when it is an initial decision', () => {\n    it('should be true', () => {\n      expect(isInitialDecision(['initial'])).toBe(true);\n    });\n  });\n\n  describe('when it is not an initial decision', () => {\n    it('should be false', () => {\n      expect(isInitialDecision(['initial', 'foo'])).toBe(false);\n    });\n  });\n});\n\ndescribe('treeIsErrorFree', () => {\n  describe('when the tree is error free', () => {\n    it('should return true', () => {\n      expect(treeIsErrorFree({} as any)).toBe(true);\n    });\n  });\n\n  describe('when the tree has an error', () => {\n    it('should return false', () => {\n      expect(treeIsErrorFree({error: true} as any)).toBe(false);\n    });\n  });\n});\n\ndescribe('nodeHasOptions', () => {\n  describe('when node has options', () => {\n    it('should return true', () => {\n      expect(nodeHasOptions({options: ['123']} as any)).toBe(true);\n    });\n  });\n\n  describe('when node has no options', () => {\n    it('should return false', () => {\n      expect(nodeHasOptions({} as any)).toBe(false);\n    });\n  });\n});\n"
  },
  {
    "path": "apps/rxjs.dev/src/app/custom-elements/operator-decision-tree/utils.ts",
    "content": "import { OperatorDecisionTree, OperatorTreeNode, OperatorTreeNodeWithOptions } from './interfaces';\n\nexport function isInitialDecision(previousBranchIds: string[]): boolean {\n  return (\n    previousBranchIds.includes('initial') && previousBranchIds.length === 1\n  );\n}\n\nexport function treeIsErrorFree(tree: OperatorDecisionTree): boolean {\n  return !tree.error;\n}\n\nexport function nodeHasOptions(node: OperatorTreeNode): node is OperatorTreeNodeWithOptions {\n  return !!node.options;\n}\n"
  },
  {
    "path": "apps/rxjs.dev/src/app/custom-elements/resource/resource-list.component.spec.ts",
    "content": "import { ReflectiveInjector } from '@angular/core';\nimport { PlatformLocation } from '@angular/common';\n\nimport { of } from 'rxjs';\n\nimport { ResourceListComponent } from './resource-list.component';\nimport { ResourceService } from './resource.service';\n\nimport { Category } from './resource.model';\n\n// Testing the component class behaviors, independent of its template\n// Let e2e tests verify how it displays.\ndescribe('ResourceListComponent', () => {\n\n  let injector: ReflectiveInjector;\n  let location: TestPlatformLocation;\n\n  beforeEach(() => {\n    injector = ReflectiveInjector.resolveAndCreate([\n      ResourceListComponent,\n      {provide: PlatformLocation, useClass: TestPlatformLocation },\n      {provide: ResourceService, useClass: TestResourceService }\n    ]);\n\n    location = injector.get(PlatformLocation);\n  });\n\n  it('should set the location w/o leading slashes', () => {\n    location.pathname = '////resources';\n    const component = getComponent();\n    expect(component.location).toBe('resources');\n  });\n\n  it('href(id) should return the expected href', () => {\n    location.pathname = '////resources';\n    const component = getComponent();\n    expect(component.href({id: 'foo'})).toBe('resources#foo');\n  });\n\n  it('should set scroll position to zero when no target element', () => {\n    const component = getComponent();\n    component.onScroll(undefined);\n    expect(component.scrollPos).toBe(0);\n  });\n\n  it('should set scroll position to element.scrollTop when that is defined', () => {\n    const component = getComponent();\n    component.onScroll({scrollTop: 42});\n    expect(component.scrollPos).toBe(42);\n  });\n\n  it('should set scroll position to element.body.scrollTop when that is defined', () => {\n    const component = getComponent();\n    component.onScroll({body: {scrollTop: 42}});\n    expect(component.scrollPos).toBe(42);\n  });\n\n  it('should set scroll position to 0 when no target.body.scrollTop defined', () => {\n    const component = getComponent();\n    component.onScroll({body: {}});\n    expect(component.scrollPos).toBe(0);\n  });\n\n  //// Test Helpers ////\n  function  getComponent(): ResourceListComponent { return injector.get(ResourceListComponent); }\n\n  class TestPlatformLocation {\n    pathname = 'resources';\n  }\n\n  class TestResourceService {\n    categories = of(getTestData);\n  }\n\n  function getTestData(): Category[] {\n    return []; // Not interested in the data in these tests\n  }\n});\n"
  },
  {
    "path": "apps/rxjs.dev/src/app/custom-elements/resource/resource-list.component.ts",
    "content": "import { Component, HostListener, OnInit } from '@angular/core';\nimport { PlatformLocation } from '@angular/common';\n\nimport { Category } from './resource.model';\nimport { ResourceService } from './resource.service';\n\n@Component({\n  selector: 'aio-resource-list',\n  template: `\n    <div class=\"resources-container\">\n      <div class=\"l-flex--column\">\n        <div class=\"showcase\" *ngFor=\"let category of categories\">\n          <header class=\"c-resource-header\">\n            <!-- eslint-disable-next-line @angular-eslint/template/accessibility-elements-content -->\n            <a class=\"h-anchor-offset\" id=\"{{ category.id }}\"></a>\n            <h2>{{ category.title }}</h2>\n          </header>\n\n          <div class=\"shadow-1\">\n            <div *ngFor=\"let subCategory of category.subCategories\">\n            <!-- eslint-disable-next-line @angular-eslint/template/accessibility-elements-content -->\n              <a class=\"h-anchor-offset\" id=\"{{ subCategory.id }}\"></a>\n              <h3 class=\"subcategory-title\">{{ subCategory.title }}</h3>\n\n              <div *ngFor=\"let resource of subCategory.resources\">\n                <div class=\"c-resource\" *ngIf=\"resource.rev\">\n                  <a class=\"l-flex--column resource-row-link\" target=\"_blank\" [href]=\"resource.url\">\n                    <div>\n                      <h4>{{ resource.title }}</h4>\n                      <p class=\"resource-description\">{{ resource.desc || 'No Description' }}</p>\n                    </div>\n                  </a>\n                </div>\n              </div>\n            </div>\n          </div>\n        </div>\n      </div>\n    </div>\n  `,\n})\nexport class ResourceListComponent implements OnInit {\n  categories: Category[];\n  location: string;\n  scrollPos = 0;\n\n  constructor(location: PlatformLocation, private resourceService: ResourceService) {\n    this.location = location.pathname.replace(/^\\/+/, '');\n  }\n\n  href(cat: { id: string }) {\n    return this.location + '#' + cat.id;\n  }\n\n  ngOnInit() {\n    // Not using async pipe because cats appear twice in template\n    // No need to unsubscribe because categories observable completes.\n    this.resourceService.categories.subscribe((cats) => (this.categories = cats));\n  }\n\n  @HostListener('window:scroll', ['$event.target'])\n  onScroll(target: any) {\n    this.scrollPos = target ? target.scrollTop || target.body.scrollTop || 0 : 0;\n  }\n}\n"
  },
  {
    "path": "apps/rxjs.dev/src/app/custom-elements/resource/resource-list.module.ts",
    "content": "import { NgModule, Type } from '@angular/core';\nimport { CommonModule } from '@angular/common';\nimport { ResourceListComponent } from './resource-list.component';\nimport { ResourceService } from './resource.service';\nimport { WithCustomElementComponent } from '../element-registry';\n\n@NgModule({\n  imports: [ CommonModule ],\n  declarations: [ ResourceListComponent ],\n  providers: [ ResourceService ]\n})\nexport class ResourceListModule implements WithCustomElementComponent {\n  customElementComponent: Type<any> = ResourceListComponent;\n}\n"
  },
  {
    "path": "apps/rxjs.dev/src/app/custom-elements/resource/resource.model.ts",
    "content": "export class Category {\n  id: string;    // \"education\"\n  title: string; // \"Education\"\n  order: number; // 2\n  subCategories: SubCategory[];\n}\n\nexport class SubCategory {\n  id: string;    // \"books\"\n  title: string; // \"Books\"\n  order: number; // 1\n  resources: Resource[];\n}\n\nexport class Resource {\n  category: string;    // \"Education\"\n  subCategory: string; // \"Books\"\n  id: string;          // \"-KLI8vJ0ZkvWhqPembZ7\"\n  desc: string;        // \"This books shows all the steps necessary for the development of SPA\"\n  rev: boolean;        // true (always true in the original)\n  title: string;       // \"Practical Angular 2\",\n  url: string;         // \"https://leanpub.com/practical-angular-2\"\n}\n"
  },
  {
    "path": "apps/rxjs.dev/src/app/custom-elements/resource/resource.service.spec.ts",
    "content": "import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing';\nimport { Injector } from '@angular/core';\nimport { TestBed } from '@angular/core/testing';\n\nimport { ResourceService } from './resource.service';\nimport { Category } from './resource.model';\n\ndescribe('ResourceService', () => {\n\n  let injector: Injector;\n  let resourceService: ResourceService;\n  let httpMock: HttpTestingController;\n\n  beforeEach(() => {\n    injector = TestBed.configureTestingModule({\n      imports: [HttpClientTestingModule],\n      providers: [\n        ResourceService\n      ]\n    });\n\n    resourceService = injector.get(ResourceService);\n    httpMock = injector.get(HttpTestingController);\n  });\n\n  afterEach(() => httpMock.verify());\n\n  it('should make a single connection to the server', () => {\n    const req = httpMock.expectOne({});\n    expect(req.request.url).toBe('generated/resources.json');\n  });\n\n  describe('#categories', () => {\n\n    let categories: Category[];\n    let testData: any;\n\n    beforeEach(() => {\n      testData = getTestResources();\n      httpMock.expectOne({}).flush(testData);\n      resourceService.categories.subscribe(results => categories = results);\n    });\n\n    it('categories observable should complete', () => {\n      let completed = false;\n      resourceService.categories.subscribe(undefined, undefined, () => completed = true);\n      expect(completed).toBe(true, 'observable completed');\n    });\n\n    it('should reshape contributors.json to sorted category array', () => {\n      const actualIds = categories.map(c => c.id).join(',');\n      expect(actualIds).toBe('cat-1,cat-3');\n    });\n\n    it('should convert ids to canonical form', () => {\n      // canonical form is lowercase with dashes for spaces\n      const cat = categories[1];\n      const sub = cat.subCategories[0];\n      const res = sub.resources[0];\n\n      expect(cat.id).toBe('cat-3', 'category id');\n      expect(sub.id).toBe('cat3-subcat2', 'subcat id');\n      expect(res.id).toBe('cat3-subcat2-res1', 'resources id');\n    });\n\n    it('resource knows its category and sub-category titles', () => {\n      const cat = categories[1];\n      const sub = cat.subCategories[0];\n      const res = sub.resources[0];\n      expect(res.category).toBe(cat.title, 'category title');\n      expect(res.subCategory).toBe(sub.title, 'subcategory title');\n    });\n\n    it('should have expected SubCategories of \"Cat 3\"', () => {\n      const actualIds = categories[1].subCategories.map(s => s.id).join(',');\n      expect(actualIds).toBe('cat3-subcat2,cat3-subcat1');\n    });\n\n    it('should have expected sorted resources of \"Cat 1:SubCat1\"', () => {\n      const actualIds = categories[0].subCategories[0].resources.map(r => r.id).join(',');\n      expect(actualIds).toBe('a-a-a,s-s-s,z-z-z');\n    });\n  });\n\n  it('should do WHAT(?) if the request fails');\n});\n\nfunction getTestResources() {\n  return {\n    'Cat 3': {\n      order: 3,\n      subCategories: {\n        'Cat3 SubCat1': {\n          order: 2,\n          resources: {\n            'Cat3 SubCat1 Res1': {\n              desc: 'Meetup in Barcelona, Spain. ',\n              rev: true,\n              title: 'Angular Beers',\n              url: 'http://www.meetup.com/AngularJS-Beers/'\n            },\n            'Cat3 SubCat1 Res2': {\n              desc: 'Angular Camps in Barcelona, Spain.',\n              rev: true,\n              title: 'Angular Camp',\n              url: 'http://angularcamp.org/'\n            }\n          }\n        },\n        'Cat3 SubCat2': {\n          order: 1,\n          resources: {\n            'Cat3 SubCat2 Res1': {\n              desc: 'A community index of components and libraries',\n              rev: true,\n              title: 'Catalog of Angular Components & Libraries',\n              url: 'https://a/b/c'\n            }\n          }\n        },\n      }\n    },\n    'Cat 1': {\n      order: 1,\n      subCategories: {\n        'Cat1 SubCat1': {\n          order: 1,\n          resources: {\n            'S S S': {\n              desc: 'SSS',\n              rev: true,\n              title: 'Sssss',\n              url: 'http://s/s/s'\n            },\n            'A A A': {\n             desc: 'AAA',\n              rev: true,\n              title: 'Aaaa',\n              url: 'http://a/a/a'\n            },\n            'Z Z Z': {\n             desc: 'ZZZ',\n              rev: true,\n              title: 'Zzzzz',\n              url: 'http://z/z/z'\n            }\n          }\n        },\n      },\n    }\n  };\n}\n"
  },
  {
    "path": "apps/rxjs.dev/src/app/custom-elements/resource/resource.service.ts",
    "content": "import { Injectable } from '@angular/core';\nimport { HttpClient } from '@angular/common/http';\n\nimport { ConnectableObservable, Observable } from 'rxjs';\nimport { map, publishLast } from 'rxjs/operators';\n\nimport { Category, Resource, SubCategory } from './resource.model';\nimport { CONTENT_URL_PREFIX } from 'app/documents/document.service';\n\nconst resourcesPath = CONTENT_URL_PREFIX + 'resources.json';\n\n@Injectable()\nexport class ResourceService {\n  categories: Observable<Category[]>;\n\n  constructor(private http: HttpClient) {\n    this.categories = this.getCategories();\n  }\n\n  private getCategories(): Observable<Category[]> {\n\n    const categories = this.http.get<any>(resourcesPath).pipe(\n      map(data => mkCategories(data)),\n      publishLast(),\n    );\n\n    (categories as ConnectableObservable<Category[]>).connect();\n    return categories;\n  };\n}\n\n// Extract sorted Category[] from resource JSON data\nfunction mkCategories(categoryJson: any): Category[] {\n  return Object.keys(categoryJson).map(catKey => {\n    const cat = categoryJson[catKey];\n    return {\n      id: makeId(catKey),\n      title: catKey,\n      order: cat.order,\n      subCategories: mkSubCategories(cat.subCategories, catKey)\n    } as Category;\n  })\n  .sort(compareCats);\n}\n\n// Extract sorted SubCategory[] from JSON category data\nfunction mkSubCategories(subCategoryJson: any, catKey: string): SubCategory[] {\n  return Object.keys(subCategoryJson).map(subKey => {\n      const sub = subCategoryJson[subKey];\n      return {\n        id: makeId(subKey),\n        title: subKey,\n        order: sub.order,\n        resources: mkResources(sub.resources, subKey, catKey)\n      } as SubCategory;\n  })\n  .sort(compareCats);\n}\n\n// Extract sorted Resource[] from JSON subcategory data\nfunction mkResources(resourceJson: any, subKey: string, catKey: string): Resource[] {\n  return Object.keys(resourceJson).map(resKey => {\n    const res = resourceJson[resKey];\n    res.category = catKey;\n    res.subCategory = subKey;\n    res.id = makeId(resKey);\n    return res as Resource;\n  })\n  .sort(compareTitles);\n}\n\nfunction compareCats(l: Category | SubCategory, r: Category | SubCategory) {\n  return l.order === r.order ? compareTitles(l, r) : l.order > r.order ? 1 : -1;\n}\n\nfunction compareTitles(l: {title: string}, r: {title: string}) {\n return l.title.toUpperCase() > r.title.toUpperCase() ? 1 : -1;\n}\n\nfunction makeId(title: string) {\n  return title.toLowerCase().replace(/\\s+/g, '-');\n}\n"
  },
  {
    "path": "apps/rxjs.dev/src/app/custom-elements/search/file-not-found-search.component.spec.ts",
    "content": "import { ComponentFixture, TestBed } from '@angular/core/testing';\nimport { By } from '@angular/platform-browser';\nimport { Subject } from 'rxjs';\nimport { LocationService } from 'app/shared/location.service';\nimport { MockLocationService } from 'testing/location.service';\nimport { SearchResults } from 'app/search/interfaces';\nimport { SearchResultsComponent } from 'app/shared/search-results/search-results.component';\nimport { SearchService } from 'app/search/search.service';\nimport { FileNotFoundSearchComponent } from './file-not-found-search.component';\n\n\ndescribe('FileNotFoundSearchComponent', () => {\n  let fixture: ComponentFixture<FileNotFoundSearchComponent>;\n  let searchService: SearchService;\n  let searchResultSubject: Subject<SearchResults>;\n\n  beforeEach(() => {\n\n    TestBed.configureTestingModule({\n      declarations: [ FileNotFoundSearchComponent, SearchResultsComponent ],\n      providers: [\n        { provide: LocationService, useValue: new MockLocationService('base/initial-url?some-query') },\n        SearchService\n      ]\n    });\n\n    fixture = TestBed.createComponent(FileNotFoundSearchComponent);\n    searchService = TestBed.inject(SearchService);\n    searchResultSubject = new Subject<SearchResults>();\n    spyOn(searchService, 'search').and.callFake(() => searchResultSubject.asObservable());\n    fixture.detectChanges();\n  });\n\n  it('should run a search with a query built from the current url', () => {\n    expect(searchService.search).toHaveBeenCalledWith('base initial url');\n  });\n\n  it('should pass through any results to the `aio-search-results` component', () => {\n    const searchResultsComponent = fixture.debugElement.query(By.directive(SearchResultsComponent)).componentInstance;\n    expect(searchResultsComponent.searchResults).toBe(null);\n\n    const results = { query: 'base initial url', results: []};\n    searchResultSubject.next(results);\n    fixture.detectChanges();\n    expect(searchResultsComponent.searchResults).toEqual(results);\n  });\n});\n"
  },
  {
    "path": "apps/rxjs.dev/src/app/custom-elements/search/file-not-found-search.component.ts",
    "content": "import { Component, OnInit } from '@angular/core';\nimport { Observable } from 'rxjs';\nimport { switchMap } from 'rxjs/operators';\nimport { LocationService } from 'app/shared/location.service';\nimport { SearchResults } from 'app/search/interfaces';\nimport { SearchService } from 'app/search/search.service';\n\n@Component({\n  selector: 'aio-file-not-found-search',\n  template:\n  `<p>Let's see if any of these search results help...</p>\n  <aio-search-results class=\"embedded\" [searchResults]=\"searchResults | async\"></aio-search-results>`\n})\nexport class FileNotFoundSearchComponent implements OnInit {\n  searchResults: Observable<SearchResults>;\n  constructor(private location: LocationService, private search: SearchService) {}\n\n  ngOnInit() {\n    this.searchResults = this.location.currentPath.pipe(switchMap(path => {\n      const query = path.split(/\\W+/).join(' ');\n      return this.search.search(query);\n    }));\n  }\n}\n"
  },
  {
    "path": "apps/rxjs.dev/src/app/custom-elements/search/file-not-found-search.module.ts",
    "content": "import { NgModule, Type } from '@angular/core';\nimport { CommonModule } from '@angular/common';\nimport { SharedModule } from '../../shared/shared.module';\nimport { FileNotFoundSearchComponent } from './file-not-found-search.component';\nimport { WithCustomElementComponent } from '../element-registry';\n\n@NgModule({\n  imports: [ CommonModule, SharedModule ],\n  declarations: [ FileNotFoundSearchComponent ]\n})\nexport class FileNotFoundSearchModule implements WithCustomElementComponent {\n  customElementComponent: Type<any> = FileNotFoundSearchComponent;\n}\n"
  },
  {
    "path": "apps/rxjs.dev/src/app/custom-elements/toc/toc.component.ts",
    "content": "import { AfterViewInit, Component, ElementRef, OnDestroy, OnInit, QueryList, ViewChildren } from '@angular/core';\nimport { asapScheduler as asap, combineLatest, Subject } from 'rxjs';\nimport { startWith, subscribeOn, takeUntil } from 'rxjs/operators';\n\nimport { ScrollService } from 'app/shared/scroll.service';\nimport { TocItem, TocService } from 'app/shared/toc.service';\n\ntype TocType = 'None' | 'Floating' | 'EmbeddedSimple' | 'EmbeddedExpandable';\n\n@Component({\n  selector: 'aio-toc',\n  template: `<div *ngIf=\"type !== 'None'\" class=\"toc-inner no-print\" [class.collapsed]=\"isCollapsed\">\n    <div *ngIf=\"type === 'EmbeddedSimple'\" class=\"toc-heading embedded\">Contents</div>\n\n    <button\n      *ngIf=\"type === 'EmbeddedExpandable'\"\n      type=\"button\"\n      (click)=\"toggle(false)\"\n      class=\"toc-heading embedded secondary\"\n      title=\"Expand/collapse contents\"\n      aria-label=\"Expand/collapse contents\"\n      [attr.aria-pressed]=\"!isCollapsed\"\n    >\n      Contents\n      <mat-icon class=\"rotating-icon\" svgIcon=\"keyboard_arrow_right\" [class.collapsed]=\"isCollapsed\"></mat-icon>\n    </button>\n\n    <ul class=\"toc-list\" [class.embedded]=\"type !== 'Floating'\">\n      <ng-container *ngFor=\"let toc of tocList; let i = index\">\n        <li\n          #tocItem\n          title=\"{{ toc.title }}\"\n          *ngIf=\"type === 'Floating' || toc.level !== 'h1'\"\n          class=\"{{ toc.level }}\"\n          [class.secondary]=\"type === 'EmbeddedExpandable' && i >= primaryMax\"\n          [class.active]=\"i === activeIndex\"\n        >\n          <a [href]=\"toc.href\" [innerHTML]=\"toc.content\"></a>\n        </li>\n      </ng-container>\n    </ul>\n\n    <button\n      *ngIf=\"type === 'EmbeddedExpandable'\"\n      type=\"button\"\n      (click)=\"toggle()\"\n      class=\"toc-more-items embedded material-icons\"\n      [class.collapsed]=\"isCollapsed\"\n      title=\"Expand/collapse contents\"\n      aria-label=\"Expand/collapse contents\"\n      [attr.aria-pressed]=\"!isCollapsed\"\n    ></button>\n  </div> `,\n  styles: [],\n})\nexport class TocComponent implements OnInit, AfterViewInit, OnDestroy {\n  activeIndex: number | null = null;\n  type: TocType = 'None';\n  isCollapsed = true;\n  isEmbedded = false;\n  @ViewChildren('tocItem') private items: QueryList<ElementRef>;\n  private onDestroy = new Subject();\n  primaryMax = 4;\n  tocList: TocItem[];\n\n  constructor(private scrollService: ScrollService, elementRef: ElementRef, private tocService: TocService) {\n    this.isEmbedded = elementRef.nativeElement.className.indexOf('embedded') !== -1;\n  }\n\n  ngOnInit() {\n    this.tocService.tocList.pipe(takeUntil(this.onDestroy)).subscribe((tocList) => {\n      this.tocList = tocList;\n      const itemCount = count(this.tocList, (item) => item.level !== 'h1');\n\n      this.type =\n        itemCount > 0 ? (this.isEmbedded ? (itemCount > this.primaryMax ? 'EmbeddedExpandable' : 'EmbeddedSimple') : 'Floating') : 'None';\n    });\n  }\n\n  ngAfterViewInit() {\n    if (!this.isEmbedded) {\n      // We use the `asap` scheduler because updates to `activeItemIndex` are triggered by DOM changes,\n      // which, in turn, are caused by the rendering that happened due to a ChangeDetection.\n      // Without asap, we would be updating the model while still in a ChangeDetection handler, which is disallowed by Angular.\n      combineLatest(this.tocService.activeItemIndex.pipe(subscribeOn(asap)), this.items.changes.pipe(startWith(this.items)))\n        .pipe(takeUntil(this.onDestroy))\n        .subscribe(([index, items]) => {\n          this.activeIndex = index;\n          if (index === null || index >= items.length) {\n            return;\n          }\n\n          const e = items.toArray()[index].nativeElement;\n          const p = e.offsetParent;\n\n          const eRect = e.getBoundingClientRect();\n          const pRect = p.getBoundingClientRect();\n\n          const isInViewport = eRect.top >= pRect.top && eRect.bottom <= pRect.bottom;\n\n          if (!isInViewport) {\n            p.scrollTop += eRect.top - pRect.top - p.clientHeight / 2;\n          }\n        });\n    }\n  }\n\n  ngOnDestroy() {\n    this.onDestroy.next(null);\n  }\n\n  toggle(canScroll = true) {\n    this.isCollapsed = !this.isCollapsed;\n    if (canScroll && this.isCollapsed) {\n      this.toTop();\n    }\n  }\n\n  toTop() {\n    this.scrollService.scrollToTop();\n  }\n}\n\nfunction count<T>(array: T[], fn: (item: T) => boolean) {\n  return array.reduce((result, item) => (fn(item) ? result + 1 : result), 0);\n}\n"
  },
  {
    "path": "apps/rxjs.dev/src/app/custom-elements/toc/toc.module.ts",
    "content": "import { NgModule, Type } from '@angular/core';\nimport { CommonModule } from '@angular/common';\nimport { MatIconModule } from '@angular/material/icon';\nimport { WithCustomElementComponent } from '../element-registry';\nimport { TocComponent } from './toc.component';\n\n@NgModule({\n  imports: [ CommonModule, MatIconModule ],\n  declarations: [ TocComponent ]\n})\nexport class TocModule implements WithCustomElementComponent {\n  customElementComponent: Type<any> = TocComponent;\n}\n"
  },
  {
    "path": "apps/rxjs.dev/src/app/documents/document-contents.ts",
    "content": "export interface DocumentContents {\n  /** The unique identifier for this document */\n  id: string;\n  /** The HTML to display in the doc viewer */\n  contents: string|null;\n}\n"
  },
  {
    "path": "apps/rxjs.dev/src/app/documents/document.service.spec.ts",
    "content": "import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing';\nimport { TestBed } from '@angular/core/testing';\n\nimport { Subscription } from 'rxjs';\n\nimport { LocationService } from 'app/shared/location.service';\nimport { MockLocationService } from 'testing/location.service';\nimport { Logger } from 'app/shared/logger.service';\nimport { MockLogger } from 'testing/logger.service';\nimport { DocumentService, DocumentContents, FETCHING_ERROR_ID, FILE_NOT_FOUND_ID } from './document.service';\n\nconst CONTENT_URL_PREFIX = 'generated/docs/';\n\ndescribe('DocumentService', () => {\n  let httpMock: HttpTestingController;\n\n  function createInjector(initialUrl: string) {\n    return TestBed.configureTestingModule({\n      imports: [HttpClientTestingModule],\n      providers: [\n        DocumentService,\n        { provide: LocationService, useFactory: () => new MockLocationService(initialUrl) },\n        { provide: Logger, useClass: MockLogger },\n      ],\n    });\n  }\n\n  function getServices(initialUrl: string = '') {\n    const injector = createInjector(initialUrl);\n    httpMock = injector.get(HttpTestingController) as HttpTestingController;\n    return {\n      locationService: injector.get(LocationService) as MockLocationService,\n      docService: injector.get(DocumentService) as DocumentService,\n      logger: injector.get(Logger) as MockLogger,\n    };\n  }\n\n  afterEach(() => httpMock.verify());\n\n  describe('currentDocument', () => {\n    it('should fetch a document for the initial location', () => {\n      const { docService } = getServices('initial/doc');\n      docService.currentDocument.subscribe();\n\n      httpMock.expectOne(CONTENT_URL_PREFIX + 'initial/doc.json');\n    });\n\n    it('should emit a document each time the location changes', () => {\n      let latestDocument: DocumentContents | undefined;\n      const doc0 = { contents: 'doc 0', id: 'initial/doc' };\n      const doc1 = { contents: 'doc 1', id: 'new/doc' };\n      const { docService, locationService } = getServices('initial/doc');\n\n      docService.currentDocument.subscribe((doc) => (latestDocument = doc));\n      expect(latestDocument).toBeUndefined();\n\n      httpMock.expectOne({}).flush(doc0);\n      expect(latestDocument).toEqual(doc0);\n\n      locationService.go('new/doc');\n      httpMock.expectOne({}).flush(doc1);\n      expect(latestDocument).toEqual(doc1);\n    });\n\n    it('should emit the not-found document if the document is not found on the server', () => {\n      let currentDocument: DocumentContents | undefined;\n      const notFoundDoc = { id: FILE_NOT_FOUND_ID, contents: '<h1>Page Not Found</h1>' };\n      const { docService, logger } = getServices('missing/doc');\n      docService.currentDocument.subscribe((doc) => (currentDocument = doc));\n\n      // Initial request return 404.\n      httpMock.expectOne({}).flush(null, { status: 404, statusText: 'NOT FOUND' });\n      expect(logger.output.error).toEqual([[jasmine.any(Error)]]);\n      expect(logger.output.error[0][0].message).toEqual(\"Document file not found at 'missing/doc'\");\n\n      // Subsequent request for not-found document.\n      logger.output.error = [];\n      httpMock.expectOne(CONTENT_URL_PREFIX + 'file-not-found.json').flush(notFoundDoc);\n      expect(logger.output.error).toEqual([]); // does not report repeated errors\n      expect(currentDocument).toEqual(notFoundDoc);\n    });\n\n    it('should emit a hard-coded not-found document if the not-found document is not found on the server', () => {\n      let currentDocument: DocumentContents | undefined;\n      const hardCodedNotFoundDoc = { contents: 'Document not found', id: FILE_NOT_FOUND_ID };\n      const nextDoc = { contents: 'Next Doc', id: 'new/doc' };\n      const { docService, locationService } = getServices(FILE_NOT_FOUND_ID);\n\n      docService.currentDocument.subscribe((doc) => (currentDocument = doc));\n\n      httpMock.expectOne({}).flush(null, { status: 404, statusText: 'NOT FOUND' });\n      expect(currentDocument).toEqual(hardCodedNotFoundDoc);\n\n      // now check that we haven't killed the currentDocument observable sequence\n      locationService.go('new/doc');\n      httpMock.expectOne({}).flush(nextDoc);\n      expect(currentDocument).toEqual(nextDoc);\n    });\n\n    it('should use a hard-coded error doc if the request fails (but not cache it)', () => {\n      let latestDocument!: DocumentContents;\n      const doc1 = { contents: 'doc 1' } as DocumentContents;\n      const doc2 = { contents: 'doc 2' } as DocumentContents;\n      const { docService, locationService, logger } = getServices('initial/doc');\n\n      docService.currentDocument.subscribe((doc) => (latestDocument = doc));\n\n      httpMock.expectOne({}).flush(null, { status: 500, statusText: 'Server Error' });\n      expect(latestDocument.id).toEqual(FETCHING_ERROR_ID);\n      expect(logger.output.error).toEqual([[jasmine.any(Error)]]);\n      expect(logger.output.error[0][0].message).toEqual(\n        \"Error fetching document 'initial/doc': (Http failure response for generated/docs/initial/doc.json: 500 Server Error)\"\n      );\n\n      locationService.go('new/doc');\n      httpMock.expectOne({}).flush(doc1);\n      expect(latestDocument).toEqual(jasmine.objectContaining(doc1));\n\n      locationService.go('initial/doc');\n      httpMock.expectOne({}).flush(doc2);\n      expect(latestDocument).toEqual(jasmine.objectContaining(doc2));\n    });\n\n    it('should not crash the app if the response is invalid JSON', () => {\n      let latestDocument!: DocumentContents;\n      const doc1 = { contents: 'doc 1' } as DocumentContents;\n      const { docService, locationService } = getServices('initial/doc');\n\n      docService.currentDocument.subscribe((doc) => (latestDocument = doc));\n\n      httpMock.expectOne({}).flush('this is invalid JSON');\n      expect(latestDocument.id).toEqual(FETCHING_ERROR_ID);\n\n      locationService.go('new/doc');\n      httpMock.expectOne({}).flush(doc1);\n      expect(latestDocument).toEqual(jasmine.objectContaining(doc1));\n    });\n\n    it('should not make a request to the server if the doc is in the cache already', () => {\n      let latestDocument!: DocumentContents;\n      let subscription: Subscription;\n\n      const doc0 = { contents: 'doc 0' } as DocumentContents;\n      const doc1 = { contents: 'doc 1' } as DocumentContents;\n      const { docService, locationService } = getServices('url/0');\n\n      subscription = docService.currentDocument.subscribe((doc) => (latestDocument = doc));\n      httpMock.expectOne({}).flush(doc0);\n      expect(latestDocument).toEqual(jasmine.objectContaining(doc0));\n      subscription.unsubscribe();\n\n      subscription = docService.currentDocument.subscribe((doc) => (latestDocument = doc));\n      locationService.go('url/1');\n      httpMock.expectOne({}).flush(doc1);\n      expect(latestDocument).toEqual(jasmine.objectContaining(doc1));\n      subscription.unsubscribe();\n\n      // This should not trigger a new request.\n      subscription = docService.currentDocument.subscribe((doc) => (latestDocument = doc));\n      locationService.go('url/0');\n      httpMock.expectNone({});\n      expect(latestDocument).toEqual(jasmine.objectContaining(doc0));\n      subscription.unsubscribe();\n\n      // This should not trigger a new request.\n      subscription = docService.currentDocument.subscribe((doc) => (latestDocument = doc));\n      locationService.go('url/1');\n      httpMock.expectNone({});\n      expect(latestDocument).toEqual(jasmine.objectContaining(doc1));\n      subscription.unsubscribe();\n    });\n  });\n\n  describe('computeMap', () => {\n    it('should map the \"empty\" location to the correct document request', () => {\n      const { docService } = getServices();\n      docService.currentDocument.subscribe();\n\n      httpMock.expectOne(CONTENT_URL_PREFIX + 'index.json');\n    });\n\n    it('should map the \"folder\" locations to the correct document request', () => {\n      const { docService } = getServices('guide');\n      docService.currentDocument.subscribe();\n\n      httpMock.expectOne(CONTENT_URL_PREFIX + 'guide.json');\n    });\n  });\n});\n"
  },
  {
    "path": "apps/rxjs.dev/src/app/documents/document.service.ts",
    "content": "import { Injectable } from '@angular/core';\nimport { HttpClient, HttpErrorResponse } from '@angular/common/http';\n\nimport { AsyncSubject, Observable, of } from 'rxjs';\nimport { catchError, switchMap, tap } from 'rxjs/operators';\n\nimport { DocumentContents } from './document-contents';\nexport { DocumentContents } from './document-contents';\n\nimport { LocationService } from 'app/shared/location.service';\nimport { Logger } from 'app/shared/logger.service';\n\nexport const FILE_NOT_FOUND_ID = 'file-not-found';\nexport const FETCHING_ERROR_ID = 'fetching-error';\n\nexport const CONTENT_URL_PREFIX = 'generated/';\nexport const DOC_CONTENT_URL_PREFIX = CONTENT_URL_PREFIX + 'docs/';\nconst FETCHING_ERROR_CONTENTS = (path: string) => `\n  <div class=\"nf-container l-flex-wrap flex-center\">\n    <div class=\"nf-icon material-icons\">error_outline</div>\n    <div class=\"nf-response l-flex-wrap\">\n      <h1 class=\"no-toc\">Request for document failed.</h1>\n      <p>\n        We are unable to retrieve the \"${path}\" page at this time.\n        Please check your connection and try again later.\n      </p>\n    </div>\n  </div>\n`;\n\n@Injectable()\nexport class DocumentService {\n\n  private cache = new Map<string, Observable<DocumentContents>>();\n\n  currentDocument: Observable<DocumentContents>;\n\n  constructor(\n    private logger: Logger,\n    private http: HttpClient,\n    location: LocationService) {\n    // Whenever the URL changes we try to get the appropriate doc\n    this.currentDocument = location.currentPath.pipe(switchMap(path => this.getDocument(path)));\n  }\n\n  private getDocument(url: string) {\n    const id = url || 'index';\n    this.logger.log('getting document', id);\n    if (!this.cache.has(id)) {\n      this.cache.set(id, this.fetchDocument(id));\n    }\n    return this.cache.get(id)!;\n  }\n\n  private fetchDocument(id: string): Observable<DocumentContents> {\n    const requestPath = `${DOC_CONTENT_URL_PREFIX}${id}.json`;\n    const subject = new AsyncSubject<DocumentContents>();\n\n    this.logger.log('fetching document from', requestPath);\n    this.http\n      .get<DocumentContents>(requestPath, {responseType: 'json'})\n      .pipe(\n        tap(data => {\n          if (!data || typeof data !== 'object') {\n            this.logger.log('received invalid data:', data);\n            throw Error('Invalid data');\n          }\n        }),\n        catchError((error: HttpErrorResponse) => error.status === 404 ? this.getFileNotFoundDoc(id) : this.getErrorDoc(id, error)),\n      )\n      .subscribe(subject);\n\n    return subject.asObservable();\n  }\n\n  private getFileNotFoundDoc(id: string): Observable<DocumentContents> {\n    if (id !== FILE_NOT_FOUND_ID) {\n      this.logger.error(new Error(`Document file not found at '${id}'`));\n      // using `getDocument` means that we can fetch the 404 doc contents from the server and cache it\n      return this.getDocument(FILE_NOT_FOUND_ID);\n    } else {\n      return of({\n        id: FILE_NOT_FOUND_ID,\n        contents: 'Document not found'\n      });\n    }\n  }\n\n  private getErrorDoc(id: string, error: HttpErrorResponse): Observable<DocumentContents> {\n    this.logger.error(new Error(`Error fetching document '${id}': (${error.message})`));\n    this.cache.delete(id);\n    return of({\n      id: FETCHING_ERROR_ID,\n      contents: FETCHING_ERROR_CONTENTS(id),\n    });\n  }\n}\n"
  },
  {
    "path": "apps/rxjs.dev/src/app/layout/doc-viewer/doc-viewer.component.spec.ts",
    "content": "import { ComponentFixture, TestBed } from '@angular/core/testing';\nimport { Meta, Title } from '@angular/platform-browser';\n\nimport { Observable, asapScheduler, of } from 'rxjs';\n\nimport { FILE_NOT_FOUND_ID, FETCHING_ERROR_ID } from 'app/documents/document.service';\nimport { Logger } from 'app/shared/logger.service';\nimport { CustomElementsModule } from 'app/custom-elements/custom-elements.module';\nimport { TocService } from 'app/shared/toc.service';\nimport { ElementsLoader } from 'app/custom-elements/elements-loader';\nimport {\nMockTitle, MockTocService, ObservableWithSubscriptionSpies,\nTestDocViewerComponent, TestModule, TestParentComponent, MockElementsLoader\n} from 'testing/doc-viewer-utils';\nimport { MockLogger } from 'testing/logger.service';\nimport { DocViewerComponent, NO_ANIMATIONS } from './doc-viewer.component';\n\ndescribe('DocViewerComponent', () => {\n  let parentFixture: ComponentFixture<TestParentComponent>;\n  let parentComponent: TestParentComponent;\n  let docViewerEl: HTMLElement;\n  let docViewer: TestDocViewerComponent;\n  let metaServiceMock: jasmine.SpyObj<Meta>;\n\n  const safeFlushAsapScheduler = () => asapScheduler.actions.length && asapScheduler.flush();\n\n  beforeEach(() => {\n    metaServiceMock = jasmine.createSpyObj(['updateTag', 'addTag', 'removeTag']);\n    TestBed.configureTestingModule({\n      imports: [CustomElementsModule, TestModule],\n      providers: [{provide: Meta, useValue: metaServiceMock}]\n    });\n\n    parentFixture = TestBed.createComponent(TestParentComponent);\n    parentComponent = parentFixture.componentInstance;\n\n    parentFixture.detectChanges();\n\n    docViewerEl = parentFixture.debugElement.children[0].nativeElement;\n    docViewer = parentComponent.docViewer as any;\n  });\n\n  it('should create a `DocViewer`', () => {\n    expect(docViewer).toEqual(jasmine.any(DocViewerComponent));\n  });\n\n  describe('#doc', () => {\n    let renderSpy: jasmine.Spy;\n\n    const setCurrentDoc = (newDoc: TestParentComponent['currentDoc']) => {\n\n      parentComponent.currentDoc =  newDoc; // set default with id if parameter is not defined\n      parentFixture.detectChanges();  // Run change detection to propagate the new doc to `DocViewer`.\n      safeFlushAsapScheduler();  // Flush `asapScheduler` to trigger `DocViewer#render()`.\n    };\n\n    beforeEach(() => renderSpy = spyOn(docViewer, 'render').and.callFake(() => of(undefined)));\n\n    it('should render the new document', () => {\n      setCurrentDoc({contents: 'foo', id: 'bar'});\n      expect(renderSpy).toHaveBeenCalledTimes(1);\n      expect(renderSpy.calls.mostRecent().args).toEqual([{id: 'bar', contents: 'foo'}]);\n\n      setCurrentDoc({contents: null, id: 'baz'});\n      expect(renderSpy).toHaveBeenCalledTimes(2);\n      expect(renderSpy.calls.mostRecent().args).toEqual([{id: 'baz', contents: null}]);\n    });\n\n    it('should unsubscribe from the previous \"render\" observable upon new document', () => {\n      const obs = new ObservableWithSubscriptionSpies();\n      renderSpy.and.returnValue(obs);\n\n      setCurrentDoc({contents: 'foo', id: 'bar'});\n      expect(obs.subscribeSpy).toHaveBeenCalledTimes(1);\n      expect(obs.unsubscribeSpies[0]).not.toHaveBeenCalled();\n\n      setCurrentDoc({contents: 'baz', id: 'qux'});\n      expect(obs.subscribeSpy).toHaveBeenCalledTimes(2);\n      expect(obs.unsubscribeSpies[0]).toHaveBeenCalledTimes(1);\n    });\n\n    it('should ignore falsy document values', () => {\n      setCurrentDoc(null);\n      expect(renderSpy).not.toHaveBeenCalled();\n\n      setCurrentDoc(undefined);\n      expect(renderSpy).not.toHaveBeenCalled();\n    });\n  });\n\n  describe('#ngOnDestroy()', () => {\n    it('should stop responding to document changes', () => {\n      const renderSpy = spyOn(docViewer, 'render').and.callFake(() => of(undefined));\n\n      expect(renderSpy).not.toHaveBeenCalled();\n\n      docViewer.doc = {contents: 'Some content', id: 'some-id'};\n      safeFlushAsapScheduler();\n      expect(renderSpy).toHaveBeenCalledTimes(1);\n\n      docViewer.ngOnDestroy();\n\n      docViewer.doc = {contents: 'Other content', id: 'other-id'};\n      safeFlushAsapScheduler();\n      expect(renderSpy).toHaveBeenCalledTimes(1);\n\n      docViewer.doc = {contents: 'More content', id: 'more-id'};\n      safeFlushAsapScheduler();\n      expect(renderSpy).toHaveBeenCalledTimes(1);\n    });\n  });\n\n  describe('#prepareTitleAndToc()', () => {\n    const EMPTY_DOC = '';\n    const DOC_WITHOUT_H1 = 'Some content';\n    const DOC_WITH_H1 = '<h1>Features</h1>Some content';\n    const DOC_WITH_NO_TOC_H1 = '<h1 class=\"no-toc\">Features</h1>Some content';\n    const DOC_WITH_EMBEDDED_TOC = '<h1>Features</h1><aio-toc class=\"embedded\"></aio-toc>Some content';\n    const DOC_WITH_EMBEDDED_TOC_WITHOUT_H1 = '<aio-toc class=\"embedded\"></aio-toc>Some content';\n    const DOC_WITH_EMBEDDED_TOC_WITH_NO_TOC_H1 = '<aio-toc class=\"embedded\"></aio-toc>Some content';\n    const DOC_WITH_HIDDEN_H1_CONTENT = '<h1><i style=\"visibility: hidden\">link</i>Features</h1>Some content';\n    let titleService: MockTitle;\n    let tocService: MockTocService;\n    let targetEl: HTMLElement;\n\n    const getTocEl = () => targetEl.querySelector('aio-toc');\n    const doPrepareTitleAndToc = (contents: string, docId = '') => {\n      targetEl.innerHTML = contents;\n      return docViewer.prepareTitleAndToc(targetEl, docId);\n    };\n    const doAddTitleAndToc = (contents: string, docId = '') => {\n      const addTitleAndToc = doPrepareTitleAndToc(contents, docId);\n      return addTitleAndToc();\n    };\n\n    beforeEach(() => {\n      titleService = TestBed.inject(Title) as unknown as MockTitle;\n      tocService = TestBed.inject(TocService) as unknown as MockTocService;\n\n      targetEl = document.createElement('div');\n      document.body.appendChild(targetEl);  // Required for `innerText` to work as expected.\n    });\n\n    afterEach(() => document.body.removeChild(targetEl));\n\n    it('should return a function for doing the actual work', () => {\n      const addTitleAndToc = doPrepareTitleAndToc(DOC_WITH_H1);\n\n      expect(getTocEl()).toBeTruthy();\n      expect(titleService.setTitle).not.toHaveBeenCalled();\n      expect(tocService.reset).not.toHaveBeenCalled();\n      expect(tocService.genToc).not.toHaveBeenCalled();\n\n      addTitleAndToc();\n\n      expect(titleService.setTitle).toHaveBeenCalledTimes(1);\n      expect(tocService.reset).toHaveBeenCalledTimes(1);\n      expect(tocService.genToc).toHaveBeenCalledTimes(1);\n    });\n\n    describe('(title)', () => {\n      it('should set the title if there is an `<h1>` heading', () => {\n        doAddTitleAndToc(DOC_WITH_H1);\n        expect(titleService.setTitle).toHaveBeenCalledWith('RxJS - Features');\n      });\n\n      it('should set the title if there is a `.no-toc` `<h1>` heading', () => {\n        doAddTitleAndToc(DOC_WITH_NO_TOC_H1);\n        expect(titleService.setTitle).toHaveBeenCalledWith('RxJS - Features');\n      });\n\n      it('should set the default title if there is no `<h1>` heading', () => {\n        doAddTitleAndToc(DOC_WITHOUT_H1);\n        expect(titleService.setTitle).toHaveBeenCalledWith('RxJS');\n\n        doAddTitleAndToc(EMPTY_DOC);\n        expect(titleService.setTitle).toHaveBeenCalledWith('RxJS');\n      });\n\n      it('should not include hidden content of the `<h1>` heading in the title', () => {\n        doAddTitleAndToc(DOC_WITH_HIDDEN_H1_CONTENT);\n        expect(titleService.setTitle).toHaveBeenCalledWith('RxJS - Features');\n      });\n\n      it('should fall back to `textContent` if `innerText` is not available', () => {\n        const querySelector = targetEl.querySelector;\n        spyOn(targetEl, 'querySelector').and.callFake((selector: string) => {\n          const elem = querySelector.call(targetEl, selector);\n          return elem && Object.defineProperties(elem, {\n            innerText: {value: undefined},\n            textContent: {value: 'Text Content'},\n          });\n        });\n\n        doAddTitleAndToc(DOC_WITH_HIDDEN_H1_CONTENT);\n\n        expect(titleService.setTitle).toHaveBeenCalledWith('RxJS - Text Content');\n      });\n\n      it('should still use `innerText` if available but empty', () => {\n        const querySelector = targetEl.querySelector;\n        spyOn(targetEl, 'querySelector').and.callFake((selector: string) => {\n          const elem = querySelector.call(targetEl, selector);\n          return elem && Object.defineProperties(elem, {\n            innerText: { value: '' },\n            textContent: { value: 'Text Content' }\n          });\n        });\n\n        doAddTitleAndToc(DOC_WITH_HIDDEN_H1_CONTENT);\n\n        expect(titleService.setTitle).toHaveBeenCalledWith('RxJS');\n      });\n    });\n\n    describe('(ToC)', () => {\n      describe('needed', () => {\n        it('should add an embedded ToC element if there is an `<h1>` heading', () => {\n          doPrepareTitleAndToc(DOC_WITH_H1);\n          const tocEl = getTocEl()!;\n\n          expect(tocEl).toBeTruthy();\n          expect(tocEl.classList.contains('embedded')).toBe(true);\n        });\n\n        it('should not add a second ToC element if there a hard coded one in place', () => {\n          doPrepareTitleAndToc(DOC_WITH_EMBEDDED_TOC);\n          expect(targetEl.querySelectorAll('aio-toc').length).toEqual(1);\n        });\n      });\n\n\n      describe('not needed', () => {\n        it('should not add a ToC element if there is a `.no-toc` `<h1>` heading', () => {\n          doPrepareTitleAndToc(DOC_WITH_NO_TOC_H1);\n          expect(getTocEl()).toBeFalsy();\n        });\n\n        it('should not add a ToC element if there is no `<h1>` heading', () => {\n          doPrepareTitleAndToc(DOC_WITHOUT_H1);\n          expect(getTocEl()).toBeFalsy();\n\n          doPrepareTitleAndToc(EMPTY_DOC);\n          expect(getTocEl()).toBeFalsy();\n        });\n\n        it('should remove ToC a hard coded one', () => {\n          doPrepareTitleAndToc(DOC_WITH_EMBEDDED_TOC_WITHOUT_H1);\n          expect(getTocEl()).toBeFalsy();\n\n          doPrepareTitleAndToc(DOC_WITH_EMBEDDED_TOC_WITH_NO_TOC_H1);\n          expect(getTocEl()).toBeFalsy();\n        });\n      });\n\n\n      it('should generate ToC entries if there is an `<h1>` heading', () => {\n        doAddTitleAndToc(DOC_WITH_H1, 'foo');\n\n        expect(tocService.genToc).toHaveBeenCalledTimes(1);\n        expect(tocService.genToc).toHaveBeenCalledWith(targetEl, 'foo');\n      });\n\n      it('should not generate ToC entries if there is a `.no-toc` `<h1>` heading', () => {\n        doAddTitleAndToc(DOC_WITH_NO_TOC_H1);\n        expect(tocService.genToc).not.toHaveBeenCalled();\n      });\n\n      it('should not generate ToC entries if there is no `<h1>` heading', () => {\n        doAddTitleAndToc(DOC_WITHOUT_H1);\n        doAddTitleAndToc(EMPTY_DOC);\n\n        expect(tocService.genToc).not.toHaveBeenCalled();\n      });\n\n      it('should always reset the ToC (before generating the new one)', () => {\n        doAddTitleAndToc(DOC_WITH_H1, 'foo');\n        expect(tocService.reset).toHaveBeenCalledTimes(1);\n        expect(tocService.reset).toHaveBeenCalledBefore(tocService.genToc);\n        expect(tocService.genToc).toHaveBeenCalledWith(targetEl, 'foo');\n\n        tocService.genToc.calls.reset();\n\n        doAddTitleAndToc(DOC_WITH_NO_TOC_H1, 'bar');\n        expect(tocService.reset).toHaveBeenCalledTimes(2);\n        expect(tocService.genToc).not.toHaveBeenCalled();\n\n        doAddTitleAndToc(DOC_WITHOUT_H1, 'baz');\n        expect(tocService.reset).toHaveBeenCalledTimes(3);\n        expect(tocService.genToc).not.toHaveBeenCalled();\n\n        doAddTitleAndToc(EMPTY_DOC, 'qux');\n        expect(tocService.reset).toHaveBeenCalledTimes(4);\n        expect(tocService.genToc).not.toHaveBeenCalled();\n      });\n    });\n  });\n\n  describe('#render()', () => {\n    let prepareTitleAndTocSpy: jasmine.Spy;\n    let swapViewsSpy: jasmine.Spy;\n    let loadElementsSpy: jasmine.Spy;\n\n    const doRender = (contents: string | null, id = 'foo') =>\n      docViewer.render({contents, id}).toPromise();\n\n    beforeEach(() => {\n      const elementsLoader = TestBed.inject(ElementsLoader) as Partial<ElementsLoader> as MockElementsLoader;\n      loadElementsSpy = elementsLoader.loadContainedCustomElements.and.callFake(() => of(undefined));\n      prepareTitleAndTocSpy = spyOn(docViewer, 'prepareTitleAndToc');\n      swapViewsSpy = spyOn(docViewer, 'swapViews').and.callFake(() => of(undefined));\n    });\n\n    it('should return an `Observable`', () => {\n      expect(docViewer.render({contents: '', id: ''})).toEqual(jasmine.any(Observable));\n    });\n\n    describe('(contents, title, ToC)', () => {\n      beforeEach(() => swapViewsSpy.and.callThrough());\n\n      it('should display the document contents', async () => {\n        const contents = '<h1>Hello,</h1> <div>world!</div>';\n        await doRender(contents);\n\n        expect(docViewerEl.innerHTML).toContain(contents);\n        expect(docViewerEl.textContent).toBe('Hello, world!');\n      });\n\n      it('should display nothing if the document has no contents', async () => {\n        await doRender('Test');\n        expect(docViewerEl.textContent).toBe('Test');\n\n        await doRender('');\n        expect(docViewerEl.textContent).toBe('');\n\n        docViewer.currViewContainer.innerHTML = 'Test';\n        expect(docViewerEl.textContent).toBe('Test');\n\n        await doRender(null);\n        expect(docViewerEl.textContent).toBe('');\n      });\n\n      it('should prepare the title and ToC (before embedding components)', async () => {\n        prepareTitleAndTocSpy.and.callFake((targetEl: HTMLElement, docId: string) => {\n          expect(targetEl.innerHTML).toBe('Some content');\n          expect(docId).toBe('foo');\n        });\n\n        await doRender('Some content', 'foo');\n\n        expect(prepareTitleAndTocSpy).toHaveBeenCalledTimes(1);\n        expect(prepareTitleAndTocSpy).toHaveBeenCalledBefore(loadElementsSpy);\n      });\n\n      it('should set the title and ToC (after the content has been set)', async () => {\n        const addTitleAndTocSpy = jasmine.createSpy('addTitleAndToc');\n        prepareTitleAndTocSpy.and.returnValue(addTitleAndTocSpy);\n\n        addTitleAndTocSpy.and.callFake(() => expect(docViewerEl.textContent).toBe('Foo content'));\n        await doRender('Foo content');\n        expect(addTitleAndTocSpy).toHaveBeenCalledTimes(1);\n\n        addTitleAndTocSpy.and.callFake(() => expect(docViewerEl.textContent).toBe('Bar content'));\n        await doRender('Bar content');\n        expect(addTitleAndTocSpy).toHaveBeenCalledTimes(2);\n\n        addTitleAndTocSpy.and.callFake(() => expect(docViewerEl.textContent).toBe(''));\n        await doRender('');\n        expect(addTitleAndTocSpy).toHaveBeenCalledTimes(3);\n\n        addTitleAndTocSpy.and.callFake(() => expect(docViewerEl.textContent).toBe('Qux content'));\n        await doRender('Qux content');\n        expect(addTitleAndTocSpy).toHaveBeenCalledTimes(4);\n      });\n\n      it('should remove the \"noindex\" meta tag if the document is valid', async () => {\n        await doRender('foo', 'bar');\n        expect(TestBed.inject(Meta).removeTag).toHaveBeenCalledWith('name=\"robots\"');\n      });\n\n      it('should add the \"noindex\" meta tag if the document is 404', async () => {\n        await doRender('missing', FILE_NOT_FOUND_ID);\n        expect(TestBed.inject(Meta).addTag).toHaveBeenCalledWith({ name: 'robots', content: 'noindex' });\n      });\n\n      it('should add a \"noindex\" meta tag if the document fetching fails', async () => {\n        await doRender('error', FETCHING_ERROR_ID);\n        expect(TestBed.inject(Meta).addTag).toHaveBeenCalledWith({ name: 'robots', content: 'noindex' });\n      });\n    });\n\n    describe('(embedding components)', () => {\n      it('should embed components', async () => {\n        await doRender('Some content');\n        expect(loadElementsSpy).toHaveBeenCalledTimes(1);\n        expect(loadElementsSpy).toHaveBeenCalledWith(docViewer.nextViewContainer);\n      });\n\n      it('should attempt to embed components even if the document is empty', async () => {\n        await doRender('');\n        await doRender(null);\n\n        expect(loadElementsSpy).toHaveBeenCalledTimes(2);\n        expect(loadElementsSpy.calls.argsFor(0)).toEqual([docViewer.nextViewContainer]);\n        expect(loadElementsSpy.calls.argsFor(1)).toEqual([docViewer.nextViewContainer]);\n      });\n\n      it('should unsubscribe from the previous \"embed\" observable when unsubscribed from', () => {\n        const obs = new ObservableWithSubscriptionSpies();\n        loadElementsSpy.and.returnValue(obs);\n\n        const renderObservable = docViewer.render({contents: 'Some content', id: 'foo'});\n        const subscription = renderObservable.subscribe();\n\n        expect(obs.subscribeSpy).toHaveBeenCalledTimes(1);\n        expect(obs.unsubscribeSpies[0]).not.toHaveBeenCalled();\n\n        subscription.unsubscribe();\n\n        expect(obs.subscribeSpy).toHaveBeenCalledTimes(1);\n        expect(obs.unsubscribeSpies[0]).toHaveBeenCalledTimes(1);\n      });\n    });\n\n    describe('(swapping views)', () => {\n      it('should still swap the views if the document is empty', async () => {\n        await doRender('');\n        expect(swapViewsSpy).toHaveBeenCalledTimes(1);\n\n        await doRender(null);\n        expect(swapViewsSpy).toHaveBeenCalledTimes(2);\n      });\n\n      it('should pass the `addTitleAndToc` callback', async () => {\n        const addTitleAndTocSpy = jasmine.createSpy('addTitleAndToc');\n        prepareTitleAndTocSpy.and.returnValue(addTitleAndTocSpy);\n\n        await doRender('<div></div>');\n\n        expect(swapViewsSpy).toHaveBeenCalledWith(addTitleAndTocSpy);\n      });\n\n      it('should unsubscribe from the previous \"swap\" observable when unsubscribed from', () => {\n        const obs = new ObservableWithSubscriptionSpies();\n        swapViewsSpy.and.returnValue(obs);\n\n        const renderObservable = docViewer.render({contents: 'Hello, world!', id: 'foo'});\n        const subscription = renderObservable.subscribe();\n\n        expect(obs.subscribeSpy).toHaveBeenCalledTimes(1);\n        expect(obs.unsubscribeSpies[0]).not.toHaveBeenCalled();\n\n        subscription.unsubscribe();\n\n        expect(obs.subscribeSpy).toHaveBeenCalledTimes(1);\n        expect(obs.unsubscribeSpies[0]).toHaveBeenCalledTimes(1);\n      });\n    });\n\n    describe('(on error) should clean up, log the error and recover', () => {\n      let logger: MockLogger;\n\n      beforeEach(() => {\n        logger = TestBed.inject(Logger) as unknown as MockLogger;\n      });\n\n      it('when `prepareTitleAndTocSpy()` fails', async () => {\n        const error = Error('Typical `prepareTitleAndToc()` error');\n        prepareTitleAndTocSpy.and.callFake(() => {\n          expect(docViewer.nextViewContainer.innerHTML).not.toBe('');\n          throw error;\n        });\n\n        await doRender('Some content', 'foo');\n\n        expect(prepareTitleAndTocSpy).toHaveBeenCalledTimes(1);\n        expect(swapViewsSpy).not.toHaveBeenCalled();\n        expect(docViewer.nextViewContainer.innerHTML).toBe('');\n        expect(logger.output.error).toEqual([\n          [jasmine.any(Error)]\n        ]);\n        expect(logger.output.error[0][0].message).toEqual(`[DocViewer] Error preparing document 'foo': ${error.stack}`);\n        expect(TestBed.inject(Meta).addTag).toHaveBeenCalledWith({ name: 'robots', content: 'noindex' });\n      });\n\n      it('when `EmbedComponentsService.embedInto()` fails', async () => {\n        const error = Error('Typical `embedInto()` error');\n        loadElementsSpy.and.callFake(() => {\n          expect(docViewer.nextViewContainer.innerHTML).not.toBe('');\n          throw error;\n        });\n\n        await doRender('Some content', 'bar');\n\n        expect(prepareTitleAndTocSpy).toHaveBeenCalledTimes(1);\n        expect(loadElementsSpy).toHaveBeenCalledTimes(1);\n        expect(swapViewsSpy).not.toHaveBeenCalled();\n        expect(docViewer.nextViewContainer.innerHTML).toBe('');\n        expect(logger.output.error).toEqual([\n          [jasmine.any(Error)]\n        ]);\n        expect(TestBed.inject(Meta).addTag).toHaveBeenCalledWith({ name: 'robots', content: 'noindex' });\n      });\n\n      it('when `swapViews()` fails', async () => {\n        const error = Error('Typical `swapViews()` error');\n        swapViewsSpy.and.callFake(() => {\n          expect(docViewer.nextViewContainer.innerHTML).not.toBe('');\n          throw error;\n        });\n\n        await doRender('Some content', 'qux');\n\n        expect(prepareTitleAndTocSpy).toHaveBeenCalledTimes(1);\n        expect(swapViewsSpy).toHaveBeenCalledTimes(1);\n        expect(docViewer.nextViewContainer.innerHTML).toBe('');\n        expect(logger.output.error).toEqual([\n          [jasmine.any(Error)]\n        ]);\n        expect(logger.output.error[0][0].message).toEqual(`[DocViewer] Error preparing document 'qux': ${error.stack}`);\n        expect(TestBed.inject(Meta).addTag).toHaveBeenCalledWith({ name: 'robots', content: 'noindex' });\n      });\n\n      it('when something fails with non-Error', async () => {\n        const error = 'Typical string error';\n        swapViewsSpy.and.callFake(() => {\n          expect(docViewer.nextViewContainer.innerHTML).not.toBe('');\n          throw error;\n        });\n\n        await doRender('Some content', 'qux');\n\n        expect(swapViewsSpy).toHaveBeenCalledTimes(1);\n        expect(docViewer.nextViewContainer.innerHTML).toBe('');\n        expect(logger.output.error).toEqual([\n          [jasmine.any(Error)]\n        ]);\n        expect(logger.output.error[0][0].message).toEqual(`[DocViewer] Error preparing document 'qux': ${error}`);\n        expect(TestBed.inject(Meta).addTag).toHaveBeenCalledWith({ name: 'robots', content: 'noindex' });\n      });\n    });\n\n    describe('(events)', () => {\n      it('should emit `docReady` after loading elements', async () => {\n        const onDocReadySpy = jasmine.createSpy('onDocReady');\n        docViewer.docReady.subscribe(onDocReadySpy);\n\n        await doRender('Some content');\n\n        expect(onDocReadySpy).toHaveBeenCalledTimes(1);\n        expect(loadElementsSpy).toHaveBeenCalledBefore(onDocReadySpy);\n      });\n\n      it('should emit `docReady` before swapping views', async () => {\n        const onDocReadySpy = jasmine.createSpy('onDocReady');\n        docViewer.docReady.subscribe(onDocReadySpy);\n\n        await doRender('Some content');\n\n        expect(onDocReadySpy).toHaveBeenCalledTimes(1);\n        expect(onDocReadySpy).toHaveBeenCalledBefore(swapViewsSpy);\n      });\n\n      it('should emit `docRendered` after swapping views', async () => {\n        const onDocRenderedSpy = jasmine.createSpy('onDocRendered');\n        docViewer.docRendered.subscribe(onDocRenderedSpy);\n\n        await doRender('Some content');\n\n        expect(onDocRenderedSpy).toHaveBeenCalledTimes(1);\n        expect(swapViewsSpy).toHaveBeenCalledBefore(onDocRenderedSpy);\n      });\n    });\n  });\n\n  describe('#swapViews()', () => {\n    let oldCurrViewContainer: HTMLElement;\n    let oldNextViewContainer: HTMLElement;\n\n    const doSwapViews = (cb?: () => void) => docViewer.swapViews(cb).toPromise();\n\n    beforeEach(() => {\n      oldCurrViewContainer = docViewer.currViewContainer;\n      oldNextViewContainer = docViewer.nextViewContainer;\n\n      oldCurrViewContainer.innerHTML = 'Current view';\n      oldNextViewContainer.innerHTML = 'Next view';\n\n      docViewerEl.appendChild(oldCurrViewContainer);\n\n      expect(docViewerEl.contains(oldCurrViewContainer)).toBe(true);\n      expect(docViewerEl.contains(oldNextViewContainer)).toBe(false);\n    });\n\n    [true, false].forEach(animationsEnabled => {\n      describe(`(animationsEnabled: ${animationsEnabled})`, () => {\n        beforeEach(() => DocViewerComponent.animationsEnabled = animationsEnabled);\n        afterEach(() => DocViewerComponent.animationsEnabled = true);\n\n        [true, false].forEach(noAnimations => {\n          describe(`(.${NO_ANIMATIONS}: ${noAnimations})`, () => {\n            beforeEach(() => docViewerEl.classList[noAnimations ? 'add' : 'remove'](NO_ANIMATIONS));\n\n            it('should return an observable', done => {\n              docViewer.swapViews().subscribe(done, done.fail);\n            });\n\n            it('should swap the views', async () => {\n              await doSwapViews();\n\n              expect(docViewerEl.contains(oldCurrViewContainer)).toBe(false);\n              expect(docViewerEl.contains(oldNextViewContainer)).toBe(true);\n              expect(docViewer.currViewContainer).toBe(oldNextViewContainer);\n              expect(docViewer.nextViewContainer).toBe(oldCurrViewContainer);\n\n              await doSwapViews();\n\n              expect(docViewerEl.contains(oldCurrViewContainer)).toBe(true);\n              expect(docViewerEl.contains(oldNextViewContainer)).toBe(false);\n              expect(docViewer.currViewContainer).toBe(oldCurrViewContainer);\n              expect(docViewer.nextViewContainer).toBe(oldNextViewContainer);\n            });\n\n            it('should emit `docRemoved` after removing the leaving view', async () => {\n              const onDocRemovedSpy = jasmine.createSpy('onDocRemoved').and.callFake(() => {\n                expect(docViewerEl.contains(oldCurrViewContainer)).toBe(false);\n                expect(docViewerEl.contains(oldNextViewContainer)).toBe(false);\n              });\n\n              docViewer.docRemoved.subscribe(onDocRemovedSpy);\n\n              expect(docViewerEl.contains(oldCurrViewContainer)).toBe(true);\n              expect(docViewerEl.contains(oldNextViewContainer)).toBe(false);\n\n              await doSwapViews();\n\n              expect(onDocRemovedSpy).toHaveBeenCalledTimes(1);\n              expect(docViewerEl.contains(oldCurrViewContainer)).toBe(false);\n              expect(docViewerEl.contains(oldNextViewContainer)).toBe(true);\n            });\n\n            it('should not emit `docRemoved` if the leaving view is already removed', async () => {\n              const onDocRemovedSpy = jasmine.createSpy('onDocRemoved');\n\n              docViewer.docRemoved.subscribe(onDocRemovedSpy);\n              docViewerEl.removeChild(oldCurrViewContainer);\n\n              await doSwapViews();\n\n              expect(onDocRemovedSpy).not.toHaveBeenCalled();\n            });\n\n            it('should emit `docInserted` after inserting the entering view', async () => {\n              const onDocInsertedSpy = jasmine.createSpy('onDocInserted').and.callFake(() => {\n                expect(docViewerEl.contains(oldCurrViewContainer)).toBe(false);\n                expect(docViewerEl.contains(oldNextViewContainer)).toBe(true);\n              });\n\n              docViewer.docInserted.subscribe(onDocInsertedSpy);\n\n              expect(docViewerEl.contains(oldCurrViewContainer)).toBe(true);\n              expect(docViewerEl.contains(oldNextViewContainer)).toBe(false);\n\n              await doSwapViews();\n\n              expect(onDocInsertedSpy).toHaveBeenCalledTimes(1);\n              expect(docViewerEl.contains(oldCurrViewContainer)).toBe(false);\n              expect(docViewerEl.contains(oldNextViewContainer)).toBe(true);\n            });\n\n            it('should call the callback after inserting the entering view', async () => {\n              const onInsertedCb = jasmine.createSpy('onInsertedCb').and.callFake(() => {\n                expect(docViewerEl.contains(oldCurrViewContainer)).toBe(false);\n                expect(docViewerEl.contains(oldNextViewContainer)).toBe(true);\n              });\n              const onDocInsertedSpy = jasmine.createSpy('onDocInserted');\n\n              docViewer.docInserted.subscribe(onDocInsertedSpy);\n\n              expect(docViewerEl.contains(oldCurrViewContainer)).toBe(true);\n              expect(docViewerEl.contains(oldNextViewContainer)).toBe(false);\n\n              await doSwapViews(onInsertedCb);\n\n              expect(onInsertedCb).toHaveBeenCalledTimes(1);\n              expect(onInsertedCb).toHaveBeenCalledBefore(onDocInsertedSpy);\n              expect(docViewerEl.contains(oldCurrViewContainer)).toBe(false);\n              expect(docViewerEl.contains(oldNextViewContainer)).toBe(true);\n            });\n\n            it('should empty the previous view', async () => {\n              await doSwapViews();\n\n              expect(docViewer.currViewContainer.innerHTML).toBe('Next view');\n              expect(docViewer.nextViewContainer.innerHTML).toBe('');\n\n              docViewer.nextViewContainer.innerHTML = 'Next view 2';\n              await doSwapViews();\n\n              expect(docViewer.currViewContainer.innerHTML).toBe('Next view 2');\n              expect(docViewer.nextViewContainer.innerHTML).toBe('');\n            });\n\n            if (animationsEnabled && !noAnimations) {\n              // Only test this when there are animations. Without animations, the views are swapped\n              // synchronously, so there is no need (or way) to abort.\n              it('should abort swapping if the returned observable is unsubscribed from', async () => {\n                docViewer.swapViews().subscribe().unsubscribe();\n                await doSwapViews();\n\n                // Since the first call was cancelled, only one swapping should have taken place.\n                expect(docViewerEl.contains(oldCurrViewContainer)).toBe(false);\n                expect(docViewerEl.contains(oldNextViewContainer)).toBe(true);\n                expect(docViewer.currViewContainer).toBe(oldNextViewContainer);\n                expect(docViewer.nextViewContainer).toBe(oldCurrViewContainer);\n                expect(docViewer.currViewContainer.innerHTML).toBe('Next view');\n                expect(docViewer.nextViewContainer.innerHTML).toBe('');\n              });\n            } else {\n              it('should swap views synchronously when animations are disabled', () => {\n                const cbSpy = jasmine.createSpy('cb');\n\n                docViewer.swapViews(cbSpy).subscribe();\n\n                expect(cbSpy).toHaveBeenCalledTimes(1);\n                expect(docViewerEl.contains(oldCurrViewContainer)).toBe(false);\n                expect(docViewerEl.contains(oldNextViewContainer)).toBe(true);\n                expect(docViewer.currViewContainer).toBe(oldNextViewContainer);\n                expect(docViewer.nextViewContainer).toBe(oldCurrViewContainer);\n                expect(docViewer.currViewContainer.innerHTML).toBe('Next view');\n                expect(docViewer.nextViewContainer.innerHTML).toBe('');\n              });\n            }\n          });\n        });\n      });\n    });\n  });\n});\n"
  },
  {
    "path": "apps/rxjs.dev/src/app/layout/doc-viewer/doc-viewer.component.ts",
    "content": "import { Component, ElementRef, EventEmitter, Input, OnDestroy, Output } from '@angular/core';\nimport { Title, Meta } from '@angular/platform-browser';\n\nimport { asapScheduler, Observable, of, timer } from 'rxjs';\nimport { catchError, observeOn, switchMap, takeUntil, tap } from 'rxjs/operators';\n\nimport { DocumentContents, FILE_NOT_FOUND_ID, FETCHING_ERROR_ID } from 'app/documents/document.service';\nimport { Logger } from 'app/shared/logger.service';\nimport { TocService } from 'app/shared/toc.service';\nimport { ElementsLoader } from 'app/custom-elements/elements-loader';\n\n// Constants\nexport const NO_ANIMATIONS = 'no-animations';\n\n// Initialization prevents flicker once pre-rendering is on\nconst initialDocViewerElement = document.querySelector('aio-doc-viewer');\nconst initialDocViewerContent = initialDocViewerElement ? initialDocViewerElement.innerHTML : '';\n\n@Component({\n  selector: 'aio-doc-viewer',\n  template: '',\n  // TODO(robwormald): shadow DOM and emulated don't work here (?!)\n  // encapsulation: ViewEncapsulation.Native\n})\nexport class DocViewerComponent implements OnDestroy {\n  // Enable/Disable view transition animations.\n  static animationsEnabled = true;\n\n  private hostElement: HTMLElement;\n\n  private void$ = of<void>(undefined);\n  private onDestroy$ = new EventEmitter<void>();\n  private docContents$ = new EventEmitter<DocumentContents>();\n\n  protected currViewContainer: HTMLElement = document.createElement('div');\n  protected nextViewContainer: HTMLElement = document.createElement('div');\n\n  @Input()\n  set doc(newDoc: DocumentContents) {\n    // Ignore `undefined` values that could happen if the host component\n    // does not initially specify a value for the `doc` input.\n    if (newDoc) {\n      this.docContents$.emit(newDoc);\n    }\n  }\n\n  // The new document is ready to be inserted into the viewer.\n  // (Embedded components have been loaded and instantiated, if necessary.)\n  @Output() docReady = new EventEmitter<void>();\n\n  // The previous document has been removed from the viewer.\n  // (The leaving animation (if any) has been completed and the node has been removed from the DOM.)\n  @Output() docRemoved = new EventEmitter<void>();\n\n  // The new document has been inserted into the viewer.\n  // (The node has been inserted into the DOM, but the entering animation may still be in progress.)\n  @Output() docInserted = new EventEmitter<void>();\n\n  // The new document has been fully rendered into the viewer.\n  // (The entering animation has been completed.)\n  @Output() docRendered = new EventEmitter<void>();\n\n  constructor(\n    elementRef: ElementRef,\n    private logger: Logger,\n    private titleService: Title,\n    private metaService: Meta,\n    private tocService: TocService,\n    private elementsLoader: ElementsLoader\n  ) {\n    this.hostElement = elementRef.nativeElement;\n    // Security: the initialDocViewerContent comes from the prerendered DOM and is considered to be secure\n    this.hostElement.innerHTML = initialDocViewerContent;\n\n    if (this.hostElement.firstElementChild) {\n      this.currViewContainer = this.hostElement.firstElementChild as HTMLElement;\n    }\n\n    this.docContents$\n      .pipe(\n        observeOn(asapScheduler),\n        switchMap((newDoc) => this.render(newDoc)),\n        takeUntil(this.onDestroy$)\n      )\n      .subscribe();\n  }\n\n  ngOnDestroy() {\n    this.onDestroy$.emit();\n  }\n\n  /**\n   * Prepare for setting the window title and ToC.\n   * Return a function to actually set them.\n   */\n  protected prepareTitleAndToc(targetElem: HTMLElement, docId: string): () => void {\n    const descriptionEl = targetElem.querySelector('.api-body > p:nth-child(2)');\n    const titleEl = targetElem.querySelector('h1');\n    const needsToc = !!titleEl && !/no-?toc/i.test(titleEl.className);\n    const embeddedToc = targetElem.querySelector('aio-toc.embedded');\n\n    if (needsToc && !embeddedToc) {\n      // Add an embedded ToC if it's needed and there isn't one in the content already.\n      titleEl!.insertAdjacentHTML('afterend', '<aio-toc class=\"embedded\"></aio-toc>');\n    } else if (!needsToc && embeddedToc) {\n      // Remove the embedded Toc if it's there and not needed.\n      embeddedToc.remove();\n    }\n\n    return () => {\n      this.tocService.reset();\n      let title: string | null = '';\n      let description: string | null = '';\n\n      // Only create ToC for docs with an `<h1>` heading.\n      // If you don't want a ToC, add \"no-toc\" class to `<h1>`.\n      if (titleEl) {\n        title = typeof titleEl.innerText === 'string' ? titleEl.innerText : titleEl.textContent;\n\n        if (needsToc) {\n          this.tocService.genToc(targetElem, docId);\n        }\n      }\n      if (descriptionEl) {\n        description = descriptionEl.innerHTML;\n      }\n      const formattedTitle = title ? `RxJS - ${title}` : 'RxJS';\n      this.addDocumentMetaTags(formattedTitle, description);\n      this.titleService.setTitle(formattedTitle);\n    };\n  }\n\n  /**\n   * Add doc content to host element and build it out with embedded components.\n   */\n  protected render(doc: DocumentContents): Observable<void> {\n    let addTitleAndToc: () => void;\n\n    this.setNoIndex(doc.id === FILE_NOT_FOUND_ID || doc.id === FETCHING_ERROR_ID);\n\n    return this.void$.pipe(\n      // Security: `doc.contents` is always authored by the documentation team\n      //           and is considered to be safe.\n      tap(() => (this.nextViewContainer.innerHTML = doc.contents || '')),\n      tap(() => (addTitleAndToc = this.prepareTitleAndToc(this.nextViewContainer, doc.id))),\n      switchMap(() => this.elementsLoader.loadContainedCustomElements(this.nextViewContainer)),\n      tap(() => this.docReady.emit()),\n      switchMap(() => this.swapViews(addTitleAndToc)),\n      tap(() => this.docRendered.emit()),\n      catchError((err) => {\n        const errorMessage = err instanceof Error ? err.stack : err;\n        this.logger.error(new Error(`[DocViewer] Error preparing document '${doc.id}': ${errorMessage}`));\n        this.nextViewContainer.innerHTML = '';\n        this.setNoIndex(true);\n        return this.void$;\n      })\n    );\n  }\n\n  /**\n   * Tell search engine crawlers whether to index this page\n   */\n  private setNoIndex(val: boolean) {\n    if (val) {\n      this.metaService.addTag({ name: 'robots', content: 'noindex' });\n    } else {\n      this.metaService.removeTag('name=\"robots\"');\n    }\n  }\n\n  /**\n   * Swap the views, removing `currViewContainer` and inserting `nextViewContainer`.\n   * (At this point all content should be ready, including having loaded and instantiated embedded\n   *  components.)\n   *\n   * Optionally, run a callback as soon as `nextViewContainer` has been inserted, but before the\n   * entering animation has been completed. This is useful for work that needs to be done as soon as\n   * the element has been attached to the DOM.\n   */\n  protected swapViews(onInsertedCb = () => {}): Observable<void> {\n    const raf$ = new Observable<void>((subscriber) => {\n      const rafId = requestAnimationFrame(() => {\n        subscriber.next();\n        subscriber.complete();\n      });\n      return () => cancelAnimationFrame(rafId);\n    });\n\n    // Get the actual transition duration (taking global styles into account).\n    // According to the [CSSOM spec](https://drafts.csswg.org/cssom/#serializing-css-values),\n    // `time` values should be returned in seconds.\n    const getActualDuration = (elem: HTMLElement) => {\n      const cssValue = getComputedStyle(elem).transitionDuration || '';\n      const seconds = Number(cssValue.replace(/s$/, ''));\n      return 1000 * seconds;\n    };\n    const animateProp = <T extends keyof CSSStyleDeclaration>(\n      elem: HTMLElement,\n      prop: T,\n      from: CSSStyleDeclaration[T],\n      to: CSSStyleDeclaration[T],\n      duration = 200\n    ) => {\n      const animationsDisabled = !DocViewerComponent.animationsEnabled || this.hostElement.classList.contains(NO_ANIMATIONS);\n      if (prop === 'length' || prop === 'parentRule') {\n        // We cannot animate length or parentRule properties because they are readonly\n        return this.void$;\n      }\n      elem.style.transition = '';\n      return animationsDisabled\n        ? this.void$.pipe(tap(() => (elem.style[prop] = to)))\n        : this.void$.pipe(\n            // In order to ensure that the `from` value will be applied immediately (i.e.\n            // without transition) and that the `to` value will be affected by the\n            // `transition` style, we need to ensure an animation frame has passed between\n            // setting each style.\n            switchMap(() => raf$),\n            tap(() => (elem.style[prop] = from)),\n            switchMap(() => raf$),\n            tap(() => (elem.style.transition = `all ${duration}ms ease-in-out`)),\n            switchMap(() => raf$),\n            tap(() => (elem.style[prop] = to)),\n            switchMap(() => timer(getActualDuration(elem))),\n            switchMap(() => this.void$)\n          );\n    };\n\n    const animateLeave = (elem: HTMLElement) => animateProp(elem, 'opacity', '1', '0.1');\n    const animateEnter = (elem: HTMLElement) => animateProp(elem, 'opacity', '0.1', '1');\n\n    let done$ = this.void$;\n\n    if (this.currViewContainer.parentElement) {\n      done$ = done$.pipe(\n        // Remove the current view from the viewer.\n        switchMap(() => animateLeave(this.currViewContainer)),\n        tap(() => this.currViewContainer.parentElement?.removeChild(this.currViewContainer)),\n        tap(() => this.docRemoved.emit())\n      );\n    }\n\n    return done$.pipe(\n      // Insert the next view into the viewer.\n      tap(() => this.hostElement.appendChild(this.nextViewContainer)),\n      tap(() => onInsertedCb()),\n      tap(() => this.docInserted.emit()),\n      switchMap(() => animateEnter(this.nextViewContainer)),\n      // Update the view references and clean up unused nodes.\n      tap(() => {\n        const prevViewContainer = this.currViewContainer;\n        this.currViewContainer = this.nextViewContainer;\n        this.nextViewContainer = prevViewContainer;\n        this.nextViewContainer.innerHTML = ''; // Empty to release memory.\n      })\n    );\n  }\n\n  private addDocumentMetaTags(title: string, description: string | null): void {\n    this.metaService.updateTag({ name: 'twitter:title', content: title });\n    this.metaService.updateTag({ name: 'twitter:card', content: 'summary' });\n    this.metaService.updateTag({ property: 'og:title', content: title });\n    this.metaService.updateTag({ property: 'og:type', content: 'article' });\n\n    if (description) {\n      const formattedDescription = description.replace(/<\\/?\\w*>/gm, '');\n      this.metaService.updateTag({ name: 'twitter:description', content: formattedDescription });\n      this.metaService.updateTag({ property: 'og:description', content: formattedDescription });\n    }\n  }\n}\n"
  },
  {
    "path": "apps/rxjs.dev/src/app/layout/doc-viewer/dt.component.ts",
    "content": "import { Component, ElementRef, EventEmitter, Input, Output, ViewChild } from '@angular/core';\nimport { DocumentContents } from 'app/documents/document.service';\n\n@Component({\n  selector: 'aio-dt',\n  template: `\n  <div *ngIf=\"on\">\n    <hr>\n    <textarea #dt [value]=\"text\" rows=\"10\" cols=\"80\"></textarea>\n    <br/>\n    <button (click)=\"dtextSet()\">Show change</button>\n  </div>\n  `\n})\nexport class DtComponent {\n\n  @Input() on = false;\n  @Input() doc: DocumentContents;\n  @Output() docChange = new EventEmitter<DocumentContents>();\n\n  @ViewChild('dt', { read: ElementRef })\n  dt: ElementRef;\n\n  get text() { return this.doc && this.doc.contents; }\n\n  dtextSet() {\n    this.doc.contents = this.dt.nativeElement.value;\n    this.docChange.emit({ ...this.doc });\n  }\n}\n"
  },
  {
    "path": "apps/rxjs.dev/src/app/layout/footer/footer.component.ts",
    "content": "import { Component, Input } from '@angular/core';\n\nimport { NavigationNode, VersionInfo } from 'app/navigation/navigation.service';\n\n@Component({\n  selector: 'aio-footer',\n  template: `<p>\n      Code licensed under an <a href=\"https://www.apache.org/licenses/LICENSE-2.0\">Apache-2.0 License</a>. Documentation licensed under\n      <a href=\"http://creativecommons.org/licenses/by/4.0/\">CC BY 4.0</a>.\n    </p>\n    <p>Version {{ versionInfo?.full }}.</p>`,\n})\nexport class FooterComponent {\n  @Input() nodes: NavigationNode[];\n  @Input() versionInfo: VersionInfo;\n}\n"
  },
  {
    "path": "apps/rxjs.dev/src/app/layout/mode-banner/mode-banner.component.ts",
    "content": "import { Component, Input } from '@angular/core';\nimport { VersionInfo } from 'app/navigation/navigation.service';\n\n@Component({\n  selector: 'aio-mode-banner',\n  template: `\n  <div *ngIf=\"mode == 'archive'\" class=\"mode-banner\">\n    This is the <strong>archived documentation for Angular v{{version?.major}}.</strong>\n    Please visit <a href=\"https://angular.io/\">angular.io</a> to see documentation for the current version of Angular.\n  </div>\n  `\n})\nexport class ModeBannerComponent {\n  @Input() mode: string;\n  @Input() version: VersionInfo;\n}\n"
  },
  {
    "path": "apps/rxjs.dev/src/app/layout/nav-item/nav-item.component.spec.ts",
    "content": "import { ComponentFixture, TestBed } from '@angular/core/testing';\nimport { By } from '@angular/platform-browser';\nimport { NO_ERRORS_SCHEMA } from '@angular/core';\n\nimport { NavItemComponent } from './nav-item.component';\nimport { NavigationNode } from 'app/navigation/navigation.model';\n\ndescribe('NavItemComponent', () => {\n\n  // Testing the component class behaviors, independent of its template\n  // No dependencies. Just new it and test :)\n  // Let e2e tests verify how it displays.\n  describe('(class-only)', () => {\n\n    let component: NavItemComponent;\n\n    let selectedNodes: NavigationNode[];\n    let setClassesSpy: jasmine.Spy;\n\n    function initialize(nd: NavigationNode) {\n      component.node = nd;\n      onChanges(); // Angular calls when initializing the component\n    }\n\n    // Enough to triggers component's ngOnChange method\n    function onChanges() {\n      component.ngOnChanges();\n    }\n\n    beforeEach(() => {\n\n      component = new NavItemComponent();\n      setClassesSpy = spyOn(component, 'setClasses').and.callThrough();\n\n      // Selected nodes is the selected node and its header ancestors\n      selectedNodes = [\n        { title: 'a' },           // selected node: an item or a header\n        { title: 'parent' },      // selected node's header parent\n        { title: 'grandparent' }, // selected node's header grandparent\n      ];\n      component.selectedNodes = selectedNodes;\n    });\n\n    describe('should have expected classes when initialized', () => {\n      it('with selected node', () => {\n        initialize(selectedNodes[0]);\n        expect(component.classes).toEqual(\n          // selected node should be expanded even if is a header.\n          { 'level-1': true, collapsed: false, expanded: true, selected: true }\n        );\n      });\n\n      it('with selected node ancestor', () => {\n        initialize(selectedNodes[1]);\n        expect(component.classes).toEqual(\n          // ancestor is a header and should be expanded\n          { 'level-1': true, collapsed: false, expanded: true, selected: true }\n        );\n      });\n\n      it('with other than a selected node or ancestor', () => {\n        initialize({ title: 'x' });\n        expect(component.classes).toEqual(\n          { 'level-1': true, collapsed: true, expanded: false, selected: false }\n        );\n      });\n    });\n\n    describe('when becomes a non-selected node', () => {\n\n      // this node won't be the selected node when ngOnChanges() called\n      beforeEach(() => component.node = { title: 'x' });\n\n      it('should de-select if previously selected', () => {\n        component.isSelected = true;\n        onChanges();\n        expect(component.isSelected).toBe(false, 'becomes de-selected');\n      });\n\n      it('should collapse if previously expanded in narrow mode', () => {\n        component.isWide = false;\n        component.isExpanded = true;\n        onChanges();\n        expect(component.isExpanded).toBe(false, 'becomes collapsed');\n      });\n\n      it('should remain expanded in wide mode', () => {\n        component.isWide = true;\n        component.isExpanded = true;\n        onChanges();\n        expect(component.isExpanded).toBe(true, 'remains expanded');\n      });\n    });\n\n    describe('when becomes a selected node', () => {\n\n      // this node will be the selected node when ngOnChanges() called\n      beforeEach(() => component.node = selectedNodes[0]);\n\n      it('should select when previously not selected', () => {\n        component.isSelected = false;\n        onChanges();\n        expect(component.isSelected).toBe(true, 'becomes selected');\n      });\n\n      it('should expand the current node or keep it expanded', () => {\n        component.isExpanded = false;\n        onChanges();\n        expect(component.isExpanded).toBe(true, 'becomes true');\n\n        component.isExpanded = true;\n        onChanges();\n        expect(component.isExpanded).toBe(true, 'remains true');\n      });\n    });\n\n    describe('when becomes a selected ancestor node', () => {\n\n      // this node will be a selected node ancestor header when ngOnChanges() called\n      beforeEach(() => component.node = selectedNodes[2]);\n\n      it('should select when previously not selected', () => {\n        component.isSelected = false;\n        onChanges();\n        expect(component.isSelected).toBe(true, 'becomes selected');\n      });\n\n      it('should always expand this header', () => {\n        component.isExpanded = false;\n        onChanges();\n        expect(component.isExpanded).toBe(true, 'becomes expanded');\n\n        component.isExpanded = false;\n        onChanges();\n        expect(component.isExpanded).toBe(true, 'stays expanded');\n      });\n    });\n\n    describe('when headerClicked()', () => {\n      // current node doesn't matter in these tests.\n\n      it('should expand when headerClicked() and previously collapsed', () => {\n        component.isExpanded = false;\n        component.headerClicked();\n        expect(component.isExpanded).toBe(true, 'should be expanded');\n      });\n\n      it('should collapse when headerClicked() and previously expanded', () => {\n        component.isExpanded = true;\n        component.headerClicked();\n        expect(component.isExpanded).toBe(false, 'should be collapsed');\n      });\n\n      it('should not change isSelected when headerClicked()', () => {\n        component.isSelected = true;\n        component.headerClicked();\n        expect(component.isSelected).toBe(true, 'remains selected');\n\n        component.isSelected = false;\n        component.headerClicked();\n        expect(component.isSelected).toBe(false, 'remains not selected');\n      });\n\n      it('should set classes', () => {\n        component.headerClicked();\n        expect(setClassesSpy).toHaveBeenCalled();\n      });\n    });\n  });\n\n  describe('(via TestBed)', () => {\n    let component: NavItemComponent;\n    let fixture: ComponentFixture<NavItemComponent>;\n\n    beforeEach(() => {\n      TestBed.configureTestingModule({\n        declarations: [NavItemComponent],\n        schemas: [NO_ERRORS_SCHEMA]\n      });\n      fixture = TestBed.createComponent(NavItemComponent);\n      component = fixture.componentInstance;\n      component.node = {\n        title: 'x',\n        children: [\n          { title: 'a' },\n          { title: 'b', hidden: true},\n          { title: 'c' }\n        ]\n      };\n    });\n\n    it('should not show the hidden child nav-item', () => {\n      component.ngOnChanges(); // assume component.ngOnChanges ignores arguments\n      fixture.detectChanges();\n      const children = fixture.debugElement.queryAll(By.directive(NavItemComponent));\n      expect(children.length).toEqual(2);\n    });\n\n    it('should pass the `isWide` property to all displayed child nav-items', () => {\n      component.isWide = true;\n      component.ngOnChanges(); // assume component.ngOnChanges ignores arguments\n      fixture.detectChanges();\n      let children = fixture.debugElement.queryAll(By.directive(NavItemComponent));\n      expect(children.length).toEqual(2, 'when IsWide is true');\n      children.forEach(child => expect(child.componentInstance.isWide).toBe(true));\n\n      component.isWide = false;\n      component.ngOnChanges();\n      fixture.detectChanges();\n      children = fixture.debugElement.queryAll(By.directive(NavItemComponent));\n      expect(children.length).toEqual(2, 'when IsWide is false');\n      children.forEach(child => expect(child.componentInstance.isWide).toBe(false));\n    });\n  });\n});\n"
  },
  {
    "path": "apps/rxjs.dev/src/app/layout/nav-item/nav-item.component.ts",
    "content": "import { Component, Input, OnChanges } from '@angular/core';\nimport { NavigationNode } from 'app/navigation/navigation.model';\n\n@Component({\n  selector: 'aio-nav-item',\n  template: `<div *ngIf=\"!node.children\">\n      <a href=\"{{ node.url }}\" [ngClass]=\"classes\" title=\"{{ node.tooltip }}\" class=\"vertical-menu-item\">\n        {{ node.title }}\n      </a>\n    </div>\n\n    <div *ngIf=\"node.children\">\n      <a\n        *ngIf=\"node.url != null\"\n        href=\"{{ node.url }}\"\n        [ngClass]=\"classes\"\n        title=\"{{ node.tooltip }}\"\n        (click)=\"headerClicked()\"\n        class=\"vertical-menu-item heading\"\n      >\n        {{ node.title }}\n        <mat-icon class=\"rotating-icon\" svgIcon=\"keyboard_arrow_right\"></mat-icon>\n      </a>\n\n      <button\n        *ngIf=\"node.url == null\"\n        type=\"button\"\n        [ngClass]=\"classes\"\n        title=\"{{ node.tooltip }}\"\n        (click)=\"headerClicked()\"\n        class=\"vertical-menu-item heading\"\n        [attr.aria-pressed]=\"isExpanded\"\n      >\n        {{ node.title }}\n        <mat-icon class=\"rotating-icon\" svgIcon=\"keyboard_arrow_right\"></mat-icon>\n      </button>\n\n      <div class=\"heading-children\" [ngClass]=\"classes\">\n        <aio-nav-item\n          *ngFor=\"let node of nodeChildren\"\n          [level]=\"level + 1\"\n          [isWide]=\"isWide\"\n          [isParentExpanded]=\"isExpanded\"\n          [node]=\"node\"\n          [selectedNodes]=\"selectedNodes\"\n        ></aio-nav-item>\n      </div>\n    </div>`,\n})\nexport class NavItemComponent implements OnChanges {\n  @Input() isWide = false;\n  @Input() level = 1;\n  @Input() node: NavigationNode;\n  @Input() isParentExpanded = true;\n  @Input() selectedNodes: NavigationNode[] | undefined;\n\n  isExpanded = false;\n  isSelected = false;\n  classes: { [index: string]: boolean };\n  nodeChildren: NavigationNode[];\n\n  ngOnChanges() {\n    this.nodeChildren = this.node && this.node.children ? this.node.children.filter((n) => !n.hidden) : [];\n\n    if (this.selectedNodes) {\n      const ix = this.selectedNodes.indexOf(this.node);\n      this.isSelected = ix !== -1; // this node is the selected node or its ancestor\n      this.isExpanded =\n        this.isParentExpanded &&\n        (this.isSelected || // expand if selected or ...\n          // preserve expanded state when display is wide; collapse in mobile.\n          (this.isWide && this.isExpanded));\n    } else {\n      this.isSelected = false;\n    }\n\n    this.setClasses();\n  }\n\n  setClasses() {\n    this.classes = {\n      ['level-' + this.level]: true,\n      collapsed: !this.isExpanded,\n      expanded: this.isExpanded,\n      selected: this.isSelected,\n    };\n  }\n\n  headerClicked() {\n    this.isExpanded = !this.isExpanded;\n    this.setClasses();\n  }\n}\n"
  },
  {
    "path": "apps/rxjs.dev/src/app/layout/nav-menu/nav-menu.component.spec.ts",
    "content": "import { NavMenuComponent } from './nav-menu.component';\nimport { NavigationNode } from 'app/navigation/navigation.service';\n\n// Testing the component class behaviors, independent of its template\n// No dependencies, no life-cycle hooks. Just new it and test :)\n// Let e2e tests verify how it displays.\ndescribe('NavMenuComponent (class-only)', () => {\n  it('should filter out hidden nodes', () => {\n    const component = new NavMenuComponent();\n    const nodes: NavigationNode[] =\n      [ { title: 'a' }, { title: 'b', hidden: true}, { title: 'c'} ];\n    component.nodes = nodes;\n    expect(component.filteredNodes).toEqual([ nodes[0], nodes[2] ]);\n  });\n});\n"
  },
  {
    "path": "apps/rxjs.dev/src/app/layout/nav-menu/nav-menu.component.ts",
    "content": "import { Component, Input } from '@angular/core';\nimport { CurrentNode, NavigationNode } from 'app/navigation/navigation.service';\n\n@Component({\n  selector: 'aio-nav-menu',\n  template: ` <aio-nav-item *ngFor=\"let node of filteredNodes\" [node]=\"node\" [selectedNodes]=\"currentNode?.nodes\" [isWide]=\"isWide\">\n  </aio-nav-item>`,\n})\nexport class NavMenuComponent {\n  @Input() currentNode: CurrentNode | undefined;\n  @Input() isWide = false;\n  @Input() nodes: NavigationNode[];\n  get filteredNodes() {\n    return this.nodes ? this.nodes.filter((n) => !n.hidden) : [];\n  }\n}\n"
  },
  {
    "path": "apps/rxjs.dev/src/app/layout/notification/notification.component.ts",
    "content": "import { animate, state, style, trigger, transition } from '@angular/animations';\nimport { Component, EventEmitter, HostBinding, Inject, Input, OnInit, Output } from '@angular/core';\nimport { CurrentDateToken } from 'app/shared/current-date';\nimport { WindowToken } from 'app/shared/window';\n\nconst LOCAL_STORAGE_NAMESPACE = 'aio-notification/';\n\n@Component({\n  selector: 'aio-notification',\n  template: `\n  <!-- eslint-disable-next-line @angular-eslint/template/click-events-have-key-events -->\n  <span class=\"content\" (click)=\"contentClick()\">\n      <ng-content></ng-content>\n    </span>\n\n    <button mat-icon-button class=\"close-button\" aria-label=\"Close\" (click)=\"dismiss()\">\n      <mat-icon svgIcon=\"close\" aria-label=\"Dismiss notification\"></mat-icon>\n    </button> `,\n  animations: [\n    trigger('hideAnimation', [\n      state('show', style({ height: '*' })),\n      state('hide', style({ height: 0 })),\n      // this should be kept in sync with the animation durations in:\n      // - aio/src/styles/2-modules/_notification.scss\n      // - aio/src/app/app.component.ts : notificationDismissed()\n      transition('show => hide', animate(250)),\n    ]),\n  ],\n})\nexport class NotificationComponent implements OnInit {\n  private storage: Storage;\n\n  @Input() dismissOnContentClick: boolean;\n  @Input() notificationId: string;\n  @Input() expirationDate: string;\n  @Output() dismissed = new EventEmitter();\n\n  @HostBinding('@hideAnimation')\n  showNotification: 'show' | 'hide';\n\n  constructor(@Inject(WindowToken) window: Window, @Inject(CurrentDateToken) private currentDate: Date) {\n    try {\n      this.storage = window.localStorage;\n    } catch {\n      // When cookies are disabled in the browser, even trying to access\n      // `window.localStorage` throws an error. Use a no-op storage.\n      this.storage = {\n        length: 0,\n        clear: () => undefined,\n        getItem: () => null,\n        key: () => null,\n        removeItem: () => undefined,\n        setItem: () => undefined,\n      };\n    }\n  }\n\n  ngOnInit() {\n    const previouslyHidden = this.storage.getItem(LOCAL_STORAGE_NAMESPACE + this.notificationId) === 'hide';\n    const expired = this.currentDate > new Date(this.expirationDate);\n    this.showNotification = previouslyHidden || expired ? 'hide' : 'show';\n  }\n\n  contentClick() {\n    if (this.dismissOnContentClick) {\n      this.dismiss();\n    }\n  }\n\n  dismiss() {\n    this.storage.setItem(LOCAL_STORAGE_NAMESPACE + this.notificationId, 'hide');\n    this.showNotification = 'hide';\n    this.dismissed.next(null);\n  }\n}\n"
  },
  {
    "path": "apps/rxjs.dev/src/app/layout/top-menu/top-menu.component.spec.ts",
    "content": "import { ComponentFixture, TestBed } from '@angular/core/testing';\n\nimport { BehaviorSubject } from 'rxjs';\n\nimport { TopMenuComponent } from './top-menu.component';\nimport { NavigationService, NavigationViews } from 'app/navigation/navigation.service';\n\ndescribe('TopMenuComponent', () => {\n  let component: TopMenuComponent;\n  let fixture: ComponentFixture<TopMenuComponent>;\n\n  beforeEach(() => {\n    TestBed.configureTestingModule({\n      declarations: [ TopMenuComponent ],\n      providers: [\n        { provide: NavigationService, useClass: TestNavigationService }\n      ]\n    });\n  });\n\n  beforeEach(() => {\n    fixture = TestBed.createComponent(TopMenuComponent);\n    component = fixture.componentInstance;\n    fixture.detectChanges();\n  });\n\n  it('should create', () => {\n    expect(component).toBeTruthy();\n  });\n});\n\n//// Test Helpers ////\nclass TestNavigationService {\n  navJson = {\n    TopBar: [\n      {url: 'api', title: 'API' },\n      {url: 'features', title: 'Features' }\n    ],\n  };\n\n  navigationViews = new BehaviorSubject<NavigationViews>(this.navJson);\n}\n"
  },
  {
    "path": "apps/rxjs.dev/src/app/layout/top-menu/top-menu.component.ts",
    "content": "import { Component, Input } from '@angular/core';\nimport { NavigationNode } from 'app/navigation/navigation.service';\n\n@Component({\n  selector: 'aio-top-menu',\n  template: `\n    <ul role=\"navigation\">\n      <li *ngFor=\"let node of nodes\"><a class=\"nav-link\" [href]=\"node.url\" [title]=\"node.title\">{{ node.title }}</a></li>\n    </ul>`\n})\nexport class TopMenuComponent {\n  @Input() nodes: NavigationNode[];\n\n}\n"
  },
  {
    "path": "apps/rxjs.dev/src/app/navigation/navigation.model.ts",
    "content": "// Pulled all interfaces out of `navigation.service.ts` because of this:\n// https://github.com/angular/angular-cli/issues/2034\n// Then re-export them from `navigation.service.ts`\n\nexport interface NavigationNode {\n  url?: string;\n  title: string;\n  tooltip?: string;\n  hidden?: boolean;\n  children?: NavigationNode[];\n}\n\nexport type NavigationResponse = { __versionInfo: VersionInfo } & { [name: string]: NavigationNode[] | VersionInfo };\n\nexport interface NavigationViews {\n  [name: string]: NavigationNode[];\n}\n\n/**\n *  Navigation information about a node at specific URL\n *  url: the current URL\n *  view: 'SideNav' | 'TopBar' | 'Footer' | etc\n *  nodes: the current node and its ancestor nodes within that view\n */\nexport interface CurrentNode {\n  url: string;\n  view: string;\n  nodes: NavigationNode[];\n}\n\n/**\n * A map of current nodes by view.\n * This is needed because some urls map to nodes in more than one view.\n * If a view does not contain a node that matches the current url then the value will be undefined.\n */\nexport interface CurrentNodes {\n  [view: string]: CurrentNode;\n}\n\nexport interface VersionInfo {\n  raw: string;\n  major: number;\n  minor: number;\n  patch: number;\n  prerelease: string[];\n  build: string;\n  version: string;\n  codeName: string;\n  isSnapshot: boolean;\n  full: string;\n  branch: string;\n  commitSHA: string;\n}\n"
  },
  {
    "path": "apps/rxjs.dev/src/app/navigation/navigation.service.spec.ts",
    "content": "import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing';\nimport { Injector } from '@angular/core';\nimport { TestBed } from '@angular/core/testing';\n\nimport { CurrentNodes, NavigationService, NavigationViews, NavigationNode, VersionInfo } from 'app/navigation/navigation.service';\nimport { LocationService } from 'app/shared/location.service';\nimport { MockLocationService } from 'testing/location.service';\n\ndescribe('NavigationService', () => {\n  let injector: Injector;\n  let navService: NavigationService;\n  let httpMock: HttpTestingController;\n\n  beforeEach(() => {\n    injector = TestBed.configureTestingModule({\n      imports: [HttpClientTestingModule],\n      providers: [NavigationService, { provide: LocationService, useFactory: () => new MockLocationService('a') }],\n    });\n\n    navService = injector.get(NavigationService);\n    httpMock = injector.get(HttpTestingController);\n  });\n\n  afterEach(() => httpMock.verify());\n\n  describe('navigationViews', () => {\n    it('should make a single connection to the server', () => {\n      const req = httpMock.expectOne({});\n      expect(req.request.url).toBe('generated/navigation.json');\n    });\n\n    it('navigationViews observable should complete', () => {\n      navService.navigationViews.subscribe();\n      // Stop `$httpMock.verify()` from complaining.\n      httpMock.expectOne({});\n    });\n\n    it('should return the same object to all subscribers', () => {\n      let views1: NavigationViews | undefined;\n      navService.navigationViews.subscribe((views) => (views1 = views));\n\n      let views2: NavigationViews | undefined;\n      navService.navigationViews.subscribe((views) => (views2 = views));\n\n      httpMock.expectOne({}).flush({ TopBar: [{ url: 'a' }] });\n\n      let views3: NavigationViews | undefined;\n      navService.navigationViews.subscribe((views) => (views3 = views));\n\n      expect(views2).toBe(views1);\n      expect(views3).toBe(views1);\n\n      // Verify that subsequent subscriptions did not trigger another request.\n      httpMock.expectNone({});\n    });\n\n    it('should do WHAT(?) if the request fails');\n  });\n\n  describe('node.tooltip', () => {\n    let view: NavigationNode[];\n\n    const sideNav: NavigationNode[] = [{ title: 'a', tooltip: 'a tip' }, { title: 'b' }, { title: 'c!' }, { url: 'foo', title: '' }];\n\n    beforeEach(() => {\n      navService.navigationViews.subscribe((views) => (view = views.sideNav));\n      httpMock.expectOne({}).flush({ sideNav });\n    });\n\n    it('should have the supplied tooltip', () => {\n      expect(view[0].tooltip).toEqual('a tip');\n    });\n\n    it('should create a tooltip from title + period', () => {\n      expect(view[1].tooltip).toEqual('b.');\n    });\n\n    it('should create a tooltip from title, keeping its trailing punctuation', () => {\n      expect(view[2].tooltip).toEqual('c!');\n    });\n\n    it('should not create a tooltip if there is no title', () => {\n      expect(view[3].tooltip).toBeUndefined();\n    });\n  });\n\n  describe('currentNode', () => {\n    let currentNodes: CurrentNodes;\n    let locationService: MockLocationService;\n\n    const topBarNodes: NavigationNode[] = [{ url: 'features', title: 'Features', tooltip: 'tip' }];\n    const sideNavNodes: NavigationNode[] = [\n      {\n        title: 'a',\n        tooltip: 'tip',\n        children: [\n          {\n            url: 'b',\n            title: 'b',\n            tooltip: 'tip',\n            children: [\n              { url: 'c', title: 'c', tooltip: 'tip' },\n              { url: 'd', title: 'd', tooltip: 'tip' },\n            ],\n          },\n          { url: 'e', title: 'e', tooltip: 'tip' },\n        ],\n      },\n      { url: 'f', title: 'f', tooltip: 'tip' },\n    ];\n\n    const navJson = {\n      TopBar: topBarNodes,\n      SideNav: sideNavNodes,\n      __versionInfo: {},\n    };\n\n    beforeEach(() => {\n      locationService = injector.get(LocationService) as any as MockLocationService;\n      navService.currentNodes.subscribe((selected) => (currentNodes = selected));\n      httpMock.expectOne({}).flush(navJson);\n    });\n\n    it('should list the side navigation node that matches the current location, and all its ancestors', () => {\n      locationService.go('b');\n      expect(currentNodes).toEqual({\n        SideNav: {\n          url: 'b',\n          view: 'SideNav',\n          nodes: [sideNavNodes[0].children![0], sideNavNodes[0]],\n        },\n      } as any);\n\n      locationService.go('d');\n      expect(currentNodes).toEqual({\n        SideNav: {\n          url: 'd',\n          view: 'SideNav',\n          nodes: [sideNavNodes[0].children![0].children![1], sideNavNodes[0].children![0], sideNavNodes[0]],\n        },\n      } as any);\n\n      locationService.go('f');\n      expect(currentNodes).toEqual({\n        SideNav: {\n          url: 'f',\n          view: 'SideNav',\n          nodes: [sideNavNodes[1]],\n        },\n      });\n    });\n\n    it('should be a TopBar selected node if the current location is a top menu node', () => {\n      locationService.go('features');\n      expect(currentNodes).toEqual({\n        TopBar: {\n          url: 'features',\n          view: 'TopBar',\n          nodes: [topBarNodes[0]],\n        },\n      });\n    });\n\n    it('should be a plain object if no navigation node matches the current location', () => {\n      locationService.go('g?search=moo#anchor-1');\n      expect(currentNodes).toEqual({\n        '': {\n          url: 'g',\n          view: '',\n          nodes: [],\n        },\n      });\n    });\n\n    it('should ignore trailing slashes, hashes, and search params on URLs in the navmap', () => {\n      const cnode: CurrentNodes = {\n        SideNav: {\n          url: 'c',\n          view: 'SideNav',\n          nodes: [sideNavNodes[0].children![0].children![0], sideNavNodes[0].children![0], sideNavNodes[0]],\n        },\n      };\n\n      locationService.go('c');\n      expect(currentNodes).toEqual(cnode, 'location: c');\n\n      locationService.go('c#foo');\n      expect(currentNodes).toEqual(cnode, 'location: c#foo');\n\n      locationService.go('c?foo=1');\n      expect(currentNodes).toEqual(cnode, 'location: c?foo=1');\n\n      locationService.go('c#foo?bar=1&baz=2');\n      expect(currentNodes).toEqual(cnode, 'location: c#foo?bar=1&baz=2');\n    });\n  });\n\n  describe('versionInfo', () => {\n    const expectedVersionInfo = { raw: '4.0.0' } as VersionInfo;\n    let versionInfo: VersionInfo;\n\n    beforeEach(() => {\n      navService.versionInfo.subscribe((info) => (versionInfo = info));\n      httpMock.expectOne({}).flush({\n        __versionInfo: expectedVersionInfo,\n      });\n    });\n\n    it('should extract the version info', () => {\n      expect(versionInfo).toEqual(expectedVersionInfo);\n    });\n  });\n\n  describe('docVersions', () => {\n    let actualDocVersions: NavigationNode[];\n    let docVersions: NavigationNode[];\n    let expectedDocVersions: NavigationNode[];\n\n    beforeEach(() => {\n      actualDocVersions = [];\n      docVersions = [{ title: 'v4.0.0' }, { title: 'v2', url: 'https://v2.angular.io' }];\n\n      expectedDocVersions = docVersions.map((v) => ({ ...v, ...{ tooltip: v.title + '.' } }));\n\n      navService.navigationViews.subscribe((views) => (actualDocVersions = views.docVersions));\n    });\n\n    it('should extract the docVersions', () => {\n      httpMock.expectOne({}).flush({ docVersions });\n      expect(actualDocVersions).toEqual(expectedDocVersions);\n    });\n  });\n});\n"
  },
  {
    "path": "apps/rxjs.dev/src/app/navigation/navigation.service.ts",
    "content": "import { Injectable } from '@angular/core';\nimport { HttpClient } from '@angular/common/http';\n\nimport { combineLatest, ConnectableObservable, Observable } from 'rxjs';\nimport { map, publishLast, publishReplay } from 'rxjs/operators';\n\nimport { LocationService } from 'app/shared/location.service';\nimport { CONTENT_URL_PREFIX } from 'app/documents/document.service';\n\n// Import and re-export the Navigation model types\nimport { CurrentNodes, NavigationNode, NavigationResponse, NavigationViews, VersionInfo } from './navigation.model';\nexport { CurrentNodes, CurrentNode, NavigationNode, NavigationResponse, NavigationViews, VersionInfo } from './navigation.model';\n\nconst navigationPath = CONTENT_URL_PREFIX + 'navigation.json';\n\n@Injectable()\nexport class NavigationService {\n  /**\n   * An observable collection of NavigationNode trees, which can be used to render navigational menus\n   */\n  navigationViews: Observable<NavigationViews>;\n\n  /**\n   * The current version of doc-app that we are running\n   */\n  versionInfo: Observable<VersionInfo>;\n\n  /**\n   * An observable of the current node with info about the\n   * node (if any) that matches the current URL location\n   * including its navigation view and its ancestor nodes in that view\n   */\n  currentNodes: Observable<CurrentNodes>;\n\n  constructor(private http: HttpClient, private location: LocationService) {\n    const navigationInfo = this.fetchNavigationInfo();\n    this.navigationViews = this.getNavigationViews(navigationInfo);\n\n    this.currentNodes = this.getCurrentNodes(this.navigationViews);\n    // The version information is packaged inside the navigation response to save us an extra request.\n    this.versionInfo = this.getVersionInfo(navigationInfo);\n  }\n\n  /**\n   * Get an observable that fetches the `NavigationResponse` from the server.\n   * We create an observable by calling `http.get` but then publish it to share the result\n   * among multiple subscribers, without triggering new requests.\n   * We use `publishLast` because once the http request is complete the request observable completes.\n   * If you use `publish` here then the completed request observable will cause the subscribed observables to complete too.\n   * We `connect` to the published observable to trigger the request immediately.\n   * We could use `.refCount` here but then if the subscribers went from 1 -> 0 -> 1 then you would get\n   * another request to the server.\n   * We are not storing the subscription from connecting as we do not expect this service to be destroyed.\n   */\n  private fetchNavigationInfo(): Observable<NavigationResponse> {\n    const navigationInfo = this.http.get<NavigationResponse>(navigationPath)\n      .pipe(publishLast());\n    (navigationInfo as ConnectableObservable<NavigationResponse>).connect();\n    return navigationInfo;\n  }\n\n  private getVersionInfo(navigationInfo: Observable<NavigationResponse>) {\n    const versionInfo = navigationInfo.pipe(\n      map(response => response.__versionInfo),\n      publishLast(),\n    );\n    (versionInfo as ConnectableObservable<VersionInfo>).connect();\n    return versionInfo;\n  }\n\n  private getNavigationViews(navigationInfo: Observable<NavigationResponse>): Observable<NavigationViews> {\n    const navigationViews = navigationInfo.pipe(\n      map(response => {\n        const views = Object.assign({}, response);\n        Object.keys(views).forEach(key => {\n          if (key[0] === '_') { delete views[key]; }\n        });\n        return views as NavigationViews;\n      }),\n      publishLast(),\n    );\n    (navigationViews as ConnectableObservable<NavigationViews>).connect();\n    return navigationViews;\n  }\n\n  /**\n   * Get an observable of the current nodes (the ones that match the current URL)\n   * We use `publishReplay(1)` because otherwise subscribers will have to wait until the next\n   * URL change before they receive an emission.\n   * See above for discussion of using `connect`.\n   */\n  private getCurrentNodes(navigationViews: Observable<NavigationViews>): Observable<CurrentNodes> {\n    const currentNodes = combineLatest(\n      navigationViews.pipe(map(views => this.computeUrlToNavNodesMap(views))),\n      this.location.currentPath,\n\n      (navMap, url) => {\n        const urlKey = url.startsWith('api/') ? 'api' : url;\n        return navMap.get(urlKey) || { '' : { view: '', url: urlKey, nodes: [] }};\n      })\n      .pipe(publishReplay(1));\n    (currentNodes as ConnectableObservable<CurrentNodes>).connect();\n    return currentNodes;\n  }\n\n  /**\n   * Compute a mapping from URL to an array of nodes, where the first node in the array\n   * is the one that matches the URL and the rest are the ancestors of that node.\n   *\n   * @param navigation - A collection of navigation nodes that are to be mapped\n   */\n  private computeUrlToNavNodesMap(navigation: NavigationViews) {\n    const navMap = new Map<string, CurrentNodes>();\n    Object.keys(navigation)\n      .forEach(view => navigation[view]\n        .forEach(node => this.walkNodes(view, navMap, node)));\n    return navMap;\n  }\n\n  /**\n   * Add tooltip to node if it doesn't have one and have title.\n   * If don't want tooltip, specify `\"tooltip\": \"\"` in navigation.json\n   */\n  private ensureHasTooltip(node: NavigationNode) {\n    const title = node.title;\n    const tooltip = node.tooltip;\n    if (tooltip == null && title ) {\n      // add period if no trailing punctuation\n      node.tooltip = title + (/[a-zA-Z0-9]$/.test(title) ? '.' : '');\n    }\n  }\n  /**\n   * Walk the nodes of a navigation tree-view,\n   * patching them and computing their ancestor nodes\n   */\n  private walkNodes(\n    view: string, navMap: Map<string, CurrentNodes>,\n    node: NavigationNode, ancestors: NavigationNode[] = []) {\n      const nodes = [node, ...ancestors];\n      const url = node.url;\n      this.ensureHasTooltip(node);\n\n      // only map to this node if it has a url\n      if (url) {\n        // Strip off trailing slashes from nodes in the navMap - they are not relevant to matching\n        const cleanedUrl = url.replace(/\\/$/, '');\n        if (!navMap.has(cleanedUrl)) {\n          navMap.set(cleanedUrl, {});\n        }\n        const navMapItem = navMap.get(cleanedUrl)!;\n        navMapItem[view] = { url, view, nodes };\n      }\n\n      if (node.children) {\n        node.children.forEach(child => this.walkNodes(view, navMap, child, nodes));\n      }\n    }\n}\n"
  },
  {
    "path": "apps/rxjs.dev/src/app/search/interfaces.ts",
    "content": "export interface SearchResults {\n  query: string;\n  results: SearchResult[];\n}\n\nexport interface SearchResult {\n  path: string;\n  title: string;\n  type: string;\n  titleWords: string;\n  keywords: string;\n}\n\nexport interface SearchArea {\n  name: string;\n  pages: SearchResult[];\n  priorityPages: SearchResult[];\n}\n\n"
  },
  {
    "path": "apps/rxjs.dev/src/app/search/search-box/search-box.component.spec.ts",
    "content": "import { Component } from '@angular/core';\nimport { ComponentFixture, fakeAsync, inject, TestBed, tick } from '@angular/core/testing';\nimport { By } from '@angular/platform-browser';\nimport { SearchBoxComponent } from './search-box.component';\nimport { LocationService } from 'app/shared/location.service';\nimport { MockLocationService } from 'testing/location.service';\n\n@Component({\n  template: '<aio-search-box (onSearch)=\"searchHandler($event)\" (onFocus)=\"focusHandler($event)\"></aio-search-box>'\n})\nclass HostComponent {\n  searchHandler = jasmine.createSpy('searchHandler');\n  focusHandler = jasmine.createSpy('focusHandler');\n}\n\ndescribe('SearchBoxComponent', () => {\n  let component: SearchBoxComponent;\n  let host: HostComponent;\n  let fixture: ComponentFixture<HostComponent>;\n\n  beforeEach(() => {\n    TestBed.configureTestingModule({\n      declarations: [ SearchBoxComponent, HostComponent ],\n      providers: [\n        { provide: LocationService, useFactory: () => new MockLocationService('') }\n      ]\n    });\n  });\n\n  beforeEach(() => {\n    fixture = TestBed.createComponent(HostComponent);\n    host = fixture.componentInstance;\n    component = fixture.debugElement.query(By.directive(SearchBoxComponent)).componentInstance;\n    fixture.detectChanges();\n  });\n\n  describe('initialisation', () => {\n    it('should get the current search query from the location service',\n          fakeAsync(inject([LocationService], (location: MockLocationService) => {\n      location.search.and.returnValue({ search: 'initial search' });\n      component.ngOnInit();\n      expect(location.search).toHaveBeenCalled();\n      tick(300);\n      expect(host.searchHandler).toHaveBeenCalledWith('initial search');\n      expect(component.searchBox.nativeElement.value).toEqual('initial search');\n    })));\n  });\n\n  describe('onSearch', () => {\n    it('should debounce by 300ms', fakeAsync(() => {\n      component.doSearch();\n      expect(host.searchHandler).not.toHaveBeenCalled();\n      tick(300);\n      expect(host.searchHandler).toHaveBeenCalled();\n    }));\n\n    it('should pass through the value of the input box', fakeAsync(() => {\n      const input = fixture.debugElement.query(By.css('input'));\n      input.nativeElement.value = 'some query (input)';\n      component.doSearch();\n      tick(300);\n      expect(host.searchHandler).toHaveBeenCalledWith('some query (input)');\n    }));\n\n    it('should only send events if the search value has changed', fakeAsync(() => {\n      const input = fixture.debugElement.query(By.css('input'));\n\n      input.nativeElement.value = 'some query';\n      component.doSearch();\n      tick(300);\n      expect(host.searchHandler).toHaveBeenCalledTimes(1);\n\n      component.doSearch();\n      tick(300);\n      expect(host.searchHandler).toHaveBeenCalledTimes(1);\n\n      input.nativeElement.value = 'some other query';\n      component.doSearch();\n      tick(300);\n      expect(host.searchHandler).toHaveBeenCalledTimes(2);\n    }));\n  });\n\n  describe('on input', () => {\n    it('should trigger a search', () => {\n      const input = fixture.debugElement.query(By.css('input'));\n      spyOn(component, 'doSearch');\n      input.triggerEventHandler('input', { });\n      expect(component.doSearch).toHaveBeenCalled();\n    });\n  });\n\n  describe('on keyup', () => {\n    it('should trigger a search', () => {\n      const input = fixture.debugElement.query(By.css('input'));\n      spyOn(component, 'doSearch');\n      input.triggerEventHandler('keyup', { });\n      expect(component.doSearch).toHaveBeenCalled();\n    });\n  });\n\n  describe('on focus', () => {\n    it('should trigger the onFocus event', () => {\n      const input = fixture.debugElement.query(By.css('input'));\n      input.nativeElement.value = 'some query (focus)';\n      input.triggerEventHandler('focus', { });\n      expect(host.focusHandler).toHaveBeenCalledWith('some query (focus)');\n    });\n  });\n\n  describe('on click', () => {\n    it('should trigger a search', () => {\n      const input = fixture.debugElement.query(By.css('input'));\n      spyOn(component, 'doSearch');\n      input.triggerEventHandler('click', { });\n      expect(component.doSearch).toHaveBeenCalled();\n    });\n  });\n\n  describe('focus', () => {\n    it('should set the focus to the input box', () => {\n      const input = fixture.debugElement.query(By.css('input'));\n      component.focus();\n      expect(document.activeElement).toBe(input.nativeElement);\n    });\n  });\n});\n"
  },
  {
    "path": "apps/rxjs.dev/src/app/search/search-box/search-box.component.ts",
    "content": "import { Component, OnInit, ViewChild, ElementRef, EventEmitter, Output } from '@angular/core';\nimport { LocationService } from 'app/shared/location.service';\nimport { Subject } from 'rxjs';\nimport { debounceTime, distinctUntilChanged } from 'rxjs/operators';\n\n/**\n * This component provides a text box to type a search query that will be sent to the SearchService.\n *\n * When you arrive at a page containing this component, it will retrieve the `query` from the browser\n * address bar. If there is a query then this will be made.\n *\n * Focussing on the input box will resend whatever query is there. This can be useful if the search\n * results had been hidden for some reason.\n *\n */\n@Component({\n  selector: 'aio-search-box',\n  template: `<input #searchBox\n    type=\"search\"\n    aria-label=\"search\"\n    placeholder=\"Search\"\n    (input)=\"doSearch()\"\n    (keyup)=\"doSearch()\"\n    (focus)=\"doFocus()\"\n    (click)=\"doSearch()\">`\n})\nexport class SearchBoxComponent implements OnInit {\n\n  private searchDebounce = 300;\n  private searchSubject = new Subject<string>();\n\n  @ViewChild('searchBox', {static: true}) searchBox: ElementRef;\n  // eslint-disable-next-line @angular-eslint/no-output-on-prefix\n  @Output() onSearch = this.searchSubject.pipe(distinctUntilChanged(), debounceTime(this.searchDebounce));\n  // eslint-disable-next-line @angular-eslint/no-output-on-prefix\n  @Output() onFocus = new EventEmitter<string>();\n\n  constructor(private locationService: LocationService) { }\n\n  /**\n   * When we first show this search box we trigger a search if there is a search query in the URL\n   */\n  ngOnInit() {\n    const query = this.locationService.search().search;\n    if (query) {\n      this.query = query;\n      this.doSearch();\n    }\n  }\n\n  doSearch() {\n    this.searchSubject.next(this.query);\n  }\n\n  doFocus() {\n    this.onFocus.emit(this.query);\n  }\n\n  focus() {\n    this.searchBox.nativeElement.focus();\n  }\n\n  private get query() { return this.searchBox.nativeElement.value; }\n  private set query(value: string) { this.searchBox.nativeElement.value = value; }\n}\n"
  },
  {
    "path": "apps/rxjs.dev/src/app/search/search.service.ts",
    "content": "/*\nCopyright 2016 Google Inc. All Rights Reserved.\nUse of this source code is governed by an MIT-style license that\ncan be found in the LICENSE file at http://angular.io/license\n*/\n\nimport { NgZone, Injectable } from '@angular/core';\nimport { ConnectableObservable, Observable, race, ReplaySubject, timer } from 'rxjs';\nimport { concatMap, first, publishReplay } from 'rxjs/operators';\nimport { WebWorkerClient } from 'app/shared/web-worker';\nimport { SearchResults } from 'app/search/interfaces';\n\n@Injectable()\nexport class SearchService {\n  private ready: Observable<boolean>;\n  private searchesSubject = new ReplaySubject<string>(1);\n  private worker: WebWorkerClient;\n  constructor(private zone: NgZone) {}\n\n  /**\n   * Initialize the search engine. We offer an `initDelay` to prevent the search initialisation from delaying the\n   * initial rendering of the web page. Triggering a search will override this delay and cause the index to be\n   * loaded immediately.\n   *\n   * @param initDelay the number of milliseconds to wait before we load the WebWorker and generate the search index\n   */\n  initWorker(initDelay: number) {\n    // Wait for the initDelay or the first search\n    const ready = (this.ready = race<any>(timer(initDelay), this.searchesSubject.asObservable().pipe(first())).pipe(\n      concatMap(() => {\n        // Create the worker and load the index\n        const worker = new Worker(new URL('./search.worker', import.meta.url), { type: 'module' });\n        this.worker = WebWorkerClient.create(worker, this.zone);\n        return this.worker.sendMessage<boolean>('load-index');\n      }),\n      publishReplay(1)\n    ));\n\n    // Connect to the observable to kick off the timer\n    (ready as ConnectableObservable<boolean>).connect();\n    return ready;\n  }\n\n  /**\n   * Search the index using the given query and emit results on the observable that is returned.\n   *\n   * @param query The query to run against the index.\n   * @returns an observable collection of search results\n   */\n  search(query: string): Observable<SearchResults> {\n    // Trigger the searches subject to override the init delay timer\n    this.searchesSubject.next(query);\n    // Once the index has loaded, switch to listening to the searches coming in.\n    return this.ready.pipe(concatMap(() => this.worker.sendMessage<SearchResults>('query-index', query)));\n  }\n}\n"
  },
  {
    "path": "apps/rxjs.dev/src/app/search/search.worker.ts",
    "content": "/* eslint-env worker */\n/// <reference lib=\"webworker\" />\nimport * as lunr from 'lunr';\n\nimport { WebWorkerMessage } from '../shared/web-worker-message';\n\nconst SEARCH_TERMS_URL = '/generated/docs/app/search-data.json';\nlet index: lunr.Index;\nconst pageMap: SearchInfo = {};\n\ninterface SearchInfo {\n  [key: string]: PageInfo;\n}\n\ninterface PageInfo {\n  path: string;\n  type: string;\n  title: string;\n  headings: string;\n  keywords: string;\n  members: string;\n  topics: string;\n}\n\ninterface EncodedPages {\n  dictionary: string;\n  pages: EncodedPage[];\n}\n\ninterface EncodedPage {\n  path: string;\n  type: string;\n  title: string;\n  headings: number[];\n  keywords: number[];\n  members: number[];\n  topics: string;\n}\n\naddEventListener('message', handleMessage);\n\nconst customLunr = function(config: lunr.ConfigFunction) {\n  const builder = new lunr.Builder();\n  builder.pipeline.add(lunr.trimmer, lunr.stemmer);\n  builder.searchPipeline.add(lunr.stemmer);\n  config.call(builder, builder);\n  return builder.build();\n};\n\n// Create the lunr index - the docs should be an array of objects, each object containing\n// the path and search terms for a page\nfunction createIndex(loadIndexFn: IndexLoader): lunr.Index {\n  // The lunr typings are missing QueryLexer so we have to add them here manually.\n  const queryLexer = (lunr as any as { QueryLexer: { termSeparator: RegExp } }).QueryLexer;\n  queryLexer.termSeparator = lunr.tokenizer.separator = /\\s+/;\n  return customLunr(function() {\n    this.ref('path');\n    this.field('topics', { boost: 15 });\n    this.field('title', { boost: 10 });\n    this.field('headings', { boost: 5 });\n    this.field('members', { boost: 4 });\n    this.field('keywords', { boost: 2 });\n    loadIndexFn(this);\n  });\n}\n\n// The worker receives a message to load the index and to query the index\nfunction handleMessage(message: { data: WebWorkerMessage }): void {\n  const type = message.data.type;\n  const id = message.data.id;\n  const payload = message.data.payload;\n  switch (type) {\n    case 'load-index':\n      makeRequest(SEARCH_TERMS_URL, (encodedPages: EncodedPages) => {\n        index = createIndex(loadIndex(encodedPages));\n        postMessage({ type, id, payload: true });\n      });\n      break;\n    case 'query-index':\n      postMessage({ type, id, payload: { query: payload, results: queryIndex(payload) } });\n      break;\n    default:\n      postMessage({ type, id, payload: { error: 'invalid message type' } });\n  }\n}\n\n// Use XHR to make a request to the server\nfunction makeRequest(url: string, callback: (response: any) => void): void {\n  // The JSON file that is loaded should be an array of PageInfo:\n  const searchDataRequest = new XMLHttpRequest();\n  searchDataRequest.onload = function() {\n    callback(JSON.parse(this.responseText));\n  };\n  searchDataRequest.open('GET', url);\n  searchDataRequest.send();\n}\n\n// Create the search index from the searchInfo which contains the information about each page to be\n// indexed\nfunction loadIndex({ dictionary, pages }: EncodedPages): IndexLoader {\n  const dictionaryArray = dictionary.split(' ');\n  return (indexBuilder: lunr.Builder) => {\n    // Store the pages data to be used in mapping query results back to pages\n    // Add search terms from each page to the search index\n    pages.forEach((encodedPage) => {\n      const page = decodePage(encodedPage, dictionaryArray);\n      indexBuilder.add(page);\n      pageMap[page.path] = page;\n    });\n  };\n}\n\nfunction decodePage(encodedPage: EncodedPage, dictionary: string[]): PageInfo {\n  return {\n    ...encodedPage,\n    headings: encodedPage.headings?.map((i) => dictionary[i]).join(' ') ?? '',\n    keywords: encodedPage.keywords?.map((i) => dictionary[i]).join(' ') ?? '',\n    members: encodedPage.members?.map((i) => dictionary[i]).join(' ') ?? '',\n  };\n}\n\n// Query the index and return the processed results\nfunction queryIndex(query: string): PageInfo[] {\n  // Strip off quotes\n  query = query.replace(/^[\"']|['\"]$/g, '');\n  try {\n    if (query.length) {\n      let results = index.query((queryBuilder) => {\n        queryBuilder.term(lunr.tokenizer(query), {\n          fields: ['title'],\n          // eslint-disable-next-line no-bitwise\n          wildcard: lunr.Query.wildcard.TRAILING | lunr.Query.wildcard.LEADING,\n          usePipeline: true,\n          presence: lunr.Query.presence.REQUIRED,\n        });\n      });\n\n      if (results.length === 0) {\n        // First try a query where every term must be present\n        // (see https://lunrjs.com/guides/searching.html#term-presence)\n        results = index.query((queryBuilder) => {\n          const tokens = lunr.tokenizer(query);\n          for (const token of tokens) {\n            queryBuilder.term(token, {\n              usePipeline: true,\n              presence: lunr.Query.presence.REQUIRED,\n            });\n          }\n        });\n      }\n\n      // If that was too restrictive just query for any term to be present\n      if (results.length === 0) {\n        results = index.search(query);\n      }\n\n      // If that is still too restrictive then search in the title for the first word in the query\n      if (results.length === 0) {\n        // E.g. if the search is \"ngCont guide\" then we search for \"ngCont guide title:*ngCont*\"\n        const titleQuery = 'title:*' + query.split(' ', 1)[0] + '*';\n        results = index.search(query + ' ' + titleQuery);\n      }\n\n      // Map the hits into info about each page to be returned as results\n      return results.map((hit) => pageMap[hit.ref]);\n    }\n  } catch (e) {\n    // If the search query cannot be parsed the index throws an error\n    // Log it and recover\n    console.error(e);\n  }\n  return [];\n}\n\ntype IndexLoader = (indexBuilder: lunr.Builder) => void;\n"
  },
  {
    "path": "apps/rxjs.dev/src/app/shared/attribute-utils.spec.ts",
    "content": "import { ElementRef } from '@angular/core';\n\nimport { AttrMap, getAttrs, getAttrValue, getBoolFromAttribute, boolFromValue } from './attribute-utils';\n\ndescribe('Attribute Utilities', () => {\n  let testEl: HTMLElement;\n\n  beforeEach(() => {\n    const div = document.createElement('div');\n    div.innerHTML = '<div a b=\"true\" c=\"false\" D=\"foo\" d-E></div>';\n    testEl = div.querySelector('div')!;\n  });\n\n  describe('getAttrs', () => {\n    const expectedMap = {\n      a: '',\n      b: 'true',\n      c: 'false',\n      d: 'foo',\n      'd-e': ''\n    };\n\n    it('should get attr map from getAttrs(element)', () => {\n      const actual = getAttrs(testEl);\n      expect(actual).toEqual(expectedMap);\n    });\n\n    it('should get attr map from getAttrs(elementRef)', () => {\n      const actual = getAttrs(new ElementRef(testEl));\n      expect(actual).toEqual(expectedMap);\n    });\n  });\n\n  describe('getAttrValue', () => {\n    let attrMap: AttrMap;\n\n    beforeEach(() => {\n      attrMap = getAttrs(testEl);\n    });\n\n    it('should return empty string for attribute \"a\"', () => {\n      expect(getAttrValue(attrMap, 'a')).toBe('');\n    });\n\n    it('should return empty string for attribute \"A\"', () => {\n      expect(getAttrValue(attrMap, 'A')).toBe('');\n    });\n\n    it('should return \"true\" for attribute \"b\"', () => {\n      expect(getAttrValue(attrMap, 'b')).toBe('true');\n    });\n\n    it('should return empty string for attribute \"d-E\"', () => {\n      expect(getAttrValue(attrMap, 'd-E')).toBe('');\n    });\n\n    it('should return empty string for attribute [\"d-e\"]', () => {\n      expect(getAttrValue(attrMap, ['d-e'])).toBe('');\n    });\n\n    it('should return \"foo\" for attribute [\"d\", \"d-e\"]', () => {\n      // because d will be found before d-e\n      expect(getAttrValue(attrMap, ['d', 'd-e'])).toBe('foo');\n    });\n\n    it('should return empty string for attribute [\"d-e\", \"d\"]', () => {\n      // because d-e will be found before d\n      expect(getAttrValue(attrMap, ['d-e', 'd'])).toBe('');\n    });\n\n    it('should return undefined for non-existent attributes', () => {\n      expect(getAttrValue(attrMap, 'x')).toBeUndefined();\n      expect(getAttrValue(attrMap, '')).toBeUndefined();\n      expect(getAttrValue(attrMap, ['', 'x'])).toBeUndefined();\n    });\n\n  });\n\n  describe('boolFromValue', () => {\n\n    it('should return true for \"\" as in present but unassigned attr \"a\"', () => {\n      expect(boolFromValue('')).toBe(true);\n    });\n\n    it('should return false for \"false\" as in attr \"c\"', () => {\n      expect(boolFromValue('false')).toBe(false);\n    });\n    it('should return true for \"true\" as in attr \"b\"', () => {\n      expect(boolFromValue('true')).toBe(true);\n    });\n\n    it('should return true for something other than \"false\"', () => {\n      expect(boolFromValue('foo')).toBe(true);\n    });\n\n    it('should return true for \"False\" because case-sensitive', () => {\n      expect(boolFromValue('False')).toBe(true);\n    });\n\n\n    it('should return false by default as in undefined attr \"x\"', () => {\n      expect(boolFromValue(undefined)).toBe(false);\n    });\n\n    it('should return true for undefined value when default is true', () => {\n      expect(boolFromValue(undefined, true)).toBe(true);\n    });\n\n    it('should return false for undefined value when default is false', () => {\n      expect(boolFromValue(undefined, false)).toBe(false);\n    });\n\n    it('should return true for \"\" as in unassigned attr \"a\" even when default is false', () => {\n      // default value is only applied when the attribute is missing\n      expect(boolFromValue('', false)).toBe(true);\n    });\n  });\n\n  // Combines the three utilities for convenience.\n  describe('getBoolFromAttribute', () => {\n    it('should return true for present but unassigned attr \"a\"', () => {\n      expect(getBoolFromAttribute(testEl, 'a')).toBe(true);\n    });\n\n    it('should return true for attr \"b\" which is \"true\"', () => {\n      expect(getBoolFromAttribute(testEl, 'b')).toBe(true);\n    });\n\n    it('should return false for attr \"c\" which is \"false\"', () => {\n      expect(getBoolFromAttribute(testEl, 'c')).toBe(false);\n    });\n\n    it('should return true for attributes [\"d-e\", \"d\"]', () => {\n      // because d-e will be found before D=\"foo\"\n      expect(getBoolFromAttribute(testEl, ['d-e', 'd'])).toBe(true);\n    });\n\n    it('should return false for non-existent attribute \"x\"', () => {\n      expect(getBoolFromAttribute(testEl, 'x')).toBe(false);\n    });\n  });\n});\n"
  },
  {
    "path": "apps/rxjs.dev/src/app/shared/attribute-utils.ts",
    "content": "// Utilities for processing HTML element attributes\nimport { ElementRef } from '@angular/core';\n\nexport interface AttrMap {\n  [key: string]: string;\n}\n\n/**\n * Get attribute map from element or ElementRef `attributes`.\n * Attribute map keys are forced lowercase for case-insensitive lookup.\n *\n * @param el The source of the attributes.\n */\nexport function getAttrs(el:  HTMLElement | ElementRef): AttrMap {\n  const attrs: NamedNodeMap = el instanceof ElementRef ? el.nativeElement.attributes : el.attributes;\n  const attrMap: AttrMap = {};\n  for (const attr of attrs as any as Attr[] /* cast due to https://github.com/Microsoft/TypeScript/issues/2695 */) {\n    attrMap[attr.name.toLowerCase()] = attr.value;\n  }\n  return attrMap;\n}\n\n/**\n * Return the attribute that matches `attr`.\n *\n * @param attr Name of the attribute or a string of candidate attribute names.\n */\nexport function getAttrValue(attrs: AttrMap, attr: string | string[]): string | undefined {\n  const key = (typeof attr === 'string')\n      ? attr\n      : attr.find(a => attrs.hasOwnProperty(a.toLowerCase()));\n\n  return (key === undefined) ? undefined : attrs[key.toLowerCase()];\n}\n\n/**\n * Return the boolean state of an attribute value (if supplied)\n *\n * @param attrValue The string value of some attribute (or undefined if attribute not present).\n * @param def Default boolean value when attribute is undefined.\n */\nexport function boolFromValue(attrValue: string | undefined, def: boolean = false) {\n  return attrValue === undefined ? def : attrValue.trim() !== 'false';\n}\n\n/**\n * Return the boolean state of attribute from an element\n *\n * @param el The source of the attributes.\n * @param atty Name of the attribute or a string of candidate attribute names.\n * @param def Default boolean value when attribute is undefined.\n */\nexport function getBoolFromAttribute(\n  el:  HTMLElement | ElementRef,\n  attr: string | string[],\n  def: boolean = false): boolean {\n  return boolFromValue(getAttrValue(getAttrs(el), attr), def);\n}\n"
  },
  {
    "path": "apps/rxjs.dev/src/app/shared/copier.service.ts",
    "content": "import { Injectable } from '@angular/core';\n/**\n * This class is based on the code in the following projects:\n *\n * - https://github.com/zenorocha/select\n * - https://github.com/zenorocha/clipboard.js/\n *\n * Both released under MIT license - © Zeno Rocha\n */\n\n\n@Injectable()\nexport class CopierService {\n    private fakeElem: HTMLTextAreaElement|null;\n\n    /**\n     * Creates a fake textarea element, sets its value from `text` property,\n     * and makes a selection on it.\n     */\n    createFake(text: string) {\n      const isRTL = document.documentElement.getAttribute('dir') === 'rtl';\n\n      // Create a fake element to hold the contents to copy\n      this.fakeElem = document.createElement('textarea');\n\n      // Prevent zooming on iOS\n      this.fakeElem.style.fontSize = '12pt';\n\n      // Reset box model\n      this.fakeElem.style.border = '0';\n      this.fakeElem.style.padding = '0';\n      this.fakeElem.style.margin = '0';\n\n      // Move element out of screen horizontally\n      this.fakeElem.style.position = 'absolute';\n      this.fakeElem.style[ isRTL ? 'right' : 'left' ] = '-9999px';\n\n      // Move element to the same position vertically\n      const yPosition = window.pageYOffset || document.documentElement.scrollTop;\n      this.fakeElem.style.top = yPosition + 'px';\n\n      this.fakeElem.setAttribute('readonly', '');\n      this.fakeElem.value = text;\n\n      document.body.appendChild(this.fakeElem);\n\n      this.fakeElem.select();\n      this.fakeElem.setSelectionRange(0, this.fakeElem.value.length);\n    }\n\n    removeFake() {\n      if (this.fakeElem) {\n        document.body.removeChild(this.fakeElem);\n        this.fakeElem = null;\n      }\n    }\n\n    copyText(text: string) {\n      try {\n        this.createFake(text);\n        return document.execCommand('copy');\n      } catch (err) {\n        return false;\n      } finally {\n        this.removeFake();\n      }\n    }\n}\n"
  },
  {
    "path": "apps/rxjs.dev/src/app/shared/current-date.ts",
    "content": "import { InjectionToken } from '@angular/core';\n\nexport const CurrentDateToken = new InjectionToken('CurrentDate');\nexport function currentDateProvider() { return new Date(); }\n"
  },
  {
    "path": "apps/rxjs.dev/src/app/shared/custom-icon-registry.spec.ts",
    "content": "import { ErrorHandler } from '@angular/core';\nimport { MatIconRegistry } from '@angular/material/icon';\nimport { CustomIconRegistry, SvgIconInfo } from './custom-icon-registry';\n\ndescribe('CustomIconRegistry', () => {\n  it('should get the SVG element for a preloaded icon from the cache', () => {\n    const mockHttp: any = {};\n    const mockSanitizer: any = {};\n    const mockDocument: any = {};\n    const svgSrc = '<svg xmlns=\"http://www.w3.org/2000/svg\" focusable=\"false\" ' +\n                 'viewBox=\"0 0 24 24\"><path d=\"M8.59 16.34l4.58-4.59-4.58-4.59L10 5.75l6 6-6 6z\"/></svg>';\n    const svgIcons: SvgIconInfo[] = [\n      { name: 'test_icon', svgSource: svgSrc }\n    ];\n    const errorHandler = new ErrorHandler();\n    const registry = new CustomIconRegistry(mockHttp, mockSanitizer, mockDocument, svgIcons, errorHandler);\n    let svgElement: SVGElement|undefined;\n    registry.getNamedSvgIcon('test_icon').subscribe(el => svgElement = el);\n    expect(svgElement).toEqual(createSvg(svgSrc));\n  });\n\n  it('should call through to the MdIconRegistry if the icon name is not in the preloaded cache', () => {\n    const mockHttp: any = {};\n    const mockSanitizer: any = {};\n    const mockDocument: any = {};\n    const svgSrc = '<svg xmlns=\"http://www.w3.org/2000/svg\" focusable=\"false\" ' +\n                 'viewBox=\"0 0 24 24\"><path d=\"M8.59 16.34l4.58-4.59-4.58-4.59L10 5.75l6 6-6 6z\"/></svg>';\n    const svgIcons: SvgIconInfo[] = [\n      { name: 'test_icon', svgSource: svgSrc }\n    ];\n    spyOn(MatIconRegistry.prototype, 'getNamedSvgIcon');\n    const errorHandler = new ErrorHandler();\n    const registry = new CustomIconRegistry(mockHttp, mockSanitizer, mockDocument, svgIcons, errorHandler);\n\n    registry.getNamedSvgIcon('other_icon');\n    expect(MatIconRegistry.prototype.getNamedSvgIcon).toHaveBeenCalledWith('other_icon', undefined);\n\n    registry.getNamedSvgIcon('other_icon', 'foo');\n    expect(MatIconRegistry.prototype.getNamedSvgIcon).toHaveBeenCalledWith('other_icon', 'foo');\n  });\n});\n\nfunction createSvg(svgSrc: string): SVGElement {\n  const div = document.createElement('div');\n  div.innerHTML = svgSrc;\n  return div.querySelector('svg')!;\n}\n"
  },
  {
    "path": "apps/rxjs.dev/src/app/shared/custom-icon-registry.ts",
    "content": "import { InjectionToken, Inject, Injectable, Optional, ErrorHandler } from '@angular/core';\nimport { DOCUMENT } from '@angular/common';\nimport { of } from 'rxjs';\nimport { MatIconRegistry } from '@angular/material/icon';\nimport { HttpClient } from '@angular/common/http';\nimport { DomSanitizer } from '@angular/platform-browser';\n\n/**\n * Use SVG_ICONS (and SvgIconInfo) as \"multi\" providers to provide the SVG source\n * code for the icons that you wish to have preloaded in the `CustomIconRegistry`\n * For compatibility with the MdIconComponent, please ensure that the SVG source has\n * the following attributes:\n *\n * * `xmlns=\"http://www.w3.org/2000/svg\"`\n * * `focusable=\"false\"` (disable IE11 default behavior to make SVGs focusable)\n * * `height=\"100%\"` (the default)\n * * `width=\"100%\"` (the default)\n * * `preserveAspectRatio=\"xMidYMid meet\"` (the default)\n *\n */\nexport const SVG_ICONS = new InjectionToken<Array<SvgIconInfo>>('SvgIcons');\nexport interface SvgIconInfo {\n  name: string;\n  svgSource: string;\n}\n\ninterface SvgIconMap {\n  [iconName: string]: SVGElement;\n}\n\n/**\n * A custom replacement for Angular Material's `MdIconRegistry`, which allows\n * us to provide preloaded icon SVG sources.\n */\n@Injectable()\nexport class CustomIconRegistry extends MatIconRegistry {\n  private preloadedSvgElements: SvgIconMap = {};\n\n  constructor(http: HttpClient, sanitizer: DomSanitizer, @Optional() @Inject(DOCUMENT) document: Document,\n              @Inject(SVG_ICONS) svgIcons: SvgIconInfo[], errorHandler: ErrorHandler) {\n    super(http, sanitizer, document, errorHandler);\n    this.loadSvgElements(svgIcons);\n  }\n\n  override getNamedSvgIcon(iconName: string, namespace?: string) {\n    if (this.preloadedSvgElements[iconName]) {\n      return of(this.preloadedSvgElements[iconName].cloneNode(true) as SVGElement);\n    }\n    return super.getNamedSvgIcon(iconName, namespace);\n  }\n\n  private loadSvgElements(svgIcons: SvgIconInfo[]) {\n    const div = document.createElement('DIV');\n    svgIcons.forEach(icon => {\n      // SECURITY: the source for the SVG icons is provided in code by trusted developers\n      div.innerHTML = icon.svgSource;\n      this.preloadedSvgElements[icon.name] = div.querySelector('svg')!;\n    });\n  }\n}\n"
  },
  {
    "path": "apps/rxjs.dev/src/app/shared/deployment.service.spec.ts",
    "content": "import { ReflectiveInjector } from '@angular/core';\nimport { environment } from 'environments/environment';\nimport { LocationService } from 'app/shared/location.service';\nimport { MockLocationService } from 'testing/location.service';\nimport { Deployment } from './deployment.service';\n\ndescribe('Deployment service', () => {\n  describe('mode', () => {\n    it('should get the mode from the environment', () => {\n      environment.mode = 'foo';\n      const deployment = getInjector().get(Deployment);\n      expect(deployment.mode).toEqual('foo');\n    });\n\n    it('should get the mode from the `mode` query parameter if available', () => {\n      const injector = getInjector();\n\n      const locationService: MockLocationService = injector.get(LocationService);\n      locationService.search.and.returnValue({ mode: 'bar' });\n\n      const deployment = injector.get(Deployment);\n      expect(deployment.mode).toEqual('bar');\n    });\n  });\n});\n\nfunction getInjector() {\n  return ReflectiveInjector.resolveAndCreate([\n    Deployment,\n    { provide: LocationService, useFactory: () => new MockLocationService('') }\n  ]);\n}\n"
  },
  {
    "path": "apps/rxjs.dev/src/app/shared/deployment.service.ts",
    "content": "import { Injectable } from '@angular/core';\nimport { LocationService } from 'app/shared/location.service';\nimport { environment } from 'environments/environment';\n\n/**\n * Information about the deployment of this application.\n */\n@Injectable()\nexport class Deployment {\n  /**\n   * The deployment mode set from the environment provided at build time;\n   * or overridden by the `mode` query parameter: e.g. `...?mode=archive`\n   */\n  mode: string = this.location.search().mode || environment.mode;\n\n  constructor(private location: LocationService) {}\n};\n"
  },
  {
    "path": "apps/rxjs.dev/src/app/shared/ga.service.spec.ts",
    "content": "import { ReflectiveInjector } from '@angular/core';\n\nimport { GaService } from 'app/shared/ga.service';\nimport { WindowToken } from 'app/shared/window';\n\ndescribe('GaService', () => {\n  let gaService: GaService;\n  let injector: ReflectiveInjector;\n  let gaSpy: jasmine.Spy;\n  let mockWindow: any;\n\n  beforeEach(() => {\n    gaSpy = jasmine.createSpy('ga');\n    mockWindow = { ga: gaSpy };\n    injector = ReflectiveInjector.resolveAndCreate([GaService, { provide: WindowToken, useFactory: () => mockWindow }]);\n    gaService = injector.get(GaService);\n  });\n\n  it('should initialize ga with \"create\" when constructed', () => {\n    const first = gaSpy.calls.first().args;\n    expect(first[0]).toBe('create');\n  });\n\n  describe('#locationChanged(url)', () => {\n    it('should send page to url w/ leading slash', () => {\n      gaService.locationChanged('testUrl');\n      expect(gaSpy).toHaveBeenCalledWith('set', 'page', '/testUrl');\n      expect(gaSpy).toHaveBeenCalledWith('send', 'pageview');\n    });\n  });\n\n  describe('#sendPage(url)', () => {\n    it('should set page to url w/ leading slash', () => {\n      gaService.sendPage('testUrl');\n      expect(gaSpy).toHaveBeenCalledWith('set', 'page', '/testUrl');\n    });\n\n    it('should send \"pageview\" ', () => {\n      gaService.sendPage('testUrl');\n      expect(gaSpy).toHaveBeenCalledWith('send', 'pageview');\n    });\n\n    it('should not send twice with same URL, back-to-back', () => {\n      gaService.sendPage('testUrl');\n      gaSpy.calls.reset();\n      gaService.sendPage('testUrl');\n      expect(gaSpy).not.toHaveBeenCalled();\n    });\n\n    it('should send again even if only the hash changes', () => {\n      // Therefore it is up to caller NOT to call it when hash changes if this is unwanted.\n      // See LocationService and its specs\n      gaService.sendPage('testUrl#one');\n      expect(gaSpy).toHaveBeenCalledWith('set', 'page', '/testUrl#one');\n      expect(gaSpy).toHaveBeenCalledWith('send', 'pageview');\n      gaSpy.calls.reset();\n      gaService.sendPage('testUrl#two');\n      expect(gaSpy).toHaveBeenCalledWith('set', 'page', '/testUrl#two');\n      expect(gaSpy).toHaveBeenCalledWith('send', 'pageview');\n    });\n\n    it('should send same URL twice when other intervening URL', () => {\n      gaService.sendPage('testUrl');\n      expect(gaSpy).toHaveBeenCalledWith('set', 'page', '/testUrl');\n      expect(gaSpy).toHaveBeenCalledWith('send', 'pageview');\n      gaSpy.calls.reset();\n      gaService.sendPage('testUrl2');\n      expect(gaSpy).toHaveBeenCalledWith('set', 'page', '/testUrl2');\n      expect(gaSpy).toHaveBeenCalledWith('send', 'pageview');\n      gaSpy.calls.reset();\n      gaService.sendPage('testUrl');\n      expect(gaSpy).toHaveBeenCalledWith('set', 'page', '/testUrl');\n      expect(gaSpy).toHaveBeenCalledWith('send', 'pageview');\n    });\n  });\n\n  describe('sendEvent', () => {\n    it('should send \"event\" with associated data', () => {\n      gaService.sendEvent('some source', 'some campaign', 'a label', 45);\n      expect(gaSpy).toHaveBeenCalledWith('send', 'event', 'some source', 'some campaign', 'a label', 45);\n    });\n  });\n\n  it('should support replacing the `window.ga` function', () => {\n    const gaSpy2 = jasmine.createSpy('new ga');\n    mockWindow.ga = gaSpy2;\n    gaSpy.calls.reset();\n\n    gaService.sendPage('testUrl');\n    expect(gaSpy).not.toHaveBeenCalled();\n    expect(gaSpy2).toHaveBeenCalledWith('set', 'page', '/testUrl');\n    expect(gaSpy2).toHaveBeenCalledWith('send', 'pageview');\n  });\n});\n"
  },
  {
    "path": "apps/rxjs.dev/src/app/shared/ga.service.ts",
    "content": "import { Inject, Injectable } from '@angular/core';\n\nimport { environment } from '../../environments/environment';\nimport { WindowToken } from 'app/shared/window';\n\n@Injectable()\n/**\n * Google Analytics Service - captures app behaviors and sends them to Google Analytics (GA).\n * Presupposes that GA script has been loaded from a script on the host web page.\n * Associates data with a GA \"property\" from the environment (`gaId`).\n */\nexport class GaService {\n\n  private previousUrl: string;\n\n  constructor(@Inject(WindowToken) private window: Window) {\n    this.ga('create', environment.gaId , 'auto');\n  }\n\n  locationChanged(url: string) {\n    this.sendPage(url);\n  }\n\n  sendPage(url: string) {\n    // Won't re-send if the url hasn't changed.\n    if (url === this.previousUrl) { return; }\n    this.previousUrl = url;\n    this.ga('set', 'page', '/' + url);\n    this.ga('send', 'pageview');\n  }\n\n  sendEvent(source: string, action: string, label?: string, value?: number) {\n    this.ga('send', 'event', source, action, label, value);\n  }\n\n  ga(...args: any[]) {\n    const gaFn = (this.window as any).ga;\n    if (gaFn) {\n      gaFn(...args);\n    }\n  }\n}\n"
  },
  {
    "path": "apps/rxjs.dev/src/app/shared/location.service.spec.ts",
    "content": "import { ReflectiveInjector } from '@angular/core';\nimport { Location, LocationStrategy, PlatformLocation } from '@angular/common';\nimport { MockLocationStrategy } from '@angular/common/testing';\nimport { Subject } from 'rxjs';\n\nimport { GaService } from 'app/shared/ga.service';\nimport { SwUpdatesService } from 'app/sw-updates/sw-updates.service';\nimport { LocationService } from './location.service';\n\ndescribe('LocationService', () => {\n  let injector: ReflectiveInjector;\n  let location: MockLocationStrategy;\n  let service: LocationService;\n  let swUpdates: MockSwUpdatesService;\n\n  beforeEach(() => {\n    injector = ReflectiveInjector.resolveAndCreate([\n        LocationService,\n        Location,\n        { provide: GaService, useClass: TestGaService },\n        { provide: LocationStrategy, useClass: MockLocationStrategy },\n        { provide: PlatformLocation, useClass: MockPlatformLocation },\n        { provide: SwUpdatesService, useClass: MockSwUpdatesService }\n    ]);\n\n    location  = injector.get(LocationStrategy);\n    service  = injector.get(LocationService);\n    swUpdates  = injector.get(SwUpdatesService);\n  });\n\n  describe('currentUrl', () => {\n    it('should emit the latest url at the time it is subscribed to', () => {\n\n      location.simulatePopState('/initial-url1');\n      location.simulatePopState('/initial-url2');\n      location.simulatePopState('/initial-url3');\n\n      location.simulatePopState('/next-url1');\n      location.simulatePopState('/next-url2');\n      location.simulatePopState('/next-url3');\n\n      let initialUrl: string|undefined;\n      service.currentUrl.subscribe(url => initialUrl = url);\n      expect(initialUrl).toEqual('next-url3');\n    });\n\n    it('should emit all location changes after it has been subscribed to', () => {\n      location.simulatePopState('/initial-url1');\n      location.simulatePopState('/initial-url2');\n      location.simulatePopState('/initial-url3');\n\n      const urls: string[] = [];\n      service.currentUrl.subscribe(url => urls.push(url));\n\n      location.simulatePopState('/next-url1');\n      location.simulatePopState('/next-url2');\n      location.simulatePopState('/next-url3');\n\n      expect(urls).toEqual([\n        'initial-url3',\n        'next-url1',\n        'next-url2',\n        'next-url3'\n      ]);\n    });\n\n    it('should pass only the latest and later urls to each subscriber', () => {\n      location.simulatePopState('/initial-url1');\n      location.simulatePopState('/initial-url2');\n      location.simulatePopState('/initial-url3');\n\n      const urls1: string[] = [];\n      service.currentUrl.subscribe(url => urls1.push(url));\n\n      location.simulatePopState('/next-url1');\n      location.simulatePopState('/next-url2');\n\n      const urls2: string[] = [];\n      service.currentUrl.subscribe(url => urls2.push(url));\n\n      location.simulatePopState('/next-url3');\n\n      expect(urls1).toEqual([\n        'initial-url3',\n        'next-url1',\n        'next-url2',\n        'next-url3'\n      ]);\n\n      expect(urls2).toEqual([\n        'next-url2',\n        'next-url3'\n      ]);\n    });\n\n    it('should strip leading and trailing slashes', () => {\n      const urls: string[] = [];\n\n      service.currentUrl.subscribe(u => urls.push(u));\n\n      location.simulatePopState('///some/url1///');\n      location.simulatePopState('///some/url2///?foo=bar');\n      location.simulatePopState('///some/url3///#baz');\n      location.simulatePopState('///some/url4///?foo=bar#baz');\n\n      expect(urls.slice(-4)).toEqual([\n        'some/url1',\n        'some/url2?foo=bar',\n        'some/url3#baz',\n        'some/url4?foo=bar#baz'\n      ]);\n    });\n  });\n\n  describe('currentPath', () => {\n    it('should strip leading and trailing slashes off the url', () => {\n      const paths: string[] = [];\n\n      service.currentPath.subscribe(p => paths.push(p));\n\n      location.simulatePopState('///initial/url1///');\n      location.simulatePopState('///initial/url2///?foo=bar');\n      location.simulatePopState('///initial/url3///#baz');\n      location.simulatePopState('///initial/url4///?foo=bar#baz');\n\n      expect(paths.slice(-4)).toEqual([\n        'initial/url1',\n        'initial/url2',\n        'initial/url3',\n        'initial/url4'\n      ]);\n    });\n\n    it('should not strip other slashes off the url', () => {\n      const paths: string[] = [];\n\n      service.currentPath.subscribe(p => paths.push(p));\n\n      location.simulatePopState('initial///url1');\n      location.simulatePopState('initial///url2?foo=bar');\n      location.simulatePopState('initial///url3#baz');\n      location.simulatePopState('initial///url4?foo=bar#baz');\n\n      expect(paths.slice(-4)).toEqual([\n        'initial///url1',\n        'initial///url2',\n        'initial///url3',\n        'initial///url4'\n      ]);\n    });\n\n    it('should strip the query off the url', () => {\n      let path: string|undefined;\n\n      service.currentPath.subscribe(p => path = p);\n\n      location.simulatePopState('/initial/url1?foo=bar');\n\n      expect(path).toBe('initial/url1');\n    });\n\n    it('should strip the hash fragment off the url', () => {\n      const paths: string[] = [];\n\n      service.currentPath.subscribe(p => paths.push(p));\n\n      location.simulatePopState('/initial/url1#foo');\n      location.simulatePopState('/initial/url2?foo=bar#baz');\n\n      expect(paths.slice(-2)).toEqual([\n        'initial/url1',\n        'initial/url2'\n      ]);\n    });\n\n    it('should emit the latest path at the time it is subscribed to', () => {\n      location.simulatePopState('/initial/url1');\n      location.simulatePopState('/initial/url2');\n      location.simulatePopState('/initial/url3');\n\n      location.simulatePopState('/next/url1');\n      location.simulatePopState('/next/url2');\n      location.simulatePopState('/next/url3');\n\n      let initialPath: string|undefined;\n      service.currentPath.subscribe(path => initialPath = path);\n\n      expect(initialPath).toEqual('next/url3');\n    });\n\n    it('should emit all location changes after it has been subscribed to', () => {\n      location.simulatePopState('/initial/url1');\n      location.simulatePopState('/initial/url2');\n      location.simulatePopState('/initial/url3');\n\n      const paths: string[] = [];\n      service.currentPath.subscribe(path => paths.push(path));\n\n      location.simulatePopState('/next/url1');\n      location.simulatePopState('/next/url2');\n      location.simulatePopState('/next/url3');\n\n      expect(paths).toEqual([\n        'initial/url3',\n        'next/url1',\n        'next/url2',\n        'next/url3'\n      ]);\n    });\n\n    it('should pass only the latest and later paths to each subscriber', () => {\n      location.simulatePopState('/initial/url1');\n      location.simulatePopState('/initial/url2');\n      location.simulatePopState('/initial/url3');\n\n      const paths1: string[] = [];\n      service.currentPath.subscribe(path => paths1.push(path));\n\n      location.simulatePopState('/next/url1');\n      location.simulatePopState('/next/url2');\n\n      const paths2: string[] = [];\n      service.currentPath.subscribe(path => paths2.push(path));\n\n      location.simulatePopState('/next/url3');\n\n      expect(paths1).toEqual([\n        'initial/url3',\n        'next/url1',\n        'next/url2',\n        'next/url3'\n      ]);\n\n      expect(paths2).toEqual([\n        'next/url2',\n        'next/url3'\n      ]);\n    });\n  });\n\n  describe('go', () => {\n\n    it('should update the location', () => {\n      service.go('some-new-url');\n      expect(location.internalPath).toEqual('some-new-url');\n      expect(location.path(true)).toEqual('some-new-url');\n    });\n\n    it('should emit the new url', () => {\n      const urls: string[] = [];\n      service.go('some-initial-url');\n\n      service.currentUrl.subscribe(url => urls.push(url));\n      service.go('some-new-url');\n      expect(urls).toEqual([\n        'some-initial-url',\n        'some-new-url'\n      ]);\n    });\n\n    it('should strip leading and trailing slashes', () => {\n      let url: string|undefined;\n\n      service.currentUrl.subscribe(u => url = u);\n      service.go('/some/url/');\n\n      expect(location.internalPath).toEqual('some/url');\n      expect(location.path(true)).toEqual('some/url');\n      expect(url).toBe('some/url');\n    });\n\n    it('should ignore empty URL string', () => {\n        const initialUrl = 'some/url';\n        const goExternalSpy = spyOn(service, 'goExternal');\n        let url: string|undefined;\n\n        service.go(initialUrl);\n        service.currentUrl.subscribe(u => url = u);\n\n        service.go('');\n        expect(url).toEqual(initialUrl, 'should not have re-navigated locally');\n        expect(goExternalSpy).not.toHaveBeenCalled();\n    });\n\n    it('should leave the site for external url that starts with \"http\"', () => {\n      const goExternalSpy = spyOn(service, 'goExternal');\n      const externalUrl = 'http://some/far/away/land';\n      service.go(externalUrl);\n      expect(goExternalSpy).toHaveBeenCalledWith(externalUrl);\n    });\n\n    it('should do a \"full page navigation\" if a ServiceWorker update has been activated', () => {\n      const goExternalSpy = spyOn(service, 'goExternal');\n\n      // Internal URL - No ServiceWorker update\n      service.go('some-internal-url');\n      expect(goExternalSpy).not.toHaveBeenCalled();\n      expect(location.path(true)).toEqual('some-internal-url');\n\n      // Internal URL - ServiceWorker update\n      swUpdates.updateActivated.next('foo');\n      service.go('other-internal-url');\n      expect(goExternalSpy).toHaveBeenCalledWith('other-internal-url');\n      expect(location.path(true)).toEqual('some-internal-url');\n    });\n\n    it('should not update currentUrl for external url that starts with \"http\"', () => {\n      let localUrl: string|undefined;\n      spyOn(service, 'goExternal');\n      service.currentUrl.subscribe(url => localUrl = url);\n      service.go('https://some/far/away/land');\n      expect(localUrl).toBeFalsy('should not set local url');\n    });\n\n  });\n\n  describe('search', () => {\n    it('should read the query from the current location.path', () => {\n      location.simulatePopState('a/b/c?foo=bar&moo=car');\n      expect(service.search()).toEqual({ foo: 'bar', moo: 'car' });\n    });\n\n    it('should cope with an empty query', () => {\n      location.simulatePopState('a/b/c');\n      expect(service.search()).toEqual({ });\n\n      location.simulatePopState('x/y/z?');\n      expect(service.search()).toEqual({ });\n\n      location.simulatePopState('x/y/z?x=');\n      expect(service.search()).toEqual({ x: '' });\n\n      location.simulatePopState('x/y/z?x');\n      expect(service.search()).toEqual({ x: undefined });\n    });\n\n    it('should URL decode query values', () => {\n      location.simulatePopState('a/b/c?query=a%26b%2Bc%20d');\n      expect(service.search()).toEqual({ query: 'a&b+c d' });\n    });\n\n    it('should URL decode query keys', () => {\n      location.simulatePopState('a/b/c?a%26b%2Bc%20d=value');\n      expect(service.search()).toEqual({ 'a&b+c d': 'value' });\n    });\n\n    it('should cope with a hash on the URL', () => {\n      spyOn(location, 'path').and.callThrough();\n      service.search();\n      expect(location.path).toHaveBeenCalledWith(false);\n    });\n  });\n\n  describe('setSearch', () => {\n    let platformLocation: MockPlatformLocation;\n\n    beforeEach(() => {\n      platformLocation = injector.get(PlatformLocation);\n    });\n\n    it('should call replaceState on PlatformLocation', () => {\n      const params = {};\n      service.setSearch('Some label', params);\n      expect(platformLocation.replaceState).toHaveBeenCalledWith(jasmine.any(Object), 'Some label', 'a/b/c');\n    });\n\n    it('should convert the params to a query string', () => {\n      const params = { foo: 'bar', moo: 'car' };\n      service.setSearch('Some label', params);\n      expect(platformLocation.replaceState).toHaveBeenCalledWith(jasmine.any(Object), 'Some label', jasmine.any(String));\n      const [path, query] = platformLocation.replaceState.calls.mostRecent().args[2].split('?');\n      expect(path).toEqual('a/b/c');\n      expect(query).toContain('foo=bar');\n      expect(query).toContain('moo=car');\n    });\n\n    it('should URL encode param values', () => {\n      const params = { query: 'a&b+c d' };\n      service.setSearch('', params);\n      const [, query] = platformLocation.replaceState.calls.mostRecent().args[2].split('?');\n      expect(query).toContain('query=a%26b%2Bc%20d');\n    });\n\n    it('should URL encode param keys', () => {\n      const params = { 'a&b+c d': 'value' };\n      service.setSearch('', params);\n      const [, query] = platformLocation.replaceState.calls.mostRecent().args[2].split('?');\n      expect(query).toContain('a%26b%2Bc%20d=value');\n    });\n  });\n\n  describe('handleAnchorClick', () => {\n    let anchor: HTMLAnchorElement;\n\n    beforeEach(() => {\n      anchor = document.createElement('a');\n      spyOn(service, 'go');\n    });\n\n    describe('should try to navigate with go() when anchor clicked for', () => {\n      it('relative local url', () => {\n        anchor.href = 'some/local/url';\n        const result = service.handleAnchorClick(anchor);\n        expect(service.go).toHaveBeenCalledWith('/some/local/url');\n        expect(result).toBe(false);\n      });\n\n      it('absolute local url', () => {\n        anchor.href = '/some/local/url';\n        const result = service.handleAnchorClick(anchor);\n        expect(service.go).toHaveBeenCalledWith('/some/local/url');\n        expect(result).toBe(false);\n      });\n\n      it('local url with query params', () => {\n        anchor.href = 'some/local/url?query=xxx&other=yyy';\n        const result = service.handleAnchorClick(anchor);\n        expect(service.go).toHaveBeenCalledWith('/some/local/url?query=xxx&other=yyy');\n        expect(result).toBe(false);\n      });\n\n      it('local url with hash fragment', () => {\n        anchor.href = 'some/local/url#somefragment';\n        const result = service.handleAnchorClick(anchor);\n        expect(service.go).toHaveBeenCalledWith('/some/local/url#somefragment');\n        expect(result).toBe(false);\n      });\n\n      it('local url with query params and hash fragment', () => {\n        anchor.href = 'some/local/url?query=xxx&other=yyy#somefragment';\n        const result = service.handleAnchorClick(anchor);\n        expect(service.go).toHaveBeenCalledWith('/some/local/url?query=xxx&other=yyy#somefragment');\n        expect(result).toBe(false);\n      });\n\n      it('local url with period in a path segment but no extension', () => {\n        anchor.href = 'tut.or.ial/toh-p2';\n        const result = service.handleAnchorClick(anchor);\n        expect(service.go).toHaveBeenCalled();\n        expect(result).toBe(false);\n      });\n    });\n\n    describe('should let browser handle anchor click when', () => {\n      it('url is external to the site', () => {\n        anchor.href = 'http://other.com/some/local/url?query=xxx&other=yyy#somefragment';\n        let result = service.handleAnchorClick(anchor);\n        expect(service.go).not.toHaveBeenCalled();\n        expect(result).toBe(true);\n\n        anchor.href = 'some/local/url.pdf';\n        anchor.protocol = 'ftp';\n        result = service.handleAnchorClick(anchor);\n        expect(service.go).not.toHaveBeenCalled();\n        expect(result).toBe(true);\n      });\n\n      it('mouse button is not zero (middle or right)', () => {\n        anchor.href = 'some/local/url';\n        const result = service.handleAnchorClick(anchor, 1, false, false);\n        expect(service.go).not.toHaveBeenCalled();\n        expect(result).toBe(true);\n      });\n\n      it('ctrl key is pressed', () => {\n        anchor.href = 'some/local/url';\n        const result = service.handleAnchorClick(anchor, 0, true, false);\n        expect(service.go).not.toHaveBeenCalled();\n        expect(result).toBe(true);\n      });\n\n      it('meta key is pressed', () => {\n        anchor.href = 'some/local/url';\n        const result = service.handleAnchorClick(anchor, 0, false, true);\n        expect(service.go).not.toHaveBeenCalled();\n        expect(result).toBe(true);\n      });\n\n      it('anchor has (non-_self) target', () => {\n        anchor.href = 'some/local/url';\n        anchor.target = '_blank';\n        let result = service.handleAnchorClick(anchor);\n        expect(service.go).not.toHaveBeenCalled();\n        expect(result).toBe(true);\n\n        anchor.target = '_parent';\n        result = service.handleAnchorClick(anchor);\n        expect(service.go).not.toHaveBeenCalled();\n        expect(result).toBe(true);\n\n        anchor.target = '_top';\n        result = service.handleAnchorClick(anchor);\n        expect(service.go).not.toHaveBeenCalled();\n        expect(result).toBe(true);\n\n        anchor.target = 'other-frame';\n        result = service.handleAnchorClick(anchor);\n        expect(service.go).not.toHaveBeenCalled();\n        expect(result).toBe(true);\n\n        anchor.target = '_self';\n        result = service.handleAnchorClick(anchor);\n        expect(service.go).toHaveBeenCalledWith('/some/local/url');\n        expect(result).toBe(false);\n      });\n\n      it('zip url', () => {\n        anchor.href = 'tutorial/toh-p2.zip';\n        const result = service.handleAnchorClick(anchor);\n        expect(service.go).not.toHaveBeenCalled();\n        expect(result).toBe(true);\n      });\n\n      it('image or media url', () => {\n        anchor.href = 'cat-photo.png';\n        let result = service.handleAnchorClick(anchor);\n        expect(service.go).not.toHaveBeenCalled();\n        expect(result).toBe(true, 'png');\n\n        anchor.href = 'cat-photo.gif';\n        result = service.handleAnchorClick(anchor);\n        expect(service.go).not.toHaveBeenCalled();\n        expect(result).toBe(true, 'gif');\n\n        anchor.href = 'cat-photo.jpg';\n        result = service.handleAnchorClick(anchor);\n        expect(service.go).not.toHaveBeenCalled();\n        expect(result).toBe(true, 'jpg');\n\n        anchor.href = 'dog-bark.mp3';\n        result = service.handleAnchorClick(anchor);\n        expect(service.go).not.toHaveBeenCalled();\n        expect(result).toBe(true, 'mp3');\n\n        anchor.href = 'pet-tricks.mp4';\n        result = service.handleAnchorClick(anchor);\n        expect(service.go).not.toHaveBeenCalled();\n        expect(result).toBe(true, 'mp4');\n      });\n\n      it('url has any extension', () => {\n        anchor.href = 'tutorial/toh-p2.html';\n        const result = service.handleAnchorClick(anchor);\n        expect(service.go).not.toHaveBeenCalled();\n        expect(result).toBe(true);\n      });\n    });\n  });\n\n  describe('google analytics - GaService#locationChanged', () => {\n\n    let gaLocationChanged: jasmine.Spy;\n\n    beforeEach(() => {\n      const gaService = injector.get(GaService);\n      gaLocationChanged = gaService.locationChanged;\n      // execute currentPath observable so that gaLocationChanged is called\n      service.currentPath.subscribe();\n    });\n\n    it('should call locationChanged with initial URL', () => {\n      const initialUrl = location.path().replace(/^\\/+/, '');  // strip leading slashes\n\n      expect(gaLocationChanged.calls.count()).toBe(1, 'gaService.locationChanged');\n      const args = gaLocationChanged.calls.first().args;\n      expect(args[0]).toBe(initialUrl);\n    });\n\n    it('should call locationChanged when `go` to a page', () => {\n      service.go('some-new-url');\n      expect(gaLocationChanged.calls.count()).toBe(2, 'gaService.locationChanged');\n      const args = gaLocationChanged.calls.argsFor(1);\n      expect(args[0]).toBe('some-new-url');\n    });\n\n    it('should call locationChanged with url stripped of hash or query', () => {\n      // Important to keep GA service from sending tracking event when the doc hasn't changed\n      // e.g., when the user navigates within the page via # fragments.\n      service.go('some-new-url#one');\n      service.go('some-new-url#two');\n      service.go('some-new-url/?foo=\"true\"');\n      expect(gaLocationChanged.calls.count()).toBe(4, 'gaService.locationChanged called');\n      const args = gaLocationChanged.calls.allArgs();\n      expect(args[1]).toEqual(args[2], 'same url for hash calls');\n      expect(args[1]).toEqual(args[3], 'same url for query string call');\n    });\n\n    it('should call locationChanged when window history changes', () => {\n      location.simulatePopState('/next-url');\n\n      expect(gaLocationChanged.calls.count()).toBe(2, 'gaService.locationChanged');\n      const args = gaLocationChanged.calls.argsFor(1);\n      expect(args[0]).toBe('next-url');\n    });\n\n  });\n\n});\n\n/// Test Helpers ///\nclass MockPlatformLocation {\n  pathname = 'a/b/c';\n  replaceState = jasmine.createSpy('PlatformLocation.replaceState');\n}\n\nclass MockSwUpdatesService {\n  updateActivated = new Subject<string>();\n}\n\nclass TestGaService {\n  locationChanged = jasmine.createSpy('locationChanged');\n}\n"
  },
  {
    "path": "apps/rxjs.dev/src/app/shared/location.service.ts",
    "content": "import { Injectable } from '@angular/core';\nimport { Location, PlatformLocation } from '@angular/common';\n\nimport { ReplaySubject } from 'rxjs';\nimport { map, tap } from 'rxjs/operators';\n\nimport { GaService } from 'app/shared/ga.service';\nimport { SwUpdatesService } from 'app/sw-updates/sw-updates.service';\n\n@Injectable()\nexport class LocationService {\n\n  private readonly urlParser = document.createElement('a');\n  private urlSubject = new ReplaySubject<string>(1);\n  private swUpdateActivated = false;\n\n  currentUrl = this.urlSubject\n    .pipe(map(url => this.stripSlashes(url)));\n\n  currentPath = this.currentUrl.pipe(\n    map(url => (url.match(/[^?#]*/) || [])[0]),  // strip query and hash\n    tap(path => this.gaService.locationChanged(path)),\n  );\n\n  constructor(\n    private gaService: GaService,\n    private location: Location,\n    private platformLocation: PlatformLocation,\n    swUpdates: SwUpdatesService) {\n\n    this.urlSubject.next(location.path(true));\n\n    this.location.subscribe(state => this.urlSubject.next(state.url || ''));\n\n    swUpdates.updateActivated.subscribe(() => this.swUpdateActivated = true);\n  }\n\n  // TODO: ignore if url-without-hash-or-search matches current location?\n  go(url: string|null|undefined) {\n    if (!url) { return; }\n    url = this.stripSlashes(url);\n    if (/^http/.test(url) || this.swUpdateActivated) {\n      // Has http protocol so leave the site\n      // (or do a \"full page navigation\" if a ServiceWorker update has been activated)\n      this.goExternal(url);\n    } else {\n      this.location.go(url);\n      this.urlSubject.next(url);\n    }\n  }\n\n  goExternal(url: string) {\n    window.location.assign(url);\n  }\n\n  replace(url: string) {\n    window.location.replace(url);\n  }\n\n  private stripSlashes(url: string) {\n    return url.replace(/^\\/+/, '').replace(/\\/+(\\?|#|$)/, '$1');\n  }\n\n  search() {\n    const search: { [index: string]: string|undefined } = {};\n    const path = this.location.path();\n    const q = path.indexOf('?');\n    if (q > -1) {\n      try {\n          const params = path.substr(q + 1).split('&');\n          params.forEach(p => {\n            const pair = p.split('=');\n            if (pair[0]) {\n              search[decodeURIComponent(pair[0])] = pair[1] && decodeURIComponent(pair[1]);\n            }\n          });\n      } catch (e) { /* don't care */ }\n    }\n    return search;\n  }\n\n  setSearch(label: string, params: { [key: string]: string|undefined}) {\n    const search = Object.keys(params).reduce((acc, key) => {\n      const value = params[key];\n      return (value === undefined) ? acc :\n        acc += (acc ? '&' : '?') + `${encodeURIComponent(key)}=${encodeURIComponent(value)}`;\n    }, '');\n\n    this.platformLocation.replaceState({}, label, this.platformLocation.pathname + search);\n  }\n\n  /**\n   * Handle user's anchor click\n   *\n   * @param anchor {HTMLAnchorElement} - the anchor element clicked\n   * @param button Number of the mouse button held down. 0 means left or none\n   * @param ctrlKey True if control key held down\n   * @param metaKey True if command or window key held down\n   * @return false if service navigated with `go()`; true if browser should handle it.\n   *\n   * Since we are using `LocationService` to navigate between docs, without the browser\n   * reloading the page, we must intercept clicks on links.\n   * If the link is to a document that we will render, then we navigate using `Location.go()`\n   * and tell the browser not to handle the event.\n   *\n   * In most apps you might do this in a `LinkDirective` attached to anchors but in this app\n   * we have a special situation where the `DocViewerComponent` is displaying semi-static\n   * content that cannot contain directives. So all the links in that content would not be\n   * able to use such a `LinkDirective`. Instead we are adding a click handler to the\n   * `AppComponent`, whose element contains all the of the application and so captures all\n   * link clicks both inside and outside the `DocViewerComponent`.\n   */\n\n  handleAnchorClick(anchor: HTMLAnchorElement, button = 0, ctrlKey = false, metaKey = false) {\n\n    // Check for modifier keys and non-left-button, which indicate the user wants to control navigation\n    if (button !== 0 || ctrlKey || metaKey) {\n      return true;\n    }\n\n    // If there is a target and it is not `_self` then we take this\n    // as a signal that it doesn't want to be intercepted.\n    // TODO: should we also allow an explicit `_self` target to opt-out?\n    const anchorTarget = anchor.target;\n    if (anchorTarget && anchorTarget !== '_self') {\n      return true;\n    }\n\n    if (anchor.getAttribute('download') != null) {\n      return true; // let the download happen\n    }\n\n    const { pathname, search, hash } = anchor;\n    const relativeUrl = pathname + search + hash;\n    this.urlParser.href = relativeUrl;\n\n    // don't navigate if external link or has extension\n    if ( anchor.href !== this.urlParser.href ||\n         !/\\/[^/.]*$/.test(pathname) ) {\n      return true;\n    }\n\n    // approved for navigation\n    this.go(relativeUrl);\n    return false;\n  }\n}\n"
  },
  {
    "path": "apps/rxjs.dev/src/app/shared/logger.service.spec.ts",
    "content": "import { ErrorHandler, ReflectiveInjector } from '@angular/core';\nimport { Logger } from './logger.service';\n\ndescribe('logger service', () => {\n  let logSpy: jasmine.Spy;\n  let warnSpy: jasmine.Spy;\n  let logger: Logger;\n  let errorHandler: ErrorHandler;\n\n  beforeEach(() => {\n    logSpy = spyOn(console, 'log');\n    warnSpy = spyOn(console, 'warn');\n    const injector = ReflectiveInjector.resolveAndCreate([\n      Logger,\n      { provide: ErrorHandler, useClass: MockErrorHandler }\n    ]);\n    logger = injector.get(Logger);\n    errorHandler = injector.get(ErrorHandler);\n  });\n\n  describe('log', () => {\n    it('should delegate to console.log', () => {\n      logger.log('param1', 'param2', 'param3');\n      expect(logSpy).toHaveBeenCalledWith('param1', 'param2', 'param3');\n    });\n  });\n\n  describe('warn', () => {\n    it('should delegate to console.warn', () => {\n      logger.warn('param1', 'param2', 'param3');\n      expect(warnSpy).toHaveBeenCalledWith('param1', 'param2', 'param3');\n    });\n  });\n\n  describe('error', () => {\n    it('should delegate to ErrorHandler', () => {\n      const err = new Error('some error message');\n      logger.error(err);\n      expect(errorHandler.handleError).toHaveBeenCalledWith(err);\n    });\n  });\n});\n\n\nclass MockErrorHandler implements ErrorHandler {\n  handleError = jasmine.createSpy('handleError');\n}\n"
  },
  {
    "path": "apps/rxjs.dev/src/app/shared/logger.service.ts",
    "content": "import { ErrorHandler, Injectable } from '@angular/core';\nimport { environment } from '../../environments/environment';\n\n\n@Injectable()\nexport class Logger {\n\n  constructor(private errorHandler: ErrorHandler) {}\n\n  log(value: any, ...rest: any[]) {\n    if (!environment.production) {\n      console.log(value, ...rest);\n    }\n  }\n\n  error(error: Error) {\n    this.errorHandler.handleError(error);\n  }\n\n  warn(value: any, ...rest: any[]) {\n    console.warn(value, ...rest);\n  }\n}\n"
  },
  {
    "path": "apps/rxjs.dev/src/app/shared/reporting-error-handler.spec.ts",
    "content": "import { ErrorHandler, ReflectiveInjector } from '@angular/core';\nimport { TestBed } from '@angular/core/testing';\nimport { WindowToken } from 'app/shared/window';\nimport { AppModule } from 'app/app.module';\n\nimport { ReportingErrorHandler } from './reporting-error-handler';\n\ndescribe('ReportingErrorHandler service', () => {\n  let handler: ReportingErrorHandler;\n  let superHandler: jasmine.Spy;\n  let onerrorSpy: jasmine.Spy;\n\n  beforeEach(() => {\n    onerrorSpy = jasmine.createSpy('onerror');\n    superHandler = spyOn(ErrorHandler.prototype, 'handleError');\n\n    const injector = ReflectiveInjector.resolveAndCreate([\n      { provide: ErrorHandler, useClass: ReportingErrorHandler },\n      { provide: WindowToken, useFactory: () => ({ onerror: onerrorSpy }) }\n    ]);\n    handler = injector.get(ErrorHandler);\n  });\n\n  it('should be registered on the AppModule', () => {\n    handler = TestBed.configureTestingModule({ imports: [AppModule] }).get(ErrorHandler);\n    expect(handler).toEqual(jasmine.any(ReportingErrorHandler));\n  });\n\n  describe('handleError', () => {\n    it('should call the super class handleError', () => {\n      const error = new Error();\n      handler.handleError(error);\n      expect(superHandler).toHaveBeenCalledWith(error);\n    });\n\n    it('should cope with the super handler throwing an error', () => {\n      const error = new Error('initial error');\n      superHandler.and.throwError('super handler error');\n      handler.handleError(error);\n\n      expect(onerrorSpy).toHaveBeenCalledTimes(2);\n\n      // Error from super handler is reported first\n      expect(onerrorSpy.calls.argsFor(0)[0]).toEqual('super handler error');\n      expect(onerrorSpy.calls.argsFor(0)[4]).toEqual(jasmine.any(Error));\n\n      // Then error from initial exception\n      expect(onerrorSpy.calls.argsFor(1)[0]).toEqual('initial error');\n      expect(onerrorSpy.calls.argsFor(1)[4]).toEqual(error);\n    });\n\n    it('should send an error object to window.onerror', () => {\n      const error = new Error('this is an error message');\n      handler.handleError(error);\n      expect(onerrorSpy).toHaveBeenCalledWith(error.message, undefined, undefined, undefined, error);\n    });\n\n    it('should send an error string to window.onerror', () => {\n      const error = 'this is an error message';\n      handler.handleError(error);\n      expect(onerrorSpy).toHaveBeenCalledWith(error);\n    });\n  });\n});\n"
  },
  {
    "path": "apps/rxjs.dev/src/app/shared/reporting-error-handler.ts",
    "content": "import { ErrorHandler, Inject, Injectable } from '@angular/core';\nimport { WindowToken } from './window';\n\n/**\n * Extend the default error handling to report errors to an external service - e.g Google Analytics.\n *\n * Errors outside the Angular application may also be handled by `window.onerror`.\n */\n@Injectable()\nexport class ReportingErrorHandler extends ErrorHandler {\n\n  constructor(@Inject(WindowToken) private window: Window) {\n    super();\n  }\n\n  /**\n   * Send error info to Google Analytics, in addition to the default handling.\n   *\n   * @param error Information about the error.\n   */\n  override handleError(error: string | Error) {\n\n    try {\n      super.handleError(error);\n    } catch (e) {\n      this.reportError(e);\n    }\n    this.reportError(error);\n  }\n\n  private reportError(error: unknown) {\n    if (this.window.onerror) {\n      if (error instanceof Error) {\n        this.window.onerror(error.message, undefined, undefined, undefined, error);\n      } else {\n        if (typeof error === 'object') {\n          try {\n            error = JSON.stringify(error);\n          } catch {\n            // Ignore the error and just let it be stringified.\n          }\n        }\n        this.window.onerror(`${error}`);\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "apps/rxjs.dev/src/app/shared/scroll-spy.service.spec.ts",
    "content": "import { Injector, ReflectiveInjector } from '@angular/core';\nimport { fakeAsync, tick } from '@angular/core/testing';\nimport { DOCUMENT } from '@angular/common';\n\nimport { ScrollService } from 'app/shared/scroll.service';\nimport { ScrollItem, ScrollSpiedElement, ScrollSpiedElementGroup, ScrollSpyService } from 'app/shared/scroll-spy.service';\n\ndescribe('ScrollSpiedElement', () => {\n  it('should expose the spied element and index', () => {\n    const elem = {} as Element;\n    const spiedElem = new ScrollSpiedElement(elem, 42);\n\n    expect(spiedElem.element).toBe(elem);\n    expect(spiedElem.index).toBe(42);\n  });\n\n  describe('#calculateTop()', () => {\n    it('should calculate the `top` value', () => {\n      const elem = { getBoundingClientRect: () => ({ top: 100 }) } as Element;\n      const spiedElem = new ScrollSpiedElement(elem, 42);\n\n      spiedElem.calculateTop(0, 0);\n      expect(spiedElem.top).toBe(100);\n\n      spiedElem.calculateTop(20, 0);\n      expect(spiedElem.top).toBe(120);\n\n      spiedElem.calculateTop(0, 10);\n      expect(spiedElem.top).toBe(90);\n\n      spiedElem.calculateTop(20, 10);\n      expect(spiedElem.top).toBe(110);\n    });\n  });\n});\n\ndescribe('ScrollSpiedElementGroup', () => {\n  describe('#calibrate()', () => {\n    it('should calculate `top` for all spied elements', () => {\n      const spy = spyOn(ScrollSpiedElement.prototype, 'calculateTop');\n      const elems = [{}, {}, {}] as Element[];\n      const group = new ScrollSpiedElementGroup(elems);\n\n      expect(spy).not.toHaveBeenCalled();\n\n      group.calibrate(20, 10);\n      const callInfo = spy.calls.all();\n\n      expect(spy).toHaveBeenCalledTimes(3);\n      expect(callInfo[0].object.index).toBe(0);\n      expect(callInfo[1].object.index).toBe(1);\n      expect(callInfo[2].object.index).toBe(2);\n      expect(callInfo[0].args).toEqual([20, 10]);\n      expect(callInfo[1].args).toEqual([20, 10]);\n      expect(callInfo[2].args).toEqual([20, 10]);\n    });\n  });\n\n  describe('#onScroll()', () => {\n    let group: ScrollSpiedElementGroup;\n    let activeItems: (ScrollItem | null)[];\n\n    const activeIndices = () => activeItems.map((x) => x && x.index);\n\n    beforeEach(() => {\n      const tops = [50, 150, 100];\n\n      spyOn(ScrollSpiedElement.prototype, 'calculateTop').and.callFake(function(\n        this: ScrollSpiedElement,\n        scrollTop: number,\n        topOffset: number\n      ) {\n        this.top = tops[this.index];\n      });\n\n      activeItems = [];\n      group = new ScrollSpiedElementGroup([{}, {}, {}] as Element[]);\n      group.activeScrollItem.subscribe((item) => activeItems.push(item));\n      group.calibrate(20, 10);\n    });\n\n    it('should emit a `ScrollItem` on `activeScrollItem`', () => {\n      expect(activeItems.length).toBe(0);\n\n      group.onScroll(20, 140);\n      expect(activeItems.length).toBe(1);\n\n      group.onScroll(20, 140);\n      expect(activeItems.length).toBe(2);\n    });\n\n    it('should emit the lower-most element that is above `scrollTop`', () => {\n      group.onScroll(45, 200);\n      group.onScroll(55, 200);\n      expect(activeIndices()).toEqual([null, 0]);\n\n      activeItems.length = 0;\n      group.onScroll(95, 200);\n      group.onScroll(105, 200);\n      expect(activeIndices()).toEqual([0, 2]);\n\n      activeItems.length = 0;\n      group.onScroll(145, 200);\n      group.onScroll(155, 200);\n      expect(activeIndices()).toEqual([2, 1]);\n\n      activeItems.length = 0;\n      group.onScroll(75, 200);\n      group.onScroll(175, 200);\n      group.onScroll(125, 200);\n      group.onScroll(25, 200);\n      expect(activeIndices()).toEqual([0, 1, 2, null]);\n    });\n\n    it('should always emit the lower-most element if scrolled to the bottom', () => {\n      group.onScroll(140, 140);\n      group.onScroll(145, 140);\n      group.onScroll(138.5, 140);\n      group.onScroll(139.5, 140);\n\n      expect(activeIndices()).toEqual([1, 1, 2, 1]);\n    });\n\n    it('should emit null if all elements are below `scrollTop`', () => {\n      group.onScroll(0, 140);\n      expect(activeItems).toEqual([null]);\n\n      group.onScroll(49, 140);\n      expect(activeItems).toEqual([null, null]);\n    });\n\n    it('should emit null if there are no spied elements (even if scrolled to the bottom)', () => {\n      group = new ScrollSpiedElementGroup([]);\n      group.activeScrollItem.subscribe((item) => activeItems.push(item));\n\n      group.onScroll(20, 140);\n      expect(activeItems).toEqual([null]);\n\n      group.onScroll(140, 140);\n      expect(activeItems).toEqual([null, null]);\n\n      group.onScroll(145, 140);\n      expect(activeItems).toEqual([null, null, null]);\n    });\n  });\n});\n\ndescribe('ScrollSpyService', () => {\n  let injector: Injector;\n  let scrollSpyService: ScrollSpyService;\n\n  beforeEach(() => {\n    injector = ReflectiveInjector.resolveAndCreate([\n      { provide: DOCUMENT, useValue: { body: {} } },\n      { provide: ScrollService, useValue: { topOffset: 50 } },\n      ScrollSpyService,\n    ]);\n\n    scrollSpyService = injector.get(ScrollSpyService);\n  });\n\n  describe('#spyOn()', () => {\n    let getSpiedElemGroups: () => ScrollSpiedElementGroup[];\n\n    beforeEach(() => {\n      getSpiedElemGroups = () => (scrollSpyService as any).spiedElementGroups;\n    });\n\n    it('should create a `ScrollSpiedElementGroup` when called', () => {\n      expect(getSpiedElemGroups().length).toBe(0);\n\n      scrollSpyService.spyOn([]);\n      expect(getSpiedElemGroups().length).toBe(1);\n    });\n\n    it('should initialize the newly created `ScrollSpiedElementGroup`', () => {\n      const calibrateSpy = spyOn(ScrollSpiedElementGroup.prototype, 'calibrate');\n      const onScrollSpy = spyOn(ScrollSpiedElementGroup.prototype, 'onScroll');\n\n      scrollSpyService.spyOn([]);\n      expect(calibrateSpy).toHaveBeenCalledTimes(1);\n      expect(onScrollSpy).toHaveBeenCalledTimes(1);\n\n      scrollSpyService.spyOn([]);\n      expect(calibrateSpy).toHaveBeenCalledTimes(2);\n      expect(onScrollSpy).toHaveBeenCalledTimes(2);\n    });\n\n    it('should call `onResize()` if it is the first `ScrollSpiedElementGroup`', () => {\n      const actions: string[] = [];\n\n      const onResizeSpy = spyOn(ScrollSpyService.prototype as any, 'onResize').and.callFake(() => actions.push('onResize'));\n      const calibrateSpy = spyOn(ScrollSpiedElementGroup.prototype, 'calibrate').and.callFake(() => actions.push('calibrate'));\n\n      expect(onResizeSpy).not.toHaveBeenCalled();\n      expect(calibrateSpy).not.toHaveBeenCalled();\n\n      scrollSpyService.spyOn([]);\n      expect(actions).toEqual(['onResize', 'calibrate']);\n\n      scrollSpyService.spyOn([]);\n      expect(actions).toEqual(['onResize', 'calibrate', 'calibrate']);\n    });\n\n    it('should forward `ScrollSpiedElementGroup#activeScrollItem` as `active`', () => {\n      const activeIndices1: (number | null)[] = [];\n      const activeIndices2: (number | null)[] = [];\n\n      const info1 = scrollSpyService.spyOn([]);\n      const info2 = scrollSpyService.spyOn([]);\n      const spiedElemGroups = getSpiedElemGroups();\n\n      info1.active.subscribe((item) => activeIndices1.push(item && item.index));\n      info2.active.subscribe((item) => activeIndices2.push(item && item.index));\n      activeIndices1.length = 0;\n      activeIndices2.length = 0;\n\n      spiedElemGroups[0].activeScrollItem.next({ index: 1 } as ScrollItem);\n      spiedElemGroups[0].activeScrollItem.next({ index: 2 } as ScrollItem);\n      spiedElemGroups[1].activeScrollItem.next({ index: 3 } as ScrollItem);\n      spiedElemGroups[0].activeScrollItem.next(null);\n      spiedElemGroups[1].activeScrollItem.next({ index: 4 } as ScrollItem);\n      spiedElemGroups[1].activeScrollItem.next(null);\n      spiedElemGroups[0].activeScrollItem.next({ index: 5 } as ScrollItem);\n      spiedElemGroups[1].activeScrollItem.next({ index: 6 } as ScrollItem);\n\n      expect(activeIndices1).toEqual([1, 2, null, 5]);\n      expect(activeIndices2).toEqual([3, 4, null, 6]);\n    });\n\n    it('should remember and emit the last active item to new subscribers', () => {\n      const items = [{ index: 1 }, { index: 2 }, { index: 3 }] as ScrollItem[];\n      let lastActiveItem: ScrollItem | null;\n\n      const info = scrollSpyService.spyOn([]);\n      const spiedElemGroup = getSpiedElemGroups()[0];\n\n      spiedElemGroup.activeScrollItem.next(items[0]);\n      spiedElemGroup.activeScrollItem.next(items[1]);\n      spiedElemGroup.activeScrollItem.next(items[2]);\n      spiedElemGroup.activeScrollItem.next(null);\n      spiedElemGroup.activeScrollItem.next(items[1]);\n      info.active.subscribe((item) => (lastActiveItem = item));\n\n      expect(lastActiveItem!).toBe(items[1]);\n\n      spiedElemGroup.activeScrollItem.next(null);\n      info.active.subscribe((item) => (lastActiveItem = item));\n\n      expect(lastActiveItem!).toBeNull();\n    });\n\n    it('should only emit distinct values on `active`', () => {\n      const items = [{ index: 1 }, { index: 2 }] as ScrollItem[];\n      const activeIndices: (number | null)[] = [];\n\n      const info = scrollSpyService.spyOn([]);\n      const spiedElemGroup = getSpiedElemGroups()[0];\n\n      info.active.subscribe((item) => activeIndices.push(item && item.index));\n      activeIndices.length = 0;\n\n      spiedElemGroup.activeScrollItem.next(items[0]);\n      spiedElemGroup.activeScrollItem.next(items[0]);\n      spiedElemGroup.activeScrollItem.next(items[1]);\n      spiedElemGroup.activeScrollItem.next(items[1]);\n      spiedElemGroup.activeScrollItem.next(null);\n      spiedElemGroup.activeScrollItem.next(null);\n      spiedElemGroup.activeScrollItem.next(items[0]);\n      spiedElemGroup.activeScrollItem.next(items[1]);\n      spiedElemGroup.activeScrollItem.next(null);\n\n      expect(activeIndices).toEqual([1, 2, null, 1, 2, null]);\n    });\n\n    it('should remove the corresponding `ScrollSpiedElementGroup` when calling `unspy()`', () => {\n      const info1 = scrollSpyService.spyOn([]);\n      const info2 = scrollSpyService.spyOn([]);\n      const info3 = scrollSpyService.spyOn([]);\n      const groups = getSpiedElemGroups().slice();\n\n      expect(getSpiedElemGroups()).toEqual(groups);\n\n      info2.unspy();\n      expect(getSpiedElemGroups()).toEqual([groups[0], groups[2]]);\n\n      info1.unspy();\n      expect(getSpiedElemGroups()).toEqual([groups[2]]);\n\n      info3.unspy();\n      expect(getSpiedElemGroups()).toEqual([]);\n    });\n  });\n\n  describe('window resize events', () => {\n    const RESIZE_EVENT_DELAY = 300;\n    let onResizeSpy: jasmine.Spy;\n\n    beforeEach(() => {\n      onResizeSpy = spyOn(ScrollSpyService.prototype as any, 'onResize');\n    });\n\n    it('should be subscribed to when the first group of elements is spied on', fakeAsync(() => {\n      window.dispatchEvent(new Event('resize'));\n      expect(onResizeSpy).not.toHaveBeenCalled();\n\n      scrollSpyService.spyOn([]);\n      onResizeSpy.calls.reset();\n\n      window.dispatchEvent(new Event('resize'));\n      expect(onResizeSpy).not.toHaveBeenCalled();\n\n      tick(RESIZE_EVENT_DELAY);\n      expect(onResizeSpy).toHaveBeenCalled();\n    }));\n\n    it('should be unsubscribed from when the last group of elements is removed', fakeAsync(() => {\n      const info1 = scrollSpyService.spyOn([]);\n      const info2 = scrollSpyService.spyOn([]);\n      onResizeSpy.calls.reset();\n\n      window.dispatchEvent(new Event('resize'));\n      tick(RESIZE_EVENT_DELAY);\n      expect(onResizeSpy).toHaveBeenCalled();\n\n      info1.unspy();\n      onResizeSpy.calls.reset();\n\n      window.dispatchEvent(new Event('resize'));\n      tick(RESIZE_EVENT_DELAY);\n      expect(onResizeSpy).toHaveBeenCalled();\n\n      info2.unspy();\n      onResizeSpy.calls.reset();\n\n      window.dispatchEvent(new Event('resize'));\n      tick(RESIZE_EVENT_DELAY);\n      expect(onResizeSpy).not.toHaveBeenCalled();\n    }));\n\n    it(`should only fire every ${RESIZE_EVENT_DELAY}ms`, fakeAsync(() => {\n      scrollSpyService.spyOn([]);\n      onResizeSpy.calls.reset();\n\n      window.dispatchEvent(new Event('resize'));\n      tick(RESIZE_EVENT_DELAY - 2);\n      expect(onResizeSpy).not.toHaveBeenCalled();\n\n      window.dispatchEvent(new Event('resize'));\n      tick(1);\n      expect(onResizeSpy).not.toHaveBeenCalled();\n\n      window.dispatchEvent(new Event('resize'));\n      tick(1);\n      expect(onResizeSpy).toHaveBeenCalledTimes(1);\n\n      onResizeSpy.calls.reset();\n      tick(RESIZE_EVENT_DELAY / 2);\n\n      window.dispatchEvent(new Event('resize'));\n      tick(RESIZE_EVENT_DELAY - 2);\n      expect(onResizeSpy).not.toHaveBeenCalled();\n\n      window.dispatchEvent(new Event('resize'));\n      tick(1);\n      expect(onResizeSpy).not.toHaveBeenCalled();\n\n      window.dispatchEvent(new Event('resize'));\n      tick(1);\n      expect(onResizeSpy).toHaveBeenCalledTimes(1);\n    }));\n  });\n\n  describe('window scroll events', () => {\n    const SCROLL_EVENT_DELAY = 10;\n    let onScrollSpy: jasmine.Spy;\n\n    beforeEach(() => {\n      onScrollSpy = spyOn(ScrollSpyService.prototype as any, 'onScroll');\n    });\n\n    it('should be subscribed to when the first group of elements is spied on', fakeAsync(() => {\n      window.dispatchEvent(new Event('scroll'));\n      expect(onScrollSpy).not.toHaveBeenCalled();\n\n      scrollSpyService.spyOn([]);\n\n      window.dispatchEvent(new Event('scroll'));\n      expect(onScrollSpy).not.toHaveBeenCalled();\n\n      tick(SCROLL_EVENT_DELAY);\n      expect(onScrollSpy).toHaveBeenCalled();\n    }));\n\n    it('should be unsubscribed from when the last group of elements is removed', fakeAsync(() => {\n      const info1 = scrollSpyService.spyOn([]);\n      const info2 = scrollSpyService.spyOn([]);\n\n      window.dispatchEvent(new Event('scroll'));\n      tick(SCROLL_EVENT_DELAY);\n      expect(onScrollSpy).toHaveBeenCalled();\n\n      info1.unspy();\n      onScrollSpy.calls.reset();\n\n      window.dispatchEvent(new Event('scroll'));\n      tick(SCROLL_EVENT_DELAY);\n      expect(onScrollSpy).toHaveBeenCalled();\n\n      info2.unspy();\n      onScrollSpy.calls.reset();\n\n      window.dispatchEvent(new Event('scroll'));\n      tick(SCROLL_EVENT_DELAY);\n      expect(onScrollSpy).not.toHaveBeenCalled();\n    }));\n\n    it(`should only fire every ${SCROLL_EVENT_DELAY}ms`, fakeAsync(() => {\n      scrollSpyService.spyOn([]);\n\n      window.dispatchEvent(new Event('scroll'));\n      tick(SCROLL_EVENT_DELAY - 2);\n      expect(onScrollSpy).not.toHaveBeenCalled();\n\n      window.dispatchEvent(new Event('scroll'));\n      tick(1);\n      expect(onScrollSpy).not.toHaveBeenCalled();\n\n      window.dispatchEvent(new Event('scroll'));\n      tick(1);\n      expect(onScrollSpy).toHaveBeenCalledTimes(1);\n\n      onScrollSpy.calls.reset();\n      tick(SCROLL_EVENT_DELAY / 2);\n\n      window.dispatchEvent(new Event('scroll'));\n      tick(SCROLL_EVENT_DELAY - 2);\n      expect(onScrollSpy).not.toHaveBeenCalled();\n\n      window.dispatchEvent(new Event('scroll'));\n      tick(1);\n      expect(onScrollSpy).not.toHaveBeenCalled();\n\n      window.dispatchEvent(new Event('scroll'));\n      tick(1);\n      expect(onScrollSpy).toHaveBeenCalledTimes(1);\n    }));\n  });\n\n  describe('#onResize()', () => {\n    it('should re-calibrate each `ScrollSpiedElementGroup`', () => {\n      scrollSpyService.spyOn([]);\n      scrollSpyService.spyOn([]);\n      scrollSpyService.spyOn([]);\n\n      const spiedElemGroups: ScrollSpiedElementGroup[] = (scrollSpyService as any).spiedElementGroups;\n      const calibrateSpies = spiedElemGroups.map((group) => spyOn(group, 'calibrate'));\n\n      calibrateSpies.forEach((spy) => expect(spy).not.toHaveBeenCalled());\n\n      (scrollSpyService as any).onResize();\n      calibrateSpies.forEach((spy) => expect(spy).toHaveBeenCalled());\n    });\n  });\n\n  describe('#onScroll()', () => {\n    it('should propagate to each `ScrollSpiedElementGroup`', () => {\n      scrollSpyService.spyOn([]);\n      scrollSpyService.spyOn([]);\n      scrollSpyService.spyOn([]);\n\n      const spiedElemGroups: ScrollSpiedElementGroup[] = (scrollSpyService as any).spiedElementGroups;\n      const onScrollSpies = spiedElemGroups.map((group) => spyOn(group, 'onScroll'));\n\n      onScrollSpies.forEach((spy) => expect(spy).not.toHaveBeenCalled());\n\n      (scrollSpyService as any).onScroll();\n      onScrollSpies.forEach((spy) => expect(spy).toHaveBeenCalled());\n    });\n\n    it('should first re-calibrate if the content height has changed', () => {\n      const body = injector.get(DOCUMENT).body as any;\n\n      scrollSpyService.spyOn([]);\n      scrollSpyService.spyOn([]);\n      scrollSpyService.spyOn([]);\n\n      const spiedElemGroups: ScrollSpiedElementGroup[] = (scrollSpyService as any).spiedElementGroups;\n      const onScrollSpies = spiedElemGroups.map((group) => spyOn(group, 'onScroll'));\n      const calibrateSpies = spiedElemGroups.map((group, i) =>\n        spyOn(group, 'calibrate').and.callFake(() => expect(onScrollSpies[i]).not.toHaveBeenCalled())\n      );\n\n      calibrateSpies.forEach((spy) => expect(spy).not.toHaveBeenCalled());\n      onScrollSpies.forEach((spy) => expect(spy).not.toHaveBeenCalled());\n\n      // No content height change...\n      (scrollSpyService as any).onScroll();\n      calibrateSpies.forEach((spy) => expect(spy).not.toHaveBeenCalled());\n      onScrollSpies.forEach((spy) => expect(spy).toHaveBeenCalled());\n\n      onScrollSpies.forEach((spy) => spy.calls.reset());\n      body.scrollHeight = 100;\n\n      // Viewport changed...\n      (scrollSpyService as any).onScroll();\n      calibrateSpies.forEach((spy) => expect(spy).toHaveBeenCalled());\n      onScrollSpies.forEach((spy) => expect(spy).toHaveBeenCalled());\n    });\n  });\n});\n"
  },
  {
    "path": "apps/rxjs.dev/src/app/shared/scroll-spy.service.ts",
    "content": "import { Inject, Injectable } from '@angular/core';\nimport { DOCUMENT } from '@angular/common';\nimport { fromEvent, Observable, ReplaySubject, Subject } from 'rxjs';\nimport { auditTime, distinctUntilChanged, takeUntil } from 'rxjs/operators';\n\nimport { ScrollService } from 'app/shared/scroll.service';\n\n\nexport interface ScrollItem {\n  element: Element;\n  index: number;\n}\n\nexport interface ScrollSpyInfo {\n  active: Observable<ScrollItem | null>;\n  unspy: () => void;\n}\n\n/*\n * Represents a \"scroll-spied\" element. Contains info and methods for determining whether this\n * element is the active one (i.e. whether it has been scrolled passed), based on the window's\n * scroll position.\n *\n * @prop {Element} element - The element whose position relative to the viewport is tracked.\n * @prop {number}  index   - The index of the element in the original list of element (group).\n * @prop {number}  top     - The `scrollTop` value at which this element becomes active.\n */\nexport class ScrollSpiedElement implements ScrollItem {\n  top = 0;\n\n  /*\n   * @constructor\n   * @param {Element} element - The element whose position relative to the viewport is tracked.\n   * @param {number}  index   - The index of the element in the original list of element (group).\n   */\n  constructor(public readonly element: Element, public readonly index: number) {}\n\n  /*\n   * @method\n   * Calculate the `top` value, i.e. the value of the `scrollTop` property at which this element\n   * becomes active. The current implementation assumes that window is the scroll-container.\n   *\n   * @param {number} scrollTop - How much is window currently scrolled (vertically).\n   * @param {number} topOffset - The distance from the top at which the element becomes active.\n   */\n  calculateTop(scrollTop: number, topOffset: number) {\n    this.top = scrollTop + this.element.getBoundingClientRect().top - topOffset;\n  }\n}\n\n/*\n * Represents a group of \"scroll-spied\" elements. Contains info and methods for efficiently\n * determining which element should be considered \"active\", i.e. which element has been scrolled\n * passed the top of the viewport.\n *\n * @prop {Observable<ScrollItem | null>} activeScrollItem - An observable that emits ScrollItem\n *     elements (containing the HTML element and its original index) identifying the latest \"active\"\n *     element from a list of elements.\n */\nexport class ScrollSpiedElementGroup {\n  activeScrollItem: ReplaySubject<ScrollItem | null> = new ReplaySubject(1);\n  private spiedElements: ScrollSpiedElement[];\n\n  /*\n   * @constructor\n   * @param {Element[]} elements - A list of elements whose position relative to the viewport will\n   *     be tracked, in order to determine which one is \"active\" at any given moment.\n   */\n  constructor(elements: Element[]) {\n    this.spiedElements = elements.map((elem, i) => new ScrollSpiedElement(elem, i));\n  }\n\n  /*\n   * @method\n   * Calculate the `top` value of each ScrollSpiedElement of this group (based on te current\n   * `scrollTop` and `topOffset` values), so that the active element can be later determined just by\n   * comparing its `top` property with the then current `scrollTop`.\n   *\n   * @param {number} scrollTop - How much is window currently scrolled (vertically).\n   * @param {number} topOffset - The distance from the top at which the element becomes active.\n   */\n  calibrate(scrollTop: number, topOffset: number) {\n    this.spiedElements.forEach(spiedElem => spiedElem.calculateTop(scrollTop, topOffset));\n    this.spiedElements.sort((a, b) => b.top - a.top);   // Sort in descending `top` order.\n  }\n\n  /*\n   * @method\n   * Determine which element is the currently active one, i.e. the lower-most element that is\n   * scrolled passed the top of the viewport (taking offsets into account) and emit it on\n   * `activeScrollItem`.\n   * If no element can be considered active, `null` is emitted instead.\n   * If window is scrolled all the way to the bottom, then the lower-most element is considered\n   * active even if it not scrolled passed the top of the viewport.\n   *\n   * @param {number} scrollTop    - How much is window currently scrolled (vertically).\n   * @param {number} maxScrollTop - The maximum possible `scrollTop` (based on the viewport size).\n   */\n  onScroll(scrollTop: number, maxScrollTop: number) {\n    let activeItem: ScrollItem|undefined;\n\n    if (scrollTop + 1 >= maxScrollTop) {\n      activeItem = this.spiedElements[0];\n    } else {\n      this.spiedElements.some(spiedElem => {\n        if (spiedElem.top <= scrollTop) {\n          activeItem = spiedElem;\n          return true;\n        }\n        return false;\n      });\n    }\n\n    this.activeScrollItem.next(activeItem || null);\n  }\n}\n\n@Injectable()\nexport class ScrollSpyService {\n  private spiedElementGroups: ScrollSpiedElementGroup[] = [];\n  private onStopListening = new Subject();\n  private resizeEvents = fromEvent(window, 'resize').pipe(auditTime(300), takeUntil(this.onStopListening));\n  private scrollEvents = fromEvent(window, 'scroll').pipe(auditTime(10), takeUntil(this.onStopListening));\n  private lastContentHeight: number;\n  private lastMaxScrollTop: number;\n\n  constructor(@Inject(DOCUMENT) private doc: any, private scrollService: ScrollService) {}\n\n  /*\n   * @method\n   * Start tracking a group of elements and emitting active elements; i.e. elements that are\n   * currently visible in the viewport. If there was no other group being spied, start listening for\n   * `resize` and `scroll` events.\n   *\n   * @param {Element[]} elements - A list of elements to track.\n   *\n   * @return {ScrollSpyInfo} - An object containing the following properties:\n   *     - `active`: An observable of distinct ScrollItems.\n   *     - `unspy`: A method to stop tracking this group of elements.\n   */\n  spyOn(elements: Element[]): ScrollSpyInfo {\n    if (!this.spiedElementGroups.length) {\n      this.resizeEvents.subscribe(() => this.onResize());\n      this.scrollEvents.subscribe(() => this.onScroll());\n      this.onResize();\n    }\n\n    const scrollTop = this.getScrollTop();\n    const topOffset = this.getTopOffset();\n    const maxScrollTop = this.lastMaxScrollTop;\n\n    const spiedGroup = new ScrollSpiedElementGroup(elements);\n    spiedGroup.calibrate(scrollTop, topOffset);\n    spiedGroup.onScroll(scrollTop, maxScrollTop);\n\n    this.spiedElementGroups.push(spiedGroup);\n\n    return {\n      active: spiedGroup.activeScrollItem.asObservable().pipe(distinctUntilChanged()),\n      unspy: () => this.unspy(spiedGroup)\n    };\n  }\n\n  private getContentHeight() {\n    return this.doc.body.scrollHeight || Number.MAX_SAFE_INTEGER;\n  }\n\n  private getScrollTop() {\n    return window && window.pageYOffset || 0;\n  }\n\n  private getTopOffset() {\n    return this.scrollService.topOffset + 50;\n  }\n\n  private getViewportHeight() {\n    return this.doc.body.clientHeight || 0;\n  }\n\n  /*\n   * @method\n   * The size of the window has changed. Re-calculate all affected values,\n   * so that active elements can be determined efficiently on scroll.\n   */\n  private onResize() {\n    const contentHeight = this.getContentHeight();\n    const viewportHeight = this.getViewportHeight();\n    const scrollTop = this.getScrollTop();\n    const topOffset = this.getTopOffset();\n\n    this.lastContentHeight = contentHeight;\n    this.lastMaxScrollTop = contentHeight - viewportHeight;\n\n    this.spiedElementGroups.forEach(group => group.calibrate(scrollTop, topOffset));\n  }\n\n  /*\n   * @method\n   * Determine which element for each ScrollSpiedElementGroup is active. If the content height has\n   * changed since last check, re-calculate all affected values first.\n   */\n  private onScroll() {\n    if (this.lastContentHeight !== this.getContentHeight()) {\n      // Something has caused the scroll height to change.\n      // (E.g. image downloaded, accordion expanded/collapsed etc.)\n      this.onResize();\n    }\n\n    const scrollTop = this.getScrollTop();\n    const maxScrollTop = this.lastMaxScrollTop;\n    this.spiedElementGroups.forEach(group => group.onScroll(scrollTop, maxScrollTop));\n  }\n\n  /*\n   * @method\n   * Stop tracking this group of elements and emitting active elements. If there is no other group\n   * being spied, stop listening for `resize` or `scroll` events.\n   *\n   * @param {ScrollSpiedElementGroup} spiedGroup - The group to stop tracking.\n   */\n  private unspy(spiedGroup: ScrollSpiedElementGroup) {\n    spiedGroup.activeScrollItem.complete();\n    this.spiedElementGroups = this.spiedElementGroups.filter(group => group !== spiedGroup);\n\n    if (!this.spiedElementGroups.length) {\n      this.onStopListening.next(null);\n    }\n  }\n}\n"
  },
  {
    "path": "apps/rxjs.dev/src/app/shared/scroll.service.spec.ts",
    "content": "import { ReflectiveInjector } from '@angular/core';\nimport { Location, LocationStrategy, PlatformLocation, ViewportScroller } from '@angular/common';\nimport { DOCUMENT } from '@angular/common';\nimport { MockLocationStrategy, SpyLocation } from '@angular/common/testing';\nimport { fakeAsync, tick } from '@angular/core/testing';\n\nimport { ScrollService, topMargin } from './scroll.service';\n\ndescribe('ScrollService', () => {\n  const topOfPageElem = {} as Element;\n  let injector: ReflectiveInjector;\n  let document: MockDocument;\n  let platformLocation: MockPlatformLocation;\n  let scrollService: ScrollService;\n  let location: SpyLocation;\n\n  class MockPlatformLocation {\n    hash: string;\n  }\n\n  class MockDocument {\n    body = new MockElement();\n    getElementById = jasmine.createSpy('Document getElementById').and.returnValue(topOfPageElem);\n    querySelector = jasmine.createSpy('Document querySelector');\n  }\n\n  class MockElement {\n    getBoundingClientRect = jasmine.createSpy('Element getBoundingClientRect')\n                                   .and.returnValue({top: 0});\n    scrollIntoView = jasmine.createSpy('Element scrollIntoView');\n  }\n\n  const viewportScrollerStub = jasmine.createSpyObj(\n    'viewportScroller',\n    ['getScrollPosition', 'scrollToPosition']);\n\n  beforeEach(() => {\n    injector = ReflectiveInjector.resolveAndCreate([\n        ScrollService,\n        { provide: Location, useClass: SpyLocation },\n        { provide: DOCUMENT, useClass: MockDocument },\n        { provide: PlatformLocation, useClass: MockPlatformLocation },\n        { provide: ViewportScroller, useValue: viewportScrollerStub },\n        { provide: LocationStrategy, useClass: MockLocationStrategy }\n    ]);\n    platformLocation = injector.get(PlatformLocation);\n    document = injector.get(DOCUMENT);\n    scrollService = injector.get(ScrollService);\n    location = injector.get(Location);\n\n    spyOn(window, 'scrollBy');\n  });\n\n  it('should debounce `updateScrollPositonInHistory()`', fakeAsync(() => {\n    const updateScrollPositionInHistorySpy = spyOn(scrollService, 'updateScrollPositionInHistory');\n\n    window.dispatchEvent(new Event('scroll'));\n    tick(249);\n    window.dispatchEvent(new Event('scroll'));\n    tick(249);\n    window.dispatchEvent(new Event('scroll'));\n    tick(249);\n    expect(updateScrollPositionInHistorySpy).not.toHaveBeenCalled();\n    tick(1);\n    expect(updateScrollPositionInHistorySpy).toHaveBeenCalledTimes(1);\n  }));\n\n  it('should set `scrollRestoration` to `manual` if supported', () => {\n    if (scrollService.supportManualScrollRestoration) {\n      expect(window.history.scrollRestoration).toBe('manual');\n    } else {\n      expect(window.history.scrollRestoration).toBeUndefined();\n    }\n  });\n\n  describe('#topOffset', () => {\n    it('should query for the top-bar by CSS selector', () => {\n      expect(document.querySelector).not.toHaveBeenCalled();\n\n      expect(scrollService.topOffset).toBe(topMargin);\n      expect(document.querySelector).toHaveBeenCalled();\n    });\n\n    it('should be calculated based on the top-bar\\'s height + margin', () => {\n      (document.querySelector as jasmine.Spy).and.returnValue({clientHeight: 50});\n      expect(scrollService.topOffset).toBe(50 + topMargin);\n    });\n\n    it('should only query for the top-bar once', () => {\n      expect(scrollService.topOffset).toBe(topMargin);\n      (document.querySelector as jasmine.Spy).calls.reset();\n\n      expect(scrollService.topOffset).toBe(topMargin);\n      expect(document.querySelector).not.toHaveBeenCalled();\n    });\n\n    it('should retrieve the top-bar\\'s height again after resize', () => {\n      let clientHeight = 50;\n      (document.querySelector as jasmine.Spy).and.callFake(() => ({clientHeight}));\n\n      expect(scrollService.topOffset).toBe(50 + topMargin);\n      expect(document.querySelector).toHaveBeenCalled();\n\n      (document.querySelector as jasmine.Spy).calls.reset();\n      clientHeight = 100;\n\n      expect(scrollService.topOffset).toBe(50 + topMargin);\n      expect(document.querySelector).not.toHaveBeenCalled();\n\n      window.dispatchEvent(new Event('resize'));\n\n      expect(scrollService.topOffset).toBe(100 + topMargin);\n      expect(document.querySelector).toHaveBeenCalled();\n    });\n  });\n\n  describe('#topOfPageElement', () => {\n    it('should query for the top-of-page element by ID', () => {\n      expect(document.getElementById).not.toHaveBeenCalled();\n\n      expect(scrollService.topOfPageElement).toBe(topOfPageElem);\n      expect(document.getElementById).toHaveBeenCalled();\n    });\n\n    it('should only query for the top-of-page element once', () => {\n      expect(scrollService.topOfPageElement).toBe(topOfPageElem);\n      (document.getElementById as jasmine.Spy).calls.reset();\n\n      expect(scrollService.topOfPageElement).toBe(topOfPageElem);\n      expect(document.getElementById).not.toHaveBeenCalled();\n    });\n\n    it('should return `<body>` if unable to find the top-of-page element', () => {\n      (document.getElementById as jasmine.Spy).and.returnValue(null);\n      expect(scrollService.topOfPageElement).toBe(document.body as any);\n    });\n  });\n\n  describe('#scroll', () => {\n    it('should scroll to the top if there is no hash', () => {\n      platformLocation.hash = '';\n\n      const topOfPage = new MockElement();\n      document.getElementById.and\n              .callFake((id: string) => id === 'top-of-page' ? topOfPage : null);\n\n      scrollService.scroll();\n      expect(topOfPage.scrollIntoView).toHaveBeenCalled();\n    });\n\n    it('should not scroll if the hash does not match an element id', () => {\n      platformLocation.hash = 'not-found';\n      document.getElementById.and.returnValue(null);\n\n      scrollService.scroll();\n      expect(document.getElementById).toHaveBeenCalledWith('not-found');\n      expect(window.scrollBy).not.toHaveBeenCalled();\n    });\n\n    it('should scroll to the element whose id matches the hash', () => {\n      const element = new MockElement();\n      platformLocation.hash = 'some-id';\n      document.getElementById.and.returnValue(element);\n\n      scrollService.scroll();\n      expect(document.getElementById).toHaveBeenCalledWith('some-id');\n      expect(element.scrollIntoView).toHaveBeenCalled();\n      expect(window.scrollBy).toHaveBeenCalled();\n    });\n\n    it('should scroll to the element whose id matches the hash with encoded characters', () => {\n      const element = new MockElement();\n      platformLocation.hash = '%F0%9F%91%8D'; // 👍\n      document.getElementById.and.returnValue(element);\n\n      scrollService.scroll();\n      expect(document.getElementById).toHaveBeenCalledWith('👍');\n      expect(element.scrollIntoView).toHaveBeenCalled();\n      expect(window.scrollBy).toHaveBeenCalled();\n    });\n  });\n\n  describe('#scrollToElement', () => {\n    it('should scroll to element', () => {\n      const element: Element = new MockElement() as any;\n      scrollService.scrollToElement(element);\n      expect(element.scrollIntoView).toHaveBeenCalled();\n      expect(window.scrollBy).toHaveBeenCalledWith(0, -scrollService.topOffset);\n    });\n\n    it('should not scroll more than necessary (e.g. for elements close to the bottom)', () => {\n      const element: Element = new MockElement() as any;\n      const getBoundingClientRect = element.getBoundingClientRect as jasmine.Spy;\n      const topOffset = scrollService.topOffset;\n\n      getBoundingClientRect.and.returnValue({top: topOffset + 100});\n      scrollService.scrollToElement(element);\n      expect(element.scrollIntoView).toHaveBeenCalledTimes(1);\n      expect(window.scrollBy).toHaveBeenCalledWith(0, 100);\n\n      getBoundingClientRect.and.returnValue({top: topOffset - 10});\n      scrollService.scrollToElement(element);\n      expect(element.scrollIntoView).toHaveBeenCalledTimes(2);\n      expect(window.scrollBy).toHaveBeenCalledWith(0, -10);\n    });\n\n    it('should scroll all the way to the top if close enough', () => {\n      const element: Element = new MockElement() as any;\n\n      (window as any).pageYOffset = 25;\n      scrollService.scrollToElement(element);\n\n      expect(element.scrollIntoView).toHaveBeenCalled();\n      expect(window.scrollBy).toHaveBeenCalledWith(0, -scrollService.topOffset);\n      (window.scrollBy as jasmine.Spy).calls.reset();\n\n      (window as any).pageYOffset = 15;\n      scrollService.scrollToElement(element);\n\n      expect(element.scrollIntoView).toHaveBeenCalled();\n      expect(window.scrollBy).toHaveBeenCalledWith(0, -scrollService.topOffset);\n      expect(window.scrollBy).toHaveBeenCalledWith(0, -15);\n    });\n\n    it('should do nothing if no element', () => {\n      scrollService.scrollToElement(null);\n      expect(window.scrollBy).not.toHaveBeenCalled();\n    });\n  });\n\n  describe('#scrollToTop', () => {\n    it('should scroll to top', () => {\n      const topOfPageElement = new MockElement() as any as Element;\n      document.getElementById.and.callFake(\n        (id: string) => id === 'top-of-page' ? topOfPageElement : null\n      );\n\n      scrollService.scrollToTop();\n      expect(topOfPageElement.scrollIntoView).toHaveBeenCalled();\n      expect(window.scrollBy).toHaveBeenCalledWith(0, -topMargin);\n    });\n  });\n\n  describe('#isLocationWithHash', () => {\n    it('should return true when the location has a hash', () => {\n      platformLocation.hash = 'anchor';\n      expect(scrollService.isLocationWithHash()).toBe(true);\n    });\n\n    it('should return false when the location has no hash', () => {\n      platformLocation.hash = '';\n      expect(scrollService.isLocationWithHash()).toBe(false);\n    });\n  });\n\n  describe('#needToFixScrollPosition', async () => {\n    it('should return true when popState event was fired after a back navigation if the browser supports ' +\n      'scrollRestoration`. Otherwise, needToFixScrollPosition() returns false', () => {\n\n      if (scrollService.supportManualScrollRestoration) {\n        location.go('/initial-url1');\n        // We simulate a scroll down\n        location.replaceState('/initial-url1', 'hack', {scrollPosition: [2000, 0]});\n        location.go('/initial-url2');\n        location.back();\n\n        expect(scrollService.poppedStateScrollPosition).toEqual([2000, 0]);\n        expect(scrollService.needToFixScrollPosition()).toBe(true);\n      } else {\n        location.go('/initial-url1');\n        location.go('/initial-url2');\n        location.back();\n\n        expect(scrollService.poppedStateScrollPosition).toBe(null);\n        expect(scrollService.needToFixScrollPosition()).toBe(false);\n      }\n\n    });\n\n    it('should return true when popState event was fired after a forward navigation if the browser supports ' +\n      'scrollRestoration`. Otherwise, needToFixScrollPosition() returns false', () => {\n\n      if (scrollService.supportManualScrollRestoration) {\n        location.go('/initial-url1');\n        location.go('/initial-url2');\n        // We simulate a scroll down\n        location.replaceState('/initial-url1', 'hack', {scrollPosition: [2000, 0]});\n\n        location.back();\n        scrollService.poppedStateScrollPosition = [0, 0];\n        location.forward();\n\n        expect(scrollService.poppedStateScrollPosition).toEqual([2000, 0]);\n        expect(scrollService.needToFixScrollPosition()).toBe(true);\n      } else {\n        location.go('/initial-url1');\n        location.go('/initial-url2');\n        location.back();\n        location.forward();\n\n        expect(scrollService.poppedStateScrollPosition).toBe(null);\n        expect(scrollService.needToFixScrollPosition()).toBe(false);\n      }\n\n    });\n  });\n\n  describe('#scrollAfterRender', async () => {\n\n    let scrollSpy: jasmine.Spy;\n    let scrollToTopSpy: jasmine.Spy;\n    let needToFixScrollPositionSpy: jasmine.Spy;\n    let scrollToPosition: jasmine.Spy;\n    let isLocationWithHashSpy: jasmine.Spy;\n    let getStoredScrollPositionSpy: jasmine.Spy;\n    const scrollDelay = 500;\n\n    beforeEach(() => {\n      scrollSpy = spyOn(scrollService, 'scroll');\n      scrollToTopSpy = spyOn(scrollService, 'scrollToTop');\n      scrollToPosition = spyOn(scrollService, 'scrollToPosition');\n      needToFixScrollPositionSpy = spyOn(scrollService, 'needToFixScrollPosition');\n      getStoredScrollPositionSpy = spyOn(scrollService, 'getStoredScrollPosition');\n      isLocationWithHashSpy = spyOn(scrollService, 'isLocationWithHash');\n    });\n\n\n    it('should call `scroll` when we navigate to a location with anchor', fakeAsync(() => {\n      needToFixScrollPositionSpy.and.returnValue(false);\n      getStoredScrollPositionSpy.and.returnValue(null);\n      isLocationWithHashSpy.and.returnValue(true);\n\n      scrollService.scrollAfterRender(scrollDelay);\n\n      expect(scrollSpy).not.toHaveBeenCalled();\n      tick(scrollDelay);\n      expect(scrollSpy).toHaveBeenCalled();\n    }));\n\n    it('should call `scrollToTop` when we navigate to a location without anchor', fakeAsync(() => {\n      needToFixScrollPositionSpy.and.returnValue(false);\n      getStoredScrollPositionSpy.and.returnValue(null);\n      isLocationWithHashSpy.and.returnValue(false);\n\n      scrollService.scrollAfterRender(scrollDelay);\n\n      expect(scrollToTopSpy).toHaveBeenCalled();\n      tick(scrollDelay);\n      expect(scrollSpy).not.toHaveBeenCalled();\n    }));\n\n    it('should call `viewportScroller.scrollToPosition` when we reload a page', fakeAsync(() => {\n      getStoredScrollPositionSpy.and.returnValue([0, 1000]);\n\n      scrollService.scrollAfterRender(scrollDelay);\n\n      expect(viewportScrollerStub.scrollToPosition).toHaveBeenCalled();\n      expect(getStoredScrollPositionSpy).toHaveBeenCalled();\n    }));\n\n    it('should call `scrollToPosition` after a popState', fakeAsync(() => {\n      needToFixScrollPositionSpy.and.returnValue(true);\n      getStoredScrollPositionSpy.and.returnValue(null);\n      scrollService.scrollAfterRender(scrollDelay);\n      expect(scrollToPosition).toHaveBeenCalled();\n      tick(scrollDelay);\n      expect(scrollSpy).not.toHaveBeenCalled();\n      expect(scrollToTopSpy).not.toHaveBeenCalled();\n    }));\n  });\n});\n"
  },
  {
    "path": "apps/rxjs.dev/src/app/shared/scroll.service.ts",
    "content": "import { DOCUMENT, Location, PlatformLocation, PopStateEvent, ViewportScroller } from '@angular/common';\nimport { Injectable, Inject } from '@angular/core';\nimport { fromEvent } from 'rxjs';\nimport { debounceTime } from 'rxjs/operators';\n\ntype ScrollPosition = [number, number];\ninterface ScrollPositionPopStateEvent extends PopStateEvent {\n  // If there is history state, it should always include `scrollPosition`.\n  state?: {scrollPosition: ScrollPosition};\n}\n\nexport const topMargin = 16;\n/**\n * A service that scrolls document elements into view\n */\n@Injectable()\nexport class ScrollService {\n\n  private _topOffset: number | null;\n  private _topOfPageElement: Element;\n\n  // The scroll position which has to be restored, after a `popstate` event.\n  poppedStateScrollPosition: ScrollPosition | null = null;\n  // Whether the browser supports the necessary features for manual scroll restoration.\n  supportManualScrollRestoration: boolean =\n      !!window && ('scrollTo' in window) && ('scrollX' in window) && ('scrollY' in window) &&\n      !!history && ('scrollRestoration' in history);\n\n  // Offset from the top of the document to bottom of any static elements\n  // at the top (e.g. toolbar) + some margin\n  get topOffset() {\n    if (!this._topOffset) {\n      const toolbar = this.document.querySelector('.app-toolbar');\n      this._topOffset = (toolbar && toolbar.clientHeight || 0) + topMargin;\n    }\n    return this._topOffset!;\n  }\n\n  get topOfPageElement() {\n    if (!this._topOfPageElement) {\n      this._topOfPageElement = this.document.getElementById('top-of-page') || this.document.body;\n    }\n    return this._topOfPageElement;\n  }\n\n  constructor(\n      @Inject(DOCUMENT) private document: any,\n      private platformLocation: PlatformLocation,\n      private viewportScroller: ViewportScroller,\n      private location: Location) {\n    // On resize, the toolbar might change height, so \"invalidate\" the top offset.\n    fromEvent(window, 'resize').subscribe(() => this._topOffset = null);\n\n    fromEvent(window, 'scroll')\n      .pipe(debounceTime(250)).subscribe(() => this.updateScrollPositionInHistory());\n\n    // Change scroll restoration strategy to `manual` if it's supported\n    if (this.supportManualScrollRestoration) {\n      history.scrollRestoration = 'manual';\n      // we have to detect forward and back navigation thanks to popState event\n      this.location.subscribe((event: ScrollPositionPopStateEvent) => {\n        // the type is `hashchange` when the fragment identifier of the URL has changed. It allows us to go to position\n        // just before a click on an anchor\n        if (event.type === 'hashchange') {\n          this.scrollToPosition();\n        } else {\n          // Navigating with the forward/back button, we have to remove the position from the\n          // session storage in order to avoid a race-condition.\n          this.removeStoredScrollPosition();\n          // The `popstate` event is always triggered by a browser action such as clicking the\n          // forward/back button. It can be followed by a `hashchange` event.\n          this.poppedStateScrollPosition = event.state ? event.state.scrollPosition : null;\n        }\n      });\n    }\n  }\n\n  /**\n   * Scroll to the element with id extracted from the current location hash fragment.\n   * Scroll to top if no hash.\n   * Don't scroll if hash not found.\n   */\n  scroll() {\n    const hash = this.getCurrentHash();\n    const element: HTMLElement = hash\n        ? this.document.getElementById(hash)\n        : this.topOfPageElement;\n    this.scrollToElement(element);\n  }\n\n  /**\n   * test if the current location has a hash\n   */\n  isLocationWithHash(): boolean {\n    return !!this.getCurrentHash();\n  }\n\n  /**\n   * When we load a document, we have to scroll to the correct position depending on whether this is a new location,\n   * a back/forward in the history, or a refresh\n   *\n   * @param delay before we scroll to the good position\n   */\n  scrollAfterRender(delay: number) {\n    // If we do rendering following a refresh, we use the scroll position from the storage.\n    const storedScrollPosition = this.getStoredScrollPosition();\n    if (storedScrollPosition) {\n      this.viewportScroller.scrollToPosition(storedScrollPosition);\n    } else {\n      if (this.needToFixScrollPosition()) {\n        // The document was reloaded following a `popstate` event (triggered by clicking the\n        // forward/back button), so we manage the scroll position.\n        this.scrollToPosition();\n      } else {\n        // The document was loaded as a result of one of the following cases:\n        // - Typing the URL in the address bar (direct navigation).\n        // - Clicking on a link.\n        // (If the location contains a hash, we have to wait for async layout.)\n        if (this.isLocationWithHash()) {\n          // Delay scrolling by the specified amount to allow time for async layout to complete.\n          setTimeout(() => this.scroll(), delay);\n        } else {\n          // If the location doesn't contain a hash, we scroll to the top of the page.\n          this.scrollToTop();\n        }\n      }\n    }\n  }\n\n  /**\n   * Scroll to the element.\n   * Don't scroll if no element.\n   */\n  scrollToElement(element: Element|null) {\n    if (element) {\n      element.scrollIntoView();\n\n      if (window && window.scrollBy) {\n        // Scroll as much as necessary to align the top of `element` at `topOffset`.\n        // (Usually, `.top` will be 0, except for cases where the element cannot be scrolled all the\n        //  way to the top, because the viewport is larger than the height of the content after the\n        //  element.)\n        window.scrollBy(0, element.getBoundingClientRect().top - this.topOffset);\n\n        // If we are very close to the top (<20px), then scroll all the way up.\n        // (This can happen if `element` is at the top of the page, but has a small top-margin.)\n        if (window.pageYOffset < 20) {\n          window.scrollBy(0, -window.pageYOffset);\n        }\n      }\n    }\n  }\n\n  /** Scroll to the top of the document. */\n  scrollToTop() {\n    this.scrollToElement(this.topOfPageElement);\n  }\n\n  scrollToPosition() {\n    if (this.poppedStateScrollPosition) {\n      this.viewportScroller.scrollToPosition(this.poppedStateScrollPosition);\n      this.poppedStateScrollPosition = null;\n    }\n  }\n\n  /**\n   * Update the state with scroll position into history.\n   */\n  updateScrollPositionInHistory() {\n    if (this.supportManualScrollRestoration) {\n      const currentScrollPosition = this.viewportScroller.getScrollPosition();\n      if (currentScrollPosition) {\n        this.location.replaceState(this.location.path(true), undefined, {scrollPosition: currentScrollPosition});\n        window.sessionStorage.setItem('scrollPosition', currentScrollPosition.join(','));\n      }\n    }\n  }\n\n  getStoredScrollPosition(): ScrollPosition | null {\n    const position = window.sessionStorage.getItem('scrollPosition');\n    if (!position) { return null; }\n\n    const [x, y] = position.split(',');\n    return [+x, +y];\n  }\n\n  removeStoredScrollPosition() {\n    window.sessionStorage.removeItem('scrollPosition');\n  }\n\n  /**\n   * Check if the scroll position need to be manually fixed after popState event\n   */\n  needToFixScrollPosition(): boolean {\n    return this.supportManualScrollRestoration && !!this.poppedStateScrollPosition;\n  }\n\n  /**\n   * Return the hash fragment from the `PlatformLocation`, minus the leading `#`.\n   */\n  private getCurrentHash() {\n    return decodeURIComponent(this.platformLocation.hash.replace(/^#/, ''));\n  }\n}\n"
  },
  {
    "path": "apps/rxjs.dev/src/app/shared/search-results/search-results.component.spec.ts",
    "content": "import { DebugElement } from '@angular/core';\nimport { ComponentFixture, TestBed } from '@angular/core/testing';\nimport { By } from '@angular/platform-browser';\nimport { SearchResult } from 'app/search/interfaces';\nimport { SearchResultsComponent } from './search-results.component';\n\ndescribe('SearchResultsComponent', () => {\n  let component: SearchResultsComponent;\n  let fixture: ComponentFixture<SearchResultsComponent>;\n\n  /** Get all text from component element */\n  function getText() {\n    return fixture.debugElement.nativeElement.textContent;\n  }\n\n  /** Get a full set of test results. \"Take\" what you need */\n  function getTestResults(take?: number) {\n    const results: SearchResult[] = [\n      { path: 'guide/a', title: 'Guide A' },\n      { path: 'api/d', title: 'API D' },\n      { path: 'guide/b', title: 'Guide B' },\n      { path: 'guide/a/c', title: 'Guide A - C' },\n      { path: 'api/c', title: 'API C' },\n    ]\n      // fill it out to exceed 10 guide pages\n      .concat('nmlkjihgfe'.split('').map((l) => ({ path: 'guide/' + l, title: 'Guide ' + l })))\n      // add these empty fields to satisfy interface\n      .map((r) => ({ ...{ keywords: '', titleWords: '', type: '' }, ...r }));\n\n    return take === undefined ? results : results.slice(0, take);\n  }\n\n  function compareTitle(l: SearchResult, r: SearchResult) {\n    return l.title?.toUpperCase() > r.title?.toUpperCase() ? 1 : -1;\n  }\n\n  function setSearchResults(query: string, results: SearchResult[]) {\n    component.searchResults = { query, results };\n    component.ngOnChanges();\n    fixture.detectChanges();\n  }\n\n  beforeEach(() => {\n    TestBed.configureTestingModule({\n      declarations: [SearchResultsComponent],\n    });\n  });\n\n  beforeEach(() => {\n    fixture = TestBed.createComponent(SearchResultsComponent);\n    component = fixture.componentInstance;\n    fixture.detectChanges();\n  });\n\n  it('should map the search results into groups based on their containing folder', () => {\n    setSearchResults('', getTestResults(3));\n    expect(component.searchAreas).toEqual([\n      { name: 'api', priorityPages: [{ path: 'api/d', title: 'API D', type: '', keywords: '', titleWords: '' }], pages: [] },\n      {\n        name: 'guide',\n        priorityPages: [\n          { path: 'guide/a', title: 'Guide A', type: '', keywords: '', titleWords: '' },\n          { path: 'guide/b', title: 'Guide B', type: '', keywords: '', titleWords: '' },\n        ],\n        pages: [],\n      },\n    ]);\n  });\n\n  it('should special case results that are top level folders', () => {\n    setSearchResults('', [\n      { path: 'tutorial', title: 'Tutorial index', type: '', keywords: '', titleWords: '' },\n      { path: 'tutorial/toh-pt1', title: 'Tutorial - part 1', type: '', keywords: '', titleWords: '' },\n    ]);\n    expect(component.searchAreas).toEqual([\n      {\n        name: 'tutorial',\n        priorityPages: [\n          { path: 'tutorial', title: 'Tutorial index', type: '', keywords: '', titleWords: '' },\n          { path: 'tutorial/toh-pt1', title: 'Tutorial - part 1', type: '', keywords: '', titleWords: '' },\n        ],\n        pages: [],\n      },\n    ]);\n  });\n\n  it('should put first 5 results for each area into priorityPages', () => {\n    const results = getTestResults();\n    setSearchResults('', results);\n    expect(component.searchAreas[0].priorityPages).toEqual(results.filter((p) => p.path.startsWith('api')).slice(0, 5));\n    expect(component.searchAreas[1].priorityPages).toEqual(results.filter((p) => p.path.startsWith('guide')).slice(0, 5));\n  });\n\n  it('should put the nonPriorityPages into the pages array, sorted by title', () => {\n    const results = getTestResults();\n    setSearchResults('', results);\n    expect(component.searchAreas[0].pages).toEqual([]);\n    expect(component.searchAreas[1].pages).toEqual(\n      results\n        .filter((p) => p.path.startsWith('guide'))\n        .slice(5)\n        .sort(compareTitle)\n    );\n  });\n\n  it('should put a total count in the header of each area of search results', () => {\n    const results = getTestResults();\n    setSearchResults('', results);\n    fixture.detectChanges();\n    const headers = fixture.debugElement.queryAll(By.css('h3'));\n    expect(headers.length).toEqual(2);\n    expect(headers[0].nativeElement.textContent).toContain('(2)');\n    expect(headers[1].nativeElement.textContent).toContain('(13)');\n  });\n\n  it('should put search results with no containing folder into the default area (other)', () => {\n    const results = [{ path: 'news', title: 'News', type: 'marketing', keywords: '', titleWords: '' }];\n\n    setSearchResults('', results);\n    expect(component.searchAreas).toEqual([\n      { name: 'other', priorityPages: [{ path: 'news', title: 'News', type: 'marketing', keywords: '', titleWords: '' }], pages: [] },\n    ]);\n  });\n\n  it('should omit search results with no title', () => {\n    const results = [{ path: 'news', title: '', type: 'marketing', keywords: '', titleWords: '' }];\n\n    setSearchResults('something', results);\n    expect(component.searchAreas).toEqual([]);\n  });\n\n  it('should display \"Searching ...\" while waiting for search results', () => {\n    fixture.detectChanges();\n    expect(getText()).toContain('Searching ...');\n  });\n\n  describe('when a search result anchor is clicked', () => {\n    let searchResult: SearchResult;\n    let selected: SearchResult | null;\n    let anchor: DebugElement;\n\n    beforeEach(() => {\n      component.resultSelected.subscribe((result: SearchResult) => (selected = result));\n\n      selected = null;\n      searchResult = { path: 'news', title: 'News', type: 'marketing', keywords: '', titleWords: '' };\n      setSearchResults('something', [searchResult]);\n\n      fixture.detectChanges();\n      anchor = fixture.debugElement.query(By.css('a'));\n\n      expect(selected).toBeNull();\n    });\n\n    it('should emit a \"resultSelected\" event', () => {\n      anchor.triggerEventHandler('click', { button: 0, ctrlKey: false, metaKey: false });\n      fixture.detectChanges();\n      expect(selected).toBe(searchResult);\n    });\n\n    it('should not emit an event if mouse button is not zero (middle or right)', () => {\n      anchor.triggerEventHandler('click', { button: 1, ctrlKey: false, metaKey: false });\n      fixture.detectChanges();\n      expect(selected).toBeNull();\n    });\n\n    it('should not emit an event if the `ctrl` key is pressed', () => {\n      anchor.triggerEventHandler('click', { button: 0, ctrlKey: true, metaKey: false });\n      fixture.detectChanges();\n      expect(selected).toBeNull();\n    });\n\n    it('should not emit an event if the `meta` key is pressed', () => {\n      anchor.triggerEventHandler('click', { button: 0, ctrlKey: false, metaKey: true });\n      fixture.detectChanges();\n      expect(selected).toBeNull();\n    });\n  });\n\n  describe('when no query results', () => {\n    it('should display \"not found\" message', () => {\n      setSearchResults('something', []);\n      expect(getText()).toContain('No results');\n    });\n  });\n});\n"
  },
  {
    "path": "apps/rxjs.dev/src/app/shared/search-results/search-results.component.ts",
    "content": "import { Component, EventEmitter, Input, OnChanges, Output } from '@angular/core';\nimport { SearchResult, SearchResults, SearchArea } from 'app/search/interfaces';\n\n/**\n * A component to display search results in groups\n */\n@Component({\n  selector: 'aio-search-results',\n  template: `<div class=\"search-results\">\n      <div *ngIf=\"searchAreas.length; then searchResults; else notFound\"></div>\n    </div>\n\n    <ng-template #searchResults>\n      <h2 class=\"visually-hidden\">Search Results</h2>\n      <div class=\"search-area\" *ngFor=\"let area of searchAreas\">\n        <h3>{{ area.name }} ({{ area.pages.length + area.priorityPages.length }})</h3>\n        <ul class=\"priority-pages\">\n          <li class=\"search-page\" *ngFor=\"let page of area.priorityPages\">\n            <a class=\"search-result-item\" href=\"{{ page.path }}\" (click)=\"onResultSelected(page, $event)\">\n              <span class=\"symbol {{ page.type }}\" *ngIf=\"area.name === 'api'\"></span>{{ page.title }}\n            </a>\n          </li>\n        </ul>\n        <ul>\n          <li class=\"search-page\" *ngFor=\"let page of area.pages\">\n            <a class=\"search-result-item\" href=\"{{ page.path }}\" (click)=\"onResultSelected(page, $event)\">\n              <span class=\"symbol {{ page.type }}\" *ngIf=\"area.name === 'api'\"></span>{{ page.title }}\n            </a>\n          </li>\n        </ul>\n      </div>\n    </ng-template>\n\n    <ng-template #notFound>\n      <p>{{ notFoundMessage }}</p>\n    </ng-template>`,\n})\nexport class SearchResultsComponent implements OnChanges {\n  /**\n   * The results to display\n   */\n  @Input()\n  searchResults: SearchResults | null;\n\n  /**\n   * Emitted when the user selects a search result\n   */\n  @Output()\n  resultSelected = new EventEmitter<SearchResult>();\n\n  readonly defaultArea = 'other';\n  notFoundMessage = 'Searching ...';\n  readonly topLevelFolders = ['guide', 'tutorial'];\n  searchAreas: SearchArea[] = [];\n\n  ngOnChanges() {\n    this.searchAreas = this.searchResults ? this.processSearchResults(this.searchResults) : [];\n  }\n\n  onResultSelected(page: SearchResult, event: MouseEvent) {\n    // Emit a `resultSelected` event if the result is to be displayed on this page.\n    if (event.button === 0 && !event.ctrlKey && !event.metaKey) {\n      this.resultSelected.emit(page);\n    }\n  }\n\n  // Map the search results into groups by area\n  private processSearchResults(search: SearchResults) {\n    if (!search) {\n      return [];\n    }\n    this.notFoundMessage = 'No results found.';\n    const searchAreaMap: { [key: string]: SearchResult[] } = {};\n    search.results.forEach((result) => {\n      if (!result.title) {\n        return;\n      } // bad data; should fix\n      const areaName = this.computeAreaName(result) || this.defaultArea;\n      const area = (searchAreaMap[areaName] = searchAreaMap[areaName] || []);\n      area.push(result);\n    });\n    const keys = Object.keys(searchAreaMap).sort((l, r) => (l > r ? 1 : -1));\n    return keys.map((name) => {\n      let pages: SearchResult[] = searchAreaMap[name];\n\n      // Extract the top 5 most relevant results as priorityPages\n      const priorityPages = pages.splice(0, 5);\n      pages = pages.sort(compareResults);\n      return { name, pages, priorityPages };\n    });\n  }\n\n  // Split the search result path and use the top level folder, if there is one, as the area name.\n  private computeAreaName(result: SearchResult) {\n    if (this.topLevelFolders.indexOf(result.path) !== -1) {\n      return result.path;\n    }\n    const [areaName, rest] = result.path.split('/', 2);\n    return rest && areaName;\n  }\n}\n\nfunction compareResults(l: SearchResult, r: SearchResult) {\n  return l.title.toUpperCase() > r.title.toUpperCase() ? 1 : -1;\n}\n"
  },
  {
    "path": "apps/rxjs.dev/src/app/shared/select/select.component.spec.ts",
    "content": "import { Component, DebugElement } from '@angular/core';\nimport { ComponentFixture, TestBed } from '@angular/core/testing';\nimport { By } from '@angular/platform-browser';\nimport { SelectComponent, Option } from './select.component';\n\nconst options = [\n  { title: 'Option A', value: 'option-a' },\n  { title: 'Option B', value: 'option-b' }\n];\n\nlet host: HostComponent;\nlet fixture: ComponentFixture<HostComponent>;\nlet element: DebugElement;\n\ndescribe('SelectComponent', () => {\n\n  beforeEach(() => {\n    TestBed.configureTestingModule({\n      declarations: [ SelectComponent, HostComponent ],\n    });\n  });\n\n  beforeEach(() => {\n    fixture = TestBed.createComponent(HostComponent);\n    host = fixture.componentInstance;\n    element = fixture.debugElement.query(By.directive(SelectComponent));\n  });\n\n  describe('(initially)', () => {\n    it('should show the button and no options', () => {\n      expect(getButton()).toBeDefined();\n      expect(getOptionContainer()).toEqual(null);\n    });\n  });\n\n  describe('button', () => {\n    it('should display the label if provided', () => {\n      expect(getButton().textContent!.trim()).toEqual('');\n      host.label = 'Label:';\n      fixture.detectChanges();\n      expect(getButton().textContent!.trim()).toEqual('Label:');\n    });\n\n    it('should contain a symbol `<span>` if hasSymbol is true', () => {\n      expect(getButton().querySelector('span')).toEqual(null);\n      host.showSymbol = true;\n      fixture.detectChanges();\n      const span = getButton().querySelector('span');\n      expect(span).not.toEqual(null);\n      expect(span!.className).toContain('symbol');\n    });\n\n    it('should display the selected option, if there is one', () => {\n      host.showSymbol = true;\n      host.selected = options[0];\n      fixture.detectChanges();\n      expect(getButton().textContent).toContain(options[0].title);\n      expect(getButton().querySelector('span')!.className).toContain(options[0].value);\n    });\n\n    it('should toggle the visibility of the options list when clicked', () => {\n      host.options = options;\n      getButton().click();\n      fixture.detectChanges();\n      expect(getOptionContainer()).not.toEqual(null);\n      getButton().click();\n      fixture.detectChanges();\n      expect(getOptionContainer()).toEqual(null);\n    });\n  });\n\n  describe('options list', () => {\n    beforeEach(() => {\n      host.options = options;\n      host.showSymbol = true;\n      getButton().click(); // ensure the options are visible\n      fixture.detectChanges();\n    });\n\n    it('should show the corresponding title of each option', () => {\n      getOptions().forEach((li, index) => {\n        expect(li.textContent).toContain(options[index].title);\n      });\n    });\n\n    it('should select the option that is clicked', () => {\n      getOptions()[0].click();\n      fixture.detectChanges();\n      expect(host.onChange).toHaveBeenCalledWith({ option: options[0], index: 0 });\n      expect(getButton().textContent).toContain(options[0].title);\n      expect(getButton().querySelector('span')!.className).toContain(options[0].value);\n    });\n\n    it('should select the current option when enter is pressed', () => {\n      const e = new KeyboardEvent('keydown', {bubbles: true, cancelable: true, key: 'Enter'});\n      getOptions()[0].dispatchEvent(e);\n      fixture.detectChanges();\n      expect(host.onChange).toHaveBeenCalledWith({ option: options[0], index: 0 });\n      expect(getButton().textContent).toContain(options[0].title);\n      expect(getButton().querySelector('span')!.className).toContain(options[0].value);\n    });\n\n    it('should select the current option when space is pressed', () => {\n      const e = new KeyboardEvent('keydown', {bubbles: true, cancelable: true, key: ' '});\n      getOptions()[0].dispatchEvent(e);\n      fixture.detectChanges();\n      expect(host.onChange).toHaveBeenCalledWith({ option: options[0], index: 0 });\n      expect(getButton().textContent).toContain(options[0].title);\n      expect(getButton().querySelector('span')!.className).toContain(options[0].value);\n    });\n\n    it('should hide when an option is clicked', () => {\n      getOptions()[0].click();\n      fixture.detectChanges();\n      expect(getOptionContainer()).toEqual(null);\n    });\n\n    it('should hide when there is a click that is not on the option list', () => {\n      fixture.nativeElement.click();\n      fixture.detectChanges();\n      expect(getOptionContainer()).toEqual(null);\n    });\n\n    it('should hide if the escape button is pressed', () => {\n      const e = new KeyboardEvent('keydown', { bubbles: true, cancelable: true, key: 'Escape' });\n      document.dispatchEvent(e);\n      fixture.detectChanges();\n      expect(getOptionContainer()).toEqual(null);\n    });\n  });\n});\n\n\n\n@Component({\n  template: `\n    <aio-select (change)=\"onChange($event)\"\n              [options]=\"options\"\n              [selected]=\"selected\"\n              [label]=\"label\"\n              [showSymbol]=\"showSymbol\">\n    </aio-select>`\n})\nclass HostComponent {\n  onChange = jasmine.createSpy('onChange');\n  options: Option[];\n  selected: Option;\n  label: string;\n  showSymbol: boolean;\n}\n\nfunction getButton(): HTMLButtonElement {\n  return element.query(By.css('button')).nativeElement;\n}\n\nfunction getOptionContainer(): HTMLUListElement|null {\n  const de = element.query(By.css('ul'));\n  return de && de.nativeElement;\n}\n\nfunction getOptions(): HTMLLIElement[] {\n  return element.queryAll(By.css('li')).map(de => de.nativeElement);\n}\n"
  },
  {
    "path": "apps/rxjs.dev/src/app/shared/select/select.component.ts",
    "content": "import { Component, ElementRef, EventEmitter, HostListener, Input, Output, OnInit } from '@angular/core';\n\nexport interface Option {\n  title: string;\n  value?: any;\n}\n\n@Component({\n  selector: 'aio-select',\n  template: `<div class=\"form-select-menu\">\n    <button class=\"form-select-button\" (click)=\"toggleOptions()\">\n      <strong>{{ label }}</strong\n      ><span *ngIf=\"showSymbol\" class=\"symbol {{ selected?.value }}\"></span>{{ selected?.title }}\n    </button>\n    <ul class=\"form-select-dropdown\" *ngIf=\"showOptions\">\n      <li\n        *ngFor=\"let option of options; index as i\"\n        [class.selected]=\"option === selected\"\n        role=\"button\"\n        tabindex=\"0\"\n        (click)=\"select(option, i)\"\n        (keydown.enter)=\"select(option, i)\"\n        (keydown.space)=\"select(option, i); $event.preventDefault()\"\n      >\n        <span *ngIf=\"showSymbol\" class=\"symbol {{ option.value }}\"></span>{{ option.title }}\n      </li>\n    </ul>\n  </div>`,\n})\nexport class SelectComponent implements OnInit {\n  @Input()\n  selected: Option;\n\n  @Input()\n  options: Option[];\n\n  @Output()\n  // eslint-disable-next-line @angular-eslint/no-output-native\n  change = new EventEmitter<{ option: Option, index: number }>();\n\n  @Input()\n  showSymbol = false;\n\n  @Input()\n  label: string;\n\n  showOptions = false;\n\n  constructor(private hostElement: ElementRef) {}\n\n  ngOnInit() {\n    this.label = this.label || '';\n  }\n\n  toggleOptions() {\n    this.showOptions = !this.showOptions;\n  }\n\n  hideOptions() {\n    this.showOptions = false;\n  }\n\n  select(option: Option, index: number) {\n    this.selected = option;\n    this.change.emit({ option, index });\n    this.hideOptions();\n  }\n\n  @HostListener('document:click', ['$event.target'])\n  onClick(eventTarget: HTMLElement) {\n    // Hide the options if we clicked outside the component\n    if (!this.hostElement.nativeElement.contains(eventTarget)) {\n      this.hideOptions();\n    }\n  }\n\n  @HostListener('document:keydown.escape')\n  onKeyDown() {\n    this.hideOptions();\n  }\n}\n"
  },
  {
    "path": "apps/rxjs.dev/src/app/shared/shared.module.ts",
    "content": "import { NgModule } from '@angular/core';\nimport { CommonModule } from '@angular/common';\nimport { SearchResultsComponent } from './search-results/search-results.component';\nimport { SelectComponent } from './select/select.component';\n\n@NgModule({\n  imports: [\n    CommonModule\n  ],\n  exports: [\n    SearchResultsComponent,\n    SelectComponent\n  ],\n  declarations: [\n    SearchResultsComponent,\n    SelectComponent\n  ]\n})\nexport class SharedModule {}\n"
  },
  {
    "path": "apps/rxjs.dev/src/app/shared/stackblitz.service.ts",
    "content": "import StackBlitzkSDK from '@stackblitz/sdk';\nimport { Injectable } from '@angular/core';\nimport { Project } from '@stackblitz/sdk';\n\ninterface StackBlitzExampleConfig {\n  code: string;\n  language: string;\n  html?: string;\n  dependencies: {\n    [name: string]: string;\n  };\n}\n\n@Injectable({\n  providedIn: 'root',\n})\nexport class StackblitzService {\n  openProject(config: StackBlitzExampleConfig) {\n    const codeExtension: 'js' | string =\n      {\n        ts: 'ts',\n        typescript: 'ts',\n      }[config.language] || 'js';\n\n    const template: Project['template'] = codeExtension === 'ts' ? 'typescript' : 'javascript';\n\n    StackBlitzkSDK.openProject(\n      {\n        files: {\n          'index.html': config.html || '',\n          [`index.${codeExtension}`]: config.code,\n        },\n        title: 'RxJS example',\n        description: 'RxJS example',\n        template,\n        tags: ['rxjs', 'demo'],\n        dependencies: config.dependencies,\n        settings: {\n          compile: {\n            trigger: 'auto',\n            action: 'refresh',\n            clearConsole: true,\n          },\n        },\n      },\n      {\n        devToolsHeight: 50,\n      }\n    );\n  }\n}\n"
  },
  {
    "path": "apps/rxjs.dev/src/app/shared/toc.service.spec.ts",
    "content": "import { DOCUMENT } from '@angular/common';\nimport { ReflectiveInjector } from '@angular/core';\nimport { DomSanitizer, SafeHtml } from '@angular/platform-browser';\nimport { Subject } from 'rxjs';\n\nimport { ScrollItem, ScrollSpyInfo, ScrollSpyService } from 'app/shared/scroll-spy.service';\nimport { TocItem, TocService } from './toc.service';\n\ndescribe('TocService', () => {\n  let injector: ReflectiveInjector;\n  let scrollSpyService: MockScrollSpyService;\n  let tocService: TocService;\n  let lastTocList: TocItem[];\n\n  // call TocService.genToc\n  function callGenToc(html = '', docId = 'fizz/buzz'): HTMLDivElement {\n    const el = document.createElement('div');\n    el.innerHTML = html;\n    tocService.genToc(el, docId);\n    return el;\n  }\n\n  beforeEach(() => {\n    injector = ReflectiveInjector.resolveAndCreate([\n      { provide: DomSanitizer, useClass: TestDomSanitizer },\n      { provide: DOCUMENT, useValue: document },\n      { provide: ScrollSpyService, useClass: MockScrollSpyService },\n      TocService,\n    ]);\n    scrollSpyService = injector.get(ScrollSpyService);\n    tocService = injector.get(TocService);\n    tocService.tocList.subscribe(tocList => lastTocList = tocList);\n  });\n\n  describe('tocList', () => {\n    it('should emit the latest value to new subscribers', () => {\n      const expectedValue1 = createTocItem('Heading A');\n      const expectedValue2 = createTocItem('Heading B');\n      let value1: TocItem[]|undefined;\n      let value2: TocItem[]|undefined;\n\n      tocService.tocList.next([]);\n      tocService.tocList.subscribe(v => value1 = v);\n      expect(value1).toEqual([]);\n\n      tocService.tocList.next([expectedValue1, expectedValue2]);\n      tocService.tocList.subscribe(v => value2 = v);\n      expect(value2).toEqual([expectedValue1, expectedValue2]);\n    });\n\n    it('should emit the same values to all subscribers', () => {\n      const expectedValue1 = createTocItem('Heading A');\n      const expectedValue2 = createTocItem('Heading B');\n      const emittedValues: TocItem[][] = [];\n\n      tocService.tocList.subscribe(v => emittedValues.push(v));\n      tocService.tocList.subscribe(v => emittedValues.push(v));\n      tocService.tocList.next([expectedValue1, expectedValue2]);\n\n      expect(emittedValues).toEqual([\n        [expectedValue1, expectedValue2],\n        [expectedValue1, expectedValue2]\n      ]);\n    });\n  });\n\n  describe('activeItemIndex', () => {\n    it('should emit the active heading index (or null)', () => {\n      const indices: (number | null)[] = [];\n\n      tocService.activeItemIndex.subscribe(i => indices.push(i));\n      callGenToc();\n\n      scrollSpyService.$lastInfo.active.next({index: 42} as ScrollItem);\n      scrollSpyService.$lastInfo.active.next({index: 0} as ScrollItem);\n      scrollSpyService.$lastInfo.active.next(null);\n      scrollSpyService.$lastInfo.active.next({index: 7} as ScrollItem);\n\n      expect(indices).toEqual([null, 42, 0, null, 7]);\n    });\n\n    it('should reset the active index (and unspy) when calling `reset()`', () => {\n      const indices: (number | null)[] = [];\n\n      tocService.activeItemIndex.subscribe(i => indices.push(i));\n\n      callGenToc();\n      const unspy = scrollSpyService.$lastInfo.unspy;\n      scrollSpyService.$lastInfo.active.next({index: 42} as ScrollItem);\n\n      expect(unspy).not.toHaveBeenCalled();\n      expect(indices).toEqual([null, 42]);\n\n      tocService.reset();\n\n      expect(unspy).toHaveBeenCalled();\n      expect(indices).toEqual([null, 42, null]);\n    });\n\n    it('should reset the active index (and unspy) when a new `tocList` is requested', () => {\n      const indices: (number | null)[] = [];\n\n      tocService.activeItemIndex.subscribe(i => indices.push(i));\n\n      callGenToc();\n      const unspy1 = scrollSpyService.$lastInfo.unspy;\n      scrollSpyService.$lastInfo.active.next({index: 1} as ScrollItem);\n\n      expect(unspy1).not.toHaveBeenCalled();\n      expect(indices).toEqual([null, 1]);\n\n      tocService.genToc();\n\n      expect(unspy1).toHaveBeenCalled();\n      expect(indices).toEqual([null, 1, null]);\n\n      callGenToc();\n      const unspy2 = scrollSpyService.$lastInfo.unspy;\n      scrollSpyService.$lastInfo.active.next({index: 3} as ScrollItem);\n\n      expect(unspy2).not.toHaveBeenCalled();\n      expect(indices).toEqual([null, 1, null, null, 3]);\n\n      callGenToc();\n      scrollSpyService.$lastInfo.active.next({index: 4} as ScrollItem);\n\n      expect(unspy2).toHaveBeenCalled();\n      expect(indices).toEqual([null, 1, null, null, 3, null, 4]);\n    });\n\n    it('should emit the active index for the latest `tocList`', () => {\n      const indices: (number | null)[] = [];\n\n      tocService.activeItemIndex.subscribe(i => indices.push(i));\n\n      callGenToc();\n      const activeSubject1 = scrollSpyService.$lastInfo.active;\n      activeSubject1.next({index: 1} as ScrollItem);\n      activeSubject1.next({index: 2} as ScrollItem);\n\n      callGenToc();\n      const activeSubject2 = scrollSpyService.$lastInfo.active;\n      activeSubject2.next({index: 3} as ScrollItem);\n      activeSubject2.next({index: 4} as ScrollItem);\n\n      expect(indices).toEqual([null, 1, 2, null, 3, 4]);\n    });\n  });\n\n  describe('should clear tocList', () => {\n    beforeEach(() => {\n      // Start w/ dummy data from previous usage\n      const expectedValue1 = createTocItem('Heading A');\n      const expectedValue2 = createTocItem('Heading B');\n      tocService.tocList.next([expectedValue1, expectedValue2]);\n      expect(lastTocList).not.toEqual([]);\n    });\n\n    it('when reset()', () => {\n      tocService.reset();\n      expect(lastTocList).toEqual([]);\n    });\n\n    it('when given undefined doc element', () => {\n      tocService.genToc(undefined);\n      expect(lastTocList).toEqual([]);\n    });\n\n    it('when given doc element w/ no headings', () => {\n      callGenToc('<p>This</p><p>and</p><p>that</p>');\n      expect(lastTocList).toEqual([]);\n    });\n\n    it('when given doc element w/ headings other than h1, h2 & h3', () => {\n      callGenToc('<h4>and</h4><h5>that</h5>');\n      expect(lastTocList).toEqual([]);\n    });\n\n    it('when given doc element w/ no-toc headings', () => {\n      // tolerates different spellings/casing of the no-toc class\n      callGenToc(`\n        <h2 class=\"no-toc\">one</h2><p>some one</p>\n        <h2 class=\"notoc\">two</h2><p>some two</p>\n        <h2 class=\"no-Toc\">three</h2><p>some three</p>\n        <h2 class=\"noToc\">four</h2><p>some four</p>\n      `);\n      expect(lastTocList).toEqual([]);\n    });\n  });\n\n  describe('when given many headings', () => {\n    let docId: string;\n    let docEl: HTMLDivElement;\n    let headings: NodeListOf<HTMLHeadingElement>;\n\n    beforeEach(() => {\n      docId = 'fizz/buzz';\n\n      docEl = callGenToc(`\n        <h1>Fun with TOC</h1>\n\n        <h2 id=\"heading-one-special-id\">Heading one</h2>\n          <p>h2 toc 0</p>\n\n        <h2>H2 Two</h2>\n          <p>h2 toc 1</p>\n\n        <h2>H2 <b>Three</b></h2>\n          <p>h2 toc 2</p>\n          <h3 id=\"h3-3a\">H3 3a</h3> <p>h3 toc 3</p>\n          <h3 id=\"h3-3b\">H3 3b</h3> <p>h3 toc 4</p>\n\n            <!-- h4 shouldn't be in TOC -->\n            <h4 id=\"h4-3b\">H4 of h3-3b</h4> <p>an h4</p>\n\n        <h2><i>H2 4 <b>repeat</b></i></h2>\n          <p>h2 toc 5</p>\n\n        <h2><b>H2 4 <i>repeat</i></b></h2>\n          <p>h2 toc 6</p>\n\n        <h2 class=\"no-toc\" id=\"skippy\">Skippy</h2>\n          <p>Skip this header</p>\n\n        <h2 id=\"h2-6\">H2 6</h2>\n          <p>h2 toc 7</p>\n          <h3 id=\"h3-6a\">H3 6a</h3> <p>h3 toc 8</p>\n      `, docId);\n\n      headings = docEl.querySelectorAll('h1,h2,h3,h4') as NodeListOf<HTMLHeadingElement>;\n    });\n\n    it('should have tocList with expect number of TocItems', () => {\n      // should ignore h4, and the no-toc h2\n      expect(lastTocList.length).toEqual(headings.length - 2);\n    });\n\n    it('should have href with docId and heading\\'s id', () => {\n      const tocItem = lastTocList.find(item => item.title === 'Heading one')!;\n      expect(tocItem.href).toEqual(`${docId}#heading-one-special-id`);\n    });\n\n    it('should have level \"h1\" for an <h1>', () => {\n      const tocItem = lastTocList.find(item => item.title === 'Fun with TOC')!;\n      expect(tocItem.level).toEqual('h1');\n    });\n\n    it('should have level \"h2\" for an <h2>', () => {\n      const tocItem = lastTocList.find(item => item.title === 'Heading one')!;\n      expect(tocItem.level).toEqual('h2');\n    });\n\n    it('should have level \"h3\" for an <h3>', () => {\n      const tocItem = lastTocList.find(item => item.title === 'H3 3a')!;\n      expect(tocItem.level).toEqual('h3');\n    });\n\n    it('should have title which is heading\\'s textContent ', () => {\n      const heading = headings[3];\n      const tocItem = lastTocList[3];\n      expect(heading.textContent).toEqual(tocItem.title);\n    });\n\n    it('should have \"SafeHtml\" content which is heading\\'s innerHTML ', () => {\n      const heading = headings[3];\n      const content = lastTocList[3].content;\n      expect((content as TestSafeHtml).changingThisBreaksApplicationSecurity)\n        .toEqual(heading.innerHTML);\n    });\n\n    it('should calculate and set id of heading without an id', () => {\n      const id = headings[2].getAttribute('id');\n      expect(id).toEqual('h2-two');\n    });\n\n    it('should have href with docId and calculated heading id', () => {\n      const tocItem = lastTocList.find(item => item.title === 'H2 Two')!;\n      expect(tocItem.href).toEqual(`${docId}#h2-two`);\n    });\n\n    it('should ignore HTML in heading when calculating id', () => {\n      const id = headings[3].getAttribute('id');\n      const tocItem = lastTocList[3];\n      expect(id).toEqual('h2-three', 'heading id');\n      expect(tocItem.href).toEqual(`${docId}#h2-three`, 'tocItem href');\n    });\n\n    it('should avoid repeating an id when calculating', () => {\n      const tocItems = lastTocList.filter(item => item.title === 'H2 4 repeat');\n      expect(tocItems[0].href).toEqual(`${docId}#h2-4-repeat`, 'first');\n      expect(tocItems[1].href).toEqual(`${docId}#h2-4-repeat-2`, 'second');\n    });\n  });\n\n  describe('TocItem for an h2 with links and extra whitespace', () => {\n    let docId: string;\n    let tocItem: TocItem;\n\n    beforeEach(() => {\n      docId = 'fizz/buzz/';\n\n      // An almost-actual <h2> ... with extra whitespace\n      callGenToc(`\n        <h2 id=\"setup-to-develop-locally\">\n          Setup to <a href=\"moo\">develop</a> <i>locally</i>.\n          <a class=\"header-link\" href=\"tutorial/toh-pt1#setup-to-develop-locally\" aria-hidden=\"true\">\n            <span class=\"icon icon-link\"></span>\n          </a>\n        </h2>\n      `, docId);\n\n      tocItem = lastTocList[0];\n    });\n\n    it('should have expected href', () => {\n      expect(tocItem.href).toEqual(`${docId}#setup-to-develop-locally`);\n    });\n\n    it('should have expected title', () => {\n      expect(tocItem.title).toEqual('Setup to develop locally.');\n    });\n\n    it('should have removed anchor link from tocItem html content', () => {\n      expect((tocItem.content as TestSafeHtml)\n        .changingThisBreaksApplicationSecurity)\n        .toEqual('Setup to develop <i>locally</i>.');\n    });\n\n    it('should have bypassed HTML sanitizing of heading\\'s innerHTML ', () => {\n      const domSanitizer: TestDomSanitizer = injector.get(DomSanitizer);\n      expect(domSanitizer.bypassSecurityTrustHtml)\n        .toHaveBeenCalledWith('Setup to develop <i>locally</i>.');\n    });\n  });\n});\n\ninterface TestSafeHtml extends SafeHtml {\n  changingThisBreaksApplicationSecurity: string;\n  getTypeName: () => string;\n}\n\nclass TestDomSanitizer {\n  bypassSecurityTrustHtml = jasmine.createSpy('bypassSecurityTrustHtml')\n    .and.callFake((html: string) => ({\n        changingThisBreaksApplicationSecurity: html,\n        getTypeName: () => 'HTML',\n      } as TestSafeHtml));\n}\n\nclass MockScrollSpyService {\n  private $$lastInfo: {\n    active: Subject<ScrollItem | null>;\n    unspy: jasmine.Spy;\n  } | undefined;\n\n  get $lastInfo() {\n    if (!this.$$lastInfo) {\n      throw new Error('$lastInfo is not yet defined. You must call `spyOn` first.');\n    }\n    return this.$$lastInfo;\n  }\n\n  spyOn(headings: HTMLHeadingElement[]): ScrollSpyInfo {\n    return this.$$lastInfo = {\n      active: new Subject<ScrollItem | null>(),\n      unspy: jasmine.createSpy('unspy'),\n    };\n  }\n}\n\nfunction createTocItem(title: string, level = 'h2', href = '', content = title) {\n  return { title, href, level, content };\n}\n\n"
  },
  {
    "path": "apps/rxjs.dev/src/app/shared/toc.service.ts",
    "content": "import { DOCUMENT } from '@angular/common';\nimport { Inject, Injectable } from '@angular/core';\nimport { DomSanitizer, SafeHtml } from '@angular/platform-browser';\nimport { ReplaySubject } from 'rxjs';\nimport { ScrollSpyInfo, ScrollSpyService } from 'app/shared/scroll-spy.service';\n\nexport interface TocItem {\n  content: SafeHtml;\n  href: string;\n  isSecondary?: boolean;\n  level: string;\n  title: string;\n}\n\n@Injectable()\nexport class TocService {\n  tocList = new ReplaySubject<TocItem[]>(1);\n  activeItemIndex = new ReplaySubject<number | null>(1);\n  private scrollSpyInfo: ScrollSpyInfo | null = null;\n\n  constructor(@Inject(DOCUMENT) private document: any, private domSanitizer: DomSanitizer, private scrollSpyService: ScrollSpyService) {}\n\n  genToc(docElement?: Element, docId = '') {\n    this.resetScrollSpyInfo();\n\n    if (!docElement) {\n      this.tocList.next([]);\n      return;\n    }\n\n    const headings = this.findTocHeadings(docElement);\n    const idMap = new Map<string, number>();\n    const tocList = headings.map((heading) => ({\n      content: this.extractHeadingSafeHtml(heading),\n      href: `${docId}#${this.getId(heading, idMap)}`,\n      level: heading.tagName.toLowerCase(),\n      title: (heading.textContent || '').trim(),\n    }));\n\n    this.tocList.next(tocList);\n\n    this.scrollSpyInfo = this.scrollSpyService.spyOn(headings);\n    this.scrollSpyInfo.active.subscribe((item) => this.activeItemIndex.next(item && item.index));\n  }\n\n  reset() {\n    this.resetScrollSpyInfo();\n    this.tocList.next([]);\n  }\n\n  // This bad boy exists only to strip off the anchor link attached to a heading\n  private extractHeadingSafeHtml(heading: HTMLHeadingElement) {\n    const div: HTMLDivElement = this.document.createElement('div');\n    div.innerHTML = heading.innerHTML;\n    const anchorLinks: NodeListOf<HTMLAnchorElement> = div.querySelectorAll('a');\n    // eslint-disable-next-line @typescript-eslint/prefer-for-of\n    for (let i = 0; i < anchorLinks.length; i++) {\n      const anchorLink = anchorLinks[i];\n      if (!anchorLink.classList.contains('header-link')) {\n        // this is an anchor that contains actual content that we want to keep\n        // move the contents of the anchor into its parent\n        const parent = anchorLink.parentNode!;\n        while (anchorLink.childNodes.length) {\n          parent.insertBefore(anchorLink.childNodes[0], anchorLink);\n        }\n      }\n      // now remove the anchor\n      anchorLink.remove();\n    }\n    // security: the document element which provides this heading content\n    // is always authored by the documentation team and is considered to be safe\n    return this.domSanitizer.bypassSecurityTrustHtml(div.innerHTML.trim());\n  }\n\n  private findTocHeadings(docElement: Element): HTMLHeadingElement[] {\n    const headings = docElement.querySelectorAll('h1,h2,h3');\n    const skipNoTocHeadings = (heading: HTMLHeadingElement) => !/(?:no-toc|notoc)/i.test(heading.className);\n\n    return Array.prototype.filter.call(headings, skipNoTocHeadings);\n  }\n\n  private resetScrollSpyInfo() {\n    if (this.scrollSpyInfo) {\n      this.scrollSpyInfo.unspy();\n      this.scrollSpyInfo = null;\n    }\n\n    this.activeItemIndex.next(null);\n  }\n\n  // Extract the id from the heading; create one if necessary\n  // Is it possible for a heading to lack an id?\n  private getId(h: HTMLHeadingElement, idMap: Map<string, number>) {\n    let id = h.id;\n    if (id) {\n      addToMap(id);\n    } else {\n      id = (h.textContent || '').trim().toLowerCase().replace(/\\W+/g, '-');\n      id = addToMap(id);\n      h.id = id;\n    }\n    return id;\n\n    // Map guards against duplicate id creation.\n    function addToMap(key: string) {\n      const oldCount = idMap.get(key) || 0;\n      const count = oldCount + 1;\n      idMap.set(key, count);\n      return count === 1 ? key : `${key}-${count}`;\n    }\n  }\n}\n"
  },
  {
    "path": "apps/rxjs.dev/src/app/shared/web-worker-message.ts",
    "content": "export interface WebWorkerMessage {\n  type: string;\n  payload: any;\n  id?: number;\n}\n"
  },
  {
    "path": "apps/rxjs.dev/src/app/shared/web-worker.ts",
    "content": "/*\nCopyright 2016 Google Inc. All Rights Reserved.\nUse of this source code is governed by an MIT-style license that\ncan be found in the LICENSE file at http://angular.io/license\n*/\n\nimport { NgZone } from '@angular/core';\nimport { Observable } from 'rxjs';\nimport { WebWorkerMessage } from './web-worker-message';\n\nexport class WebWorkerClient {\n  private nextId = 0;\n\n  static create(worker: Worker, zone: NgZone) {\n    return new WebWorkerClient(worker, zone);\n  }\n\n  private constructor(private worker: Worker, private zone: NgZone) {}\n\n  sendMessage<T>(type: string, payload?: any): Observable<T> {\n    return new Observable<T>((subscriber) => {\n      const id = this.nextId++;\n\n      const handleMessage = (response: MessageEvent) => {\n        const { type: responseType, id: responseId, payload: responsePayload } = response.data as WebWorkerMessage;\n        if (type === responseType && id === responseId) {\n          this.zone.run(() => {\n            subscriber.next(responsePayload);\n            subscriber.complete();\n          });\n        }\n      };\n\n      const handleError = (error: ErrorEvent) => {\n        // Since we do not check type and id any error from the webworker will kill all subscribers\n        this.zone.run(() => subscriber.error(error));\n      };\n\n      // Wire up the event listeners for this message\n      this.worker.addEventListener('message', handleMessage);\n      this.worker.addEventListener('error', handleError);\n\n      // Post the message to the web worker\n      this.worker.postMessage({ type, id, payload });\n\n      // At completion/error unwire the event listeners\n      return () => {\n        this.worker.removeEventListener('message', handleMessage);\n        this.worker.removeEventListener('error', handleError);\n      };\n    });\n  }\n}\n"
  },
  {
    "path": "apps/rxjs.dev/src/app/shared/window.ts",
    "content": "import { InjectionToken } from '@angular/core';\n\nexport const WindowToken = new InjectionToken('Window');\nexport function windowProvider() { return window; }\n"
  },
  {
    "path": "apps/rxjs.dev/src/app/sw-updates/sw-updates.module.ts",
    "content": "import { NgModule } from '@angular/core';\n\nimport { SwUpdatesService } from './sw-updates.service';\n\n\n@NgModule({\n  providers: [\n    SwUpdatesService\n  ]\n})\nexport class SwUpdatesModule {}\n"
  },
  {
    "path": "apps/rxjs.dev/src/app/sw-updates/sw-updates.service.spec.ts",
    "content": "import { ApplicationRef, ReflectiveInjector } from '@angular/core';\nimport { discardPeriodicTasks, fakeAsync, tick } from '@angular/core/testing';\nimport { SwUpdate } from '@angular/service-worker';\nimport { Subject } from 'rxjs';\n\nimport { Logger } from 'app/shared/logger.service';\nimport { SwUpdatesService } from './sw-updates.service';\n\n\ndescribe('SwUpdatesService', () => {\n  let injector: ReflectiveInjector;\n  let appRef: MockApplicationRef;\n  let service: SwUpdatesService;\n  let swu: MockSwUpdate;\n  let checkInterval: number;\n\n  // Helpers\n  // NOTE:\n  //   Because `SwUpdatesService` uses the `interval` operator, it needs to be instantiated and\n  //   destroyed inside the `fakeAsync` zone (when `fakeAsync` is used for the test). Thus, we can't\n  //   run `setup()`/`tearDown()` in `beforeEach()`/`afterEach()` blocks. We use the `run()` helper\n  //   to call them inside each test's zone.\n  const setup = (isSwUpdateEnabled: boolean) => {\n    injector = ReflectiveInjector.resolveAndCreate([\n      { provide: ApplicationRef, useClass: MockApplicationRef },\n      { provide: Logger, useClass: MockLogger },\n      { provide: SwUpdate, useFactory: () => new MockSwUpdate(isSwUpdateEnabled) },\n      SwUpdatesService\n    ]);\n\n    appRef = injector.get(ApplicationRef);\n    service = injector.get(SwUpdatesService);\n    swu = injector.get(SwUpdate);\n    checkInterval = (service as any).checkInterval;\n  };\n  const finalize = () => service.ngOnDestroy();\n  const run = (specFn: VoidFunction, isSwUpdateEnabled = true) => () => {\n    setup(isSwUpdateEnabled);\n    specFn();\n    finalize();\n  };\n\n\n  it('should create', run(() => {\n    expect(service).toBeTruthy();\n  }));\n\n  it('should start checking for updates when instantiated (once the app stabilizes)', run(() => {\n    expect(swu.checkForUpdate).not.toHaveBeenCalled();\n\n    appRef.isStable.next(false);\n    expect(swu.checkForUpdate).not.toHaveBeenCalled();\n\n    appRef.isStable.next(true);\n    expect(swu.checkForUpdate).toHaveBeenCalled();\n  }));\n\n  it('should periodically check for updates', fakeAsync(run(() => {\n    appRef.isStable.next(true);\n    swu.checkForUpdate.calls.reset();\n\n    tick(checkInterval);\n    expect(swu.checkForUpdate).toHaveBeenCalledTimes(1);\n\n    tick(checkInterval);\n    expect(swu.checkForUpdate).toHaveBeenCalledTimes(2);\n\n    appRef.isStable.next(false);\n\n    tick(checkInterval);\n    expect(swu.checkForUpdate).toHaveBeenCalledTimes(3);\n\n    discardPeriodicTasks();\n  })));\n\n  it('should activate available updates immediately', fakeAsync(run(() => {\n    appRef.isStable.next(true);\n    expect(swu.activateUpdate).not.toHaveBeenCalled();\n\n    swu.$$availableSubj.next({available: {hash: 'foo'}});\n    expect(swu.activateUpdate).toHaveBeenCalled();\n  })));\n\n  it('should keep periodically checking for updates even after one is available/activated', fakeAsync(run(() => {\n    appRef.isStable.next(true);\n    swu.checkForUpdate.calls.reset();\n\n    tick(checkInterval);\n    expect(swu.checkForUpdate).toHaveBeenCalledTimes(1);\n\n    swu.$$availableSubj.next({available: {hash: 'foo'}});\n\n    tick(checkInterval);\n    expect(swu.checkForUpdate).toHaveBeenCalledTimes(2);\n\n    tick(checkInterval);\n    expect(swu.checkForUpdate).toHaveBeenCalledTimes(3);\n\n    discardPeriodicTasks();\n  })));\n\n  it('should emit on `updateActivated` when an update has been activated', run(() => {\n    const activatedVersions: (string|undefined)[] = [];\n    service.updateActivated.subscribe(v => activatedVersions.push(v));\n\n    swu.$$availableSubj.next({available: {hash: 'foo'}});\n    swu.$$activatedSubj.next({current: {hash: 'bar'}});\n    swu.$$availableSubj.next({available: {hash: 'baz'}});\n    swu.$$activatedSubj.next({current: {hash: 'qux'}});\n\n    expect(activatedVersions).toEqual(['bar', 'qux']);\n  }));\n\n  describe('when `SwUpdate` is not enabled', () => {\n    const runDeactivated = (specFn: VoidFunction) => run(specFn, false);\n\n    it('should not check for updates', fakeAsync(runDeactivated(() => {\n      appRef.isStable.next(true);\n\n      tick(checkInterval);\n      tick(checkInterval);\n\n      swu.$$availableSubj.next({available: {hash: 'foo'}});\n      swu.$$activatedSubj.next({current: {hash: 'bar'}});\n\n      tick(checkInterval);\n      tick(checkInterval);\n\n      expect(swu.checkForUpdate).not.toHaveBeenCalled();\n    })));\n\n    it('should not activate available updates', fakeAsync(runDeactivated(() => {\n      swu.$$availableSubj.next({available: {hash: 'foo'}});\n      expect(swu.activateUpdate).not.toHaveBeenCalled();\n    })));\n\n    it('should never emit on `updateActivated`', runDeactivated(() => {\n      const activatedVersions: (string|undefined)[] = [];\n      service.updateActivated.subscribe(v => activatedVersions.push(v));\n\n      swu.$$availableSubj.next({available: {hash: 'foo'}});\n      swu.$$activatedSubj.next({current: {hash: 'bar'}});\n      swu.$$availableSubj.next({available: {hash: 'baz'}});\n      swu.$$activatedSubj.next({current: {hash: 'qux'}});\n\n      expect(activatedVersions).toEqual([]);\n    }));\n  });\n\n  describe('when destroyed', () => {\n    it('should not schedule a new check for update (after current check)', fakeAsync(run(() => {\n      appRef.isStable.next(true);\n      expect(swu.checkForUpdate).toHaveBeenCalled();\n\n      service.ngOnDestroy();\n      swu.checkForUpdate.calls.reset();\n\n      tick(checkInterval);\n      tick(checkInterval);\n\n      expect(swu.checkForUpdate).not.toHaveBeenCalled();\n    })));\n\n    it('should not schedule a new check for update (after activating an update)', fakeAsync(run(() => {\n      appRef.isStable.next(true);\n      expect(swu.checkForUpdate).toHaveBeenCalled();\n\n      service.ngOnDestroy();\n      swu.checkForUpdate.calls.reset();\n\n      swu.$$availableSubj.next({available: {hash: 'foo'}});\n      swu.$$activatedSubj.next({current: {hash: 'baz'}});\n\n      tick(checkInterval);\n      tick(checkInterval);\n\n      expect(swu.checkForUpdate).not.toHaveBeenCalled();\n    })));\n\n    it('should not activate available updates', fakeAsync(run(() => {\n      service.ngOnDestroy();\n      swu.$$availableSubj.next({available: {hash: 'foo'}});\n\n      expect(swu.activateUpdate).not.toHaveBeenCalled();\n    })));\n\n    it('should stop emitting on `updateActivated`', run(() => {\n      const activatedVersions: (string|undefined)[] = [];\n      service.updateActivated.subscribe(v => activatedVersions.push(v));\n\n      swu.$$availableSubj.next({available: {hash: 'foo'}});\n      swu.$$activatedSubj.next({current: {hash: 'bar'}});\n      service.ngOnDestroy();\n      swu.$$availableSubj.next({available: {hash: 'baz'}});\n      swu.$$activatedSubj.next({current: {hash: 'qux'}});\n\n      expect(activatedVersions).toEqual(['bar']);\n    }));\n  });\n});\n\n// Mocks\nclass MockApplicationRef {\n  isStable = new Subject<boolean>();\n}\n\nclass MockLogger {\n  log = jasmine.createSpy('MockLogger.log');\n}\n\nclass MockSwUpdate {\n  $$availableSubj = new Subject<{available: {hash: string}}>();\n  $$activatedSubj = new Subject<{current: {hash: string}}>();\n\n  available = this.$$availableSubj.asObservable();\n  activated = this.$$activatedSubj.asObservable();\n\n  activateUpdate = jasmine.createSpy('MockSwUpdate.activateUpdate')\n                          .and.callFake(() => Promise.resolve());\n\n  checkForUpdate = jasmine.createSpy('MockSwUpdate.checkForUpdate')\n                          .and.callFake(() => Promise.resolve());\n\n  constructor(public isEnabled: boolean) {}\n}\n"
  },
  {
    "path": "apps/rxjs.dev/src/app/sw-updates/sw-updates.service.ts",
    "content": "import { ApplicationRef, Injectable, OnDestroy } from '@angular/core';\nimport { SwUpdate } from '@angular/service-worker';\nimport { concat, interval, NEVER, Observable, Subject } from 'rxjs';\nimport { first, map, takeUntil, tap } from 'rxjs/operators';\n\nimport { Logger } from 'app/shared/logger.service';\n\n\n/**\n * SwUpdatesService\n *\n * @description\n * 1. Checks for available ServiceWorker updates once instantiated.\n * 2. Re-checks every 6 hours.\n * 3. Whenever an update is available, it activates the update.\n *\n * @property\n * `updateActivated` {Observable<string>} - Emit the version hash whenever an update is activated.\n */\n@Injectable()\nexport class SwUpdatesService implements OnDestroy {\n  private checkInterval = 1000 * 60 * 60 * 6;  // 6 hours\n  private onDestroy = new Subject<void>();\n  updateActivated: Observable<string>;\n\n  constructor(appRef: ApplicationRef, private logger: Logger, private swu: SwUpdate) {\n    if (!swu.isEnabled) {\n      this.updateActivated = NEVER.pipe(takeUntil(this.onDestroy));\n      return;\n    }\n\n    // Periodically check for updates (after the app is stabilized).\n    const appIsStable = appRef.isStable.pipe(first(v => v));\n    concat(appIsStable, interval(this.checkInterval))\n        .pipe(\n            tap(() => this.log('Checking for update...')),\n            takeUntil(this.onDestroy),\n        )\n        .subscribe(() => this.swu.checkForUpdate());\n\n    // Activate available updates.\n    this.swu.available\n        .pipe(\n            tap(evt => this.log(`Update available: ${JSON.stringify(evt)}`)),\n            takeUntil(this.onDestroy),\n        )\n        .subscribe(() => this.swu.activateUpdate());\n\n    // Notify about activated updates.\n    this.updateActivated = this.swu.activated.pipe(\n        tap(evt => this.log(`Update activated: ${JSON.stringify(evt)}`)),\n        map(evt => evt.current.hash),\n        takeUntil(this.onDestroy),\n    );\n  }\n\n  ngOnDestroy() {\n    this.onDestroy.next();\n  }\n\n  private log(message: string) {\n    const timestamp = (new Date()).toISOString();\n    this.logger.log(`[SwUpdates - ${timestamp}]: ${message}`);\n  }\n}\n"
  },
  {
    "path": "apps/rxjs.dev/src/assets/.gitkeep",
    "content": ""
  },
  {
    "path": "apps/rxjs.dev/src/assets/js/devtools-welcome.js",
    "content": "var welcomeText = (\n  ' ____           _ ____      \\n' +\n  '|  _ \\\\ __  __  | / ___|    \\n' +\n  '| |_) |\\\\ \\\\/ /  | \\\\___ \\\\  \\n' +\n  '|  _ <  >  < |_| |___) |    \\n' +\n  '|_| \\\\_\\\\/_/\\\\_\\\\___/|____/ \\n' +\n  '\\nTo start experimenting with RxJS: https://stackblitz.com/edit/rxjs\\n'\n);\nif (console.info) {\n  console.info(welcomeText);\n} else {\n  console.log(welcomeText);\n}\n"
  },
  {
    "path": "apps/rxjs.dev/src/assets/js/prettify.js",
    "content": "!function(){/*\n\n Copyright (C) 2006 Google Inc.\n\n Licensed under the Apache License, Version 2.0 (the \"License\");\n you may not use this file except in compliance with the License.\n You may obtain a copy of the License at\n\n      http://www.apache.org/licenses/LICENSE-2.0\n\n Unless required by applicable law or agreed to in writing, software\n distributed under the License is distributed on an \"AS IS\" BASIS,\n WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n See the License for the specific language governing permissions and\n limitations under the License.\n*/\nwindow.PR_SHOULD_USE_CONTINUATION=!0;\n(function(){function T(a){function d(e){var b=e.charCodeAt(0);if(92!==b)return b;var a=e.charAt(1);return(b=w[a])?b:\"0\"<=a&&\"7\">=a?parseInt(e.substring(1),8):\"u\"===a||\"x\"===a?parseInt(e.substring(2),16):e.charCodeAt(1)}function f(e){if(32>e)return(16>e?\"\\\\x0\":\"\\\\x\")+e.toString(16);e=String.fromCharCode(e);return\"\\\\\"===e||\"-\"===e||\"]\"===e||\"^\"===e?\"\\\\\"+e:e}function b(e){var b=e.substring(1,e.length-1).match(/\\\\u[0-9A-Fa-f]{4}|\\\\x[0-9A-Fa-f]{2}|\\\\[0-3][0-7]{0,2}|\\\\[0-7]{1,2}|\\\\[\\s\\S]|-|[^-\\\\]/g);e=\n[];var a=\"^\"===b[0],c=[\"[\"];a&&c.push(\"^\");for(var a=a?1:0,g=b.length;a<g;++a){var h=b[a];if(/\\\\[bdsw]/i.test(h))c.push(h);else{var h=d(h),k;a+2<g&&\"-\"===b[a+1]?(k=d(b[a+2]),a+=2):k=h;e.push([h,k]);65>k||122<h||(65>k||90<h||e.push([Math.max(65,h)|32,Math.min(k,90)|32]),97>k||122<h||e.push([Math.max(97,h)&-33,Math.min(k,122)&-33]))}}e.sort(function(e,a){return e[0]-a[0]||a[1]-e[1]});b=[];g=[];for(a=0;a<e.length;++a)h=e[a],h[0]<=g[1]+1?g[1]=Math.max(g[1],h[1]):b.push(g=h);for(a=0;a<b.length;++a)h=b[a],\nc.push(f(h[0])),h[1]>h[0]&&(h[1]+1>h[0]&&c.push(\"-\"),c.push(f(h[1])));c.push(\"]\");return c.join(\"\")}function v(e){for(var a=e.source.match(/(?:\\[(?:[^\\x5C\\x5D]|\\\\[\\s\\S])*\\]|\\\\u[A-Fa-f0-9]{4}|\\\\x[A-Fa-f0-9]{2}|\\\\[0-9]+|\\\\[^ux0-9]|\\(\\?[:!=]|[\\(\\)\\^]|[^\\x5B\\x5C\\(\\)\\^]+)/g),c=a.length,d=[],g=0,h=0;g<c;++g){var k=a[g];\"(\"===k?++h:\"\\\\\"===k.charAt(0)&&(k=+k.substring(1))&&(k<=h?d[k]=-1:a[g]=f(k))}for(g=1;g<d.length;++g)-1===d[g]&&(d[g]=++A);for(h=g=0;g<c;++g)k=a[g],\"(\"===k?(++h,d[h]||(a[g]=\"(?:\")):\"\\\\\"===\nk.charAt(0)&&(k=+k.substring(1))&&k<=h&&(a[g]=\"\\\\\"+d[k]);for(g=0;g<c;++g)\"^\"===a[g]&&\"^\"!==a[g+1]&&(a[g]=\"\");if(e.ignoreCase&&n)for(g=0;g<c;++g)k=a[g],e=k.charAt(0),2<=k.length&&\"[\"===e?a[g]=b(k):\"\\\\\"!==e&&(a[g]=k.replace(/[a-zA-Z]/g,function(a){a=a.charCodeAt(0);return\"[\"+String.fromCharCode(a&-33,a|32)+\"]\"}));return a.join(\"\")}for(var A=0,n=!1,l=!1,m=0,c=a.length;m<c;++m){var p=a[m];if(p.ignoreCase)l=!0;else if(/[a-z]/i.test(p.source.replace(/\\\\u[0-9a-f]{4}|\\\\x[0-9a-f]{2}|\\\\[^ux]/gi,\"\"))){n=!0;\nl=!1;break}}for(var w={b:8,t:9,n:10,v:11,f:12,r:13},r=[],m=0,c=a.length;m<c;++m){p=a[m];if(p.global||p.multiline)throw Error(\"\"+p);r.push(\"(?:\"+v(p)+\")\")}return new RegExp(r.join(\"|\"),l?\"gi\":\"g\")}function U(a,d){function f(a){var c=a.nodeType;if(1==c){if(!b.test(a.className)){for(c=a.firstChild;c;c=c.nextSibling)f(c);c=a.nodeName.toLowerCase();if(\"br\"===c||\"li\"===c)v[l]=\"\\n\",n[l<<1]=A++,n[l++<<1|1]=a}}else if(3==c||4==c)c=a.nodeValue,c.length&&(c=d?c.replace(/\\r\\n?/g,\"\\n\"):c.replace(/[ \\t\\r\\n]+/g,\n\" \"),v[l]=c,n[l<<1]=A,A+=c.length,n[l++<<1|1]=a)}var b=/(?:^|\\s)nocode(?:\\s|$)/,v=[],A=0,n=[],l=0;f(a);return{a:v.join(\"\").replace(/\\n$/,\"\"),c:n}}function J(a,d,f,b,v){f&&(a={h:a,l:1,j:null,m:null,a:f,c:null,i:d,g:null},b(a),v.push.apply(v,a.g))}function V(a){for(var d=void 0,f=a.firstChild;f;f=f.nextSibling)var b=f.nodeType,d=1===b?d?a:f:3===b?W.test(f.nodeValue)?a:d:d;return d===a?void 0:d}function G(a,d){function f(a){for(var l=a.i,m=a.h,c=[l,\"pln\"],p=0,w=a.a.match(v)||[],r={},e=0,t=w.length;e<\nt;++e){var z=w[e],q=r[z],g=void 0,h;if(\"string\"===typeof q)h=!1;else{var k=b[z.charAt(0)];if(k)g=z.match(k[1]),q=k[0];else{for(h=0;h<A;++h)if(k=d[h],g=z.match(k[1])){q=k[0];break}g||(q=\"pln\")}!(h=5<=q.length&&\"lang-\"===q.substring(0,5))||g&&\"string\"===typeof g[1]||(h=!1,q=\"src\");h||(r[z]=q)}k=p;p+=z.length;if(h){h=g[1];var B=z.indexOf(h),D=B+h.length;g[2]&&(D=z.length-g[2].length,B=D-h.length);q=q.substring(5);J(m,l+k,z.substring(0,B),f,c);J(m,l+k+B,h,K(q,h),c);J(m,l+k+D,z.substring(D),f,c)}else c.push(l+\nk,q)}a.g=c}var b={},v;(function(){for(var f=a.concat(d),l=[],m={},c=0,p=f.length;c<p;++c){var w=f[c],r=w[3];if(r)for(var e=r.length;0<=--e;)b[r.charAt(e)]=w;w=w[1];r=\"\"+w;m.hasOwnProperty(r)||(l.push(w),m[r]=null)}l.push(/[\\0-\\uffff]/);v=T(l)})();var A=d.length;return f}function y(a){var d=[],f=[];a.tripleQuotedStrings?d.push([\"str\",/^(?:\\'\\'\\'(?:[^\\'\\\\]|\\\\[\\s\\S]|\\'{1,2}(?=[^\\']))*(?:\\'\\'\\'|$)|\\\"\\\"\\\"(?:[^\\\"\\\\]|\\\\[\\s\\S]|\\\"{1,2}(?=[^\\\"]))*(?:\\\"\\\"\\\"|$)|\\'(?:[^\\\\\\']|\\\\[\\s\\S])*(?:\\'|$)|\\\"(?:[^\\\\\\\"]|\\\\[\\s\\S])*(?:\\\"|$))/,\nnull,\"'\\\"\"]):a.multiLineStrings?d.push([\"str\",/^(?:\\'(?:[^\\\\\\']|\\\\[\\s\\S])*(?:\\'|$)|\\\"(?:[^\\\\\\\"]|\\\\[\\s\\S])*(?:\\\"|$)|\\`(?:[^\\\\\\`]|\\\\[\\s\\S])*(?:\\`|$))/,null,\"'\\\"`\"]):d.push([\"str\",/^(?:\\'(?:[^\\\\\\'\\r\\n]|\\\\.)*(?:\\'|$)|\\\"(?:[^\\\\\\\"\\r\\n]|\\\\.)*(?:\\\"|$))/,null,\"\\\"'\"]);a.verbatimStrings&&f.push([\"str\",/^@\\\"(?:[^\\\"]|\\\"\\\")*(?:\\\"|$)/,null]);var b=a.hashComments;b&&(a.cStyleComments?(1<b?d.push([\"com\",/^#(?:##(?:[^#]|#(?!##))*(?:###|$)|.*)/,null,\"#\"]):d.push([\"com\",/^#(?:(?:define|e(?:l|nd)if|else|error|ifn?def|include|line|pragma|undef|warning)\\b|[^\\r\\n]*)/,\nnull,\"#\"]),f.push([\"str\",/^<(?:(?:(?:\\.\\.\\/)*|\\/?)(?:[\\w-]+(?:\\/[\\w-]+)+)?[\\w-]+\\.h(?:h|pp|\\+\\+)?|[a-z]\\w*)>/,null])):d.push([\"com\",/^#[^\\r\\n]*/,null,\"#\"]));a.cStyleComments&&(f.push([\"com\",/^\\/\\/[^\\r\\n]*/,null]),f.push([\"com\",/^\\/\\*[\\s\\S]*?(?:\\*\\/|$)/,null]));if(b=a.regexLiterals){var v=(b=1<b?\"\":\"\\n\\r\")?\".\":\"[\\\\S\\\\s]\";f.push([\"lang-regex\",RegExp(\"^(?:^^\\\\.?|[+-]|[!=]=?=?|\\\\#|%=?|&&?=?|\\\\(|\\\\*=?|[+\\\\-]=|->|\\\\/=?|::?|<<?=?|>>?>?=?|,|;|\\\\?|@|\\\\[|~|{|\\\\^\\\\^?=?|\\\\|\\\\|?=?|break|case|continue|delete|do|else|finally|instanceof|return|throw|try|typeof)\\\\s*(\"+\n(\"/(?=[^/*\"+b+\"])(?:[^/\\\\x5B\\\\x5C\"+b+\"]|\\\\x5C\"+v+\"|\\\\x5B(?:[^\\\\x5C\\\\x5D\"+b+\"]|\\\\x5C\"+v+\")*(?:\\\\x5D|$))+/\")+\")\")])}(b=a.types)&&f.push([\"typ\",b]);b=(\"\"+a.keywords).replace(/^ | $/g,\"\");b.length&&f.push([\"kwd\",new RegExp(\"^(?:\"+b.replace(/[\\s,]+/g,\"|\")+\")\\\\b\"),null]);d.push([\"pln\",/^\\s+/,null,\" \\r\\n\\t\\u00a0\"]);b=\"^.[^\\\\s\\\\w.$@'\\\"`/\\\\\\\\]*\";a.regexLiterals&&(b+=\"(?!s*/)\");f.push([\"lit\",/^@[a-z_$][a-z_$@0-9]*/i,null],[\"typ\",/^(?:[@_]?[A-Z]+[a-z][A-Za-z_$@0-9]*|\\w+_t\\b)/,null],[\"pln\",/^[a-z_$][a-z_$@0-9]*/i,\nnull],[\"lit\",/^(?:0x[a-f0-9]+|(?:\\d(?:_\\d+)*\\d*(?:\\.\\d*)?|\\.\\d\\+)(?:e[+\\-]?\\d+)?)[a-z]*/i,null,\"0123456789\"],[\"pln\",/^\\\\[\\s\\S]?/,null],[\"pun\",new RegExp(b),null]);return G(d,f)}function L(a,d,f){function b(a){var c=a.nodeType;if(1==c&&!A.test(a.className))if(\"br\"===a.nodeName)v(a),a.parentNode&&a.parentNode.removeChild(a);else for(a=a.firstChild;a;a=a.nextSibling)b(a);else if((3==c||4==c)&&f){var d=a.nodeValue,q=d.match(n);q&&(c=d.substring(0,q.index),a.nodeValue=c,(d=d.substring(q.index+q[0].length))&&\na.parentNode.insertBefore(l.createTextNode(d),a.nextSibling),v(a),c||a.parentNode.removeChild(a))}}function v(a){function b(a,c){var d=c?a.cloneNode(!1):a,k=a.parentNode;if(k){var k=b(k,1),e=a.nextSibling;k.appendChild(d);for(var f=e;f;f=e)e=f.nextSibling,k.appendChild(f)}return d}for(;!a.nextSibling;)if(a=a.parentNode,!a)return;a=b(a.nextSibling,0);for(var d;(d=a.parentNode)&&1===d.nodeType;)a=d;c.push(a)}for(var A=/(?:^|\\s)nocode(?:\\s|$)/,n=/\\r\\n?|\\n/,l=a.ownerDocument,m=l.createElement(\"li\");a.firstChild;)m.appendChild(a.firstChild);\nfor(var c=[m],p=0;p<c.length;++p)b(c[p]);d===(d|0)&&c[0].setAttribute(\"value\",d);var w=l.createElement(\"ol\");w.className=\"linenums\";d=Math.max(0,d-1|0)||0;for(var p=0,r=c.length;p<r;++p)m=c[p],m.className=\"L\"+(p+d)%10,m.firstChild||m.appendChild(l.createTextNode(\"\\u00a0\")),w.appendChild(m);a.appendChild(w)}function t(a,d){for(var f=d.length;0<=--f;){var b=d[f];I.hasOwnProperty(b)?E.console&&console.warn(\"cannot override language handler %s\",b):I[b]=a}}function K(a,d){a&&I.hasOwnProperty(a)||(a=/^\\s*</.test(d)?\n\"default-markup\":\"default-code\");return I[a]}function M(a){var d=a.j;try{var f=U(a.h,a.l),b=f.a;a.a=b;a.c=f.c;a.i=0;K(d,b)(a);var v=/\\bMSIE\\s(\\d+)/.exec(navigator.userAgent),v=v&&8>=+v[1],d=/\\n/g,A=a.a,n=A.length,f=0,l=a.c,m=l.length,b=0,c=a.g,p=c.length,w=0;c[p]=n;var r,e;for(e=r=0;e<p;)c[e]!==c[e+2]?(c[r++]=c[e++],c[r++]=c[e++]):e+=2;p=r;for(e=r=0;e<p;){for(var t=c[e],z=c[e+1],q=e+2;q+2<=p&&c[q+1]===z;)q+=2;c[r++]=t;c[r++]=z;e=q}c.length=r;var g=a.h;a=\"\";g&&(a=g.style.display,g.style.display=\"none\");\ntry{for(;b<m;){var h=l[b+2]||n,k=c[w+2]||n,q=Math.min(h,k),B=l[b+1],D;if(1!==B.nodeType&&(D=A.substring(f,q))){v&&(D=D.replace(d,\"\\r\"));B.nodeValue=D;var N=B.ownerDocument,u=N.createElement(\"span\");u.className=c[w+1];var y=B.parentNode;y.replaceChild(u,B);u.appendChild(B);f<h&&(l[b+1]=B=N.createTextNode(A.substring(q,h)),y.insertBefore(B,u.nextSibling))}f=q;f>=h&&(b+=2);f>=k&&(w+=2)}}finally{g&&(g.style.display=a)}}catch(x){E.console&&console.log(x&&x.stack||x)}}var E=window,C=[\"break,continue,do,else,for,if,return,while\"],\nF=[[C,\"auto,case,char,const,default,double,enum,extern,float,goto,inline,int,long,register,restrict,short,signed,sizeof,static,struct,switch,typedef,union,unsigned,void,volatile\"],\"catch,class,delete,false,import,new,operator,private,protected,public,this,throw,true,try,typeof\"],H=[F,\"alignas,alignof,align_union,asm,axiom,bool,concept,concept_map,const_cast,constexpr,decltype,delegate,dynamic_cast,explicit,export,friend,generic,late_check,mutable,namespace,noexcept,noreturn,nullptr,property,reinterpret_cast,static_assert,static_cast,template,typeid,typename,using,virtual,where\"],\nO=[F,\"abstract,assert,boolean,byte,extends,finally,final,implements,import,instanceof,interface,null,native,package,strictfp,super,synchronized,throws,transient\"],P=[F,\"abstract,add,alias,as,ascending,async,await,base,bool,by,byte,checked,decimal,delegate,descending,dynamic,event,finally,fixed,foreach,from,get,global,group,implicit,in,interface,internal,into,is,join,let,lock,null,object,out,override,orderby,params,partial,readonly,ref,remove,sbyte,sealed,select,set,stackalloc,string,select,uint,ulong,unchecked,unsafe,ushort,value,var,virtual,where,yield\"],\nF=[F,\"abstract,async,await,constructor,debugger,enum,eval,export,function,get,implements,instanceof,interface,let,null,set,undefined,var,with,yield,Infinity,NaN\"],Q=[C,\"and,as,assert,class,def,del,elif,except,exec,finally,from,global,import,in,is,lambda,nonlocal,not,or,pass,print,raise,try,with,yield,False,True,None\"],R=[C,\"alias,and,begin,case,class,def,defined,elsif,end,ensure,false,in,module,next,nil,not,or,redo,rescue,retry,self,super,then,true,undef,unless,until,when,yield,BEGIN,END\"],C=[C,\"case,done,elif,esac,eval,fi,function,in,local,set,then,until\"],\nS=/^(DIR|FILE|array|vector|(de|priority_)?queue|(forward_)?list|stack|(const_)?(reverse_)?iterator|(unordered_)?(multi)?(set|map)|bitset|u?(int|float)\\d*)\\b/,W=/\\S/,X=y({keywords:[H,P,O,F,\"caller,delete,die,do,dump,elsif,eval,exit,foreach,for,goto,if,import,last,local,my,next,no,our,print,package,redo,require,sub,undef,unless,until,use,wantarray,while,BEGIN,END\",Q,R,C],hashComments:!0,cStyleComments:!0,multiLineStrings:!0,regexLiterals:!0}),I={};t(X,[\"default-code\"]);t(G([],[[\"pln\",/^[^<?]+/],[\"dec\",\n/^<!\\w[^>]*(?:>|$)/],[\"com\",/^<\\!--[\\s\\S]*?(?:-\\->|$)/],[\"lang-\",/^<\\?([\\s\\S]+?)(?:\\?>|$)/],[\"lang-\",/^<%([\\s\\S]+?)(?:%>|$)/],[\"pun\",/^(?:<[%?]|[%?]>)/],[\"lang-\",/^<xmp\\b[^>]*>([\\s\\S]+?)<\\/xmp\\b[^>]*>/i],[\"lang-js\",/^<script\\b[^>]*>([\\s\\S]*?)(<\\/script\\b[^>]*>)/i],[\"lang-css\",/^<style\\b[^>]*>([\\s\\S]*?)(<\\/style\\b[^>]*>)/i],[\"lang-in.tag\",/^(<\\/?[a-z][^<>]*>)/i]]),\"default-markup htm html mxml xhtml xml xsl\".split(\" \"));t(G([[\"pln\",/^[\\s]+/,null,\" \\t\\r\\n\"],[\"atv\",/^(?:\\\"[^\\\"]*\\\"?|\\'[^\\']*\\'?)/,null,\n\"\\\"'\"]],[[\"tag\",/^^<\\/?[a-z](?:[\\w.:-]*\\w)?|\\/?>$/i],[\"atn\",/^(?!style[\\s=]|on)[a-z](?:[\\w:-]*\\w)?/i],[\"lang-uq.val\",/^=\\s*([^>\\'\\\"\\s]*(?:[^>\\'\\\"\\s\\/]|\\/(?=\\s)))/],[\"pun\",/^[=<>\\/]+/],[\"lang-js\",/^on\\w+\\s*=\\s*\\\"([^\\\"]+)\\\"/i],[\"lang-js\",/^on\\w+\\s*=\\s*\\'([^\\']+)\\'/i],[\"lang-js\",/^on\\w+\\s*=\\s*([^\\\"\\'>\\s]+)/i],[\"lang-css\",/^style\\s*=\\s*\\\"([^\\\"]+)\\\"/i],[\"lang-css\",/^style\\s*=\\s*\\'([^\\']+)\\'/i],[\"lang-css\",/^style\\s*=\\s*([^\\\"\\'>\\s]+)/i]]),[\"in.tag\"]);t(G([],[[\"atv\",/^[\\s\\S]+/]]),[\"uq.val\"]);t(y({keywords:H,\nhashComments:!0,cStyleComments:!0,types:S}),\"c cc cpp cxx cyc m\".split(\" \"));t(y({keywords:\"null,true,false\"}),[\"json\"]);t(y({keywords:P,hashComments:!0,cStyleComments:!0,verbatimStrings:!0,types:S}),[\"cs\"]);t(y({keywords:O,cStyleComments:!0}),[\"java\"]);t(y({keywords:C,hashComments:!0,multiLineStrings:!0}),[\"bash\",\"bsh\",\"csh\",\"sh\"]);t(y({keywords:Q,hashComments:!0,multiLineStrings:!0,tripleQuotedStrings:!0}),[\"cv\",\"py\",\"python\"]);t(y({keywords:\"caller,delete,die,do,dump,elsif,eval,exit,foreach,for,goto,if,import,last,local,my,next,no,our,print,package,redo,require,sub,undef,unless,until,use,wantarray,while,BEGIN,END\",\nhashComments:!0,multiLineStrings:!0,regexLiterals:2}),[\"perl\",\"pl\",\"pm\"]);t(y({keywords:R,hashComments:!0,multiLineStrings:!0,regexLiterals:!0}),[\"rb\",\"ruby\"]);t(y({keywords:F,cStyleComments:!0,regexLiterals:!0}),[\"javascript\",\"js\",\"ts\",\"typescript\"]);t(y({keywords:\"all,and,by,catch,class,else,extends,false,finally,for,if,in,is,isnt,loop,new,no,not,null,of,off,on,or,return,super,then,throw,true,try,unless,until,when,while,yes\",hashComments:3,cStyleComments:!0,multilineStrings:!0,tripleQuotedStrings:!0,\nregexLiterals:!0}),[\"coffee\"]);t(G([],[[\"str\",/^[\\s\\S]+/]]),[\"regex\"]);var Y=E.PR={createSimpleLexer:G,registerLangHandler:t,sourceDecorator:y,PR_ATTRIB_NAME:\"atn\",PR_ATTRIB_VALUE:\"atv\",PR_COMMENT:\"com\",PR_DECLARATION:\"dec\",PR_KEYWORD:\"kwd\",PR_LITERAL:\"lit\",PR_NOCODE:\"nocode\",PR_PLAIN:\"pln\",PR_PUNCTUATION:\"pun\",PR_SOURCE:\"src\",PR_STRING:\"str\",PR_TAG:\"tag\",PR_TYPE:\"typ\",prettyPrintOne:E.prettyPrintOne=function(a,d,f){f=f||!1;d=d||null;var b=document.createElement(\"div\");b.innerHTML=\"<pre>\"+a+\"</pre>\";\nb=b.firstChild;f&&L(b,f,!0);M({j:d,m:f,h:b,l:1,a:null,i:null,c:null,g:null});return b.innerHTML},prettyPrint:E.prettyPrint=function(a,d){function f(){for(var b=E.PR_SHOULD_USE_CONTINUATION?c.now()+250:Infinity;p<t.length&&c.now()<b;p++){for(var d=t[p],l=g,m=d;m=m.previousSibling;){var n=m.nodeType,u=(7===n||8===n)&&m.nodeValue;if(u?!/^\\??prettify\\b/.test(u):3!==n||/\\S/.test(m.nodeValue))break;if(u){l={};u.replace(/\\b(\\w+)=([\\w:.%+-]+)/g,function(a,b,c){l[b]=c});break}}m=d.className;if((l!==g||r.test(m))&&\n!e.test(m)){n=!1;for(u=d.parentNode;u;u=u.parentNode)if(q.test(u.tagName)&&u.className&&r.test(u.className)){n=!0;break}if(!n){d.className+=\" prettyprinted\";n=l.lang;if(!n){var n=m.match(w),C;!n&&(C=V(d))&&z.test(C.tagName)&&(n=C.className.match(w));n&&(n=n[1])}if(y.test(d.tagName))u=1;else var u=d.currentStyle,x=v.defaultView,u=(u=u?u.whiteSpace:x&&x.getComputedStyle?x.getComputedStyle(d,null).getPropertyValue(\"white-space\"):0)&&\"pre\"===u.substring(0,3);x=l.linenums;(x=\"true\"===x||+x)||(x=(x=m.match(/\\blinenums\\b(?::(\\d+))?/))?\nx[1]&&x[1].length?+x[1]:!0:!1);x&&L(d,x,u);M({j:n,h:d,m:x,l:u,a:null,i:null,c:null,g:null})}}}p<t.length?E.setTimeout(f,250):\"function\"===typeof a&&a()}for(var b=d||document.body,v=b.ownerDocument||document,b=[b.getElementsByTagName(\"pre\"),b.getElementsByTagName(\"code\"),b.getElementsByTagName(\"xmp\")],t=[],n=0;n<b.length;++n)for(var l=0,m=b[n].length;l<m;++l)t.push(b[n][l]);var b=null,c=Date;c.now||(c={now:function(){return+new Date}});var p=0,w=/\\blang(?:uage)?-([\\w.]+)(?!\\S)/,r=/\\bprettyprint\\b/,\ne=/\\bprettyprinted\\b/,y=/pre|xmp/i,z=/^code$/i,q=/^(?:pre|code|xmp)$/i,g={};f()}},H=E.define;\"function\"===typeof H&&H.amd&&H(\"google-code-prettify\",[],function(){return Y})})();}()\n"
  },
  {
    "path": "apps/rxjs.dev/src/environments/environment.archive.ts",
    "content": "// This is for archived sites, which are hosted at https://vX.angular.io, where X is the major Angular version.\nexport const environment = {\n  gaId: 'UA-36380079-2', // Production id (since it is linked from the main site)\n  production: true,\n  mode: 'archive'\n};\n"
  },
  {
    "path": "apps/rxjs.dev/src/environments/environment.next.ts",
    "content": "// This is for the staging site, which is hosted at https://next.angular.io (and https://aio-staging.firebaseapp.org)\nexport const environment = {\n  gaId: 'UA-36380079-2', // Production id (since it is linked from the main site)\n  production: true,\n  mode: 'next'\n};\n"
  },
  {
    "path": "apps/rxjs.dev/src/environments/environment.stable.ts",
    "content": "// This is for the production site, which is hosted at https://angular.io\nexport const environment = {\n  gaId: 'UA-36380079-2', // Production id\n  production: true,\n  mode: 'stable'\n};\n"
  },
  {
    "path": "apps/rxjs.dev/src/environments/environment.ts",
    "content": "// The file contents for the current environment will overwrite these during build.\n// The build system defaults to the dev environment which uses `environment.ts`, but if you do\n// `ng build --env=prod` then `environment.prod.ts` will be used instead.\n// The list of which env maps to which file can be found in `angular-cli.json`.\n\nexport const environment = {\n  gaId: 'UA-36380079-2', // Development id\n  production: false,\n  mode: 'stable'\n};\n"
  },
  {
    "path": "apps/rxjs.dev/src/extra-files/README.md",
    "content": "# Extra files folder\n\nThis folder is used for extra files that should be included in deployments to firebase.\n\nAfter the AIO application had been built and before it is deployed all files and folders\ninside the folder with the same name as the current deployment mode (next, stable, archive)\nwill be copied to the `dist` folder.\n\nSee the `scripts/deploy-to-firebase.sh` script for more detail.\n\n**Note:**\nThe `deploy-to-firebase.sh` script always expects there to be a folder for the current deployment\nmode (even if it is empty).\n"
  },
  {
    "path": "apps/rxjs.dev/src/extra-files/archive/robots.txt",
    "content": "# Disallow all URLs (see http://www.robotstxt.org/robotstxt.html)\nUser-agent: *\nDisallow: /\n"
  },
  {
    "path": "apps/rxjs.dev/src/extra-files/next/robots.txt",
    "content": "# Disallow all URLs (see http://www.robotstxt.org/robotstxt.html)\nUser-agent: *\nDisallow: /\n"
  },
  {
    "path": "apps/rxjs.dev/src/extra-files/stable/robots.txt",
    "content": "# Allow all URLs (see http://www.robotstxt.org/robotstxt.html)\nUser-agent: *\nDisallow:\nSitemap: https://rxjs.dev/generated/sitemap.xml\n"
  },
  {
    "path": "apps/rxjs.dev/src/google385281288605d160.html",
    "content": "google-site-verification: google385281288605d160.html"
  },
  {
    "path": "apps/rxjs.dev/src/index.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n<head>\n  <meta charset=\"utf-8\">\n  <title>RxJS</title>\n  <base href=\"/\">\n\n  <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\n\n  <link rel=\"icon\" type=\"image/x-icon\" href=\"assets/images/favicons/favicon.ico\">\n  <!--<link rel=\"icon\" type=\"image/png\" href=\"assets/images/favicons/favicon-32x32.png\"-->\n        <!--sizes=\"32x32\">-->\n  <!--<link rel=\"icon\" type=\"image/png\" href=\"assets/images/favicons/favicon-194x194.png\"-->\n        <!--sizes=\"194x194\">-->\n  <!--<link rel=\"icon\" type=\"image/png\" href=\"assets/images/favicons/favicon-96x96.png\"-->\n        <!--sizes=\"96x96\">-->\n  <!--<link rel=\"icon\" type=\"image/png\" href=\"assets/images/favicons/favicon-16x16.png\"-->\n        <!--sizes=\"16x16\">-->\n  <!--<link rel=\"apple-touch-icon\" sizes=\"144x144\" href=\"assets/images/favicons/apple-touch-icon-144x144.png\">-->\n  <!--<link rel=\"apple-touch-icon-precomposed\" sizes=\"144x144\" href=\"assets/images/favicons/apple-touch-icon-144x144.png\">-->\n\n  <!-- NOTE: These need to be kept in sync with `ngsw-config.json`. -->\n  <link href=\"https://fonts.googleapis.com/icon?family=Material+Icons\" rel=\"stylesheet\">\n  <link href=\"https://fonts.googleapis.com/css?family=Droid+Sans+Mono\" rel=\"stylesheet\">\n  <link href=\"https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css\" rel=\"stylesheet\">\n  <!-- -->\n\n  <link rel=\"manifest\" href=\"pwa-manifest.json\">\n  <meta name=\"theme-color\" content=\"#d81b60\">\n  <meta name=\"apple-mobile-web-app-capable\" content=\"yes\">\n  <meta name=\"apple-mobile-web-app-status-bar-style\" content=\"translucent\">\n\n  <script>\n    // Dynamically, preemptively, add `noindex`, which will be removed when the doc is ready and valid\n    var tag = document.createElement('meta'); tag.name = 'robots'; tag.content = 'noindex';\n    document.head.appendChild(tag);\n  </script>\n\n  <!-- Google Analytics -->\n  <script>\n  // Note this is a customised version of the GA tracking snippet\n  // See the comments below for more info\n  (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){\n  (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),\n  m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;\n  ~i.name.indexOf('NG_DEFER_BOOTSTRAP')|| // only load library if not running e2e tests\n  m.parentNode.insertBefore(a,m)\n  })(window,document,'script','https://www.google-analytics.com/analytics.js','ga');\n  </script>\n  <!-- End Google Analytics -->\n\n  <script>\n    // Report fatal errors to Google Analytics\n    window.onerror = function() {\n      ga('send', 'exception', {exDescription: formatError.apply(null, arguments), exFatal: true});\n\n      function formatError(msg, url, line, col, e) {\n        var stack;\n        msg = msg.replace(/^Error: /, '');\n        if (e) {\n          stack = e.stack\n              // strip the leading \"Error: \" from the stack trace\n              .replace(/^Error: /, '')\n              // strip the message from the stack trace, if present\n              .replace(msg + '\\n', '')\n              // strip leading spaces\n              .replace(/^ +/gm, '')\n              // strip all leading \"at \" for each frame\n              .replace(/^at /gm, '')\n              // replace long urls with just the last segment: `filename:line:column`\n              .replace(/(?: \\(|@)http.+\\/([^/)]+)\\)?(?:\\n|$)/gm, '@$1\\n')\n              // replace \"eval code\" in Edge\n              .replace(/ *\\(eval code(:\\d+:\\d+)\\)(?:\\n|$)/gm, '@???$1\\n')\n        } else {\n          line = line || '?';\n          col = col || '?';\n          stack = url + ':' + line + ':' + col;\n        }\n        return (msg + '\\n' + stack).substr(0, 150);\n      }\n    };\n  </script>\n\n  <script>\n    if (!Object.assign) {\n      // polyfill other non-evergreen browsers in a blocking way\n      var polyfillUrl = \"https://cdnjs.cloudflare.com/polyfill/v2/polyfill.min.js?features=default,Array.prototype.find&flags=gated&unknown=polyfill\";\n\n      // send a blocking XHR to fetch the polyfill\n      // then append it to the document so that its eval-ed synchronously\n      // this is required because the method used for IE is not reliable with other non-evergreen browsers\n      var xhr = new XMLHttpRequest();\n      xhr.addEventListener(\"load\", function() {\n        var s = document.createElement('script');\n        s.type = 'text/javascript';\n        var code = this.responseText;\n        s.appendChild(document.createTextNode(code));\n        document.head.appendChild(s);\n      });\n      xhr.open(\"GET\", polyfillUrl, false);\n      xhr.send();\n    }\n  </script>\n\n  <script>\n    //load CE polyfill\n    //HACK: webpack's html plugin mangles the document.write calls if we don't trick it.\n\n    //load the ES5 shim for browsers with native CE support\n    function loadCustomElementsShim(){\n      document.write('<scri' + 'pt src=\"assets/js/native-shim.js\"><' + '/script>');\n    }\n\n    //load the full custom elements polyfill for browsers without support\n    function loadCustomElementsPolyfill(){\n      document.write('<scri' + 'pt src=\"assets/js/custom-elements.min.js\"><' + '/script>');\n    }\n    //detect if we have native CE support\n    if(!window.customElements){\n      loadCustomElementsPolyfill();\n    }\n    else {\n      loadCustomElementsShim();\n    }\n  </script>\n\n</head>\n<body>\n\n  <aio-shell></aio-shell>\n\n  <noscript>\n    <div class=\"background-sky hero\"></div>\n    <section id=\"intro\">\n      <div class=\"hero-logo\">\n        <img src=\"assets/images/favicons/favicon-192x192.png\" width=\"250\" height=\"250\" alt=\"RxJS logo\">\n      </div>\n      <div class=\"headline-container\">\n        <h2 class=\"hero-headline\">RxJS</h2>\n        <span class=\"hero-subheadline\">Reactive Extensions Library for JavaScript</span>\n      </div>\n    </section>\n    <h2 style=\"color: red; text-align: center;\">\n      <b><i>This website requires JavaScript.</i></b>\n    </h2>\n  </noscript>\n  <script src=\"assets/js/devtools-welcome.js\"></script>\n</body>\n</html>\n"
  },
  {
    "path": "apps/rxjs.dev/src/karma.conf.js",
    "content": "// Karma configuration file, see link for more information\n// https://karma-runner.github.io/1.0/config/configuration-file.html\n\nmodule.exports = function (config) {\n  config.set({\n    basePath: '',\n    frameworks: ['jasmine', '@angular-devkit/build-angular'],\n    plugins: [\n      require('karma-jasmine'),\n      require('karma-chrome-launcher'),\n      require('karma-jasmine-html-reporter'),\n      require('karma-coverage-istanbul-reporter'),\n      require('@angular-devkit/build-angular/plugins/karma')\n    ],\n    client: {\n      clearContext: false // leave Jasmine Spec Runner output visible in browser\n    },\n    coverageIstanbulReporter: {\n      dir: require('path').join(__dirname, './coverage/site'),\n      reports: ['html', 'lcovonly', 'text-summary'],\n      fixWebpackSourcePaths: true\n    },\n    reporters: ['progress', 'kjhtml'],\n    port: 9876,\n    colors: true,\n    logLevel: config.LOG_INFO,\n    autoWatch: true,\n    browsers: ['Chrome'],\n    browserNoActivityTimeout: 60000,\n    singleRun: false,\n    restartOnFileChange: true\n  });\n};"
  },
  {
    "path": "apps/rxjs.dev/src/main.ts",
    "content": "import { enableProdMode } from '@angular/core';\nimport { platformBrowserDynamic } from '@angular/platform-browser-dynamic';\n\nimport { AppModule } from './app/app.module';\nimport { environment } from './environments/environment';\n\nif (environment.production) {\n  enableProdMode();\n}\n\nplatformBrowserDynamic().bootstrapModule(AppModule);\n"
  },
  {
    "path": "apps/rxjs.dev/src/noop-worker-basic.js",
    "content": "/**\n * A simple, no-op service worker that takes immediate control.\n * Use this file if the active service worker has a bug and we\n * want to deactivate the worker on client browsers while we\n * investigate the problem.\n *\n * To activate this service worker file, rename it to `worker-basic.min.js`\n * and deploy to the hosting. When the original worker files cache\n * expires, this one will take its place. (Browsers ensure that the expiry\n * time is never longer than 24 hours, but the default expiry time on Firebase\n * is 60 mins).\n */\n\n// Skip over the \"waiting\" lifecycle state, to ensure that our\n// new service worker is activated immediately, even if there's\n// another tab open controlled by our older service worker code.\nself.addEventListener('install', function(event) {\n  event.waitUntil(self.skipWaiting());\n});\n\n\n// Get a list of all the current open windows/tabs under\n// our service worker's control, and force them to reload.\n// This can \"unbreak\" any open windows/tabs as soon as the new\n// service worker activates, rather than users having to manually reload.\nself.addEventListener('activate', function(event) {\n  event.waitUntil(self.clients.claim());\n});\n"
  },
  {
    "path": "apps/rxjs.dev/src/polyfills.ts",
    "content": "/**\n * This file includes polyfills needed by Angular and is loaded before the app.\n * You can add your own extra polyfills to this file.\n *\n * This file is divided into 2 sections:\n *   1. Browser polyfills. These are applied before loading ZoneJS and are sorted by browsers.\n *   2. Application imports. Files imported after ZoneJS that should be loaded before your main\n *      file.\n *\n * The current setup is for so-called \"evergreen\" browsers; the last versions of browsers that\n * automatically update themselves. This includes Safari >= 10, Chrome >= 55 (including Opera),\n * Edge >= 13 on the desktop, and iOS 10 and Chrome on mobile.\n *\n * Learn more in https://angular.io/docs/ts/latest/guide/browser-support.html\n */\n\n/***************************************************************************************************\n * BROWSER POLYFILLS\n */\n\n/** HACK: force import of environment.ts/environment.prod.ts to load env specific polyfills */\nimport './environments/environment';\n\n/***************************************************************************************************\n * Zone JS is required by Angular itself.\n */\nimport 'zone.js';  // Included with Angular CLI.\n\n/***************************************************************************************************\n * APPLICATION IMPORTS\n */\n\n/**\n * Date, currency, decimal and percent pipes.\n * Needed for: All but Chrome, Firefox, Edge, IE11 and Safari 10\n */\n// import 'intl';  // Run `npm install --save intl`.\n"
  },
  {
    "path": "apps/rxjs.dev/src/pwa-manifest.json",
    "content": "{\n  \"short_name\": \"RxJS\",\n  \"name\": \"RxJS\",\n  \"icons\": [\n    {\n      \"src\": \"assets/images/favicons/apple-touch-icon-144x144.png\",\n      \"sizes\": \"144x144\",\n      \"type\": \"image/png\"\n    },\n    {\n      \"src\": \"assets/images/favicons/favicon-72x72.png\",\n      \"sizes\": \"72x72\",\n      \"type\": \"image/png\"\n    },\n    {\n      \"src\": \"assets/images/favicons/favicon-96x96.png\",\n      \"sizes\": \"96x96\",\n      \"type\": \"image/png\"\n    },\n    {\n      \"src\": \"assets/images/favicons/favicon-128x128.png\",\n      \"sizes\": \"128x128\",\n      \"type\": \"image/png\"\n    },\n    {\n      \"src\": \"assets/images/favicons/favicon-144x144.png\",\n      \"sizes\": \"144x144\",\n      \"type\": \"image/png\"\n    },\n    {\n      \"src\": \"assets/images/favicons/favicon-152x152.png\",\n      \"sizes\": \"152x152\",\n      \"type\": \"image/png\"\n    },\n    {\n      \"src\": \"assets/images/favicons/favicon-192x192.png\",\n      \"sizes\": \"192x192\",\n      \"type\": \"image/png\"\n    },\n    {\n      \"src\": \"assets/images/favicons/favicon-384x384.png\",\n      \"sizes\": \"384x384\",\n      \"type\": \"image/png\"\n    },\n    {\n      \"src\": \"assets/images/favicons/favicon-512x512.png\",\n      \"sizes\": \"512x512\",\n      \"type\": \"image/png\"\n    }\n  ],\n  \"start_url\": \"/?utm_source=homescreen\",\n  \"background_color\": \"#ffffff\",\n  \"theme_color\": \"#d81b60\",\n  \"display\": \"standalone\"\n}\n"
  },
  {
    "path": "apps/rxjs.dev/src/styles/0-base/_base-dir.scss",
    "content": "/* ==============================\n   BASE STYLES\n   ============================== */\n\n@import 'typography';"
  },
  {
    "path": "apps/rxjs.dev/src/styles/0-base/_typography.scss",
    "content": "body {\n  font-family: $main-font;\n  margin: 0;\n  color: $darkgray;\n  font-size: 14px;\n  -webkit-font-smoothing: antialiased;\n  -moz-osx-font-smoothing: grayscale;\n}\n\nh1 {\n  display: inline-block;\n  font-size: 24px;\n  font-weight: 500;\n  margin: 8px 0px;\n\n  @media screen and (max-width: 600px) {\n    margin-top: 0;\n  }\n}\n\nh2 {\n  font-size: 22px;\n  font-weight: 500;\n  margin: 32px 0px 24px;\n  clear: both;\n}\n\nh3 {\n  font-size: 20px;\n  font-weight: 400;\n  margin: 24px 0px;\n  clear: both;\n}\n\nh4 {\n  font-size: 18px;\n  font-weight: 400;\n  margin: 8px 0px;\n  clear: both;\n}\n\nh5 {\n  font-size: 16px;\n  font-weight: 500;\n  margin: 8px 0px;\n  clear: both;\n}\n\nh6 {\n  color: $mediumgray;\n  font-size: 16px;\n  font-weight: 500;\n  margin: 8px 0px;\n  clear: both;\n}\n\nh2, h3, h4, h5, h6 {\n  @media screen and (max-width: 600px) {\n    margin: 8px 0;\n  }\n}\n\n.mat-tab-body-wrapper h2 {\n  margin-top: 0;\n}\n\np, ol, ul, ol, li, input, a  {\n  font-size: 14px;\n  line-height: 24px;\n  letter-spacing: 0.30px;\n  font-weight: 400;\n  & > em {\n    letter-spacing: 0.30px;\n  }\n}\n\nol {\n  li, p {\n    margin: 4px 0;\n  }\n}\n\nli p {\n  margin: 0;\n}\n\na {\n  text-decoration: none;\n}\n\n.app-toolbar a {\n  font-size: 16px;\n  font-weight: 400;\n  color: white;\n  font-family: $main-font;\n  text-transform: uppercase;\n  padding: 21px 0;\n}\n\nstrong {\n  font-weight: 600;\n}\n\ntable {\n  border-collapse: collapse;\n  border-radius: 2px;\n  border-spacing: 0;\n  margin: 0 0 32px 0;\n}\n\ntable tbody th {\n  max-width: 100px;\n  padding: 13px 32px;\n  text-align: left;\n}\n\ntd {\n  font-weight: 400;\n  padding: 8px 30px;\n  letter-spacing: 0.30px;\n\n  p {\n    margin: 0;\n  }\n}\n\nth {\n  font-size: 16px;\n  font-weight: 500;\n  padding: 13px 32px;\n  text-align: left;\n}\n\np > code, li > code, td > code, th > code {\n  font-family: $code-font;\n  font-size: 85%;\n  color: $darkgray;\n  letter-spacing: 0;\n  line-height: 1;\n  padding: 2px 0;\n  background-color: $backgroundgray;\n  border-radius: 4px;\n}\n\ncode {\n  font-family: $code-font;\n  font-size: 90%;\n}\n\n.sidenav-content a {\n  color: $pink;\n  &:hover {\n    color: $mediumgray;\n  }\n}\n\n.informal {\n  display: block;\n  padding-left: 1.3em;\n  border-left: 5px solid #dfdfdf;\n  font-size: 1.1em;\n  font-style: italic;\n  margin: 22px 0;\n}\n"
  },
  {
    "path": "apps/rxjs.dev/src/styles/1-layouts/_api-page.scss",
    "content": ".api-section {\n  position: relative;\n\n  pre {\n    white-space: pre-wrap;\n  }\n\n  table.api-table {\n    min-width: 680px;\n\n    thead th {\n      color: white;\n      font-size: 16px;\n      background-color: $pink;\n      border-radius: 4px 4px 0 0;\n      text-transform: none;\n      padding: 8px 24px;\n    }\n\n    tbody {\n      pre {\n        white-space: normal;\n        margin: 4px;\n        padding: 4px 16px;\n      }\n\n      td,\n      th {\n        padding: 0;\n      }\n\n      th {\n        max-width: 150px;\n      }\n    }\n  }\n}\n\n.api-body {\n  max-width: 1200px;\n\n  table {\n    th {\n      text-transform: none;\n      font-size: 16px;\n      font-weight: bold;\n    }\n\n    tr {\n      border-bottom: 1px solid $lightgray;\n    }\n\n    td {\n      vertical-align: middle;\n    }\n\n    hr {\n      margin: 16px 0;\n    }\n\n    tr:last-child {\n      border-bottom: none;\n    }\n\n    &.item-table {\n      td {\n        padding: 32px;\n      }\n    }\n\n    &.list-table {\n      td {\n        padding: 16px 24px;\n      }\n    }\n  }\n\n  /* used to target the short description */\n  > p:nth-child(2) {\n    border-left: 5px solid $pink;\n    font-size: 1rem;\n    line-height: 1.25;\n    padding-left: 0.5rem;\n  }\n\n  .export-list {\n    a {\n      &.deprecated {\n        text-decoration: line-through;\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "apps/rxjs.dev/src/styles/1-layouts/_content-layout.scss",
    "content": "aio-shell.page-docs {\n  .sidenav-content {\n    // padding: 6rem 3rem 3rem 3rem; // THIS CAUSES THE TOP NAV TOOLBAR TO JUMP BETWEEN DOCS AND OTHER PAGES\n    margin: auto;\n  }\n}\n\n.sidenav-content {\n  min-height: 100vh;\n  padding: 80px 3rem 1rem;\n}\n\n@media (max-width: 600px) {\n  aio-menu {\n    display: none;\n  }\n\n  .sidenav-content {\n    min-height: 450px;\n    padding: 80px 1rem 1rem;\n  }\n}\n\n.sidenav-container {\n  width: 100%;\n  height: 100vh;\n}\n\n.sidenav-content button {\n  min-width: 50px;\n}\n\n#guide-change-log h2::before {\n  content: \"\";\n  display: block;\n  height: 1px;\n  margin: 24px 0px;\n  background: $lightgray;\n}\n"
  },
  {
    "path": "apps/rxjs.dev/src/styles/1-layouts/_doc-viewer.scss",
    "content": ".no-animations aio-doc-viewer > * {\n  // Disable view transition animations.\n  transition: none !important;\n}\n"
  },
  {
    "path": "apps/rxjs.dev/src/styles/1-layouts/_footer.scss",
    "content": "footer {\n  position: relative;\n  line-height: 24px;\n  flex: 1;\n  padding: 48px;\n  z-index: 0;\n  background-color: $pink;\n  color: $offwhite;\n  font-weight: 300;\n\n  aio-footer {\n    position: relative;\n    z-index: 0;\n  }\n\n  .footer-block {\n    margin: 0 24px;\n    vertical-align: top;\n  }\n\n  a {\n    color: $offwhite;\n    font-weight: 300;\n    text-decoration: none;\n    z-index: 20;\n    position: relative;\n    &:hover {\n      text-decoration: underline;\n    }\n    &:visited {\n      text-decoration: none;\n    }\n  }\n  a.action {\n    cursor: pointer;\n  }\n  h3 {\n    font-size: 16px;\n    text-transform: uppercase;\n    font-weight: 400;\n    margin: 0 0 16px;\n  }\n  p {\n    text-align: center;\n    margin: 10px 0px 5px;\n\n    @media (max-width: 480px) {\n      text-align: left;\n    }\n  }\n\n  div.grid-fluid {\n    display: -ms-flexbox;\n    display: -webkit-flex;\n    display: flex;\n\n    justify-content: center;\n\n    text-align: left;\n    margin: 0 0 40px;\n\n    ul {\n      list-style-position: inside;\n      padding: 0px;\n      margin: 0px;\n\n      li {\n        list-style-type: none;\n        padding: 0px;\n        text-align: left;\n      }\n    }\n\n    @media (max-width: 480px) {\n      flex-direction: column;\n      .footer-block {\n        margin: 8px 24px;\n      }\n    }\n  }\n\n  @media (max-width: 700px) {\n    h3 {\n      font-size: 110%;\n    }\n  }\n  @media (max-width: 600px) {\n    h3 {\n      font-size: 100%;\n    }\n  }\n}\n\nfooter::after {\n  content: '';\n  position: absolute;\n  z-index: -1;\n  top: 0;\n  bottom: 0;\n  left: 0;\n  right: 0;\n  background-size: 320px auto;\n}\n"
  },
  {
    "path": "apps/rxjs.dev/src/styles/1-layouts/_layout-global.scss",
    "content": "html, body {\n    height: 100%;\n}\n\nbody {\n    background-color: $offwhite;\n}\n\n.clearfix {\n    content: \"\";\n    display: table;\n    clear: both;\n}\n\n.clear {\n    clear: both;\n}\n\n.l-clearfix:after, .clearfix:after {\n    content: \"\";\n    display: table;\n    clear: both;\n}\n\n.is-visible {\n    display: block!important;\n}\n\n.l-flex-wrap {\n  display: flex;\n  flex-wrap: wrap;\n}\n\n.flex-center {\n    display: flex;\n    justify-content: center;\n}\n\n.center {\n    text-align: center;\n}\n\n.visually-hidden {\n    position: absolute !important;\n    top: -9999px !important;\n    left: -9999px !important;\n}\n\n.text-uppercase {\n  text-transform: uppercase;\n}"
  },
  {
    "path": "apps/rxjs.dev/src/styles/1-layouts/_layouts-dir.scss",
    "content": "/* ==============================\n   LAYOUT STYLES\n   ============================== */\n\n@import 'api-page';\n@import 'content-layout';\n@import 'doc-viewer';\n@import 'footer';\n@import 'layout-global';\n@import 'marketing-layout';\n@import 'not-found';\n@import 'sidenav';\n@import 'table-of-contents';\n@import 'top-menu';\n@import 'print-layout';"
  },
  {
    "path": "apps/rxjs.dev/src/styles/1-layouts/_marketing-layout.scss",
    "content": ".hero {\n  display: flex;\n  flex-direction: column;\n  justify-content: center;\n  align-items: center;\n  width: 100%;\n  box-sizing: border-box;\n  padding: 48px 48px 32px 48px;\n  overflow: hidden;\n\n  .hero-title {\n    display: inline-block;\n    font-size: 28px;\n    font-weight: 400;\n    line-height: 48px;\n    margin: 0 8px 0 0;\n    text-transform: uppercase;\n\n    &.is-standard-case {\n      text-transform: none;\n    }\n  }\n}\n\nsection#intro {\n  display: flex;\n  align-items: center;\n  position: relative;\n  width: 900px;\n  height: 480px;\n  margin: 0 auto;\n  padding: 0;\n  color: white;\n\n  @media (max-width: 780px) {\n    flex-direction: column;\n    justify-content: center;\n    width: 100%;\n    max-width: 100vw;\n    padding: 70px 0 32px;\n\n    button {\n      margin: 0;\n      height: 60px;\n    }\n  }\n\n  .homepage-container {\n    width: 100%;\n    max-width: 1040px;\n    margin: 0 auto;\n    margin-top: -7%;\n    padding-top: 0;\n    padding-bottom: 0;\n    display: flex;\n    flex-direction: column;\n    justify-content: center;\n    align-items: center;\n\n    .hero-cta + .hero-cta {\n      margin-top: 15px;\n    }\n\n    @media (max-width: 780px) {\n      display: flex;\n      flex-direction: column;\n      align-items: center;\n      width: 100%;\n      max-width: 100%;\n      padding: 0;\n    }\n  }\n\n  .headline-container {\n    margin: 32px 0;\n    text-align: center;\n  }\n\n  .hero-headline {\n    font-size: 40px;\n    line-height: 64px;\n    font-weight: 500;\n    color: $pink;\n\n    &:after {\n      display: none;\n    }\n\n    @media (max-width: 780px) {\n      text-align: center;\n    }\n\n    @media (max-width: 575px) {\n      font-size: 32px;\n      line-height: 50px;\n    }\n  }\n\n  .hero-subheadline {\n    font-size: 22px;\n    line-height: 32px;\n    color: $accentgrey;\n  }\n\n  .hero-logo {\n    display: flex;\n    width: 400px;\n\n    @media (max-width: 780px) {\n      justify-content: center;\n    }\n\n    img {\n      width: 400px;\n      height: 400px;\n      margin-bottom: 8px;\n      padding: 0;\n      filter: drop-shadow(0 2px 2px rgba($black, 0.24));\n\n      @media (max-width: 780px) {\n        width: 250px;\n        height: 250px;\n      }\n    }\n  }\n}\n\n.announcement-bar {\n  display: flex;\n  flex-direction: row;\n  flex-wrap: wrap;\n  justify-content: space-around;\n  align-items: center;\n  max-width: 50vw;\n  margin: 0 auto;\n  padding: 16px;\n  background-color: $white;\n  border-radius: 4px;\n  box-shadow: 0 2px 2px rgba($black, 0.24), 0 0 2px rgba($black, 0.12);\n  box-sizing: border-box;\n  transition: all 0.3s ease-in;\n\n  @media (max-width: 992px) {\n    flex-direction: column;\n    text-align: center;\n    padding: 32px 16px;\n  }\n\n  @media (max-width: 768px) {\n    width: 100%;\n    max-width: none;\n  }\n\n  & > * {\n    margin: 8px;\n  }\n\n  img {\n    filter: drop-shadow(0 2px 5px rgba(0, 0, 0, 0.26));\n  }\n\n  .button {\n    display: flex;\n    justify-content: center;\n    align-items: center;\n    height: 40px;\n    min-width: 160px;\n    font-size: 16px;\n    color: $white;\n    background-color: $pink;\n    border-radius: 48px;\n    box-shadow: 0 2px 5px 0 rgba(0, 0, 0, 0.26);\n    box-sizing: border-box;\n    cursor: pointer;\n\n    &:hover {\n      color: rgba($white, 0.7);\n    }\n  }\n\n  .material-icons {\n    display: none;\n    right: 0;\n    position: static;\n    transition: all 0.3s ease-in;\n    font-size: 16px;\n  }\n\n  p {\n    strong {\n      font-weight: 700;\n    }\n\n    font-size: 16px;\n    margin: 8px;\n    text-align: center;\n  }\n}\n\n// ANGULAR LINE\n.background-sky {\n  background-color: $pink;\n  background: $pink;\n  color: $white;\n}\n\n.home-row .card {\n  @include card(70%, auto);\n  display: flex;\n  flex-direction: row;\n  align-items: center;\n  justify-content: center;\n  position: relative;\n  width: 70%;\n  min-width: 270px;\n  text-align: center;\n  height: auto;\n  margin: auto;\n  padding: 24px;\n  box-shadow: 0 6px 6px rgba(10, 16, 20, 0.15), 0 0 52px rgba(10, 16, 20, 0.12);\n\n  @media (max-width: 600px) {\n    margin: 16px auto 0;\n\n    h2 {\n      margin: 0;\n    }\n\n    img {\n      max-width: none;\n      height: 70px;\n    }\n  }\n\n  @media (max-width: 1300px) {\n    img {\n      height: 70px;\n      max-width: none;\n    }\n  }\n\n  img {\n    margin: 16px;\n  }\n\n  .card-text-container {\n    margin: 0 16px;\n\n    p {\n      text-align: left;\n      color: $darkgray;\n      margin: 0;\n      padding: 8px 0;\n    }\n  }\n\n  &:hover {\n    h2 {\n      color: $pink;\n    }\n  }\n\n  ul {\n    list-style-type: none;\n  }\n}\n\n.text {\n  color: $darkgray;\n}\n\n.button.hero-cta {\n  display: flex;\n  align-items: center;\n  justify-content: center;\n  width: 184px;\n  height: 40px;\n  padding: 0 24px;\n  font-size: 18px;\n  font-weight: 600;\n  line-height: 40px;\n  background-color: $white;\n  border-radius: 48px;\n  box-shadow: 0 2px 5px 0 rgba(0, 0, 0, 0.26);\n  box-sizing: border-box;\n  cursor: pointer;\n\n  &:hover {\n    opacity: 0.9;\n  }\n}\n\naio-shell {\n  &.page-home {\n    section {\n      padding: 0;\n    }\n  }\n\n  &.page-home,\n  &.page-resources,\n  &.page-events,\n  &.page-contribute {\n    article {\n      padding: 32px;\n\n      @media (max-width: 800px) {\n        padding: 24px;\n      }\n    }\n  }\n\n  &.page-features {\n    article {\n      padding: 0 3rem;\n    }\n  }\n\n  &.page-home,\n  &.page-resources,\n  &.page-events,\n  &.page-features {\n    .content img {\n      @media (max-width: 1300px) {\n        max-width: none;\n      }\n    }\n\n    .feature-section img {\n      max-width: 70px;\n    }\n\n    @media (max-width: 600px) {\n      mat-sidenav-container.sidenav-container {\n        padding-top: 0;\n      }\n    }\n  }\n\n  .cta-bar .hero-cta {\n    color: $pink;\n  }\n}\n\n.cta-bar.announcement-bar {\n  background: none;\n  box-shadow: none;\n}\n\n.text-headline {\n  font-size: 20px;\n  font-weight: 500;\n  color: $pink;\n  margin-top: 10px;\n  text-transform: uppercase;\n}\n\naio-shell:not(.view-SideNav) {\n  mat-sidenav-container.sidenav-container {\n    max-width: none;\n  }\n}\n\ndiv[layout='row'] {\n  display: flex;\n  justify-content: center;\n  align-items: center;\n  box-sizing: border-box;\n\n  @media (max-width: 480px) {\n    display: block;\n  }\n}\n\n.layout-row {\n  flex-direction: row;\n}\n\n.home-rows {\n  overflow: hidden;\n  @media (max-width: 600px) {\n    margin: 0;\n  }\n}\n\n.background-superhero-paper {\n  background-size: 100%;\n  background-blend-mode: multiply;\n}\n\n.home-row {\n  max-width: 920px;\n  margin: 32px auto;\n\n  .promo-img-container,\n  .text-container {\n    max-width: 50%;\n\n    @media (max-width: 480px) {\n      max-width: 100%;\n      text-align: center;\n\n      &:nth-child(even) {\n        flex-direction: column-reverse;\n      }\n    }\n  }\n\n  .text-block {\n    padding-right: 15%;\n\n    @media (max-width: 600px) {\n      padding: 0;\n    }\n  }\n\n  .promo-img-container {\n    img {\n      max-width: 90% !important;\n    }\n\n    p {\n      margin: 0 20px;\n    }\n\n    img {\n      max-width: 90%;\n\n      @media (max-width: 599px) {\n        max-width: 100%;\n        float: initial !important;\n      }\n    }\n  }\n}\n\n.marketing-banner {\n  background-color: lighten($pink, 10);\n  margin-top: 64px;\n  padding: 32px;\n\n  @media (max-width: 600px) {\n    margin-top: 56px;\n    padding: 18px;\n  }\n\n  .banner-headline {\n    text-transform: uppercase;\n    font-size: 24px;\n    font-weight: 300;\n    color: white;\n    margin: 0;\n    -webkit-margin-before: 0;\n    -webkit-margin-after: 0;\n\n    @media (max-width: 600px) {\n      font-size: 18px;\n      font-weight: 400;\n    }\n\n    &:after {\n      display: none;\n    }\n  }\n}\n.page-features .marketing-banner {\n  margin-bottom: 20px;\n}\n\n.blm-background {\n  background-color: black;\n  color: white;\n  display: flex;\n  min-height: calc(100vh - 64px);\n}\n\n.text-container.blm-container {\n  text-align: center;\n  line-height: inherit;\n  max-width: inherit;\n}\n\n.blm-text {\n  font-size: 2rem;\n  line-height: inherit;\n}\n\n.blm-list-item {\n  margin: 10px 0;\n}\n"
  },
  {
    "path": "apps/rxjs.dev/src/styles/1-layouts/_not-found.scss",
    "content": "#file-not-found {\n    padding: 3rem 3rem 3rem;\n}\n\n.nf-container {\n    align-items: center;\n    padding: 32px;\n}\n\n.nf-response {\n    margin: 32px;\n    height: 100%;\n    flex-direction: column;\n\n    h1 {\n        font-size: 48px;\n        color: $pink;\n        text-transform: uppercase;\n        margin: 8px 0;\n    }\n}\n\n.nf-icon.material-icons {\n    color: $pink;\n    font-size: 100px;\n    position: static;\n}\n"
  },
  {
    "path": "apps/rxjs.dev/src/styles/1-layouts/_print-layout.scss",
    "content": "@media print {\n\n    // General Adjustments\n    * {\n        box-shadow: none !important;\n    }\n\n    h1 {\n        height: 40px !important;\n        color: $darkgray !important;\n    }\n\n    h1, h2, h3, h4, h5, h6 {\n        page-break-after: avoid;\n    }\n\n    ul, ol, img, code-example, table, tr, .alert, .l-subsection, .feature {\n        page-break-inside: avoid;\n    }   \n\n    table tbody tr:last-child td {\n        border-bottom: 1px solid $lightgray !important;\n    }\n\n    img {\n        max-width: 100% !important;\n    }\n\n    p {\n        widows: 4;\n    }\n\n    p > code, li > code, table code {\n        color: $pink !important;\n    }\n\n    // No Print Class\n    .no-print {\n        display: none !important;\n    }\n\n    // Custom No Print for Sidenav Menu\n    mat-sidenav.sidenav.mat-sidenav {\n        display: none !important;\n    }\n\n    // Custom No Print Element Adjustments\n    .mat-sidenav-content {\n        margin: 0 !important;\n    }\n\n    mat-sidenav-container.sidenav-container {\n        min-width: 100vw;\n    }\n\n    .sidenav-content {\n        overflow: visible;\n    }\n\n    .filetree {\n        max-width: 100%;\n    }\n\n    aio-code code {\n        border: none !important;\n    }\n\n    code-example {\n        pre.lang-bash code span {\n            color: $mediumgray !important;\n        }\n\n        pre.lang-sh code span {\n            color: $darkgray !important;\n        }\n\n        header {\n            border: 0.5px solid $lightgray;\n            color: $darkgray;\n        }\n    }\n\n    .content code { \n        border: 0.5px solid $lightgray;\n    }\n\n    .mat-tab-labels {\n        div.mat-tab-label {\n            &:not(.mat-tab-label-active) span {\n                font-style: italic;\n            }\n\n            &.mat-tab-label-active span {\n                font-weight: bold;\n            }\n        }\n    }\n\n    .api-header label { \n        color: $darkgray !important;\n        font-weight: bold !important;\n        margin: 2px !important;\n        padding: 0 !important;\n        display: block !important;\n    }\n\n    .feature-section img {\n        max-width: 70px !important;\n    }\n}"
  },
  {
    "path": "apps/rxjs.dev/src/styles/1-layouts/_sidenav.scss",
    "content": "// Disable sidenav animations for the initial render.\n.starting.mat-drawer-transition .mat-drawer-content {\n  transition: none;\n}\n\naio-nav-menu {\n  display: block;\n  margin: 0 auto;\n  font-size: 13px;\n  ul, a {\n    padding: 0;\n    margin: 0;\n  }\n\n  &:first-child {\n    margin-top: 16px;\n  }\n\n  aio-nav-item div a {\n    padding-left: 6px;\n  }\n}\n\nmat-sidenav.mat-sidenav.sidenav {\n  position: fixed;\n  top: 64px;\n  bottom: 0;\n  left: 0;\n  padding: 0;\n  min-width: 260px;\n  background-color: $offwhite;\n  box-shadow: 6px 0 6px rgba(0,0,0,0.10);\n\n  &.collapsed {\n    top: 56px;\n  }\n}\n\nmat-sidenav-container.sidenav-container {\n  min-height: 100%;\n  height: auto !important;\n  max-width: 100%;\n  margin: 0;\n  transform: none;\n\n  &.has-floating-toc {\n    max-width: 82%;\n  }\n}\n\nmat-sidenav-container div.mat-sidenav-content {\n  height: auto;\n}\n\n.vertical-menu-item {\n  box-sizing: border-box;\n  color: $darkgray;\n  cursor: pointer;\n  display: block;\n  max-width: 260px;\n  overflow-wrap: break-word;\n  padding-top: 4px;\n  padding-bottom: 4px;\n  text-decoration: none;\n  text-align: left;\n  width: 93%;\n  word-wrap: break-word;\n\n  &:hover {\n    background-color: $lightgray;\n    color: $pink;\n    text-shadow: 0 0 5px #ffffff;\n  }\n\n  &:focus {\n    outline: $accentgrey auto 2px;\n  }\n\n  //icons _within_ nav\n  .mat-icon {\n    position: absolute;\n    top: 0;\n    right: 0;\n    margin: 4px;\n  }\n}\n\n.vertical-menu-item.selected {\n  color: $pink;\n}\n\nbutton.vertical-menu-item {\n  border: none;\n  background-color: transparent;\n  margin-right: 0;\n  padding-left: 6px;\n  padding-top: 8px;\n  padding-bottom: 10px;\n}\n\n.heading {\n  color: $darkgray;\n  cursor: pointer;\n  position: relative;\n  text-transform: uppercase;\n}\n\n.heading-children.expanded {\n  visibility: visible;\n  opacity: 1;\n  max-height: 4000px; // Arbitrary max-height. Can increase if needed. Must have measurement to transition height.\n  transition: visibility 500ms, opacity 500ms, max-height 500ms;\n  -webkit-transition-timing-function: ease-in-out;\n  transition-timing-function: ease-in-out;\n}\n\n.heading-children.collapsed {\n  visibility: hidden;\n  opacity: 0;\n  max-height: 1px; // Must have measurement to transition height.\n  transition: visibility 275ms, opacity 275ms, max-height 280ms;\n  -webkit-transition-timing-function: ease-out;\n  transition-timing-function: ease-out;\n}\n\n.no-animations {\n  .heading-children.expanded, .heading-children.collapsed {\n    transition: none! important;\n  }\n}\n\n.level-1 {\n  font-family: $main-font;\n  font-size: 14px;\n  font-weight: 400;\n  margin-left: 14px;\n  transition: background-color 0.2s;\n  text-transform: uppercase;\n}\n\n.level-2 {\n  color: $mediumgray;\n  font-family: $main-font;\n  font-size: 14px;\n  font-weight: 400;\n  margin-left: 12px;\n  text-transform: none;\n}\n\n.level-3 {\n  color: $mediumgray;\n  font-family: $main-font;\n  font-size: 14px;\n  margin-left: 10px;\n}\n\n.level-1.expanded .mat-icon, .level-2.expanded .mat-icon {\n  @include rotate(90deg);\n}\n\n.level-1:not(.expanded) .mat-icon, .level-2:not(.expanded) .mat-icon {\n  @include rotate(0deg);\n}\n\naio-nav-menu.top-menu {\n  padding: 24px 0 0;\n\n  aio-nav-item:last-child div {\n    border-bottom: 1px solid rgba($mediumgray, 0.5);\n  }\n\n  aio-nav-item:first-child div {\n    border-top: 1px solid rgba($mediumgray, 0.5);\n  }\n}\n\n// Angular Version Selector\nmat-sidenav .doc-version {\n  padding: 8px;\n  border-top: 1px solid $lightgray;\n\n  select {\n    outline: none;\n    width: 100%;\n    background: rgba($lightgray, 0.5);\n    height: 32px;\n    border: 1px solid $lightgray;\n    color: $darkgray;\n\n    option {\n      font-family: $main-font;\n      font-size: 14px;\n    }\n  }\n}\n"
  },
  {
    "path": "apps/rxjs.dev/src/styles/1-layouts/_table-of-contents.scss",
    "content": "nav#main-table-of-contents {\n    width: 200px;\n    height: 900px;\n    position: fixed;\n    right: 0;\n    top: 50px;\n    bottom: 100px;\n    margin-left: 32px;\n    background-color: $pink;\n}"
  },
  {
    "path": "apps/rxjs.dev/src/styles/1-layouts/_top-menu.scss",
    "content": "// VARIABLES\n$hamburgerShownMargin: 0;\n$hamburgerHiddenMargin: 0 24px 0 -88px;\n\n// DOCS PAGE / STANDARD: TOPNAV TOOLBAR FIXED\nmat-toolbar.mat-toolbar {\n  position: fixed;\n  top: 0;\n  right: 0;\n  left: 0;\n  z-index: 10;\n  box-shadow: 0 2px 5px 0 rgba(0, 0, 0, 0.3);\n\n  mat-toolbar-row {\n    padding: 0 16px 0 0;\n  }\n\n  mat-icon {\n    color: $white;\n  }\n}\n\n// HOME PAGE OVERRIDE: TOPNAV TOOLBAR\naio-shell.page-home mat-toolbar.mat-toolbar {\n  background-color: $pink;\n\n  @media (min-width: 481px) {\n    &:not(.transitioning) {\n      background-color: $pink;\n      transition: background-color 0.2s linear;\n    }\n  }\n}\n\n// MARKETING PAGES OVERRIDE: TOPNAV TOOLBAR AND HAMBURGER\naio-shell.page-home mat-toolbar.mat-toolbar,\naio-shell.page-features mat-toolbar.mat-toolbar,\naio-shell.page-events mat-toolbar.mat-toolbar {\n  box-shadow: none;\n\n  // FIXED TOPNAV TOOLBAR FOR SMALL MOBILE\n  @media (min-width: 481px) {\n    position: absolute;\n  }\n}\n\n// DOCS PAGES OVERRIDE: HAMBURGER\naio-shell.folder-api mat-toolbar.mat-toolbar,\naio-shell.folder-docs mat-toolbar.mat-toolbar,\naio-shell.folder-guide mat-toolbar.mat-toolbar,\naio-shell.folder-tutorial mat-toolbar.mat-toolbar {\n  @media (min-width: 992px) {\n    .hamburger.mat-button {\n      // Hamburger shown on non-marketing pages on large screens.\n      margin: $hamburgerShownMargin;\n    }\n  }\n}\n\n// HAMBURGER BUTTON\n.hamburger.mat-button {\n  height: 100%;\n  margin: $hamburgerShownMargin;\n  padding: 0;\n\n  &:not(.starting) {\n    transition-duration: 0.4s;\n    transition-property: color, margin;\n    transition-timing-function: cubic-bezier(0.25, 0.8, 0.25, 1);\n  }\n\n  @media (min-width: 992px) {\n    // Hamburger hidden by default on large screens.\n    // (Will be shown per doc.)\n    margin: $hamburgerHiddenMargin;\n  }\n\n  &:hover {\n    color: $offwhite;\n  }\n\n  & .mat-icon {\n    color: white;\n    position: inherit;\n  }\n}\n\n// HOME NAV-LINK\n.nav-link.home img {\n  position: relative;\n  margin-top: -21px;\n  margin-right: 20px;\n  top: 12px;\n  height: 40px;\n\n  @media (max-width: 992px) {\n    &:hover {\n      transform: scale(1.1);\n    }\n  }\n}\n\n// TOP MENU\naio-top-menu {\n  display: flex;\n  flex-direction: row;\n  align-items: center;\n  width: 80%;\n\n  ul {\n    display: flex;\n    flex-direction: row;\n    align-items: center;\n    list-style-position: inside;\n    padding: 0px;\n    margin: 0px;\n\n    li {\n      padding-bottom: 2px;\n      list-style-type: none;\n      cursor: pointer;\n\n      &:hover {\n        opacity: 0.7;\n      }\n\n      &:focus {\n        background-color: $accentgrey;\n        outline: none;\n      }\n    }\n  }\n\n  a.nav-link {\n    margin: 0;\n    padding: 24px 16px;\n    cursor: pointer;\n\n    &:focus {\n      background: rgba($white, 0.15);\n      border-radius: 4px;\n      outline: none;\n      padding: 8px 16px;\n    }\n  }\n}\n\n// SEARCH BOX\naio-search-box.search-container {\n  display: flex;\n  justify-content: flex-end;\n  align-items: center;\n  width: 100%;\n  min-width: 150px;\n  height: 100%;\n\n  input {\n    color: $darkgray;\n    border: none;\n    border-radius: 100px;\n    background-color: $offwhite;\n    padding: 5px 16px;\n    margin-left: 8px;\n    width: 180px;\n    max-width: 240px;\n    height: 50%;\n    -webkit-appearance: none;\n\n    &:focus {\n      outline: none;\n    }\n\n    @include bp(big) {\n      transition: width 0.4s ease-in-out;\n\n      &:focus {\n        width: 50%;\n      }\n    }\n    @media (max-width: 480px) {\n      width: 150px;\n    }\n  }\n}\n\n// EXTERNAL LINK ICONS\n.app-toolbar {\n  .toolbar-external-icons-container {\n    display: flex;\n    flex-direction: row;\n    height: 100%;\n\n    a {\n      display: flex;\n      align-items: center;\n      margin-left: 16px;\n\n      @media screen and (max-width: 480px) {\n        margin-left: 8px;\n      }\n\n      &:hover {\n        opacity: 0.8;\n      }\n\n      img {\n        height: 24px;\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "apps/rxjs.dev/src/styles/2-modules/_alert.scss",
    "content": ".alert {\n    padding: 16px;\n    margin: 24px 0px;\n    font-size: 14px;\n    color: $darkgray;\n    width: 100%;\n    box-sizing: border-box;\n\n    &.is-critical {\n        border-left: 10px solid $pink;\n        background-color: rgba($pink, 0.05);\n\n        h1, h2, h3, h4, h5, h6 {\n            color: $pink;\n        }\n    }\n\n    &.is-important {\n        border-left: 10px solid $orange;\n        background-color: rgba($orange, 0.05);\n\n        h1, h2, h3, h4, h5, h6 {\n            color: $orange;\n        }\n    }\n\n    &.is-helpful {\n        border-left: 10px solid $pink;\n        background-color: rgba($pink, 0.05);\n\n        h1, h2, h3, h4, h5, h6 {\n            color: $pink;\n        }\n    }\n\n    > * {\n        margin: 0;\n        padding: 8px 16px;\n    }\n}"
  },
  {
    "path": "apps/rxjs.dev/src/styles/2-modules/_api-list.scss",
    "content": "/* API EDIT ICON */\n#api {\n  .api-filter .material-icons {\n    right: 48px;\n  }\n}\n\n/* API LIST STYLES */\n\naio-api-list {\n    div.form-search i.material-icons {\n        width: 20px;\n        pointer-events: none;\n    }\n\n    .form-search input {\n        width: 182px;\n    }\n\n    .api-list-container {\n      display: flex;\n      flex-direction: column;\n      margin: 0 auto;\n\n      h2 {\n        margin-top: 16px;\n      }\n    }\n}\n\n.api-filter {\n  display: flex;\n  margin: 0 auto;\n\n  @media (max-width: 600px) {\n      flex-direction: column;\n      margin: 16px auto;\n  }\n\n  .form-select-menu, .form-search {\n      margin: 8px;\n  }\n}\n\n/* LAYOUT */\n\n.docs-content {\n  position: relative;\n}\n\n.l-content-small {\n  padding: 16px;\n  max-width: 1100px;\n  margin: 0;\n\n  @media handheld and (max-width: $phone-breakpoint),\n  screen and (max-device-width: $phone-breakpoint),\n  screen and (max-width: $tablet-breakpoint) {\n    padding: 24px 0 0;\n  }\n}\n\n/* SEARCH BAR */\n\n.form-search {\n  position: relative;\n\n  input {\n    box-shadow: 0 2px 2px rgba($black, 0.24), 0 0 2px rgba($black, 0.12);\n    box-sizing: border-box;\n    border: 1px solid $white;\n    color: $blue-600;\n    font-size: 16px;\n    height: 32px;\n    line-height: 32px;\n    outline: none;\n    padding: 0 16px 0 32px;\n    transition: all .2s;\n\n    // PLACEHOLDER TEXT\n    &::-webkit-input-placeholder { /* Chrome/Opera/Safari */\n      color: $blue-grey-100;\n      font-size: 14px;\n    }\n    &::-moz-placeholder { /* Firefox 19+ */\n      color: $blue-grey-100;\n      font-size: 14px;\n    }\n    &:-ms-input-placeholder { /* IE 10+ */\n      color: $blue-grey-100;\n      font-size: 14px;\n    }\n    &:-moz-placeholder { /* Firefox 18- */\n      color: $blue-grey-100;\n      font-size: 14px;\n    }\n\n    &:focus {\n      border: 1px solid $blue-400;\n      box-shadow: 0 2px 2px rgba($blue-400, 0.24), 0 0 2px rgba($blue-400, 0.12);\n    }\n  }\n\n  .material-icons {\n    color: $blue-grey-100;\n    font-size: 20px;\n    left: 8px;\n    position: absolute;\n    top: 6px;\n    z-index: $layer-1;\n  }\n}\n\n/* API SYMBOLS */\n\n/* SYMBOL CLASS */\n\n.symbol {\n  border-radius: 2px;\n  box-shadow: 0 1px 2px rgba($black, .24);\n  color: $white;\n  display: inline-block;\n  font-size: 10px;\n  font-weight: 600;\n  line-height: 16px;\n  text-align: center;\n  width: 16px;\n\n  // SYMBOL TYPES\n  // Symbol mapping variables in *constants*\n  @each $name, $symbol in $api-symbols {\n    &.#{$name} {\n      background: map-get($symbol, background);\n\n      &:before {\n        content: map-get($symbol, content);\n      }\n    }\n  }\n}\n\n/* API HOMEE PAGE */\n\n/* API FILTER MENU */\n\n.api-filter {\n  aio-select {\n    width: 200px;\n\n    .symbol {\n      margin-right: 8px;\n    }\n  }\n\n  .form-search {\n    float: left;\n  }\n}\n\n/* API CLASS LIST */\n\n.docs-content .api-list {\n  list-style: none;\n  margin: 0 0 32px -8px;\n  padding: 0;\n  overflow: hidden;\n\n  @media screen and (max-width: 600px) {\n        margin: 0 0 0 -8px;\n    }\n\n  li {\n    font-size: 14px;\n    margin: 8px 0;\n    line-height: 14px;\n    padding: 0;\n    float: left;\n    width: 33%;\n    overflow: hidden;\n    min-width: 220px;\n    text-overflow: ellipsis;\n    white-space: nowrap;\n\n    .symbol {\n      margin-right: 8px;\n    }\n    a {\n      color: $blue-grey-600;\n      display: inline-block;\n      line-height: 16px;\n      padding: 0 16px 0;\n      text-decoration: none;\n      transition: all .3s;\n      overflow: hidden;\n      text-overflow: ellipsis;\n\n      &:hover {\n        background: $blue-grey-50;\n        color: $blue-500;\n      }\n    }\n\n    .stability {\n      &.deprecated {\n        text-decoration: line-through;\n      }\n\n      &.experimental {\n        font-style: italic;\n      }\n    }\n  }\n}\n\n.docs-content .h2-api-docs,\n.docs-content .h2-api-docs:first-of-type {\n  font-size: 18px;\n  line-height: 24px;\n  margin-top: 0;\n}\n\n.code-links {\n  a {\n    code, .api-doc-code {\n      color: #1E88E5 !important;\n    }\n  }\n}\n\n.openParens {\n  margin-top: 15px;\n}\n\n.endParens {\n  margin-bottom: 20px !important;\n}\n\np {\n\n  &.selector {\n    margin: 0;\n  }\n\n  &.location-badge {\n    margin: 0 0 16px 16px !important;\n  }\n\n  .api-doc-code {\n    border-bottom: 0;\n\n    :hover {\n      border-bottom: none;\n    }\n  }\n}\n\n.row-margin {\n  margin-bottom: 36px;\n  h2 {\n    line-height: 28px;\n  }\n}\n\n.code-margin {\n  margin-bottom: 8px;\n}\n\n.no-bg {\n  background: none;\n  padding: 0;\n}\n\n.no-bg-with-indent {\n  padding-top: 0;\n  padding-bottom: 0;\n  padding-left: 16px;\n  margin-top: 6px;\n  margin-bottom: 0;\n  background: none;\n}\n\n.code-background {\n  padding: 0 5px 0;\n\n  span.pln {\n    color: #1E88E5 !important;\n  }\n}\n\n.code-anchor {\n  cursor: pointer;\n\n  &:hover {\n    text-decoration: underline;\n  }\n}\n\n.api-doc-code {\n  font-size: 14px;\n  color: #1a2326;\n\n  // the last .pln (white space) creates additional spacing between sections of the api doc. Remove it.\n  &.no-pln {\n    .pln:last-child {\n      display: none;\n    }\n  }\n}\n\n@media screen and (max-width: 600px) {\n  .docs-content {\n    // Overrides display flex from angular material.\n    // This was added because Safari doesn't play nice with layout=\"column\".\n    // Look of API doc in Chrome and Firefox remains the same, and is fixed for Safari.\n    .layout-xs-column {\n      display: block !important;\n    }\n  }\n\n  .api-doc-code {\n    font-size: 12px;\n  }\n\n  p.location-badge {\n    position: relative;\n    font-size: 11px;\n  }\n}\n"
  },
  {
    "path": "apps/rxjs.dev/src/styles/2-modules/_api-pages.scss",
    "content": ".page-actions {\n  float: right;\n  .material-icons {\n    border-radius: 4px;\n    padding: 4px;\n    font-size: 20px;\n    &:hover {\n      background-color: $mist;\n    }\n  }\n}\n\n.api-header {\n  display: flex;\n  align-items: center;\n\n  @media screen and (max-width: 600px) {\n    flex-direction: column;\n    align-items: flex-start;\n  }\n\n  > h1 {\n    margin-right: 1rem;\n  }\n}\n\n.api-body {\n\n  .class-overview {\n    position: relative;\n\n    code-example {\n        clear: left;\n    }\n  }\n\n  .description img {\n    border: 1px solid #dfdfdf;\n    max-width: 100%;\n    width: 100%;\n  }\n\n  .method-table {\n    h3 {\n      margin: 6px 0;\n      font-weight: bold;\n    }\n\n    h4 {\n      font-size: 14px;\n      font-weight: bold;\n      margin-top: 12px;\n    }\n  }\n\n  .api-heading {\n    padding: 5px 0;\n    font-size: 16px;\n    font-weight: bold;\n  }\n\n  .short-description {\n    margin: 6px 0 0 10px;\n  }\n\n  .properties-table {\n    font-size: 14px;\n\n    thead th {\n      &:nth-child(1) {\n        width: 20%;\n      }\n      &:nth-child(2) {\n        width: 20%;\n      }\n    }\n  }\n\n  .parameters-table {\n    margin-top: 0;\n    font-size: 14px;\n    td:nth-child(1) {\n      width: 20%;\n    }\n  }\n\n  details.overloads {\n    margin-left: -8px;\n\n    summary {\n      height: inherit;\n      padding: 8px 12px;\n      h4 {\n        margin: 0;\n        clear: left;\n      }\n    }\n}\n\n  .api-section aio-code {\n    background-color: rgba(241, 241, 241, 0.2);\n  }\n\n  .from-constructor, .read-only-property {\n    font-style: italic;\n    color: $pink;\n  }\n}\n\n\n.deprecated-api-item {\n  text-decoration: line-through;\n}\n"
  },
  {
    "path": "apps/rxjs.dev/src/styles/2-modules/_buttons.scss",
    "content": "/* Button Styles */\n\n.button,\na.button.mat-button {\n  display: inline-block;\n  line-height: 32px;\n  padding: 0px 16px;\n  font-size: 14px;\n  font-weight: 400;\n  border-radius: 3px;\n  text-decoration: none;\n  text-transform: uppercase;\n  overflow: hidden;\n  border: none;\n\n  // SIZES\n  &.button-small {\n    font-size: 12px;\n    line-height: 24px;\n    padding: 0px 8px;\n  }\n\n  &.button-large {\n    font-size: 15px;\n    line-height: 48px;\n    padding: 0px 24px;\n  }\n\n  &.button-x-large {\n    font-size: 16px;\n    line-height: 56px;\n    padding: 0px 24px;\n  }\n\n\n  // COLORS\n\n  &.button-secondary {\n    background: $mediumgray;\n    color: rgba($white, .87);\n  }\n\n  &.button-plain {\n    background: $white;\n    color: rgba($darkgray, .87);\n  }\n\n  &.button-subtle {\n    background: $mediumgray;\n    color: darken($offwhite, 10%);\n  }\n\n  &.button-navy {\n    background: $pink;\n    color: rgba($white, .87);\n  }\n\n  &.button-banner {\n    background: $darkgray;\n    color: rgba($white, .87);\n  }\n\n  // &.button-shield,\n  // &.button-shield.mat-button {\n  //   background-color: $pink;\n  //   background: $pink url('assets/images/logos/angular/angular_whiteTransparent.svg') 24px 13px no-repeat;\n  //   color: rgba($white, .87);\n  //   padding-left: 54px;\n  //   background-size: 22px 22px;\n\n  //   @media only screen and (-webkit-min-device-pixel-ratio: 2), only screen and (min-device-pixel-ratio: 2) {\n  //     background: $pink url('assets/images/logos/angular/angular_whiteTransparent.svg') 24px 13px no-repeat;\n  //     background-size: 22px 22px;\n\n  //   }\n  // }\n}\n\n.cta-bar {\n  text-align: center;\n\n  .button {\n    margin: 0px 8px;\n    box-shadow: 0 2px 5px 0 rgba(0,0,0,.26);\n    transition: all .2s ease-in-out;\n    &:hover {\n        transform: scale(1.1);\n        color: $offwhite;\n    }\n  }\n}\n\na.filter-button {\n  width: 140px;\n  font-size: 14px;\n  padding: 0px 16px;\n  margin: 8px;\n  line-height: 48px;\n  border: 2px solid $pink;\n  border-radius: 4px;\n\n  &:hover {\n    background-color: $pink;\n    color: white;\n  }\n}\n\n[mat-button], [mat-raised-button], [mat-button], [mat-raised-button] {\n  text-transform: uppercase;\n}\n"
  },
  {
    "path": "apps/rxjs.dev/src/styles/2-modules/_callout.scss",
    "content": ".callout {\n  @extend .alert;\n  padding: 0px;\n  border-left: none !important;\n  border-radius: 4px;\n\n  header {\n    color: $white;\n    line-height: 24px;\n    font-weight: 500;\n    text-transform: uppercase;\n    border-radius: 4px 4px 0 0;\n  }\n\n  p {\n    padding: 16px;\n    margin: 0px;\n    font-size: 14px;\n  }\n\n  &.is-critical {\n    border-color: $brightred;\n    background: rgba($brightred, 0.05);\n\n    header {\n      background: $brightred;\n    }\n  }\n\n  &.is-important {\n    border-color: $orange;\n    background: rgba($orange, 0.05);\n\n    header {\n      background: $amber-700;\n    }\n  }\n\n  &.is-helpful {\n    border-color: $pink;\n    background: rgba($pink, 0.05);\n\n    header {\n      background: $pink;\n    }\n  }\n}"
  },
  {
    "path": "apps/rxjs.dev/src/styles/2-modules/_card.scss",
    "content": ".card-container {\n    display: flex;\n    flex-direction: row;\n    flex-wrap: wrap;\n    margin: 24px 0;\n}\n\n.docs-card {\n  @include card(194px, 30%);\n  max-width: 340px;\n  min-width: 262px;\n  margin: 24px 8px;\n  padding-bottom: 48px;\n  position: relative;\n\n  &:hover {\n    text-decoration: none;\n\n    section {\n      color: $pink;\n    }\n\n    p {\n      color: $darkgray;\n      padding: 0 16px;\n    }\n\n    .card-footer {\n      line-height: 32px;\n      padding: 8px 16px;\n      background-color: rgba($pink, 0.1);\n      color: $pink;\n    }\n  }\n\n\n  section {\n    color: $darkgray;\n    font-size: 20px;\n    line-height: 24px;\n    margin: 0;\n    padding: 32px 0 24px;\n    text-transform: none;\n    text-align: center;\n  }\n\n  p {\n    color: $darkgray;\n    font-size: 13px;\n    line-height: 24px;\n    padding: 0 16px;\n    margin: 0;\n    text-align: center;\n  }\n\n  .card-footer {\n    bottom: 0;\n    border-top: 0.5px solid $lightgray;\n    box-sizing: border-box;\n    line-height: 48px;\n    left: 0;\n    position: absolute;\n    right: 0;\n    text-align: right;\n    color: $mediumgray;\n\n    a {\n      color: $mediumgray;\n      font-size: 13px;\n    }\n  }\n  .card-footer.center {\n    text-align: center;\n  }\n}\n"
  },
  {
    "path": "apps/rxjs.dev/src/styles/2-modules/_code.scss",
    "content": "code-example, code-tabs {\n    clear: both;\n    display: block;\n}\n\ncode-example,\ncode-tabs mat-tab-body {\n  &:not(.no-box) {\n    background-color: rgba($backgroundgray, 0.2);\n    border: 0.5px solid $lightgray;\n    border-radius: 5px;\n    color: $darkgray;\n    margin: 16px auto;\n  }\n\n  &.no-box {\n    pre {\n      margin: 0;\n    }\n    code {\n      background-color: transparent;\n    }\n  }\n\n  code {\n    overflow: auto;\n  }\n}\n\n// TERMINAL / SHELL TEXT STYLES\n\ncode-example.code-shell, code-example[language=sh], code-example[language=bash] {\n  background-color: $darkgray;\n}\n\ncode-example header {\n  background-color: $accentgrey;\n  border-radius: 5px 5px 0 0;\n  color: $offwhite;\n  font-size: 16px;\n  padding: 8px 16px;\n}\n\ncode-example.avoid header,\ncode-example.avoidFile header {\n  border: 2px solid $anti-pattern;\n  background: $anti-pattern;\n}\n\ncode-example.avoid,\ncode-example.avoidFile,\ncode-tabs.avoid mat-tab-body,\ncode-tabs.avoidFile mat-tab-body {\n  border: 0.5px solid $anti-pattern;\n}\n\ncode-tabs div .mat-tab-body-content {\n  height: auto;\n}\n\ncode-tabs .mat-tab-body-wrapper mat-tab-body .mat-tab-body {\n  overflow-y: hidden;\n}\n\ncode-tabs mat-tab-body-content .fadeIn {\n  animation: opacity 2s ease-in;\n}\n\naio-code pre {\n    display: flex;\n    min-height: 32px;\n    margin: 16px 24px;\n    white-space: pre-wrap;\n    align-items: center;\n\n    code span {\n      line-height: 24px;\n    }\n}\n\n\n.code-missing {\n  color: $darkred;\n}\n\n\n.copy-button,\n.edit-button {\n  position: absolute;\n  top: -8px;\n  right: -32px;\n\n  color: $blue-grey-200;\n  background-color: transparent;\n  border: none;\n  cursor: pointer;\n  &:hover {\n    color: $mediumgray;\n  }\n}\n.edit-button {\n  right: 0;\n}\n\n.lang-sh .copy-button, .lang-bash .copy-button {\n  color: $mediumgray;\n  &:hover {\n    color: $lightgray;\n  }\n}\n\n.code-tab-group .mat-tab-label {\n  white-space: nowrap;\n}\n\n.code-tab-group .mat-tab-body-content {\n  height: auto;\n  transform: none;\n}\n\n\n[role=\"tabpanel\"] {\n    transition: none;\n}\n\n.sidenav-content code a {\n  color: inherit;\n  font-size: inherit;\n}\n\n/* PRETTY PRINTING STYLES for prettify.js. */\n\n.prettyprint {\n  position: relative;\n}\n\n/* Specify class=linenums on a pre to get line numbering */\nol.linenums {\n  margin: 0;\n  font-family: $main-font;\n  color: #B3B6B7;\n  li {\n    margin: 0;\n    font-family: $code-font;\n    font-size: 90%;\n    line-height: 24px;\n  }\n}\n\n/* The following class|color styles are derived from https://github.com/google/code-prettify/blob/master/src/prettify.css*/\n\n/* SPAN elements with the classes below are added by prettyprint. */\n.pln { color: #000 }  /* plain text */\n\n@media screen {\n  .str { color: #800 }  /* string content */\n  .kwd { color: #00f }  /* a keyword */\n  .com { color: #060 }  /* a comment */\n  .typ { color: #de0000 }  /* a type name */\n  .lit { color: #0074af }  /* a literal value */\n  /* punctuation, lisp open bracket, lisp close bracket */\n  .pun, .opn, .clo { color: #660 }\n  .tag { color: #008 }  /* a markup tag name */\n  .atn { color: #606 }  /* a markup attribute name */\n  .atv { color: #800 }  /* a markup attribute value */\n  .dec, .var { color: #606 }  /* a declaration; a variable name */\n  .fun { color: #de0000 }  /* a function name */\n}\n\n/* Use higher contrast and text-weight for printable form. */\n@media print, projection {\n  .str { color: #060 }\n  .kwd { color: #006; font-weight: bold }\n  .com { color: #600; font-style: italic }\n  .typ { color: #404; font-weight: bold }\n  .lit { color: #044 }\n  .pun, .opn, .clo { color: #440 }\n  .tag { color: #006; font-weight: bold }\n  .atn { color: #404 }\n  .atv { color: #060 }\n}\n\n/* SHELL / TERMINAL CODE BLOCKS */\n\ncode-example.code-shell, code-example[language=sh], code-example[language=bash] {\n  & .pnk, .blk,.pln, .otl, .kwd, .typ, .tag, .str, .atv, .atn, .com, .lit, .pun, .dec {\n    color: $codegreen;\n  }\n}\n"
  },
  {
    "path": "apps/rxjs.dev/src/styles/2-modules/_contribute.scss",
    "content": ".contribute-container {\n  h2 {\n    margin: 0;\n  }\n\n  .l-sub-section {\n    width: 90%;\n    margin-bottom: 20px;\n\n    &:last-child {\n      margin-bottom: 0;\n    }\n  }\n}\n"
  },
  {
    "path": "apps/rxjs.dev/src/styles/2-modules/_contributor.scss",
    "content": "aio-contributor-list {\n  @media handheld and (max-width: 480px), screen and (max-width: 480px), screen and (max-width: 900px) {\n    .grid-fluid{\n      width: auto;\n    }\n  }\n\n  @media handheld and (max-width: 480px), screen and (max-width: 480px), screen and (max-width: 900px) {\n    .grid-fluid{\n      margin-left: 20px;\n      margin-right: 20px;\n      float: none;\n      display: block;\n      width: auto;\n    }\n  }\n}\n\n.group-buttons {\n  margin: 32px auto;\n\n  a {\n    &.selected {\n      background-color: $pink;\n      color: white;\n    }\n  }\n}\n\n.contributor-group {\n  display: flex;\n  flex-direction: row;\n  flex-wrap: wrap;\n  justify-content: center;\n}\n\naio-contributor {\n  background: $white;\n  margin: 8px;\n  position: relative;\n  cursor: pointer;\n  border-radius: 4px;\n  box-shadow: 0 2px 2px rgba(10, 16, 20, 0.24), 0 0 2px rgba(10, 16, 20, 0.12);\n  transition: all .3s;\n  perspective: 800px;\n\n  &:hover {\n    transform: translate3d(0,-3px,0);\n    box-shadow: 0 8px 8px rgba(10, 16, 20, 0.24), 0 0 8px rgba(10, 16, 20, 0.12);\n\n    .contributor-image {\n      transform: scale(1.05);\n    }\n\n    .contributor-info {\n      opacity: 1;\n    }\n  }\n\n  .contributor-info {\n    background: rgba($darkgray, 0.5);\n    height: 168px;\n    width: 168px;\n    display: flex;\n    flex-direction: row;\n    justify-content: center;\n    align-items: center;\n    text-align: center;\n    opacity: 0;\n    border-radius: 50%;\n\n    [mat-button] {\n      color: $white;\n      font-size: 14px;\n      font-weight: 500;\n      margin: 8px;\n      padding: 0;\n\n      &:hover {\n        color: $lightgray;\n      }\n\n      &.icon {\n        min-width: 20px;\n        width: 20px;\n\n        .fa-2x {\n          font-size: 20px;\n        }\n      }\n    }\n  }\n\n  div.contributor-card {\n    width: 250px;\n    height: 270px;\n    display: flex;\n    flex-direction: column;\n    align-items: center;\n    justify-content: space-between;\n    position: relative;\n    overflow: hidden;\n    border-radius: 4px;\n    transform-style:preserve-3d;\n    transition:transform ease 500ms;\n\n    h3 {\n      margin: 8px 0;\n    }\n\n    .card-front, .card-back {\n      width: 100%;\n      height: 100%;\n      text-align: center;\n      display: flex;\n      flex-direction: column;\n      box-sizing: border-box;\n    }\n\n    .card-front {\n      justify-content: center;\n    }\n\n    .card-back {\n      height: 100%;\n      display: flex;\n      flex-direction: column;\n      justify-content: center;\n      padding: 16px 24px;\n      transform:rotateY(180deg);\n\n      section {\n        display: none;\n      }\n\n      p {\n        margin: 8px 0;\n        font-size: 12px;\n        line-height: 14px;\n        text-align: left;\n      }\n\n    }\n\n    &.flipped {\n      transform:rotateY(180deg);\n      .card-front {\n        display: none;\n      }\n    }\n  }\n\n  .contributor-image {\n    display: flex;\n    justify-content: center;\n    border-radius: 50%;\n    align-items: center;\n    height: 168px;\n    width: 168px;\n    background-size: cover;\n    background-position: center;\n    margin: 8px auto;\n    border: 2px solid $lightgray;\n    transition: all .2s ease-in-out;\n  }\n\n  section {\n    font-size: 14px;\n    font-weight: 500;\n    padding: 8px;\n    margin: 0;\n    white-space: nowrap;\n    overflow: hidden;\n    text-overflow: ellipsis;\n    text-transform: uppercase;\n  }\n\n  p {\n    cursor: pointer;\n    font-size: 14px;\n    line-height: 18px;\n    margin: 8px 16px;\n    text-overflow: ellipsis;\n    overflow: scroll;\n    font-weight: 400;\n  }\n}\n"
  },
  {
    "path": "apps/rxjs.dev/src/styles/2-modules/_deploy-theme.scss",
    "content": "\naio-shell.mode-archive {\n\n  .mat-toolbar.mat-primary, footer {\n    background: linear-gradient(145deg,#263238,#78909C);\n  }\n\n  .vertical-menu-item {\n    &.selected, &:hover {\n      color: #263238;\n    }\n  }\n\n  .toc-inner ul.toc-list li.active a {\n    color: #263238;\n\n    &:before {\n      background-color: #263238;\n    }\n  }\n\n  .toc-inner ul.toc-list li:hover a {\n    color: #263238;\n  }\n}\n\naio-shell.mode-next {\n\n  .mat-toolbar.mat-primary, footer {\n    background: linear-gradient(145deg,#DD0031,#C3002F);\n  }\n\n  .vertical-menu-item {\n    &.selected, &:hover {\n      color: #DD0031;\n    }\n  }\n\n  .toc-inner ul.toc-list li.active a {\n    color: #DD0031;\n\n    &:before {\n      background-color: #DD0031;\n    }\n  }\n\n  .toc-inner ul.toc-list li:hover a {\n    color: #DD0031;\n  }\n}\n"
  },
  {
    "path": "apps/rxjs.dev/src/styles/2-modules/_details.scss",
    "content": "/*\n * General styling to make detail/summary tags look a bit more material\n * To get the best out of it you should structure your usage like this:\n *\n * ```\n * <details>\n *   <summary>Some title</summary>\n *   <div class=\"details-content\">\n *     Some content\n *   </div>\n *  </details>\n *\n */\n\nsummary {\n  cursor: pointer;\n  font-size: 16px;\n  position: relative;\n  padding: 16px 24px;\n  color: $black;\n  height: 16px;\n  display: block; // Remove the built in details marker in FF\n\n  &::-webkit-details-marker {\n    display: none; // Remove the built in details marker in webkit\n  }\n\n  &::before {\n    content: '\\E5CE'; // See https://material.io/icons/#ic_expand_less\n    font-family: 'Material Icons';\n    font-size: 24px;\n    -webkit-font-smoothing: antialiased;\n    @include rotate(0deg); // We will rotate 180 degrees when details is open\n    float: right;\n  }\n}\n\ndetails {\n  box-shadow: 0 1px 4px 0 rgba($black, 0.37);\n\n  .detail-contents {\n    padding: 16px 24px;\n  }\n\n  &[open] > summary::before {\n    @include rotate(180deg); // Rotate the icon\n  }\n}\n"
  },
  {
    "path": "apps/rxjs.dev/src/styles/2-modules/_edit-page-cta.scss",
    "content": ".edit-page-cta {\n    font-weight: 400;\n    font-size: 14px;\n    color: $pink;\n    text-align: right;\n    margin-right: 32px;\n    display: block;\n    position: absolute;\n    right: 0;\n}"
  },
  {
    "path": "apps/rxjs.dev/src/styles/2-modules/_features.scss",
    "content": "// FEATURES MARKETING PAGE SPECIFIC STYLES\n\n.feature-section {\n  margin: 0 0 32px;\n\n  .feature-header, .text-headline {\n    text-align: center;\n  }\n\n  .feature-header img {\n    margin: 16px;\n  }\n\n  .feature-title {\n    font-size: 16px;\n    font-weight: 500;\n    margin: 8px 0px;\n    clear: both;\n  }\n\n  .feature-row {\n    display: flex;\n    flex-wrap: wrap;\n\n    @media (max-width: 600px) {\n      flex-direction: column;\n    }\n\n    .feature {\n      max-width: 300px;\n      margin: 0 16px;  \n      \n      @media (max-width: 768px) {\n        max-width: 100%;\n      }\n    }\n  }\n}"
  },
  {
    "path": "apps/rxjs.dev/src/styles/2-modules/_filetree.scss",
    "content": ".filetree {\n  background: $offwhite;\n  border: 4px solid $lightgray;\n  border-radius: 4px;\n  margin: 0 0 24px 0;\n  padding: 16px 32px;\n\n  .file {\n    display: block;\n    font-family: $main-font;\n    letter-spacing: 0.3px;\n    line-height: 32px;\n    color: $darkgray;\n  }\n\n  .children {\n    padding-left: 24px;\n    position: relative;\n    overflow: hidden;\n\n    .file {\n      position: relative;\n\n      &:before {\n        content: '';\n        left: -18px;\n        bottom: 16px;\n        width: 16px;\n        height: 9999px;\n        position: absolute;\n        border-width: 0 0 1px 1px;\n        border-style: solid;\n        border-color: $lightgray;\n        border-radius: 0 0 0 3px;\n      }\n    }\n  }\n}"
  },
  {
    "path": "apps/rxjs.dev/src/styles/2-modules/_heading-anchors.scss",
    "content": ".sidenav-content {\n  h1, h2, h3, h4, h5, h6 {\n\n    .header-link {\n      color: $mediumgray;\n      margin: 0 4px;\n      text-decoration: none;\n      user-select: none;\n      visibility: hidden;\n      display: inline-block;\n      vertical-align: text-top;\n    }\n\n    &:hover .header-link {\n      visibility: visible;\n    }\n  }\n}\n"
  },
  {
    "path": "apps/rxjs.dev/src/styles/2-modules/_hr.scss",
    "content": "hr {\n    border: none;\n    background: $lightgray;\n    height: 1px;\n}\n\n.hr-margin {\n    display: block;\n    height: 1px;\n    border: 0;\n    margin-top: 16px;\n    margin-bottom: 16px;\n    padding: 0;\n}"
  },
  {
    "path": "apps/rxjs.dev/src/styles/2-modules/_images.scss",
    "content": ".content {\n  img {\n\n    &.right {\n      clear: both;\n      float: right;\n      margin-left: 20px;\n      margin-bottom: 20px;\n    }\n\n    &.left {\n      clear: both;\n      float: left;\n      margin-right: 20px;\n      margin-bottom: 20px;\n    }\n\n    @media (max-width: 1300px) {\n      max-width: 100%;\n      height: auto;\n    }\n\n    @media (max-width: 600px) {\n      float: none !important;\n      &.right {\n        margin-left: 0;\n      }\n      &.left {\n        margin-right: 0;\n      }\n    }\n  }\n\n  figure {\n    border-radius: 4px;\n    background: $white;\n    padding: 20px;\n    display: inline-block;\n    box-shadow: 2px 2px 5px 0 rgba(0, 0, 0, .2);\n    margin: 0 0 14px 0;\n\n    img {\n      border-radius: 4px;\n    }\n  }\n}\n"
  },
  {
    "path": "apps/rxjs.dev/src/styles/2-modules/_label.scss",
    "content": "label.raised, .api-header label {\n    border-radius: 4px;\n    padding: 4px 16px;\n    display: inline;\n    font-size: 14px;\n    color: white;\n    margin-right: 8px;\n    font-weight: 500;\n    text-transform: uppercase;\n\n    @media screen and (max-width: 600px) {\n        display: block;\n        margin: 8px 0;\n    }\n\n    &.page-label {\n        display: flex;\n        flex-direction: row;\n        justify-content: center;\n        align-items: center;\n        background-color: $mist;\n        color: $mediumgray;\n        margin-bottom: 8px;\n        width: 140px;\n\n        .material-icons {\n            margin-right: 8px;\n        }\n    }\n\n    &.property-type-label {\n        font-size: 12px;\n        background-color: $darkgray;\n        color: $white;\n        text-transform: none;\n    }\n}\n\n.api-header {\n\n    margin-right: 10px;\n\n    label {\n\n        // The API badges should be a little smaller\n        padding: 2px 10px;\n        font-size: 12px;\n\n        @media screen and (max-width: 600px) {\n            margin: 4px 0;\n        }\n\n        &.api-status-label {\n            background-color: $mediumgray;\n\n            &.impure-pipe {\n                background-color: $brightred;\n            }\n\n            &.operator {\n                background-color: $brightred;\n            }\n        }\n\n        &.api-type-label {\n            background-color: $accentgrey;\n\n            @each $name, $symbol in $api-symbols {\n                &.#{$name} {\n                    background: map-get($symbol, background);\n                }\n            }\n\n        }\n    }\n}\n"
  },
  {
    "path": "apps/rxjs.dev/src/styles/2-modules/_modules-dir.scss",
    "content": "/* ==============================\n   MODULE STYLES\n   ============================== */\n\n   @import 'alert';\n   @import 'api-pages';\n   @import 'api-list';\n   @import 'buttons';\n   @import 'callout';\n   @import 'card';\n   @import 'code';\n   @import 'contribute';\n   @import 'contributor';\n   @import 'details';\n   @import 'edit-page-cta';\n   @import 'features';\n   @import 'filetree';\n   @import 'heading-anchors';\n   @import 'hr';\n   @import 'images';\n   @import 'progress-bar';\n   @import 'table';\n   @import 'presskit';\n   @import 'resources';\n   @import 'scrollbar';\n   @import 'search-results';\n   @import 'subsection';\n   @import 'toc';\n   @import 'select-menu';\n   @import 'deploy-theme';\n   @import 'notification';\n   @import 'label';\n"
  },
  {
    "path": "apps/rxjs.dev/src/styles/2-modules/_notification.scss",
    "content": "$notificationHeight: 56px;\n\n// we need to override some of the toolbar styling\n.mat-toolbar mat-toolbar-row.notification-container {\n  padding: 0;\n  height: auto;\n  overflow: hidden;\n}\n\naio-notification {\n  background: $darkgray;\n  display: flex;\n  position: relative;\n  align-items: center;\n  width: 100%;\n  height: $notificationHeight;\n  justify-content: center;\n\n  @media (max-width: 430px) {\n    justify-content: flex-start;\n    padding-left: 10px;\n  }\n\n  .close-button {\n    position: absolute;\n    top: 0;\n    right: 0;\n    width: $notificationHeight;\n    height: $notificationHeight;\n    background: $darkgray;\n  }\n\n  .content {\n    display: flex;\n    max-width: calc(100% - #{$notificationHeight});\n    text-transform: none;\n    padding: 0;\n\n    .icon {\n      margin-right: 10px;\n      @media (max-width: 464px) {\n        display: none;\n      }\n    }\n\n    .message {\n      overflow: hidden;\n      text-overflow: ellipsis;\n    }\n\n    .action-button {\n      margin-left: 10px;\n      background: $pink;\n      border-radius: 15px;\n      text-transform: uppercase;\n      padding: 6px 10px;\n      font-size: 12px;\n      @media (max-width: 780px) {\n        display: none;\n      }\n    }\n  }\n}\n\n// Here are all the hacks to make the content and sidebars the right height\n// when the notification is visible\n.aio-notification-show {\n  .sidenav-content {\n    padding-top: 80px + $notificationHeight;\n  }\n\n  mat-sidenav.mat-sidenav.sidenav {\n    top: 56px + $notificationHeight;\n\n    @media (max-width: 600px) {\n      top: 56px + $notificationHeight;\n    }\n  }\n\n  .toc-container {\n    top: 76px + $notificationHeight;\n  }\n\n  .search-results {\n    padding-top: 68px + $notificationHeight;\n  }\n\n  &.page-home, &.page-resources, &.page-events, &.page-features, &.page-presskit, &.page-contribute  {\n    section {\n      padding-top: $notificationHeight;\n    }\n  }\n}\n\n// Animate the content when the notification bar is dismissed\n// this should be kept in sync with the animation durations in\n// - aio/src/app/layout/notification/notification.component.ts\n// - aio/src/app/app.component.ts : notificationDismissed()\n.aio-notification-animating {\n  .sidenav-content {\n    transition: padding-top 250ms ease;\n  }\n  mat-sidenav.mat-sidenav.sidenav, .toc-container {\n    transition: top 250ms ease;\n  }\n}\n"
  },
  {
    "path": "apps/rxjs.dev/src/styles/2-modules/_presskit.scss",
    "content": ".presskit-container {\n  padding: 0 32px 32px 32px;\n\n  h2 {\n    color: #37474F;\n  }\n\n  .l-space-left-3 {\n    margin-left: 3 * 8px;\n  }\n\n  .cc-by-anchor {\n    text-decoration: underline;\n    color: grey !important;\n  }\n\n  .presskit-row {\n    margin: 48px 0;\n    width: 100%;\n\n    .presskit-inner {\n      display: flex;\n      align-items: center;\n\n      @media(max-width: 599px) {\n        flex-direction: column;\n      }\n\n      h3 {\n        font-weight: 500;\n        margin-top: 0;\n        margin-bottom: 0;\n        color: #455A64;\n\n        @media(max-width: 599px) {\n          padding-bottom: 16px;\n        }\n      }\n\n      .transparent-img-bg {\n        margin-top: 10px;\n        border-radius: 4px;\n        width: 128px;\n        height: 128px;\n        background-color: #34474F;\n      }\n\n      ul {\n        padding: 0;\n        list-style-type: none;\n\n        @media(max-width: 599px) {\n          padding: 0 !important;\n          margin: 0 !important;\n        }\n\n        li {\n          margin: 0 0 8px 0;\n        }\n      }\n    }\n\n    .presskit-image-container {\n\n      @media(max-width: 599px) {\n        text-align: center;\n      }\n\n      img {\n        width: 128px;\n        height: 128px;\n        margin-bottom: 8px * 2;\n      }\n    }\n  }\n\n  .presskit-row:first-child {\n    margin-top: 0;\n\n    @media(max-width: 599px) {\n      margin-top: 48px;\n    }\n  }\n}\n"
  },
  {
    "path": "apps/rxjs.dev/src/styles/2-modules/_progress-bar.scss",
    "content": ".progress-bar-container {\n  height: 2px;\n  overflow: hidden;\n  position: fixed;\n  top: 0;\n  width: 100vw;\n  z-index: 11;\n}\n"
  },
  {
    "path": "apps/rxjs.dev/src/styles/2-modules/_resources.scss",
    "content": ".showcase {\n  width: 80%;\n}\n\n.c-resource-nav {\n  width: 20%;\n}\n\n.resources-container {\n  position: relative;\n}\n\n.grid-fixed:after, .grid-fixed:before {\n  content: '.';\n  clear: both;\n  display: block;\n  overflow: hidden;\n  visibility: hidden;\n  font-size: 0;\n  line-height: 0;\n  width: 0;\n  height: 0;\n}\n\n@media handheld and (max-width: 480px), screen and (max-width: 480px), screen and (max-width: 900px) {\n  .grid-fixed {\n    width: auto;\n  }\n}\n\n@media handheld and (max-width: 480px), screen and (max-width: 480px), screen and (max-width: 900px) {\n  .grid-fixed .c3, .grid-fixed .c8 {\n    margin-left: 20px;\n    margin-right: 20px;\n    float: none;\n    display: block;\n    width: auto;\n  }\n}\n\n@media handheld and (max-width: 480px), screen and (max-width: 480px), screen and (max-width: 480px) {\n  .grid-fixed .c3, .grid-fixed .c8 {\n    margin-left: 0px;\n    margin-right: 0px;\n    float: none;\n    display: block;\n    width: auto;\n  }\n}\n\n@media handheld and (max-width: 900px), screen and (max-width: 900px) {\n  /* line 6, ../scss/_responsive.scss */\n  .grid-fixed{\n    margin: 0 auto;\n    *zoom: 1;\n  }\n  .grid-fixed:after, .grid-fixed:before, {\n    content: '.';\n    clear: both;\n    display: block;\n    overflow: hidden;\n    visibility: hidden;\n    font-size: 0;\n    line-height: 0;\n    width: 0;\n    height: 0;\n  }\n}\n\n@media handheld and (max-width: 480px), screen and (max-width: 480px) {\n  /* line 6, ../scss/_responsive.scss */\n  .grid-fixed {\n    margin: 0 auto;\n    *zoom: 1;\n  }\n  .grid-fixed:after, .grid-fixed:before {\n    content: '.';\n    clear: both;\n    display: block;\n    overflow: hidden;\n    visibility: hidden;\n    font-size: 0;\n    line-height: 0;\n    width: 0;\n    height: 0;\n  }\n}\n\naio-resource-list {\n\n  .shadow-1 {\n    transition: box-shadow 0.28s cubic-bezier(0.4, 0, 0.2, 1);\n    box-shadow: 0 1px 4px 0 rgba($black, 0.37);\n  }\n\n  .showcase {\n    margin-bottom: 8px * 6;\n    border-radius: 4px;\n  }\n\n  .c-resource {\n    h4 {\n      margin: 0;\n      line-height: 24px;\n    }\n\n    p {\n      margin: 0;\n    }\n  }\n\n  .c-resource-nav {\n    position: fixed;\n    top: 142px;\n    right: 32px;\n    width: 8px * 20;\n    z-index: 1;\n    background-color: #fff;\n    border-radius: 2px;\n\n    a {\n      color: #373E41;\n      text-decoration: none;\n    }\n\n    .category {\n      padding: 10px 0;\n\n      .category-link {\n        display: block;\n        margin: 2px 0;\n        padding: 3px 14px;\n        font-size: 18px !important;\n\n        &:hover {\n          background: #edf0f2;\n          color: #2B85E7;\n        }\n      }\n    }\n\n    .subcategory {\n      .subcategory-link {\n        display: block;\n        margin: 2px 0;\n        padding: 4px 14px;\n\n        &:hover {\n          background: #edf0f2;\n          color: #2B85E7;\n        }\n      }\n    }\n  }\n\n  .h-anchor-offset {\n    display: block;\n    position: relative;\n    top: -20px;\n    visibility: hidden;\n  }\n\n  .l-flex--column {\n    display: flex;\n    flex-direction: column;\n  }\n\n  .c-resource-header {\n    margin-bottom: 16px;\n  }\n\n  .c-contribute {\n    margin-bottom: 24px;\n  }\n\n  .c-resource-header h2 {\n    margin: 0;\n  }\n\n  .subcategory-title {\n    padding: 16px 23px;\n    margin: 0;\n    background-color: $mist;\n    color: #373E41;\n  }\n\n  .h-capitalize {\n    text-transform: capitalize;\n  }\n\n  .h-hide {\n    display: none;\n  }\n\n  .resource-row-link {\n    color: #1a2326;\n    border: transparent solid 1px;\n    margin: 0;\n    padding: 16px 23px 16px 23px;\n    position: relative;\n    text-decoration: none;\n    transition: all .3s;\n  }\n\n  .resource-row-link:hover {\n    color: #1a2326;\n    text-decoration: none;\n    border-color: #2B85E7;\n    border-radius: 4px;\n    box-shadow: 0 8px 8px rgba(1, 67, 163, .24), 0 0 8px rgba(1, 67, 163, .12), 0 6px 18px rgba(43, 133, 231, .12);\n    transform: translateY(-2px);\n  }\n\n  @media(max-width: 900px) {\n    .c-resource-nav {\n      display: none;\n    }\n  }\n}\n"
  },
  {
    "path": "apps/rxjs.dev/src/styles/2-modules/_scrollbar.scss",
    "content": "body::-webkit-scrollbar, mat-sidenav.sidenav::-webkit-scrollbar, .mat-sidenav-content::-webkit-scrollbar {\n  height: 6px;\n  width: 6px;\n}\n\nbody::-webkit-scrollbar-track, mat-sidenav.sidenav::-webkit-scrollbar-track, .mat-sidenav-content::-webkit-scrollbar-track {\n  -webkit-box-shadow: inset 0 0 6px rgba(0,0,0,0.3);\n}\n\nbody::-webkit-scrollbar-thumb, mat-sidenav.sidenav::-webkit-scrollbar-thumb, .mat-sidenav-content::-webkit-scrollbar-thumb {\n  background-color: $mediumgray;\n  outline: 1px solid $darkgray;\n}\n\n.search-results::-webkit-scrollbar, .toc-container::-webkit-scrollbar {\n  height: 4px;\n  width: 4px;\n}\n\n.search-results::-webkit-scrollbar-track, .toc-container::-webkit-scrollbar-track {\n  -webkit-box-shadow: inset 0 0 6px rgba(0,0,0,0.3);\n}\n\n.search-results::-webkit-scrollbar-thumb, .toc-container::-webkit-scrollbar-thumb {\n  background-color: $mediumgray;\n  outline: 1px solid slategrey;\n}\n"
  },
  {
    "path": "apps/rxjs.dev/src/styles/2-modules/_search-results.scss",
    "content": "aio-search-results {\n    z-index: 10;\n}\n\n.search-results {\n    display: flex;\n    flex-direction: row;\n    justify-content: space-around;\n    overflow: auto;\n    padding: 68px 32px 0;\n    color: $offwhite;\n    width: auto;\n    max-height: 95vh;\n    position: fixed;\n    top: 0;\n    left: 0;\n    right: 0;\n    z-index: 5;\n    background-color: $darkgray;\n    box-shadow: 0 2px 5px 0 rgba(0, 0, 0, 0.3);\n    box-sizing: border-box;\n\n    @media (max-width: 480px) {\n        display: block;\n        .search-area {\n            display: block;\n            margin: 16px 16px;\n        }\n    }\n}\n\naio-search-results.embedded .search-results {\n    padding: 0;\n    color: inherit;\n    width: auto;\n    max-height: 100%;\n    position: relative;\n    background-color: inherit;\n    box-shadow: none;\n    box-sizing: border-box;\n\n    .search-area a {\n        color: lighten($darkgray, 10);\n        &:hover {\n            color: $accentgrey;\n        }\n    }\n}\n\n.search-area {\n    display: flex;\n    flex-direction: column;\n    margin: 16px 16px;\n    height: 100%;\n\n    h3 {\n        font-size: 16px;\n        font-weight: 400;\n        margin: 10px 0px 5px;\n        text-transform: uppercase;\n    }\n\n    ul {\n        margin: 0;\n        padding: 0;\n\n        li {\n            display: inline-block;\n            list-style: none;\n            min-width: 270px;\n            padding: .5em 1.5em;\n        }\n    }\n\n    a {\n        font-size: 14px;\n        color: $lightgray;\n        text-decoration: none;\n        font-weight: normal;\n        &:hover {\n            color: $white;\n        }\n        &:visited {\n          text-decoration: none;\n        }\n\n        span.symbol {\n          margin-right: 8px;\n        }\n    }\n\n    .priority-pages {\n        padding: 0.5rem 0;\n        a {\n            font-weight: bold;\n        }\n    }\n\n    @include bp(tiny) {\n        display: block;\n    }\n}\n"
  },
  {
    "path": "apps/rxjs.dev/src/styles/2-modules/_select-menu.scss",
    "content": "/* SELECT MENU */\n\n.form-select-menu {\n  position: relative;\n}\n\n.form-select-button {\n  background: $white;\n  box-shadow: 0 2px 2px rgba($black, 0.24), 0 0 2px rgba($black, 0.12);\n  box-sizing: border-box;\n  border: 1px solid $white;\n  color: $blue-grey-600;\n  font-size: 12px;\n  font-weight: 400;\n  height: 32px;\n  line-height: 32px;\n  outline: none;\n  padding: 0 16px;\n  text-align: left;\n  width: 100%;\n  cursor: pointer;\n\n  strong {\n    font-weight: 600;\n    margin-right: 8px;\n    text-transform: uppercase;\n  }\n\n  &:focus {\n    border: 1px solid $blue-400;\n    box-shadow: 0 2px 2px rgba($blue-400, 0.24), 0 0 2px rgba($blue-400, 0.12);\n  }\n}\n\n.form-select-dropdown {\n  background: $white;\n  box-shadow: 0 16px 16px rgba($black, 0.24), 0 0 16px rgba($black, 0.12);\n  border-radius: 4px;\n  list-style-type: none;\n  margin: 0;\n  padding: 0;\n  position: absolute;\n  top: 0;\n  width: 100%;\n  z-index: $layer-2;\n\n  li {\n    cursor: pointer;\n    font-size: 14px;\n    line-height: 32px;\n    margin: 0;\n    padding: 0 16px 0 40px;\n    position: relative;\n    transition: all .2s;\n\n    &:hover {\n      background: $blue-grey-50;\n      color: $blue-500;\n    }\n\n    &.selected {\n      background-color: $blue-grey-100;\n    }\n\n    .symbol {\n      left: 16px;\n      position: absolute;\n      top: 8px;\n      z-index: $layer-5;\n    }\n  }\n}\n"
  },
  {
    "path": "apps/rxjs.dev/src/styles/2-modules/_subsection.scss",
    "content": ".l-sub-section {\n    color: $darkgray;\n    background-color: rgba($pink, 0.05);\n    border-left: 8px solid $pink;\n    padding: 16px;\n    margin-bottom: 8px;\n    display: table;\n    clear: both;\n    width: 100%;\n    box-sizing: border-box;\n\n    h3 {\n        margin: 8px 0 0;\n    }\n\n    a:hover {\n        color: $pink;\n        text-decoration: underline;\n    }\n}"
  },
  {
    "path": "apps/rxjs.dev/src/styles/2-modules/_table.scss",
    "content": "table {\n  margin: 24px 0px;\n  box-shadow: 0 2px 2px rgba($black, 0.24), 0 0 2px rgba($black, 0.12);\n  border-radius: 2px;\n  background: $offwhite;\n\n  &.is-full-width {\n    width: 100%;\n  }\n\n  &.is-fixed-layout {\n    table-layout: fixed;\n  }\n\n  thead > {\n    vertical-align: middle;\n    border-color: inherit;\n\n    tr {\n      vertical-align: inherit;\n      border-color: inherit;\n    }\n\n    tr > th {\n      background: rgba($lightgray, 0.2);\n      border-bottom: 1px solid $lightgray;\n      color: $darkgray;\n      font-size: 12px;\n      font-weight: 500;\n      padding: 8px 24px;\n      text-align: left;\n      text-transform: uppercase;\n      line-height: 28px;\n    }\n  }\n\n  tbody > tr {\n    th,\n    td {\n      border-bottom: 1px solid $lightgray;\n      padding: 16px;\n      text-align: left;\n      line-height: 24px;\n      vertical-align: top;\n\n      @media (max-width: 480px) {\n        &:before {\n          // content: **ADD TABLE HEADER**;\n          display: inline-block;\n        }\n      }\n\n    }\n\n    td {\n      letter-spacing: 0.30px;\n\n    tr td:first-child {\n      @media (max-width: 480px) {\n        background-color: $lightgray;\n      }\n    }\n\n    }\n\n    th {\n      background: rgba($lightgray, 0.2);\n      border-right: 1px solid $lightgray;\n      font-weight: 600;\n      max-width: 100px;\n    }\n\n    &:last-child td {\n      border: none;\n\n      @media (max-width: 480px) {\n        border-bottom: 1px solid $lightgray;\n      }\n    }\n  }\n}\n\n#cheatsheet {\n\n  table tbody td {\n    overflow: auto;\n  }\n\n  @media only screen and (max-width: 990px) {\n\n    /* Force table to not be like tables anymore */\n    table, thead, tbody, tfoot, tr, th, td {\n      display: block;\n      position: relative;\n      max-width: 100%;\n\n      code {\n        padding: 0;\n        background-color: inherit;\n      }\n    }\n\n    th {\n      border-right: none;\n    }\n\n    th, td {\n      &:not(:last-child) {\n        border-bottom: none;\n        padding-bottom: 0px;\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "apps/rxjs.dev/src/styles/2-modules/_toc.scss",
    "content": ".toc-container {\n  width: 18%;\n  position: fixed;\n  top: 76px;\n  right: 0;\n  bottom: 12px;\n  overflow-y: auto;\n  overflow-x: hidden;\n}\n\naio-toc.embedded {\n  @media (min-width: 801px) {\n    display: none;\n  }\n\n  .toc-inner {\n    padding: 12px 0 0 0;\n\n    .toc-heading {\n      margin: 0 0 8px;\n    }\n  }\n}\n\n.toc-inner {\n  font-size: 13px;\n  overflow-y: visible;\n  padding: 4px 0 0 10px;\n\n  .toc-heading,\n  .toc-list .h1 {\n    font-size: 115%;\n  }\n\n  .toc-heading {\n    font-weight: 500;\n    margin: 0 0 16px 8px;\n    padding: 0;\n  }\n\n  .toc-heading.secondary {\n    position: relative;\n    top: -8px;\n\n    &:hover {\n      color: $accentgrey;\n    }\n  }\n\n  button.toc-heading,\n  button.toc-more-items {\n    cursor: pointer;\n    display: inline-block;\n    background: 0;\n    background-color: transparent;\n    border: none;\n    box-shadow: none;\n    padding: 0;\n    text-align: start;\n\n    &.embedded:focus {\n      outline: none;\n      background: $lightgray;\n    }\n  }\n\n  button.toc-heading {\n    mat-icon.rotating-icon {\n      height: 18px;\n      width: 18px;\n      position: relative;\n      left: -4px;\n      top: 5px;\n    }\n\n    &:hover:not(.embedded) {\n      color: $accentgrey;\n    }\n  }\n\n  button.toc-more-items {\n    color: $mediumgray;\n    top: 10px;\n    position: relative;\n\n    &:hover {\n      color: $accentgrey;\n    }\n  }\n\n  button.toc-more-items::after {\n    content: 'expand_less';\n  }\n\n  button.toc-more-items.collapsed::after {\n    content: 'more_horiz';\n  }\n\n\n  .mat-icon.collapsed {\n    @include rotate(0deg);\n  }\n\n  .mat-icon:not(.collapsed) {\n    @include rotate(90deg);\n    // margin: 4px;\n  }\n\n  ul.toc-list {\n    list-style-type: none;\n    margin: 0;\n    padding: 0 8px 0 0;\n\n    @media (max-width: 800px) {\n      width: auto;\n    }\n\n    li {\n      box-sizing: border-box;\n      font-size: 12px;\n      line-height: 16px;\n      padding: 3px 0 3px 12px;\n      position: relative;\n      transition: all 0.3s ease-in-out;\n\n      &.h1:after {\n        content: '';\n        display: block;\n        height: 1px;\n        width: 40%;\n        margin: 7px 0 4px 0;\n        background: #DBDBDB;\n        clear: both;\n      }\n\n      &.h3 {\n        padding-left: 24px;\n      }\n\n      a {\n        font-size: inherit;\n        color: lighten($darkgray, 10);\n        display:table-cell;\n        overflow: visible;\n        font-size: 12px;\n        display: table-cell;\n      }\n\n      &:hover a {\n        color: $accentgrey;\n      }\n\n      &.active {\n        a {\n          color: $pink;\n          font-weight: 500;\n\n          &:before {\n            content: '';\n            border-radius: 50%;\n            left: -3px;\n            top: 12px;\n            background: $pink;\n            position: absolute;\n            width: 6px;\n            height: 6px;\n          }\n        }\n      }\n    }\n\n    &:not(.embedded) li {\n      &:before {\n        border-left: 1px solid $lightgray;\n        bottom: 0;\n        content: '';\n        left: 0;\n        position: absolute;\n        top: 0;\n      }\n\n      &:first-child:before {\n        top: 13px;\n      }\n\n      &:last-child:before {\n        bottom: calc(100% - 14px);\n      }\n\n      &:not(.active):hover a:before {\n        content: '';\n        border-radius: 50%;\n        left: -3px;\n        top: 12px;\n        background: $lightgray;\n        position: absolute;\n        width: 6px;\n        height: 6px;\n      }\n    }\n  }\n\n}\n\naio-toc.embedded > div.collapsed li.secondary {\n  display: none;\n}\n"
  },
  {
    "path": "apps/rxjs.dev/src/styles/_constants.scss",
    "content": "// TYPOGRAPHY\n$main-font: \"Roboto\",\"Helvetica Neue Light\",\"Helvetica Neue\",Helvetica,Arial,\"Lucida Grande\",sans-serif;\n$code-font: \"Droid Sans Mono\", monospace;\n\n// Z-LAYER\n$layer-1: 1;\n$layer-2: 2;\n$layer-3: 3;\n$layer-4: 4;\n$layer-5: 5;\n\n// COLOR PALETTE\n$pink: #d81b60;\n$accentgrey: #62757f;\n$brightred: #DD0031;\n$darkred: #C3002F;\n$white: #FFFFFF;\n$offwhite: #FAFAFA;\n$backgroundgray: #F1F1F1;\n$lightgray: #DBDBDB;\n$mist: #ECEFF1;\n$mediumgray: #6e6e6e;\n$darkgray: #333;\n$black: #0A1014;\n$orange: #FF9800;\n$anti-pattern: $brightred;\n\n// API & CODE COLORS\n$amber-700: #FFA000;\n$blue-400: #42A5F5;\n$blue-500: #2196F3;\n$blue-600: #1E88E5;\n$blue-800: #1565C0;\n$blue-900: #0D47A1;\n$blue-grey-50: #ECEFF1;\n$blue-grey-100: #CFD8DC;\n$blue-grey-200: #B0BEC5;\n$blue-grey-300: #90A4AE;\n$blue-grey-400: #78909C;\n$blue-grey-500: #607D8B;\n$blue-grey-600: #546E7A;\n$blue-grey-700: #455A64;\n$blue-grey-800: #37474F;\n$blue-grey-900: #263238;\n$codegreen: #17ff0b;\n$green-500: #4CAF50;\n$green-800: #2E7D32;\n$light-green-600: #7CB342;\n$pink-600: #D81B60;\n$purple-600: #8E24AA;\n$teal-500: #009688;\n$lightgrey: #F5F6F7;\n\n// GRADIENTS\n$bluegradient: linear-gradient(145deg,#0D47A1,#42A5F5);\n$redgradient: linear-gradient(145deg,$darkred,$brightred);\n\n// API LABEL COLOR AND SYMBOLS MAP\n$api-symbols: (\n  all: (\n    content: ' ',\n    background: $white\n  ),\n  decorator: (\n    content: '@',\n    background: $blue-800\n  ),\n  directive: (\n    content: 'D',\n    background: $pink-600\n  ),\n  pipe: (\n    content: 'P',\n    background: $blue-grey-600\n  ),\n  class: (\n    content: 'C',\n    background: $blue-500\n  ),\n  interface: (\n    content: 'I',\n    background: $teal-500\n  ),\n  function: (\n    content: 'F',\n    background: $green-800\n  ),\n  enum: (\n    content: 'E',\n    background: $amber-700\n  ),\n  const: (\n    content: 'K',\n    background: $mediumgray\n  ),\n  let: (\n    content: 'K',\n    background: $mediumgray\n  ),\n  var: (\n    content: 'K',\n    background: $mediumgray\n  ),\n  type-alias: (\n    content: 'T',\n    background: $light-green-600\n  ),\n  module: (\n    content: 'Pk',\n    background: $purple-600\n  )\n);\n\n// OTHER\n$small-breakpoint-width: 840px;\n$phone-breakpoint: 480px;\n$tablet-breakpoint: 800px;"
  },
  {
    "path": "apps/rxjs.dev/src/styles/_mixins.scss",
    "content": "/************************************\n\n             Media queries\n\n To use these, put this snippet in the appropriate selector:\n\n     @include bp(tiny) {\n         background-color: purple;\n     }\n\n     Replace \"tiny\" with \"medium\" or \"big\" as necessary.\n*************************************/\n\n@mixin bp($point) {\n\n  $bp-xsmall: \"(min-width: 320px)\";\n  $bp-teeny: \"(min-width: 480px)\";\n  $bp-tiny: \"(min-width: 600px)\";\n  $bp-small: \"(min-width: 650px)\";\n  $bp-medium: \"(min-width: 800px)\";\n  $bp-big: \"(min-width: 1000px)\";\n\n  @if $point == big {\n    @media #{$bp-big} { @content; }\n  }\n  @else if $point == medium {\n    @media #{$bp-medium} { @content; }\n  }\n  @else if $point == small {\n    @media #{$bp-small}  { @content; }\n  }\n  @else if $point == tiny {\n    @media #{$bp-tiny}  { @content; }\n  }\n  @else if $point == teeny {\n    @media #{$bp-teeny}  { @content; }\n  }\n  @else if $point == xsmall {\n    @media #{$bp-xsmall}  { @content; }\n  }\n}\n\n@mixin rotate($degrees) {\n  -moz-transform: rotate($degrees);\n  -webkit-transform: rotate($degrees);\n  -o-transform: rotate($degrees);\n  -ms-transform: rotate($degrees);\n  transform: rotate($degrees);\n  transition: transform 150ms;\n  transition-timing-function: ease-in-out;\n}\n\n@mixin codeblock($bgcolor) {\n    background-color: $bgcolor;\n    border-radius: 5px;\n    padding: 20px;\n    margin: 0 auto; // was 24\n    border: 0.5px solid $lightgray;\n}\n\n// INFO CARD SKELETON\n@mixin card($height, $width) {\n  height: $height;\n  width: $width;\n  background-color: $white;\n  border-radius: 4px;\n  box-shadow: 0 2px 2px rgba($black, 0.24), 0 0 2px rgba($black, 0.12);\n  box-sizing: border-box;\n  transition: box-shadow .5s;\n\n  &:hover {\n    box-shadow: 0 8px 8px rgba($black, 0.24), 0 0 8px rgba($black, 0.12);\n    text-decoration: none;\n  }\n}"
  },
  {
    "path": "apps/rxjs.dev/src/styles/_typography-theme.scss",
    "content": "@use '@angular/material' as mat;\n\n@mixin docs-site-typography-theme($theme) {\n  $primary: map-get($theme, primary);\n  $accent: map-get($theme, accent);\n  $warn: map-get($theme, warn);\n  $background: map-get($theme, background);\n  $foreground: map-get($theme, foreground);\n\n  .docs-component-viewer-tabbed-content,\n  .docs-guide-content {\n      h1 {\n        color: mat.get-color-from-palette($primary, 800);\n        background: rgba(mat.get-color-from-palette($foreground, secondary-text), .03);\n      }\n\n      h3, h2, h4, h5, p, ol, li {\n        color: mat.get-color-from-palette($foreground, secondary-text);\n      }\n\n      a {\n        color: mat.get-color-from-palette($primary);\n      }\n\n      .nav-link:visited {\n        text-decoration: none;\n      }\n\n      table {\n        box-shadow: 0 2px 2px rgba(0,0,0,0.24), 0 0 2px rgba(0,0,0,0.12);\n      }\n\n      table > tbody > tr > th {\n        border: 1px solid rgba(mat.get-color-from-palette($foreground, secondary-text), .03);\n      }\n\n      td {\n        color: mat.get-color-from-palette($foreground, secondary-text);\n        border: 1px solid rgba(mat.get-color-from-palette($foreground, secondary-text), .03);\n      }\n\n      th {\n        color: mat.get-color-from-palette($foreground, secondary-text);\n        background: rgba(mat.get-color-from-palette($foreground, secondary-text), .03);\n      }\n  }\n}\n"
  },
  {
    "path": "apps/rxjs.dev/src/styles/main.scss",
    "content": "// import global themes\n@import './rxjs-theme';\n\n// import global variables\n@import './constants';\n\n// import global mixins\n@import './mixins';\n\n// import directories\n@import './0-base/base-dir';\n@import './1-layouts/layouts-dir';\n@import './2-modules/modules-dir';\n"
  },
  {
    "path": "apps/rxjs.dev/src/styles/rxjs-theme.scss",
    "content": "@use '@angular/material' as mat;\n// Plus imports for other components in your app.\n\n// Include the base styles for Angular Material core. We include this here so that you only\n// have to load a single css file for Angular Material in your app.\n@include mat.core();\n\n// Define the palettes for your theme using the Material Design palettes available in palette.scss\n// (imported above). For each palette, you can optionally specify a default, lighter, and darker\n// hue.\n$rxjs-primary: mat.define-palette(mat.$pink-palette, 700, 600, 800);\n$rxjs-accent:  mat.define-palette(mat.$red-palette, 700, 600, 800);\n\n// The warn palette is optional (defaults to red).\n$rxjs-warn:    mat.define-palette(mat.$red-palette);\n\n// Create the theme object (a Sass map containing all of the palettes).\n$rxjs-theme: mat.define-light-theme($rxjs-primary, $rxjs-accent, $rxjs-warn);\n\n// Include theme styles for core and each component used in your app.\n// Alternatively, you can import and @include the theme mixins for each component\n// that you are using.\n@include mat.all-component-themes($rxjs-theme);\n"
  },
  {
    "path": "apps/rxjs.dev/src/styles.scss",
    "content": "/* You can add global styles to this file, and also import other style files */\n@import './styles/rxjs-theme';\n@import './styles/main.scss';\n"
  },
  {
    "path": "apps/rxjs.dev/src/test.ts",
    "content": "// This file is required by karma.conf.js and loads recursively all the .spec and framework files\n\nimport 'zone.js/testing';\nimport { getTestBed } from '@angular/core/testing';\nimport { BrowserDynamicTestingModule, platformBrowserDynamicTesting } from '@angular/platform-browser-dynamic/testing';\n\ndeclare const require: any;\n\n// Reflect.metadata polyfill is only needed in the JIT mode which we use only for unit tests\nimport 'core-js/es/reflect';\n// import 'core-js/es7/reflect';\n\n// First, initialize the Angular testing environment.\ngetTestBed().initTestEnvironment(BrowserDynamicTestingModule, platformBrowserDynamicTesting(), {\n  teardown: { destroyAfterEach: false },\n});\n// Then we find all the tests.\nconst context = require.context('./', true, /\\.spec\\.ts$/);\n// And load the modules.\ncontext.keys().map(context);\n"
  },
  {
    "path": "apps/rxjs.dev/src/testing/doc-viewer-utils.ts",
    "content": "import { Component, NgModule, ViewChild, Injectable } from '@angular/core';\nimport { Title, Meta } from '@angular/platform-browser';\n\nimport { Observable } from 'rxjs';\n\nimport { DocumentContents } from 'app/documents/document.service';\nimport { DocViewerComponent } from 'app/layout/doc-viewer/doc-viewer.component';\nimport { Logger } from 'app/shared/logger.service';\nimport { TocService } from 'app/shared/toc.service';\nimport { MockLogger } from 'testing/logger.service';\nimport { ElementsLoader } from 'app/custom-elements/elements-loader';\n\n\n////////////////////////////////////////////////////////////////////////////////////////////////////\n/// `TestDocViewerComponent` (for exposing internal `DocViewerComponent` methods as public).     ///\n/// Only used for type-casting; the actual implementation is irrelevant.                         ///\n////////////////////////////////////////////////////////////////////////////////////////////////////\n\nexport class TestDocViewerComponent extends DocViewerComponent {\n  override currViewContainer: HTMLElement;\n  override nextViewContainer: HTMLElement;\n\n  override prepareTitleAndToc(targetElem: HTMLElement, docId: string): () => void { return null as any; }\n  override render(doc: DocumentContents): Observable<void> { return null as any; }\n  override swapViews(onInsertedCb?: () => void): Observable<void> { return null as any; }\n}\n\n\n////////////////////////////////////////////////////////////////////////////////////////////////////\n/// `TestModule` and `TestParentComponent`.                                                      ///\n////////////////////////////////////////////////////////////////////////////////////////////////////\n\n// Test parent component.\n@Component({\n  selector: 'aio-test',\n  template: '<aio-doc-viewer [doc]=\"currentDoc\">Test Component</aio-doc-viewer>',\n})\nexport class TestParentComponent {\n  currentDoc?: DocumentContents|null;\n  @ViewChild(DocViewerComponent) docViewer: DocViewerComponent;\n}\n\n// Mock services.\n@Injectable()\nexport class MockTitle {\n  setTitle = jasmine.createSpy('Title#reset');\n}\n\n@Injectable()\nexport class MockMeta {\n  addTag = jasmine.createSpy('Meta#addTag');\n  removeTag = jasmine.createSpy('Meta#removeTag');\n}\n\n@Injectable()\nexport class MockTocService {\n  genToc = jasmine.createSpy('TocService#genToc');\n  reset = jasmine.createSpy('TocService#reset');\n}\n\n@Injectable()\nexport class MockElementsLoader {\n  loadContainedCustomElements =\n      jasmine.createSpy('MockElementsLoader#loadContainedCustomElements');\n}\n\n@NgModule({\n  declarations: [\n    DocViewerComponent,\n    TestParentComponent,\n  ],\n  providers: [\n    { provide: Logger, useClass: MockLogger },\n    { provide: Title, useClass: MockTitle },\n    { provide: Meta, useClass: MockMeta },\n    { provide: TocService, useClass: MockTocService },\n    { provide: ElementsLoader, useClass: MockElementsLoader },\n  ],\n})\nexport class TestModule { }\n\n\n////////////////////////////////////////////////////////////////////////////////////////////////////\n/// An observable with spies to test subscribing/unsubscribing.                                  ///\n////////////////////////////////////////////////////////////////////////////////////////////////////\n\nexport class ObservableWithSubscriptionSpies<T = void> extends Observable<T> {\n  unsubscribeSpies: jasmine.Spy[] = [];\n  subscribeSpy = spyOn(this as any, 'subscribe').and.callFake((...args: any[]) => {\n    const subscription = super.subscribe(...args);\n    const unsubscribeSpy = spyOn(subscription, 'unsubscribe').and.callThrough();\n    this.unsubscribeSpies.push(unsubscribeSpy);\n    return subscription;\n  });\n\n  constructor(subscriber = () => undefined) { super(subscriber); }\n}\n"
  },
  {
    "path": "apps/rxjs.dev/src/testing/location.service.ts",
    "content": "import { BehaviorSubject } from 'rxjs';\nimport { map } from 'rxjs/operators';\n\nexport class MockLocationService {\n  urlSubject = new BehaviorSubject<string>(this.initialUrl);\n  currentUrl = this.urlSubject.asObservable().pipe(map(url => this.stripSlashes(url)));\n  // strip off query and hash\n  currentPath = this.currentUrl.pipe(map(url => url.match(/[^?#]*/)![0]));\n  search = jasmine.createSpy('search').and.returnValue({});\n  setSearch = jasmine.createSpy('setSearch');\n  go = jasmine.createSpy('Location.go').and\n              .callFake((url: string) => this.urlSubject.next(url));\n  goExternal = jasmine.createSpy('Location.goExternal');\n  replace = jasmine.createSpy('Location.replace');\n  handleAnchorClick = jasmine.createSpy('Location.handleAnchorClick')\n      .and.returnValue(false); // prevent click from causing a browser navigation\n\n  constructor(private initialUrl: string) {}\n\n  private stripSlashes(url: string) {\n    return url.replace(/^\\/+/, '').replace(/\\/+(\\?|#|$)/, '$1');\n  }\n}\n\n"
  },
  {
    "path": "apps/rxjs.dev/src/testing/logger.service.ts",
    "content": "import { Injectable } from '@angular/core';\n\n@Injectable()\nexport class MockLogger {\n\n  output: { log: any[], error: any[], warn: any[] } = {\n    log: [],\n    error: [],\n    warn: []\n  };\n\n  log(value: any, ...rest: any[]) {\n    this.output.log.push([value, ...rest]);\n  }\n\n  error(value: any, ...rest: any[]) {\n    this.output.error.push([value, ...rest]);\n  }\n\n  warn(value: any, ...rest: any[]) {\n    this.output.warn.push([value, ...rest]);\n  }\n}\n"
  },
  {
    "path": "apps/rxjs.dev/src/testing/search.service.ts",
    "content": "import { Subject } from 'rxjs';\nimport { SearchResults } from 'app/search/interfaces';\n\nexport class MockSearchService {\n  searchResults = new Subject<SearchResults>();\n  initWorker = jasmine.createSpy('initWorker');\n  loadIndex = jasmine.createSpy('loadIndex');\n  search = jasmine.createSpy('search');\n}\n"
  },
  {
    "path": "apps/rxjs.dev/src/typings.d.ts",
    "content": "/* SystemJS module definition */\ndeclare var module: NodeModule;\ninterface NodeModule {\n  id: string;\n}\n"
  },
  {
    "path": "apps/rxjs.dev/tests/e2e/protractor.conf.js",
    "content": "// Protractor configuration file, see link for more information\n// https://github.com/angular/protractor/blob/master/lib/config.ts\n\nconst { SpecReporter } = require('jasmine-spec-reporter');\n\nexports.config = {\n  allScriptsTimeout: 11000,\n  specs: [\n    './*.e2e-spec.ts'\n  ],\n  capabilities: {\n    browserName: 'chrome',\n    // For Travis\n    chromeOptions: {\n      binary: process.env.CHROME_BIN,\n      args: ['--no-sandbox']\n    }\n  },\n  directConnect: true,\n  baseUrl: 'http://localhost:4200/',\n  framework: 'jasmine',\n  jasmineNodeOpts: {\n    showColors: true,\n    defaultTimeoutInterval: 30000,\n    print: function() {}\n  },\n  beforeLaunch: function() {\n    require('ts-node').register({\n      project: 'tests/e2e/tsconfig.e2e.json'\n    });\n  },\n  onPrepare() {\n    jasmine.getEnv().addReporter(new SpecReporter({ spec: { displayStacktrace: true } }));\n  }\n};\n"
  },
  {
    "path": "apps/rxjs.dev/tests/e2e/tsconfig.e2e.json",
    "content": "{\n  \"extends\": \"../../tsconfig.json\",\n  \"compilerOptions\": {\n    \"outDir\": \"../../out-tsc/e2e\",\n    \"baseUrl\": \"./\",\n    \"module\": \"commonjs\",\n    \"target\": \"es5\",\n    \"types\": [\n      \"jasmine\",\n      \"jasminewd2\",\n      \"node\"\n    ]\n  }\n}\n"
  },
  {
    "path": "apps/rxjs.dev/tests/e2e/visual-testing.e2e-spec.ts",
    "content": "import { browser } from 'protractor';\n\nconst Eyes = require('eyes.selenium').Eyes;\nconst eyes = new Eyes();\n\ndescribe('RxJS Docs', function() {\n  it('shows the landing page', () => {\n    eyes.open(browser, 'Landing Page', 'RxJS Docs');\n    browser.get('');\n    eyes.checkWindow('Landing page!');\n    eyes.close();\n  });\n\n  it('shows the overview page', () => {\n    eyes.open(browser, 'Overview Page', 'RxJS Docs');\n    browser.get('/guide/overview');\n    eyes.checkWindow('Overview page!');\n    eyes.close();\n  });\n\n  it('shows the API page', () => {\n    eyes.open(browser, 'API Page', 'RxJS Docs');\n    browser.get('/api');\n    eyes.checkWindow('API page!');\n    eyes.close();\n  });\n\n  it('shows the migration page', () => {\n    eyes.open(browser, 'Migration Page', 'RxJS Docs');\n    browser.get('/guide/v6/migration');\n    eyes.checkWindow('Migration page!');\n    eyes.close();\n  });\n\n  it('shows the team page', () => {\n    eyes.open(browser, 'Team Page', 'RxJS Docs');\n    browser.get('/team');\n    eyes.checkWindow('Team page!');\n    eyes.close();\n  });\n});\n"
  },
  {
    "path": "apps/rxjs.dev/tools/README.md",
    "content": "# AIO project tooling\n\nThis document gives an overview of the tools that we use to generate the content for the RxJS website.\n\nThe application that actually renders this content can be found in the `apps/rxjs.dev/src` folder.\nThe handwritten content can be found in the `apps/rxjs.dev/content` folder.\n\nEach subfolder in this `apps/rxjs.dev/tools/` folder contains a self-contained tool and its configuration. There is\na `README.md` file in each folder that describes the tool in more detail.\n\n## transforms\n\nAll the content that is rendered by the RxJS docs application, and some of its configuration files,\nare generated from source files by [Dgeni](https://github.com/angular/dgeni). Dgeni is a general\npurpose documentation generation tool.\n\nMarkdown files in `apps/rxjs.dev/content`, code comments in the core Angular source files and example\nfiles are processed and transformed into files that are consumed by the RxJS docs application.\n\nDgeni is configured by \"packages\", which contain services and processors. Some of these packages are\ninstalled as `node_modules` from the [dgeni-packages](https://github.com/angular/dgeni-packages) and\nsome are specific to the RxJS project.\n\nThe project specific packages are stored in the `apps/rxjs.dev/tools/transforms` folder. See the\n[README.md](transforms/README.md) for more details.\n"
  },
  {
    "path": "apps/rxjs.dev/tools/firebase-test-utils/FirebaseGlob.spec.ts",
    "content": "import { FirebaseGlob } from './FirebaseGlob';\ndescribe('FirebaseGlob', () => {\n\n  describe('test', () => {\n    it('should match * parts', () => {\n      testGlob('asdf/*.jpg',\n        ['asdf/.jpg', 'asdf/asdf.jpg', 'asdf/asdf_asdf.jpg'],\n        ['asdf/asdf/asdf.jpg', 'xxxasdf/asdf.jpgxxx']);\n    });\n\n    it('should match ** parts', () => {\n      testGlob('asdf/**.jpg', // treated like two consecutive single `*`s\n        ['asdf/.jpg', 'asdf/asdf.jpg', 'asdf/asdf_asdf.jpg'],\n        ['asdf/a/.jpg', 'asdf/a/b.jpg', '/asdf/asdf.jpg', 'asdff/asdf.jpg', 'xxxasdf/asdf.jpg', 'asdf/asdf.jpgxxx']);\n    });\n\n    it('should match **/ and /**/', () => {\n      testGlob('**/*.js',\n        ['asdf.js', 'asdf/asdf.js', 'asdf/asdf/asdfasdf_asdf.js', '/asdf/asdf.js', '/asdf/aasdf-asdf.2.1.4.js'],\n        ['asdf/asdf.jpg', '/asdf/asdf.jpg']);\n      testGlob('aaa/**/bbb',\n        ['aaa/xxx/bbb', 'aaa/xxx/yyy/bbb', 'aaa/bbb'],\n        ['/aaa/xxx/bbb', 'aaa/x/bbb/', 'aaa/bbb/ccc']);\n    });\n\n    it('should match choice groups', () => {\n      testGlob('aaa/*.@(bbb|ccc)',\n        ['aaa/aaa.bbb', 'aaa/aaa_aaa.ccc'],\n        ['/aaa/aaa.bbb', 'aaaf/aaa.bbb', 'aaa/aaa.ddd']);\n\n      testGlob('aaa/*(bbb|ccc)',\n        ['aaa/', 'aaa/bbb', 'aaa/ccc', 'aaa/bbbbbb', 'aaa/bbbccc', 'aaa/cccbbb', 'aaa/bbbcccbbb'],\n        ['aaa/aaa', 'aaa/bbbb']);\n\n      testGlob('aaa/+(bbb|ccc)',\n        ['aaa/bbb', 'aaa/ccc', 'aaa/bbbbbb', 'aaa/bbbccc', 'aaa/cccbbb', 'aaa/bbbcccbbb'],\n        ['aaa/', 'aaa/aaa', 'aaa/bbbb']);\n\n      testGlob('aaa/?(bbb|ccc)',\n        ['aaa/', 'aaa/bbb', 'aaa/ccc'],\n        ['aaa/aaa', 'aaa/bbbb', 'aaa/bbbbbb', 'aaa/bbbccc', 'aaa/cccbbb', 'aaa/bbbcccbbb']);\n    });\n\n    it('should error on non-supported choice groups', () => {\n      expect(() => new FirebaseGlob('/!(a|b)/c'))\n        .toThrowError('Error in FirebaseGlob: \"/!(a|b)/c\" - \"not\" expansions are not supported: \"!(a|b)\"');\n      expect(() => new FirebaseGlob('/(a|b)/c'))\n      .toThrowError('Error in FirebaseGlob: \"/(a|b)/c\" - unknown expansion type: \"/\" in \"/(a|b)\"');\n      expect(() => new FirebaseGlob('/&(a|b)/c'))\n        .toThrowError('Error in FirebaseGlob: \"/&(a|b)/c\" - unknown expansion type: \"&\" in \"&(a|b)\"');\n    });\n\n    // Globs that contain params tested via the match tests below\n  });\n\n  describe('match', () => {\n    it('should match patterns with no parameters', () => {\n      testMatch('/abc/def/*', {\n      }, {\n        '/abc/def/': {},\n        '/abc/def/ghi': {},\n        '/': undefined,\n        '/abc': undefined,\n        '/abc/def/ghi/jk;': undefined,\n      });\n    });\n\n    it('should capture a simple named param', () => {\n      testMatch('/:abc', {\n        named: ['abc']\n      }, {\n        '/a': {abc: 'a'},\n        '/abc': {abc: 'abc'},\n        '/': undefined,\n        '/a/': undefined,\n        '/a/b/': undefined,\n        '/a/a/b': undefined,\n        '/a/a/b/': undefined,\n      });\n      testMatch('/a/:b', {\n        named: ['b']\n      }, {\n        '/a/b': {b: 'b'},\n        '/a/bcd': {b: 'bcd'},\n        '/a/': undefined,\n        '/a/b/': undefined,\n        '/a': undefined,\n        '/a//': undefined,\n        '/a/a/b': undefined,\n        '/a/a/b/': undefined,\n      });\n    });\n\n    it('should capture a named param followed by non-word chars', () => {\n      testMatch('/a/:x-', {\n        named: ['x']\n      }, {\n        '/a/b-': {x: 'b'},\n        '/a/bcd-': {x: 'bcd'},\n        '/a/--': {x: '-'},\n        '/a': undefined,\n        '/a/-': undefined,\n        '/a/-/': undefined,\n        '/a/': undefined,\n        '/a/b/-': undefined,\n        '/a/b-c': undefined,\n      });\n    });\n\n    it('should capture multiple named params', () => {\n      testMatch('/a/:b/:c', {\n        named: ['b', 'c']\n      }, {\n        '/a/b/c': {b: 'b', c: 'c'},\n        '/a/bcd/efg': {b: 'bcd', c: 'efg'},\n        '/a/b/c-': {b: 'b', c: 'c-'},\n        '/a/': undefined,\n        '/a/b/': undefined,\n        '/a/b/c/': undefined,\n      });\n      testMatch('/:a/b/:c', {\n        named: ['a', 'c']\n      }, {\n        '/a/b/c': {a: 'a', c: 'c'},\n        '/abc/b/efg': {a: 'abc', c: 'efg'},\n        '/a/b/c-': {a: 'a', c: 'c-'},\n        '/a/': undefined,\n        '/a/b/': undefined,\n        '/a/b/c/': undefined,\n      });\n    });\n\n    it('should capture a simple rest param', () => {\n      testMatch('/:abc*', {\n        rest: ['abc']\n      }, {\n        '/a': {abc: 'a'},\n        '/a/b': {abc: 'a/b'},\n        '/a/bcd': {abc: 'a/bcd'},\n        '/a/': {abc: 'a/'},\n        '/a/b/': {abc: 'a/b/'},\n        '/a//': {abc: 'a//'},\n        '/a/b/c': {abc: 'a/b/c'},\n        '/a/b/c/': {abc: 'a/b/c/'},\n      });\n      testMatch('/a/:b*', {\n        rest: ['b']\n      }, {\n        '/a/b': {b: 'b'},\n        '/a/bcd': {b: 'bcd'},\n        '/a/': {b: ''},\n        '/a/b/': {b: 'b/'},\n        '/a': {b: undefined},\n        '/a//': {b: '/'},\n        '/a/a/b': {b: 'a/b'},\n        '/a/a/b/': {b: 'a/b/'},\n      });\n    });\n\n    it('should capture a rest param mixed with a named param', () => {\n      testMatch('/:abc/:rest*', {\n        named: ['abc'],\n        rest: ['rest']\n      }, {\n        '/a': {abc: 'a', rest: undefined},\n        '/a/b': {abc: 'a', rest: 'b'},\n        '/a/bcd': {abc: 'a', rest: 'bcd'},\n        '/a/': {abc: 'a', rest: ''},\n        '/a/b/': {abc: 'a', rest: 'b/'},\n        '/a//': {abc: 'a', rest: '/'},\n        '/a/b/c': {abc: 'a', rest: 'b/c'},\n        '/a/b/c/': {abc: 'a', rest: 'b/c/'},\n      });\n    });\n  });\n});\n\nfunction testGlob(pattern: string, matches: string[], nonMatches: string[]) {\n  const glob = new FirebaseGlob(pattern);\n  matches.forEach(url => expect(glob.test(url)).toBe(true, url));\n  nonMatches.forEach(url => expect(glob.test(url)).toBe(false, url));\n}\n\nfunction testMatch(pattern: string, captures: { named?: string[], rest?: string[] }, matches: { [url: string]: object|undefined }) {\n  const glob = new FirebaseGlob(pattern);\n  expect(Object.keys(glob.namedParams)).toEqual(captures.named || []);\n  expect(Object.keys(glob.restParams)).toEqual(captures.rest || []);\n  Object.keys(matches).forEach(url => expect(glob.match(url)).toEqual(matches[url]));\n}\n"
  },
  {
    "path": "apps/rxjs.dev/tools/firebase-test-utils/FirebaseGlob.ts",
    "content": "import * as XRegExp from 'xregexp';\n\nconst dot = /\\./g;\nconst star = /\\*/g;\nconst doubleStar = /(^|\\/)\\*\\*($|\\/)/g;           // e.g. a/**/b or **/b or a/** but not a**b\nconst modifiedPatterns = /(.)\\(([^)]+)\\)/g;       // e.g. `@(a|b)\nconst restParam = /\\/:([A-Za-z]+)\\*/g;            // e.g. `:rest*`\nconst namedParam = /\\/:([A-Za-z]+)/g;             // e.g. `:api`\nconst possiblyEmptyInitialSegments = /^\\.🐷\\//g;  // e.g. `**/a` can also match `a`\nconst possiblyEmptySegments = /\\/\\.🐷\\//g;        // e.g. `a/**/b` can also match `a/b`\nconst willBeStar = /🐷/g;                         // e.g. `a**b` not matched by previous rule\n\nexport class FirebaseGlob {\n  pattern: string;\n  regex: XRegExp;\n  namedParams: { [key: string]: boolean } = {};\n  restParams: { [key: string]: boolean } = {};\n  constructor(glob: string) {\n    try {\n      const pattern = glob\n          .replace(dot, '\\\\.')\n          .replace(modifiedPatterns, replaceModifiedPattern)\n          .replace(restParam, (_, param) => {\n            // capture the rest of the string\n            this.restParams[param] = true;\n            return `(?:/(?<${param}>.🐷))?`;\n          })\n          .replace(namedParam, (_, param) => {\n            // capture the named parameter\n            this.namedParams[param] = true;\n            return `/(?<${param}>[^/]+)`;\n          })\n          .replace(doubleStar, '$1.🐷$2')                 // use the pig to avoid replacing ** in next rule\n          .replace(star, '[^/]*')                         // match a single segment\n          .replace(possiblyEmptyInitialSegments, '(?:.*)')// deal with **/ special cases\n          .replace(possiblyEmptySegments, '(?:/|/.*/)')   // deal with /**/ special cases\n          .replace(willBeStar, '*');                      // other ** matches\n      this.pattern = `^${pattern}$`;\n      this.regex = XRegExp(this.pattern);\n    } catch (e) {\n      throw new Error(`Error in FirebaseGlob: \"${glob}\" - ${e.message}`);\n    }\n  }\n\n  test(url: string) {\n    return XRegExp.test(url, this.regex);\n  }\n\n  match(url: string) {\n    const match = XRegExp.exec(url, this.regex);\n    if (match) {\n      const result = {};\n      const names = (this.regex as any).xregexp.captureNames || [];\n      names.forEach(name => result[name] = match[name]);\n      return result;\n    }\n  }\n}\n\nfunction replaceModifiedPattern(_, modifier, pattern) {\n  switch (modifier) {\n    case '!':\n      throw new Error(`\"not\" expansions are not supported: \"${_}\"`);\n    case '?':\n    case '+':\n      return `(${pattern})${modifier}`;\n    case '*':\n      return `(${pattern})🐷`;  // it will become a star\n    case '@':\n      return `(${pattern})`;\n    default:\n      throw new Error(`unknown expansion type: \"${modifier}\" in \"${_}\"`);\n  }\n}\n"
  },
  {
    "path": "apps/rxjs.dev/tools/firebase-test-utils/FirebaseRedirect.spec.ts",
    "content": "import { FirebaseRedirect } from './FirebaseRedirect';\n\ndescribe('FirebaseRedirect', () => {\n  describe('replace', () => {\n    it('should return undefined if the redirect does not match the url', () => {\n      const redirect = new FirebaseRedirect('/a/b/c', '/x/y/z');\n      expect(redirect.replace('/1/2/3')).toBe(undefined);\n    });\n\n    it('should return the destination if there is a match', () => {\n      const redirect = new FirebaseRedirect('/a/b/c', '/x/y/z');\n      expect(redirect.replace('/a/b/c')).toBe('/x/y/z');\n    });\n\n    it('should inject name params into the destination', () => {\n      const redirect = new FirebaseRedirect('/api/:package/:api-*', '<:package><:api>');\n      expect(redirect.replace('/api/common/NgClass-directive')).toEqual('<common><NgClass>');\n    });\n\n    it('should inject rest params into the destination', () => {\n      const redirect = new FirebaseRedirect('/a/:rest*', '/x/:rest*/y');\n      expect(redirect.replace('/a/b/c')).toEqual('/x/b/c/y');\n    });\n\n    it('should inject both named and rest parameters into the destination', () => {\n      const redirect = new FirebaseRedirect('/:a/:rest*', '/x/:a/y/:rest*/z');\n      expect(redirect.replace('/a/b/c')).toEqual('/x/a/y/b/c/z');\n    });\n  });\n});\n"
  },
  {
    "path": "apps/rxjs.dev/tools/firebase-test-utils/FirebaseRedirect.ts",
    "content": "import * as XRegExp from 'xregexp';\nimport { FirebaseGlob } from './FirebaseGlob';\n\nexport class FirebaseRedirect {\n  glob = new FirebaseGlob(this.source);\n  constructor(public source: string, public destination: string) {}\n\n  replace(url: string) {\n    const match = this.glob.match(url);\n    if (match) {\n      const paramReplacers = Object.keys(this.glob.namedParams).map(name => [ XRegExp(`:${name}`, 'g'), match[name] ]);\n      const restReplacers = Object.keys(this.glob.restParams).map(name => [ XRegExp(`:${name}\\\\*`, 'g'), match[name] ]);\n      return XRegExp.replaceEach(this.destination, [...paramReplacers, ...restReplacers]);\n    }\n  }\n}\n"
  },
  {
    "path": "apps/rxjs.dev/tools/firebase-test-utils/FirebaseRedirector.spec.ts",
    "content": "import { FirebaseRedirector } from './FirebaseRedirector';\n\ndescribe('FirebaseRedirector', () => {\n  it('should replace with the first matching redirect', () => {\n    const redirector = new FirebaseRedirector([\n      { source: '/a/b/c', destination: '/X/Y/Z' },\n      { source: '/a/:foo/c', destination: '/X/:foo/Z' },\n      { source: '/**/:foo/c', destination: '/A/:foo/zzz' },\n    ]);\n    expect(redirector.redirect('/a/b/c')).toEqual('/X/Y/Z');\n    expect(redirector.redirect('/a/moo/c')).toEqual('/X/moo/Z');\n    expect(redirector.redirect('/x/y/a/b/c')).toEqual('/A/b/zzz');\n    expect(redirector.redirect('/x/y/c')).toEqual('/A/y/zzz');\n  });\n\n  it('should return the original url if no redirect matches', () => {\n    const redirector = new FirebaseRedirector([\n      { source: 'x', destination: 'X' },\n      { source: 'y', destination: 'Y' },\n      { source: 'z', destination: 'Z' },\n    ]);\n    expect(redirector.redirect('a')).toEqual('a');\n  });\n\n  it('should recursively redirect', () => {\n    const redirector = new FirebaseRedirector([\n      { source: 'a', destination: 'b' },\n      { source: 'b', destination: 'c' },\n      { source: 'c', destination: 'd' },\n    ]);\n    expect(redirector.redirect('a')).toEqual('d');\n  });\n\n  it('should throw if stuck in an infinite loop', () => {\n    const redirector = new FirebaseRedirector([\n      { source: 'a', destination: 'b' },\n      { source: 'b', destination: 'c' },\n      { source: 'c', destination: 'a' },\n    ]);\n    expect(() => redirector.redirect('a')).toThrowError('infinite redirect loop');\n  });\n});\n"
  },
  {
    "path": "apps/rxjs.dev/tools/firebase-test-utils/FirebaseRedirector.ts",
    "content": "import { FirebaseRedirect } from './FirebaseRedirect';\n\nexport interface FirebaseRedirectConfig {\n  source: string;\n  destination: string;\n}\n\nexport class FirebaseRedirector {\n  private redirects: FirebaseRedirect[];\n  constructor(redirects: FirebaseRedirectConfig[]) {\n    this.redirects = redirects.map(redirect => new FirebaseRedirect(redirect.source, redirect.destination));\n  }\n\n  redirect(url: string) {\n    let ttl = 50;\n    while (ttl > 0) {\n      const newUrl = this.doRedirect(url);\n      if (newUrl === url) {\n        return url;\n      } else {\n        url = newUrl;\n        ttl--;\n      }\n    }\n    throw new Error('infinite redirect loop');\n  }\n  private doRedirect(url: string) {\n    for (const redirect of this.redirects) {\n      const newUrl = redirect.replace(url);\n      if (newUrl !== undefined) {\n        return newUrl;\n      }\n    }\n    return url;\n  }\n}\n"
  },
  {
    "path": "apps/rxjs.dev/tools/marbles/diagrams/audit.txt",
    "content": "-a-xy-----b--x--cxyz-|\n\n ----i\n\n          ----i\n\n                ----i\n\n> audit()\n\n-----y--------x-----z|\n"
  },
  {
    "path": "apps/rxjs.dev/tools/marbles/diagrams/bufferWhen.txt",
    "content": "[styles]\nevent_radius = 33\noperator_height = 60\ncompletion_height = 80\n\n---a---b---c---d---e---f---g---h---|\n\n-------------s\n\n> bufferWhen()\n\n-------------x------------y--------(z|)\nx := [a, b, c]\ny := [d, e, f]\nz := [g, h]\n"
  },
  {
    "path": "apps/rxjs.dev/tools/marbles/diagrams/concatAll.txt",
    "content": "x = ----a------b------|\n\ny = ---c-d---|\n\nz = ---e--f-|\n\n-x---y----z------|\n\n> concatAll\n\n-----a------b---------c-d------e--f-|"
  },
  {
    "path": "apps/rxjs.dev/tools/marbles/diagrams/debounce.txt",
    "content": "-a----bc----d-ef----|\n\n ---x\n\n       ---x\n\n               ---x\n\n> debounce()\n\n----a-----c-------f-|\n"
  },
  {
    "path": "apps/rxjs.dev/tools/marbles/diagrams/delay.txt",
    "content": "[styles]\nevent_radius = 15\n\n---a--b--c---|\n\n> delay(20)\n\n-----a--b--c-|\n"
  },
  {
    "path": "apps/rxjs.dev/tools/marbles/diagrams/exhaustAll.txt",
    "content": "x = --a---b---c--|\n\ny = ---d--e---f---|\n\nz = ---g--h---i---|\n\n------x-------y------z--|\nghosts = y\n\n> exhaustAll\n\n--------a---b---c-------g--h---i---|\n"
  },
  {
    "path": "apps/rxjs.dev/tools/marbles/diagrams/throttle.txt",
    "content": "-a-xy-----b--x--cxyz-|\n\n ----i\n\n          ----i\n\n                ----i\n\n> throttle()\n\n-a--------b-----c----|\n"
  },
  {
    "path": "apps/rxjs.dev/tools/marbles/diagrams/windowWhen.txt",
    "content": "[styles]\nevent_radius = 33\noperator_height = 60\ncompletion_height = 80\n\n---a---b---c---d---e---f---g---h---|\n\n-------------x|\n             -------------x|\n                          -------------x|\n\n> windowWhen()\n\nx = ---a---b---c-|\n\ny = --d---e---f---g|\n\nz = -g---h---|\n\nx------------y------------z--------|\n"
  },
  {
    "path": "apps/rxjs.dev/tools/marbles/scripts/index.ts",
    "content": "import { renderMarbleDiagram } from '@swirly/renderer-node';\nimport { readdir, readFileSync, writeFileSync } from 'fs';\nimport { join } from 'path';\nimport { parseMarbleDiagramSpecification } from '@swirly/parser';\nimport { DiagramStyles } from '@swirly/types';\nimport * as SVGO from 'svgo';\n\nconst styles: DiagramStyles = {\n    frame_width: 20,\n    completion_height: 20,\n    higher_order_angle: 30,\n    arrow_fill_color: 'black',\n    background_color: 'rgba(255, 255, 255, 0.0)',\n    operator_fill_color: 'rgba(255, 255, 255, 0.0)'\n};\n\nconst optimizeXml = async (unoptXml: string): Promise<string> => {\n    const svgo = new SVGO({ plugins: [{ removeViewBox: false }] });\n    const { data } = await svgo.optimize(unoptXml);\n    return data;\n};\n\nconst renderMarble = (path: string, fileName: string): Promise<true> => {\n    const file = readFileSync(join(path, fileName));\n    const diagramSpec = parseMarbleDiagramSpecification(file.toString());\n    const { xml: unoptXml } = renderMarbleDiagram(diagramSpec, { styles });\n    const optimizedSVGPromise = optimizeXml(unoptXml);\n    return optimizedSVGPromise.then((svgXML) => {\n        const svgFileName = fileName.split('.')[0] + '.svg';\n        const svgPath = join(process.cwd(), 'src', 'assets', 'images', 'marble-diagrams', svgFileName);\n        writeFileSync(svgPath, svgXML, { encoding: 'utf-8', flag: 'w' });\n        return true;\n    });\n};\n\nconst diagramsPath = join(process.cwd(), 'tools', 'marbles', 'diagrams');\nreaddir(diagramsPath, (err, files) => {\n    Promise.all(files.map(fileName => renderMarble(diagramsPath, fileName)))\n        .then(_ => console.log('All SVGs created'))\n        .catch(e => console.error('generating SVGs failed', e));\n});"
  },
  {
    "path": "apps/rxjs.dev/tools/marbles/tsconfig.marbles.json",
    "content": "{\n    \"extends\": \"../../tsconfig.json\",\n    \"compilerOptions\": {\n      \"module\": \"commonjs\"\n    }\n  }\n  "
  },
  {
    "path": "apps/rxjs.dev/tools/stackblitz/rxjs.version.js",
    "content": "// Exposes the current RxJS version number from the library's package.json\n// for usage in TypeScript files.\n// (Since said package.json is outside of this TypeScript project, it's not\n// available for a direct TypeScript import).\n\nmodule.exports = require('../../../../packages/rxjs/package.json').version;\n"
  },
  {
    "path": "apps/rxjs.dev/tools/transforms/.eslintignore",
    "content": "**/*.template.js\n"
  },
  {
    "path": "apps/rxjs.dev/tools/transforms/.eslintrc.js",
    "content": "module.exports = {\n  root: true,\n  env: {\n    es6: true,\n    jasmine: true,\n    node: true,\n  },\n  extends: ['eslint:recommended', 'plugin:jasmine/recommended'],\n  parserOptions: {\n    ecmaVersion: 2020,\n  },\n  plugins: ['jasmine'],\n  rules: {\n    'linebreak-style': ['error', 'unix'],\n    'no-prototype-builtins': ['off'],\n    quotes: ['error', 'single'],\n    semi: ['error', 'always'],\n    'jasmine/new-line-before-expect': ['off'],\n  },\n};\n"
  },
  {
    "path": "apps/rxjs.dev/tools/transforms/README.md",
    "content": "# Overview\n\nAll the content that is rendered by the AIO application, and some of its configuration files, are\ngenerated from source files by [Dgeni](https://github.com/angular/dgeni). Dgeni is a general purpose\ndocumentation generation tool.\n\nMarkdown files in `/aio/content`, code comments in the core Angular source files and example files\nare processed and transformed into files that are consumed by the AIO application.\n\nDgeni is configured by \"packages\", which contain services and processors. Some of these packages are\ninstalled as `node_modules` from the [dgeni-packages](https://github.com/angular/dgeni-packages) and\nsome are specific to the AIO project.\n\nThe project specific packages are stored in this folder (`aio/tools/transforms`).\n\nIf you are an author and want to know how to generate the documentation, the steps are outlined in\nthe top level [README.md](../../README.md#guide-to-authoring).\n\n## Root packages\n\nTo run Dgeni, you must specify a root package, which acts as the entry point to the documentation\ngeneration.\nThis root package, in turn requires a number of other packages, some are defined locally in the\n`tools/transforms` folder, such as `tools/transforms/cheatsheet-package` and\n`tools/transforms/content-package`, etc. And some are brought in from the `dgeni-packages` node\nmodules, such as `jsdoc` and `nunjucks`.\n\n* The primary root package is defined in `tools/transforms/angular.io-package/index.js`. This package\nis used to run a full generation of all the documentation.\n* There are also root packages defined in `tools/transforms/authors-package/*-package.js`. These\npackages are used by the documentation authors when writing docs, since it allows them to run partial\ndoc generation, which is not complete but is faster for quickly seeing changes to the document that\nyou are working on.\n\n## Other packages\n\n* angular-base-package\n* angular-api-package\n* angular-content-package\n* content-package\n* links-package\n* post-process-package\n* remark-package\n* target-package\n\n## Templates\n\nAll the templates for the angular.io dgeni transformations are stored in the `tools/transforms/templates`\nfolder. See the [README](./templates/README.md).\n"
  },
  {
    "path": "apps/rxjs.dev/tools/transforms/angular-api-package/index.js",
    "content": "/**\n * @license\n * Copyright Google Inc. All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\nconst Package = require('dgeni').Package;\n\nconst basePackage = require('../angular-base-package');\nconst typeScriptPackage = require('dgeni-packages/typescript');\n// prettier-ignore\nconst { API_SOURCE_PATH, API_TEMPLATES_PATH, MARBLE_IMAGES_PATH, MARBLE_IMAGES_WEB_PATH,\n  requireFolder } = require('../config');\n\n// prettier-ignore\nmodule.exports = new Package('angular-api', [basePackage, typeScriptPackage])\n\n  // Register the processors\n  .processor(require('./processors/migrateLegacyJSDocTags'))\n  .processor(require('./processors/splitDescription'))\n  .processor(require('./processors/convertPrivateClassesToInterfaces'))\n  .processor(require('./processors/generateApiListDoc'))\n  .processor(require('./processors/generateDeprecationsListDoc'))\n  .processor(require('./processors/mergeDecoratorDocs'))\n  .processor(require('./processors/extractDecoratedClasses'))\n  .processor(require('./processors/matchUpDirectiveDecorators'))\n  .processor(require('./processors/addMetadataAliases'))\n  .processor(require('./processors/computeApiBreadCrumbs'))\n  .processor(require('./processors/filterContainedDocs'))\n  .processor(require('./processors/processClassLikeMembers'))\n  .processor(require('./processors/markBarredODocsAsPrivate'))\n  .processor(require('./processors/filterPrivateDocs'))\n  .processor(require('./processors/computeSearchTitle'))\n  .processor(require('./processors/simplifyMemberAnchors'))\n  .processor(require('./processors/computeStability'))\n  .processor(require('./processors/markAliases').markAliases)\n  .processor(require('./processors/checkOperator'))\n\n  .factory(require('./post-processors/embedMarbleDiagrams'))\n\n  /**\n   * These are the API doc types that will be rendered to actual files.\n   * This is a super set of the exported docs, since we convert some classes to\n   * more Angular specific API types, such as decorators and directives.\n   */\n  .factory(function API_DOC_TYPES_TO_RENDER(EXPORT_DOC_TYPES) {\n    return EXPORT_DOC_TYPES.concat(['decorator', 'directive', 'pipe', 'module', 'deprecation']);\n  })\n\n  /**\n   * These are the doc types that are API docs, including ones that will be merged into container docs,\n   * such as members and overloads.\n   */\n  .factory(function API_DOC_TYPES(API_DOC_TYPES_TO_RENDER) {\n    return API_DOC_TYPES_TO_RENDER.concat(['member', 'function-overload']);\n  })\n\n  // Where do we get the source files?\n  .config(function (readTypeScriptModules) {\n    // API files are typescript\n    readTypeScriptModules.basePath = API_SOURCE_PATH;\n    readTypeScriptModules.ignoreExportsMatching = [/^[_ɵ]|^VERSION$/];\n    readTypeScriptModules.hidePrivateMembers = true;\n\n    // NOTE: This list should be in sync with tools/public_api_guard/BUILD.bazel\n    readTypeScriptModules.sourceFiles = [\n      'index.ts',\n      'operators/index.ts',\n      'ajax/index.ts',\n      'fetch/index.ts',\n      'webSocket/index.ts',\n      'testing/index.ts'\n    ];\n  })\n\n  // Configure jsdoc-style tag parsing\n  .config(function (parseTagsProcessor, getInjectables) {\n    // Load up all the tag definitions in the tag-defs folder\n    parseTagsProcessor.tagDefinitions =\n        parseTagsProcessor.tagDefinitions.concat(getInjectables(requireFolder(__dirname, './tag-defs')));\n  })\n\n  .config(function (computeStability, splitDescription, EXPORT_DOC_TYPES, API_DOC_TYPES) {\n    computeStability.docTypes = EXPORT_DOC_TYPES;\n    // Only split the description on the API docs\n    splitDescription.docTypes = API_DOC_TYPES;\n  })\n\n  .config(function (computePathsProcessor, EXPORT_DOC_TYPES, generateApiListDoc, generateDeprecationListDoc) {\n    const API_SEGMENT = 'api';\n\n    generateApiListDoc.outputFolder = API_SEGMENT;\n    generateDeprecationListDoc.outputFolder = API_SEGMENT;\n\n    computePathsProcessor.pathTemplates.push({\n      docTypes: ['module'],\n      getPath: function computeModulePath(doc) {\n        doc.moduleFolder = `${API_SEGMENT}/${doc.id.replace(/\\/index$/, '')}`;\n        return doc.moduleFolder;\n      },\n      outputPathTemplate: '${moduleFolder}.json'\n    });\n    computePathsProcessor.pathTemplates.push({\n      docTypes: EXPORT_DOC_TYPES.concat(['decorator', 'directive', 'pipe']),\n      pathTemplate: '${moduleDoc.moduleFolder}/${name}',\n      outputPathTemplate: '${moduleDoc.moduleFolder}/${name}.json',\n    });\n    computePathsProcessor.pathTemplates.push({\n      docTypes: ['const', 'function', 'interface', 'class', 'type-alias'],\n      getPath: (doc) => {\n        return `${API_SEGMENT}/${doc.id.replace(/^index\\//, `index/${doc.docType}/`)}`;\n      },\n      outputPathTemplate: '${path}.json',\n    });\n  })\n\n  .config(function (templateFinder) {\n    // Where to find the templates for the API doc rendering\n    templateFinder.templateFolders.unshift(API_TEMPLATES_PATH);\n  })\n\n  .config(function (embedMarbleDiagramsPostProcessor) {\n    embedMarbleDiagramsPostProcessor.marbleImagesPath = MARBLE_IMAGES_PATH;\n    embedMarbleDiagramsPostProcessor.marbleImagesOutputWebPath = `/${MARBLE_IMAGES_WEB_PATH}`;\n  })\n\n  .config(function (convertToJsonProcessor, postProcessHtml, API_DOC_TYPES_TO_RENDER, API_DOC_TYPES, autoLinkCode, embedMarbleDiagramsPostProcessor) {\n    convertToJsonProcessor.docTypes = convertToJsonProcessor.docTypes.concat(API_DOC_TYPES_TO_RENDER);\n    postProcessHtml.docTypes = convertToJsonProcessor.docTypes.concat(API_DOC_TYPES_TO_RENDER);\n    postProcessHtml.plugins.push(embedMarbleDiagramsPostProcessor.process);\n    autoLinkCode.docTypes = API_DOC_TYPES;\n    autoLinkCode.codeElements = ['code', 'code-example', 'code-pane'];\n  });\n"
  },
  {
    "path": "apps/rxjs.dev/tools/transforms/angular-api-package/mocks/aliasedExports.ts",
    "content": "export * from './operator';\nexport { operator as aliasedOperator } from './operator';\nexport { operator } from './operator';\nexport { anotherOperator as operatorWithoutDuplicate } from './anotherOperator';\n"
  },
  {
    "path": "apps/rxjs.dev/tools/transforms/angular-api-package/mocks/anotherOperator.ts",
    "content": "export const anotherOperator = () => {};\n"
  },
  {
    "path": "apps/rxjs.dev/tools/transforms/angular-api-package/mocks/importedSrc.ts",
    "content": "/**\n * @license\n * Copyright Google Inc. All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nexport const x = 100;\n"
  },
  {
    "path": "apps/rxjs.dev/tools/transforms/angular-api-package/mocks/operator.ts",
    "content": "export const operator = () => {};\n"
  },
  {
    "path": "apps/rxjs.dev/tools/transforms/angular-api-package/mocks/testSrc.ts",
    "content": "/**\n * @license\n * Copyright Google Inc. All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\n/**\n * @module\n * @description\n * This is the module description\n */\n\nexport * from './importedSrc';\n\n/**\n * This is some random other comment\n */\n\n/**\n * This is MyClass\n */\nexport class MyClass {\n  message: String;\n\n  /**\n   * Create a new MyClass\n   * @param {String} name The name to say hello to\n   */\n  constructor(name) { this.message = 'hello ' + name; }\n\n  /**\n   * Return a greeting message\n   */\n  greet() { return this.message; }\n}\n\n/**\n * An exported function\n */\nexport const myFn = (val: number) => val * 2;\n"
  },
  {
    "path": "apps/rxjs.dev/tools/transforms/angular-api-package/post-processors/embedMarbleDiagrams.js",
    "content": "const fs = require('fs');\nconst path = require('path');\nconst visit = require('unist-util-visit');\nconst is = require('hast-util-is-element');\n\n/**\n * Find pre-rendered marble diagrams and override their <img> `src` attributes in docs.\n */\nmodule.exports = function embedMarbleDiagramsPostProcessor() {\n  const service = {\n    marbleImagesPath: null,\n    marbleImagesOutputWebPath: null,\n    process: () => {\n      return (tree) => {\n        visit(tree, node => {\n          if (is(node, 'img')) {\n            const props = node.properties;\n            const src = props.src;\n            const expectedImgPath = `${service.marbleImagesPath}/${src}`;\n            if (fs.existsSync(expectedImgPath)) {\n              const operator = path.basename(src, path.extname(src));\n              const filename = path.basename(expectedImgPath);\n\n              props.src = `${service.marbleImagesOutputWebPath}/${filename}`;\n              props.width = '100%';\n              if (!props.alt) {\n                props.alt = `${operator} marble diagram`;\n              }\n            }\n          }\n        });\n      };\n    },\n  };\n\n  return service;\n};\n"
  },
  {
    "path": "apps/rxjs.dev/tools/transforms/angular-api-package/processors/addMetadataAliases.js",
    "content": "const CssSelectorParser = require('css-selector-parser').CssSelectorParser;\nconst cssParser = new CssSelectorParser();\n/**\n * @dgProcessor addMetadataAliases\n *\n * Directives and components can also be referenced by their selectors,\n * and Pipes can be referenced by their name.\n * So let's add each selector as an alias to this doc.\n */\nmodule.exports = function addMetadataAliasesProcessor() {\n  return {\n    $runAfter: ['extractDecoratedClassesProcessor'],\n    $runBefore: ['computing-ids'],\n    $process: function(docs) {\n      docs.forEach(doc => {\n        switch(doc.docType) {\n        case 'directive':\n        case 'component':\n          doc.aliases = doc.aliases.concat(extractSelectors(doc[doc.docType + 'Options'].selector));\n          break;\n        case 'pipe':\n          if (doc.pipeOptions.name) {\n            doc.aliases = doc.aliases.concat(stripQuotes(doc.pipeOptions.name));\n          }\n          break;\n        }\n      });\n    }\n  };\n};\n\nfunction extractSelectors(selectors) {\n  const selectorAST = cssParser.parse(stripQuotes(selectors));\n  const rules = selectorAST.selectors ? selectorAST.selectors.map(ruleSet => ruleSet.rule) : [selectorAST.rule];\n  const aliases = {};\n  rules.forEach(rule => {\n    if (rule.tagName) {\n      aliases[rule.tagName] = true;\n    }\n    if (rule.attrs) {\n      rule.attrs.forEach(attr => aliases[attr.name] = true);\n    }\n  });\n  return Object.keys(aliases);\n}\n\nfunction stripQuotes(value) {\n  return (typeof(value) === 'string') ? value.trim().replace(/^(['\"])(.*)\\1$/, '$2') : value;\n}\n"
  },
  {
    "path": "apps/rxjs.dev/tools/transforms/angular-api-package/processors/addMetadataAliases.spec.js",
    "content": "const testPackage = require('../../helpers/test-package');\nconst processorFactory = require('./addMetadataAliases');\nconst Dgeni = require('dgeni');\n\ndescribe('addSelectorsAsAliases processor', () => {\n\n  it('should be available on the injector', () => {\n    const dgeni = new Dgeni([testPackage('angular-api-package')]);\n    const injector = dgeni.configureInjector();\n    const processor = injector.get('addMetadataAliasesProcessor');\n    expect(processor.$process).toBeDefined();\n  });\n\n  it('should run after the correct processor', () => {\n    const processor = processorFactory();\n    expect(processor.$runAfter).toEqual(['extractDecoratedClassesProcessor']);\n  });\n\n  it('should run before the correct processor', () => {\n    const processor = processorFactory();\n    expect(processor.$runBefore).toEqual(['computing-ids']);\n  });\n\n  it('should add new aliases for directives, components and pipes', () => {\n    const processor = processorFactory();\n    const docs = [\n      { docType: 'class', name: 'MyClass', aliases: ['MyClass'] },\n      { docType: 'interface', name: 'MyInterface', aliases: ['MyInterface'] },\n      { docType: 'enum', name: 'MyEnum', aliases: ['MyEnum'] },\n      { docType: 'function', name: 'myFunction', aliases: ['myFunction'] },\n      { docType: 'pipe', name: 'MyPipe', aliases: ['MyPipe'], pipeOptions: { name: '\\'myPipe\\'' } },\n      { docType: 'directive', name: 'MyDirective', aliases: ['MyDirective'], directiveOptions: { selector: '\\'my-directive,[myDirective],[my-directive]\\'' } },\n      { docType: 'directive', name: 'NgModel', aliases: ['NgModel'], directiveOptions: { selector: '\\'[ngModel]:not([formControlName]):not([formControl])\\'' } },\n      { docType: 'component', name: 'MyComponent', aliases: ['MyComponent'], componentOptions: { selector: '\\'my-component\\'' } },\n      { docType: 'decorator', name: 'MyDecorator', aliases: ['MyDecorator'] },\n      { docType: 'module', name: 'myModule', aliases: ['myModule'], id: 'some/myModule' },\n      { docType: 'var', name: 'myVar', aliases: ['myVar'] },\n      { docType: 'let', name: 'myLet', aliases: ['myLet'] },\n      { docType: 'const', name: 'myConst', aliases: ['myConst'] },\n      { docType: 'type-alias', name: 'myType', aliases: ['myType'] },\n    ];\n    processor.$process(docs);\n    expect(docs[0].aliases).toEqual([docs[0].name]);\n    expect(docs[1].aliases).toEqual([docs[1].name]);\n    expect(docs[2].aliases).toEqual([docs[2].name]);\n    expect(docs[3].aliases).toEqual([docs[3].name]);\n    expect(docs[4].aliases).toEqual([docs[4].name, 'myPipe']);\n    expect(docs[5].aliases).toEqual([docs[5].name, 'my-directive', 'myDirective']);\n    expect(docs[6].aliases).toEqual([docs[6].name, 'ngModel']);\n    expect(docs[7].aliases).toEqual([docs[7].name, 'my-component']);\n    expect(docs[8].aliases).toEqual([docs[8].name]);\n    expect(docs[9].aliases).toEqual([docs[9].name]);\n    expect(docs[10].aliases).toEqual([docs[10].name]);\n    expect(docs[11].aliases).toEqual([docs[11].name]);\n    expect(docs[12].aliases).toEqual([docs[12].name]);\n  });\n});\n"
  },
  {
    "path": "apps/rxjs.dev/tools/transforms/angular-api-package/processors/checkOperator.js",
    "content": "module.exports = function checkOperator() {\n  return {\n    $runAfter: ['generateApiListDoc'],\n    $runBefore: ['rendering-docs'],\n    $process(docs) {\n      docs.forEach((doc) => {\n        doc.isOperator = !!(doc.originalModule?.startsWith('internal/operators') && doc.docType === 'function');\n      });\n    },\n  };\n};\n"
  },
  {
    "path": "apps/rxjs.dev/tools/transforms/angular-api-package/processors/computeApiBreadCrumbs.js",
    "content": "module.exports = function computeApiBreadCrumbs(EXPORT_DOC_TYPES) {\n  return {\n    $runAfter: ['paths-computed'],\n    $runBefore: ['rendering-docs'],\n    $process(docs) {\n      // Compute the breadcrumb for each doc by processing its containers\n      docs.forEach(doc => {\n        if (EXPORT_DOC_TYPES.indexOf(doc.docType) !== -1) {\n          doc.breadCrumbs = [\n            { text: 'API', path: '/api' },\n            { text: 'rxjs/' + doc.moduleDoc.id, path: doc.moduleDoc.path },\n            { text: doc.name, path: doc.path }\n          ];\n        }\n      });\n    }\n  };\n};\n\n"
  },
  {
    "path": "apps/rxjs.dev/tools/transforms/angular-api-package/processors/computeApiBreadCrumbs.spec.js",
    "content": "const testPackage = require('../../helpers/test-package');\nconst processorFactory = require('./computeApiBreadCrumbs');\nconst Dgeni = require('dgeni');\n\ndescribe('angular-api-package: computeApiBreadCrumbs processor', () => {\n\n  it('should be available on the injector', () => {\n    const dgeni = new Dgeni([testPackage('angular-api-package')]);\n    const injector = dgeni.configureInjector();\n    const processor = injector.get('computeApiBreadCrumbs');\n    expect(processor.$process).toBeDefined();\n    expect(processor.$runAfter).toEqual(['paths-computed']);\n    expect(processor.$runBefore).toEqual(['rendering-docs']);\n  });\n\n  it('should attach a breadCrumbs property to each of the EXPORT_DOC_TYPES docs', () => {\n    const EXPORT_DOC_TYPES = ['class', 'interface'];\n    const processor = processorFactory(EXPORT_DOC_TYPES);\n\n    const docs = [\n      { docType: 'class', name: 'ClassA', path: 'module-1/class-a', moduleDoc: { id: 'moduleOne', path: 'module-1' } },\n      { docType: 'interface', name: 'InterfaceB', path: 'module-2/interface-b', moduleDoc: { id: 'moduleTwo', path: 'module-2' } },\n      { docType: 'guide', name: 'Guide One', path: 'guide/guide-1' },\n    ];\n    processor.$process(docs);\n\n    expect(docs[0].breadCrumbs).toEqual([\n      { text: 'API', path: '/api' },\n      { text: 'rxjs/moduleOne', path: 'module-1' },\n      { text: 'ClassA', path: 'module-1/class-a' },\n    ]);\n    expect(docs[1].breadCrumbs).toEqual([\n      { text: 'API', path: '/api' },\n      { text: 'rxjs/moduleTwo', path: 'module-2' },\n      { text: 'InterfaceB', path: 'module-2/interface-b' },\n    ]);\n    expect(docs[2].breadCrumbs).toBeUndefined();\n  });\n});\n"
  },
  {
    "path": "apps/rxjs.dev/tools/transforms/angular-api-package/processors/computeSearchTitle.js",
    "content": "module.exports = function computeSearchTitleProcessor() {\n  return {\n    $runAfter: ['ids-computed'],\n    $runBefore: ['generateKeywordsProcessor'],\n    $process(docs) {\n      docs.forEach(doc => {\n        switch(doc.docType) {\n        case 'function':\n          doc.searchTitle = `${doc.name}()`;\n          break;\n        case 'module':\n          doc.searchTitle = `${doc.id} package`;\n          break;\n        }\n      });\n    }\n  };\n};\n"
  },
  {
    "path": "apps/rxjs.dev/tools/transforms/angular-api-package/processors/computeSearchTitle.spec.js",
    "content": "const testPackage = require('../../helpers/test-package');\nconst processorFactory = require('./computeSearchTitle');\nconst Dgeni = require('dgeni');\n\ndescribe('computeSearchTitle processor', () => {\n\n  it('should be available on the injector', () => {\n    const dgeni = new Dgeni([testPackage('angular-api-package')]);\n    const injector = dgeni.configureInjector();\n    const processor = injector.get('computeSearchTitleProcessor');\n    expect(processor.$process).toBeDefined();\n  });\n\n  it('should run after the correct processor', () => {\n    const processor = processorFactory();\n    expect(processor.$runAfter).toEqual(['ids-computed']);\n  });\n\n  it('should run before the correct processor', () => {\n    const processor = processorFactory();\n    expect(processor.$runBefore).toEqual(['generateKeywordsProcessor']);\n  });\n\n  it('should compute a search title for API docs', () => {\n    const processor = processorFactory();\n    const docs = [\n      { docType: 'class', name: 'MyClass' },\n      { docType: 'interface', name: 'MyInterface' },\n      { docType: 'enum', name: 'MyEnum' },\n      { docType: 'function', name: 'myFunction' },\n      { docType: 'pipe', name: 'MyPipe', pipeOptions: { name: 'myPipe' } },\n      { docType: 'directive', name: 'MyDirective', directiveOptions: {} },\n      { docType: 'decorator', name: 'MyDecorator' },\n      { docType: 'module', name: 'myModule', id: 'some/myModule' },\n      { docType: 'var', name: 'myVar' },\n      { docType: 'let', name: 'myLet' },\n      { docType: 'const', name: 'myConst' },\n      { docType: 'type-alias', name: 'myType' },\n    ];\n    processor.$process(docs);\n    expect(docs[0].searchTitle).toBeUndefined();\n    expect(docs[1].searchTitle).toBeUndefined();\n    expect(docs[2].searchTitle).toBeUndefined();\n    expect(docs[3].searchTitle).toEqual('myFunction()');\n    expect(docs[4].searchTitle).toBeUndefined();\n    expect(docs[5].searchTitle).toBeUndefined();\n    expect(docs[6].searchTitle).toBeUndefined();\n    expect(docs[7].searchTitle).toEqual('some/myModule package');\n    expect(docs[8].searchTitle).toBeUndefined();\n    expect(docs[9].searchTitle).toBeUndefined();\n    expect(docs[10].searchTitle).toBeUndefined();\n    expect(docs[11].searchTitle).toBeUndefined();\n  });\n});\n"
  },
  {
    "path": "apps/rxjs.dev/tools/transforms/angular-api-package/processors/computeStability.js",
    "content": "module.exports = function computeStability(log, createDocMessage) {\n  return {\n    docTypes: [],\n    $runAfter: ['tags-extracted'],\n    $runBefore: ['rendering-docs'],\n    $process(docs) {\n      docs.forEach(doc => {\n        if (this.docTypes.indexOf(doc.docType) !== -1 &&\n            doc.experimental === undefined &&\n            doc.deprecated === undefined &&\n            doc.stable === undefined) {\n          log.debug(createDocMessage('Adding stable property', doc));\n          doc.stable = true;\n        }\n      });\n    }\n  };\n};\n"
  },
  {
    "path": "apps/rxjs.dev/tools/transforms/angular-api-package/processors/computeStability.spec.js",
    "content": "const log = require('dgeni/lib/mocks/log')(false);\nconst createDocMessage = require('dgeni-packages/base/services/createDocMessage')();\nconst computeStability = require('./computeStability')(log, createDocMessage);\nconst testPackage = require('../../helpers/test-package');\nconst Dgeni = require('dgeni');\n\ndescribe('computeStability processor', () => {\n\n  it('should be available on the injector', () => {\n    const dgeni = new Dgeni([testPackage('angular-api-package')]);\n    const injector = dgeni.configureInjector();\n    const processor = injector.get('computeStability');\n    expect(processor.$process).toBeDefined();\n  });\n\n  it('should run before the correct processor', () => {\n    expect(computeStability.$runBefore).toEqual(['rendering-docs']);\n  });\n\n  it('should run after the correct processor', () => {\n    expect(computeStability.$runAfter).toEqual(['tags-extracted']);\n  });\n\n  it('should compute stability based on the existence of experimental and deprecated tags', () => {\n    computeStability.docTypes = ['test'];\n    const docs = [\n      { docType: 'test' },\n      { docType: 'test', experimental: undefined },\n      { docType: 'test', experimental: true },\n      { docType: 'test', experimental: '' },\n      { docType: 'test', deprecated: undefined },\n      { docType: 'test', deprecated: true },\n      { docType: 'test', deprecated: '' },\n      { docType: 'test', experimental: true, deprecated: true },\n    ];\n    computeStability.$process(docs);\n    expect(docs.map(doc => doc.stable)).toEqual([\n      true,\n      true,\n      undefined,\n      undefined,\n      true,\n      undefined,\n      undefined,\n      undefined\n    ]);\n  });\n\n  it('should ignore docs that are not in the docTypes list', () => {\n    computeStability.docTypes = ['test1', 'test2'];\n    const docs = [\n      { docType: 'test1' },\n      { docType: 'test2' },\n      { docType: 'test3' },\n      { docType: 'test4' },\n    ];\n    computeStability.$process(docs);\n    expect(docs.map(doc => doc.stable)).toEqual([\n      true,\n      true,\n      undefined,\n      undefined\n    ]);\n  });\n\n  it('should not ignore docs where `stable` has already been defined', () => {\n    computeStability.docTypes = ['test'];\n    const docs = [\n      { docType: 'test' },\n      { docType: 'test', stable: true },\n      { docType: 'test', stable: '' },\n      { docType: 'test', stable: undefined },\n    ];\n    computeStability.$process(docs);\n    expect(docs.map(doc => doc.stable)).toEqual([\n      true,\n      true,\n      '',\n      true\n    ]);\n  });\n});\n"
  },
  {
    "path": "apps/rxjs.dev/tools/transforms/angular-api-package/processors/convertPrivateClassesToInterfaces.js",
    "content": "module.exports = function convertPrivateClassesToInterfacesProcessor(\n  convertPrivateClassesToInterfaces) {\n  return {\n    $runAfter: ['processing-docs'],\n    $runBefore: ['docs-processed'],\n    $process: function(docs) {\n      convertPrivateClassesToInterfaces(docs, false);\n      return docs;\n    }\n  };\n};"
  },
  {
    "path": "apps/rxjs.dev/tools/transforms/angular-api-package/processors/extractDecoratedClasses.js",
    "content": "var _ = require('lodash');\n\nmodule.exports = function extractDecoratedClassesProcessor(EXPORT_DOC_TYPES) {\n\n  // Add the \"directive\" docType into those that can be exported from a module\n  EXPORT_DOC_TYPES.push('directive', 'pipe');\n\n  return {\n    $runAfter: ['processing-docs'],\n    $runBefore: ['docs-processed'],\n    decoratorTypes: ['Directive', 'Component', 'Pipe'],\n    $process: function(docs) {\n      var decoratorTypes = this.decoratorTypes;\n\n      _.forEach(docs, function(doc) {\n\n        _.forEach(doc.decorators, function(decorator) {\n\n          if (decoratorTypes.indexOf(decorator.name) !== -1) {\n            doc.docType = decorator.name.toLowerCase();\n            doc[doc.docType + 'Options'] = decorator.argumentInfo[0];\n          }\n        });\n      });\n\n      return docs;\n    }\n  };\n};\n"
  },
  {
    "path": "apps/rxjs.dev/tools/transforms/angular-api-package/processors/extractDecoratedClasses.spec.js",
    "content": "var testPackage = require('../../helpers/test-package');\nvar Dgeni = require('dgeni');\n\ndescribe('extractDecoratedClasses processor', function() {\n  var dgeni, injector, processor;\n\n  beforeEach(function() {\n    dgeni = new Dgeni([testPackage('angular-api-package')]);\n    injector = dgeni.configureInjector();\n    processor = injector.get('extractDecoratedClassesProcessor');\n  });\n\n  it('should extract specified decorator arguments', function() {\n    var doc1 = {\n      id: '@angular/common/ngFor',\n      name: 'ngFor',\n      docType: 'class',\n      decorators: [{\n        name: 'Directive',\n        arguments: ['{selector: \\'[ng-for][ng-for-of]\\', properties: [\\'ngForOf\\']}'],\n        argumentInfo: [{selector: '[ng-for][ng-for-of]', properties: ['ngForOf']}]\n      }]\n    };\n    var doc2 = {\n      id: '@angular/core/DecimalPipe',\n      name: 'DecimalPipe',\n      docType: 'class',\n      decorators:\n          [{name: 'Pipe', arguments: ['{name: \\'number\\'}'], argumentInfo: [{name: 'number'}]}]\n    };\n\n    processor.$process([doc1, doc2]);\n\n    expect(doc1).toEqual(jasmine.objectContaining({\n      id: '@angular/common/ngFor',\n      name: 'ngFor',\n      docType: 'directive',\n      directiveOptions: {selector: '[ng-for][ng-for-of]', properties: ['ngForOf']}\n    }));\n\n    expect(doc2).toEqual(jasmine.objectContaining({\n      id: '@angular/core/DecimalPipe',\n      name: 'DecimalPipe',\n      docType: 'pipe',\n      pipeOptions: {name: 'number'}\n    }));\n  });\n});"
  },
  {
    "path": "apps/rxjs.dev/tools/transforms/angular-api-package/processors/filterContainedDocs.js",
    "content": "/**\n * Remove docs that are contained in (owned by) another doc\n * so that they don't get rendered as files in themselves.\n */\nmodule.exports = function filterContainedDocs() {\n  return {\n    docTypes: ['member', 'function-overload', 'get-accessor-info', 'set-accessor-info', 'parameter'],\n    $runAfter: ['extra-docs-added'],\n    $runBefore: ['computing-paths'],\n    $process: function(docs) {\n      var docTypes = this.docTypes;\n      return docs.filter(function(doc) {\n        return docTypes.indexOf(doc.docType) === -1;\n      });\n    }\n  };\n};\n"
  },
  {
    "path": "apps/rxjs.dev/tools/transforms/angular-api-package/processors/filterPrivateDocs.js",
    "content": "module.exports = function filterPrivateDocs() {\n  return {\n    $runAfter: ['extra-docs-added'],\n    $runBefore: ['computing-paths'],\n    $process: function(docs) {\n      return docs.filter(function(doc) { return doc.privateExport !== true; });\n    }\n  };\n};\n"
  },
  {
    "path": "apps/rxjs.dev/tools/transforms/angular-api-package/processors/filterPrivateDocs.spec.js",
    "content": "const testPackage = require('../../helpers/test-package');\nconst processorFactory = require('./filterPrivateDocs');\nconst Dgeni = require('dgeni');\n\ndescribe('filterPrivateDocs processor', () => {\n\n  it('should be available on the injector', () => {\n    const dgeni = new Dgeni([testPackage('angular-api-package')]);\n    const injector = dgeni.configureInjector();\n    const processor = injector.get('filterPrivateDocs');\n    expect(processor.$process).toBeDefined();\n  });\n\n  it('should run before the correct processor', () => {\n    const processor = processorFactory();\n    expect(processor.$runBefore).toEqual(['computing-paths']);\n  });\n\n  it('should run after the correct processor', () => {\n    const processor = processorFactory();\n    expect(processor.$runAfter).toEqual(['extra-docs-added']);\n  });\n\n  it('should remove docs that are marked as private exports', () => {\n    const processor = processorFactory();\n    const docs = [\n      { name: 'public1'},\n      { name: 'ɵPrivate1', privateExport: true },\n      { name: 'public2'},\n      { name: 'ɵPrivate2', privateExport: true },\n      { id: 'other'}\n    ];\n    const filteredDocs = processor.$process(docs);\n    expect(filteredDocs).toEqual([\n      { name: 'public1'},\n      { name: 'public2'},\n      { id: 'other'}\n    ]);\n  });\n});\n"
  },
  {
    "path": "apps/rxjs.dev/tools/transforms/angular-api-package/processors/generateApiListDoc.js",
    "content": "module.exports = function generateApiListDoc() {\n\n  return {\n    $runAfter: ['extra-docs-added'],\n    $runBefore: ['rendering-docs'],\n    outputFolder: null,\n    $validate: {outputFolder: {presence: true}},\n    $process: function(docs) {\n      docs.push({\n        docType: 'api-list-data',\n        template: 'json-doc.template.json',\n        path: this.outputFolder + '/api-list.json',\n        outputPath: this.outputFolder + '/api-list.json',\n        data: docs\n          .filter(doc => doc.docType === 'module')\n          .map(getModuleInfo)\n      });\n    }\n  };\n};\n\nfunction getModuleInfo(moduleDoc) {\n  const moduleName = moduleDoc.id.replace(/\\/index$/, '');\n  return {\n    name: moduleName.toLowerCase(),\n    title: moduleName,\n    items: moduleDoc.exports\n    // Ignore internals and private exports (indicated by the ɵ prefix)\n      .filter(doc => !doc.internal && !doc.privateExport)\n    // Ignore all renamed exports that are just duplicates of other docs\n      .filter(doc => !doc.duplicateOf)\n      .map(getExportInfo)\n      .sort((a, b) => a.name === b.name ? 0 : a.name > b.name ? 1 : -1)\n  };\n}\n\nfunction getExportInfo(exportDoc) {\n  return {\n    name: exportDoc.name.toLowerCase(),\n    title: exportDoc.name,\n    path: exportDoc.path,\n    docType: getDocType(exportDoc),\n    stability: getStability(exportDoc),\n    securityRisk: !!exportDoc.security\n  };\n}\n\nfunction getDocType(doc) {\n  // We map `let` and `var` types to `const`\n  if (['let', 'var'].indexOf(doc.docType) !== -1) {\n    return 'const';\n  }\n  return doc.docType;\n}\n\nconst stabilityProperties = ['stable', 'experimental', 'deprecated'];\nfunction getStability(doc) {\n  return stabilityProperties.find(prop => doc.hasOwnProperty(prop)) || '';\n}\n"
  },
  {
    "path": "apps/rxjs.dev/tools/transforms/angular-api-package/processors/generateApiListDoc.spec.js",
    "content": "const testPackage = require('../../helpers/test-package');\nconst processorFactory = require('./generateApiListDoc');\nconst Dgeni = require('dgeni');\n\ndescribe('generateApiListDoc processor', () => {\n\n  it('should be available on the injector', () => {\n    const dgeni = new Dgeni([testPackage('angular-api-package')]);\n    const injector = dgeni.configureInjector();\n    const processor = injector.get('generateApiListDoc');\n    expect(processor.$process).toBeDefined();\n  });\n\n  it('should run after the correct processor', () => {\n    const processor = processorFactory();\n    expect(processor.$runAfter).toEqual(['extra-docs-added']);\n  });\n\n  it('should run before the correct processor', () => {\n    const processor = processorFactory();\n    expect(processor.$runBefore).toEqual(['rendering-docs']);\n  });\n\n  it('should create a new api list doc', () => {\n    const processor = processorFactory();\n    const docs = [];\n    processor.outputFolder = 'test/path';\n    processor.$process(docs);\n    expect(docs[0]).toEqual({\n      docType: 'api-list-data',\n      template: 'json-doc.template.json',\n      path: 'test/path/api-list.json',\n      outputPath: 'test/path/api-list.json',\n      data: []\n    });\n  });\n\n  it('should add an info object to the doc for each module doc', () => {\n    const processor = processorFactory();\n    const docs = [\n      { docType: 'module', id: '@angular/common/index', exports: [] },\n      { docType: 'module', id: '@angular/core/index', exports: [] },\n      { docType: 'module', id: '@angular/http/index', exports: [] },\n    ];\n    processor.$process(docs);\n    expect(docs[3].data).toEqual([\n      { name: '@angular/common', title: '@angular/common', items: [] },\n      { name: '@angular/core', title: '@angular/core', items: [] },\n      { name: '@angular/http', title: '@angular/http', items: [] },\n    ]);\n  });\n\n  it('should add info about each export on each module', () => {\n    const processor = processorFactory();\n    const docs = [\n      { docType: 'module', id: '@angular/common/index', exports: [\n        { docType: 'directive', name: 'AaaAaa', path: 'aaa' },\n        { docType: 'pipe', name: 'BbbBbb', path: 'bbb' },\n        { docType: 'decorator', name: 'CccCcc', path: 'ccc' },\n        { docType: 'class', name: 'DddDdd', path: 'ddd' }\n      ] },\n      { docType: 'module', id: '@angular/core/index', exports: [\n        { docType: 'interface', name: 'EeeEee', path: 'eee' },\n        { docType: 'function', name: 'FffFff', path: 'fff' },\n        { docType: 'enum', name: 'GggGgg', path: 'ggg' },\n        { docType: 'type-alias', name: 'HhhHhh', path: 'hhh' },\n        { docType: 'const', name: 'IiiIii', path: 'iii' },\n      ] },\n    ];\n    processor.$process(docs);\n    expect(docs[2].data[0].items).toEqual([\n      { docType: 'directive', title: 'AaaAaa', name: 'aaaaaa', path: 'aaa', stability: '', securityRisk: false },\n      { docType: 'pipe', title: 'BbbBbb', name: 'bbbbbb', path: 'bbb', stability: '', securityRisk: false },\n      { docType: 'decorator', title: 'CccCcc', name: 'cccccc', path: 'ccc', stability: '', securityRisk: false },\n      { docType: 'class', title: 'DddDdd', name: 'dddddd', path: 'ddd', stability: '', securityRisk: false }\n    ]);\n    expect(docs[2].data[1].items).toEqual([\n      { docType: 'interface', title: 'EeeEee', name: 'eeeeee', path: 'eee', stability: '', securityRisk: false },\n      { docType: 'function', title: 'FffFff', name: 'ffffff', path: 'fff', stability: '', securityRisk: false },\n      { docType: 'enum', title: 'GggGgg', name: 'gggggg', path: 'ggg', stability: '', securityRisk: false },\n      { docType: 'type-alias', title: 'HhhHhh', name: 'hhhhhh', path: 'hhh', stability: '', securityRisk: false },\n      { docType: 'const', title: 'IiiIii', name: 'iiiiii', path: 'iii', stability: '', securityRisk: false },\n    ]);\n  });\n\n  it('should ignore internal and private exports', () => {\n    const processor = processorFactory();\n    const docs = [\n      { docType: 'module', id: '@angular/common/index', exports: [\n        { docType: 'directive', name: 'AaaAaa', path: 'aaa', internal: true },\n        { docType: 'class', name: 'XxxXxx', path: 'xxx', privateExport: true },\n        { docType: 'pipe', name: 'BbbBbb', path: 'bbb' }\n      ]}\n    ];\n    processor.$process(docs);\n    expect(docs[1].data[0].items).toEqual([\n      { docType: 'pipe', title: 'BbbBbb', name: 'bbbbbb', path: 'bbb', stability: '', securityRisk: false },\n    ]);\n  });\n\n  it('should convert `let` and `var` docTypes to `const`', () => {\n    const processor = processorFactory();\n    const docs = [\n      { docType: 'module', id: '@angular/common/index', exports: [\n        { docType: 'var', name: 'AaaAaa', path: 'aaa' },\n        { docType: 'let', name: 'BbbBbb', path: 'bbb' },\n      ]}\n    ];\n    processor.$process(docs);\n    expect(docs[1].data[0].items).toEqual([\n      { docType: 'const', title: 'AaaAaa', name: 'aaaaaa', path: 'aaa', stability: '', securityRisk: false },\n      { docType: 'const', title: 'BbbBbb', name: 'bbbbbb', path: 'bbb', stability: '', securityRisk: false },\n    ]);\n  });\n\n  it('should convert security to a boolean securityRisk', () => {\n    const processor = processorFactory();\n    const docs = [\n      { docType: 'module', id: '@angular/common/index', exports: [\n        { docType: 'class', name: 'AaaAaa', path: 'aaa', security: 'This is a security risk' },\n        { docType: 'class', name: 'BbbBbb', path: 'bbb', security: '' },\n      ]}\n    ];\n    processor.$process(docs);\n    expect(docs[1].data[0].items).toEqual([\n      { docType: 'class', title: 'AaaAaa', name: 'aaaaaa', path: 'aaa', stability: '', securityRisk: true },\n      { docType: 'class', title: 'BbbBbb', name: 'bbbbbb', path: 'bbb', stability: '', securityRisk: false },\n    ]);\n  });\n\n  it('should convert stability tags to the stable string property', () => {\n    const processor = processorFactory();\n    const docs = [\n      { docType: 'module', id: '@angular/common/index', exports: [\n        { docType: 'class', name: 'AaaAaa', path: 'aaa', stable: undefined },\n        { docType: 'class', name: 'BbbBbb', path: 'bbb', experimental: 'Some message' },\n        { docType: 'class', name: 'CccCcc', path: 'ccc', deprecated: null },\n        { docType: 'class', name: 'DddDdd', path: 'ddd' },\n      ]}\n    ];\n    processor.$process(docs);\n    expect(docs[1].data[0].items).toEqual([\n      { docType: 'class', title: 'AaaAaa', name: 'aaaaaa', path: 'aaa', stability: 'stable', securityRisk: false },\n      { docType: 'class', title: 'BbbBbb', name: 'bbbbbb', path: 'bbb', stability: 'experimental', securityRisk: false },\n      { docType: 'class', title: 'CccCcc', name: 'cccccc', path: 'ccc', stability: 'deprecated', securityRisk: false },\n      { docType: 'class', title: 'DddDdd', name: 'dddddd', path: 'ddd', stability: '', securityRisk: false },\n    ]);\n  });\n\n  it('should sort items in each group alphabetically', () => {\n    const processor = processorFactory();\n    const docs = [\n      { docType: 'module', id: '@angular/common/index', exports: [\n        { docType: 'class', name: 'DddDdd', path: 'uuu' },\n        { docType: 'class', name: 'BbbBbb', path: 'vvv' },\n        { docType: 'class', name: 'AaaAaa', path: 'xxx' },\n        { docType: 'class', name: 'CccCcc', path: 'yyy' },\n      ]}\n    ];\n    processor.$process(docs);\n    expect(docs[1].data[0].items).toEqual([\n      { docType: 'class', title: 'AaaAaa', name: 'aaaaaa', path: 'xxx', stability: '', securityRisk: false },\n      { docType: 'class', title: 'BbbBbb', name: 'bbbbbb', path: 'vvv', stability: '', securityRisk: false },\n      { docType: 'class', title: 'CccCcc', name: 'cccccc', path: 'yyy', stability: '', securityRisk: false },\n      { docType: 'class', title: 'DddDdd', name: 'dddddd', path: 'uuu', stability: '', securityRisk: false },\n    ]);\n  });\n\n  it('should remove duplicate exports', () => {\n    const origDoc = { docType: 'class', name: 'DddDdd', path: 'uuu' };\n    const duplicatedDoc = { docType: 'class', name: 'BbbBbb', path: 'vvv', duplicateOf: origDoc };\n    origDoc.renamedDuplicates = [duplicatedDoc];\n\n    const processor = processorFactory();\n    const docs = [\n      { docType: 'module', id: '@angular/common/index', exports: [\n        origDoc,\n        duplicatedDoc,\n        { docType: 'class', name: 'AaaAaa', path: 'xxx' },\n        { docType: 'class', name: 'CccCcc', path: 'yyy' },\n      ]}\n    ];\n    processor.$process(docs);\n    expect(docs[1].data[0].items).toEqual([\n      { docType: 'class', title: 'AaaAaa', name: 'aaaaaa', path: 'xxx', stability: '', securityRisk: false },\n      { docType: 'class', title: 'CccCcc', name: 'cccccc', path: 'yyy', stability: '', securityRisk: false },\n      { docType: 'class', title: 'DddDdd', name: 'dddddd', path: 'uuu', stability: '', securityRisk: false },\n    ]);\n  });\n});\n\n"
  },
  {
    "path": "apps/rxjs.dev/tools/transforms/angular-api-package/processors/generateDeprecationsListDoc.js",
    "content": "module.exports = function generateDeprecationListDoc() {\n\n  return {\n    $runAfter: ['extra-docs-added'],\n    $runBefore: ['rendering-docs'],\n    outputFolder: null,\n    $process: function(docs) {\n      docs.push({\n        docType: 'deprecation',\n        template: 'json-doc.template.json',\n        path: this.outputFolder + '/deprecations',\n        outputPath: this.outputFolder + '/deprecations.json',\n        data: docs\n          .filter(doc => doc.deprecated)\n          .map(doc => {\n            return {\n              name: doc.name,\n              type: doc.docType,\n              path: doc.path,\n              text: doc.deprecated\n            };\n          })\n      });\n    }\n  };\n};"
  },
  {
    "path": "apps/rxjs.dev/tools/transforms/angular-api-package/processors/markAliases.spec.ts",
    "content": "import { Dgeni, Document, DocCollection } from 'dgeni';\nimport { Injector } from 'dgeni/lib/Injector';\nimport { ReadTypeScriptModules } from 'dgeni-packages/typescript/processors/readTypeScriptModules';\nimport * as path from 'path';\nimport 'jasmine';\n\nimport * as testPackage from '../../helpers/test-package';\nimport { markAliases } from './markAliases';\n\ndescribe('markAliases processor', () => {\n  let dgeni: Dgeni;\n  let injector: Injector;\n  let readTypescript: ReadTypeScriptModules;\n\n  beforeEach(() => {\n    dgeni = new Dgeni([testPackage('angular-api-package')]);\n    injector = dgeni.configureInjector();\n    readTypescript = injector.get('readTypeScriptModules');\n\n    readTypescript.basePath = path.resolve(__dirname, '../mocks');\n    readTypescript.sourceFiles = [\n      'aliasedExports.ts'\n    ];\n  });\n\n  it('should be available on the injector', () => {\n    const processor = injector.get('markAliases');\n    expect(processor.$process).toBeDefined();\n  });\n\n  it('should mark aliased exports and remove the aliased doc', () => {\n    const exportedDocs: DocCollection = [];\n    const moduleDoc = {\n      docType: 'module', exports: exportedDocs,\n    };\n    exportedDocs.push(\n      { docType: 'class', id: 'class-1', moduleDoc: moduleDoc, name: 'aliased-name',\n        aliasSymbol: { escapedName: 'aliased-name', resolvedSymbol: { escapedName: 'original-name' } }\n      },\n      { docType: 'class', id: 'class-2', moduleDoc: moduleDoc, name: 'original-name',\n        aliasSymbol: { escapedName: 'original-name', resolvedSymbol: { escapedName: 'original-name' } }\n      },\n      { docType: 'guide', id: 'guide-1', moduleDoc: moduleDoc, name: 'guide',\n        aliasSymbol: { escapedName: 'guide', resolvedSymbol: { escapedName: 'guide' } }\n      },\n    );\n    const docs = [\n      moduleDoc,\n      ...exportedDocs,\n    ];\n\n    const processor = markAliases(console);\n    processor.$process(docs);\n\n    const originalDoc = docs.find((doc: Document) => doc.name === 'original-name');\n    const duplicateNames = originalDoc.renamedDuplicates.map((doc: Document) => doc.name);\n    expect(duplicateNames).toEqual(['aliased-name']);\n    expect(originalDoc).toBe(originalDoc.renamedDuplicates[0].duplicateOf);\n  });\n\n  it('should mark aliased exports and remove the aliased doc from a mock file', () => {\n    const processor = markAliases(console);\n    let docs: DocCollection = [];\n    readTypescript.$process(docs);\n    processor.$process(docs);\n\n    const originalDoc = docs.find((doc: Document) => doc.name === 'operator');\n    const duplicateNames = originalDoc.renamedDuplicates.map((doc: Document) => doc.name);\n    expect(duplicateNames).toEqual(['aliasedOperator']);\n    expect(originalDoc).toBe(originalDoc.renamedDuplicates[0].duplicateOf);\n  });\n\n  it('should leave non duplicate exports unmarked', () => {\n    const processor = markAliases(console);\n    let docs: DocCollection = [];\n    readTypescript.$process(docs);\n    processor.$process(docs);\n\n    const nonDuplicateOperator = docs.find((doc: Document) => doc.name === 'operatorWithoutDuplicate');\n    expect(nonDuplicateOperator.renamedDuplicates).toBeUndefined();\n  });\n});\n"
  },
  {
    "path": "apps/rxjs.dev/tools/transforms/angular-api-package/processors/markAliases.ts",
    "content": "import { DocCollection, Document, Processor } from 'dgeni';\n\nexport function markAliases(log: any): MarkAliases {\n  return new MarkAliases(log);\n}\n\nconst getOriginalName = (doc: Document): string => doc.aliasSymbol.resolvedSymbol.escapedName;\n\nclass MarkAliases implements Processor {\n  $runAfter = ['readTypeScriptModules'];\n  $runBefore = ['generateApiListDoc', 'createSitemap'];\n\n  constructor(\n    private log: any,\n  ) {\n  }\n\n  $process(docs: DocCollection): void {\n    docs\n      .filter((doc: Document) => doc.moduleDoc)\n      .forEach((doc: Document) => {\n        const duplicateDocs = this.findDuplicateDocs(doc);\n\n        if (duplicateDocs.length > 0) {\n          duplicateDocs.forEach((duplicateDoc: Document) => duplicateDoc.duplicateOf = doc);\n          doc.renamedDuplicates = duplicateDocs;\n\n          this.log.debug(`${doc.name} has the following aliases:`,\n            duplicateDocs.map((doc: Document) => doc.name).join(', '));\n        }\n      });\n  }\n\n  private findDuplicateDocs(doc: Document): DocCollection {\n    return doc.moduleDoc.exports\n      .filter((exportedDoc: Document) => exportedDoc !== doc\n        && exportedDoc.aliasSymbol\n        && getOriginalName(exportedDoc) === doc.name\n      );\n  }\n}\n"
  },
  {
    "path": "apps/rxjs.dev/tools/transforms/angular-api-package/processors/markBarredODocsAsPrivate.js",
    "content": "module.exports = function markBarredODocsAsPrivate() {\n  return {\n    $runAfter: ['readTypeScriptModules'],\n    $runBefore: ['adding-extra-docs'],\n    $process: function(docs) {\n      docs.forEach(doc => {\n        if (doc.name && doc.name.indexOf('ɵ') === 0) {\n          doc.privateExport = true;\n        }\n      });\n    }\n  };\n};\n"
  },
  {
    "path": "apps/rxjs.dev/tools/transforms/angular-api-package/processors/markBarredODocsAsPrivate.spec.js",
    "content": "const testPackage = require('../../helpers/test-package');\nconst processorFactory = require('./markBarredODocsAsPrivate');\nconst Dgeni = require('dgeni');\n\ndescribe('markBarredODocsAsPrivate processor', () => {\n\n  it('should be available on the injector', () => {\n    const dgeni = new Dgeni([testPackage('angular-api-package')]);\n    const injector = dgeni.configureInjector();\n    const processor = injector.get('markBarredODocsAsPrivate');\n    expect(processor.$process).toBeDefined();\n    expect(processor.$runAfter).toContain('readTypeScriptModules');\n    expect(processor.$runBefore).toContain('adding-extra-docs');\n  });\n\n  it('should mark docs starting with barred-o ɵ as private', () => {\n    const processor = processorFactory();\n    const docs = [\n      { name: 'ɵPrivate' },\n      { name: 'public' }\n    ];\n    processor.$process(docs);\n\n    expect(docs[0].privateExport).toBeTruthy();\n    expect(docs[1].privateExport).toBeFalsy();\n  });\n});\n\n"
  },
  {
    "path": "apps/rxjs.dev/tools/transforms/angular-api-package/processors/matchUpDirectiveDecorators.js",
    "content": "/**\n * @dgProcessor\n * @description\n * Directives in Angular are specified by various decorators. In particular the `@Directive()`\n * decorator on the class and various other property decorators, such as `@Input`.\n *\n * This processor will extract this decorator information and attach it as properties to the\n * directive document.\n *\n * Notably, the `input` and `output` binding information can be specified\n * either via property decorators (`@Input()`/`@Output()`) or by properties on the metadata\n * passed to the `@Directive` decorator. This processor will collect up info from both and\n * merge them.\n */\nmodule.exports = function matchUpDirectiveDecorators() {\n  return {\n    $runAfter: ['ids-computed', 'paths-computed'],\n    $runBefore: ['rendering-docs'],\n    $process: function(docs) {\n      docs.forEach(function(doc) {\n        if (doc.docType === 'directive') {\n\n          doc.selector = stripQuotes(doc.directiveOptions.selector);\n          doc.exportAs = stripQuotes(doc.directiveOptions.exportAs);\n\n          doc.inputs = getBindingInfo(doc.directiveOptions.inputs, doc.members, 'Input');\n          doc.outputs = getBindingInfo(doc.directiveOptions.outputs, doc.members, 'Output');\n        }\n      });\n    }\n  };\n};\n\nfunction getBindingInfo(directiveBindings, members, bindingType) {\n  const bindings = {};\n\n  // Parse the bindings from the directive decorator\n  if (directiveBindings) {\n    directiveBindings.forEach(function(binding) {\n      const bindingInfo = parseBinding(binding);\n      bindings[bindingInfo.propertyName] = bindingInfo;\n    });\n  }\n\n  if (members) {\n    members.forEach(function(member) {\n      if (member.decorators) {\n        // Search for members with binding decorators\n        member.decorators.forEach(function(decorator) {\n          if (decorator.name === bindingType) {\n            bindings[member.name] = createBindingInfo(member.name, decorator.arguments[0] || member.name);\n          }\n        });\n      }\n\n      // Now ensure that any bindings have the associated member attached\n      // Note that this binding could have come from the directive decorator\n      if (bindings[member.name]) {\n        bindings[member.name].memberDoc = member;\n      }\n    });\n  }\n\n  // Convert the map back to an array\n  return Object.keys(bindings).map(function(key) { return bindings[key]; });\n}\n\nfunction stripQuotes(value) {\n  return (typeof(value) === 'string') ? value.trim().replace(/^(['\"])(.*)\\1$/, '$2') : value;\n}\n\nfunction parseBinding(option) {\n  // Directive decorator bindings are of the form: \"propName : bindingName\" (bindingName is optional)\n  const optionPair = option.split(':');\n  const propertyName = optionPair[0].trim();\n  const bindingName = (optionPair[1] || '').trim() || propertyName;\n  return createBindingInfo(propertyName, bindingName);\n}\n\nfunction createBindingInfo(propertyName, bindingName) {\n  return {\n    propertyName: stripQuotes(propertyName),\n    bindingName: stripQuotes(bindingName)\n  };\n}"
  },
  {
    "path": "apps/rxjs.dev/tools/transforms/angular-api-package/processors/matchUpDirectiveDecorators.spec.js",
    "content": "const testPackage = require('../../helpers/test-package');\nconst processorFactory = require('./matchUpDirectiveDecorators');\nconst Dgeni = require('dgeni');\n\ndescribe('matchUpDirectiveDecorators processor', () => {\n\n  it('should be available on the injector', () => {\n    const dgeni = new Dgeni([testPackage('angular-api-package')]);\n    const injector = dgeni.configureInjector();\n    const processor = injector.get('matchUpDirectiveDecorators');\n    expect(processor.$process).toBeDefined();\n    expect(processor.$runAfter).toContain('ids-computed');\n    expect(processor.$runAfter).toContain('paths-computed');\n    expect(processor.$runBefore).toContain('rendering-docs');\n  });\n\n  it('should extract selector and exportAs from the directive decorator on directive docs', () => {\n    const docs = [{\n      docType: 'directive',\n      directiveOptions: { selector: 'a,b,c', exportAs: 'someExport' }\n    }];\n    processorFactory().$process(docs);\n    expect(docs[0].selector).toEqual('a,b,c');\n    expect(docs[0].exportAs).toEqual('someExport');\n  });\n\n  it('should ignore properties from the directive decorator on non-directive docs', () => {\n    const docs = [{\n      docType: 'class',\n      directiveOptions: { selector: 'a,b,c', exportAs: 'someExport' }\n    }];\n    processorFactory().$process(docs);\n    expect(docs[0].selector).toBeUndefined();\n    expect(docs[0].exportAs).toBeUndefined();\n  });\n\n  it('should strip whitespace and quotes off directive properties', () => {\n    const docs = [\n      {\n        docType: 'directive',\n        directiveOptions: { selector: '\"a,b,c\"', exportAs: '\\'someExport\\'' }\n      },\n      {\n        docType: 'directive',\n        directiveOptions: { selector: ' a,b,c  ', exportAs: '  someExport  ' }\n      },\n      {\n        docType: 'directive',\n        directiveOptions: { selector: ' \"a,b,c\"  ', exportAs: '  \\'someExport\\'  ' }\n      }\n    ];\n    processorFactory().$process(docs);\n    expect(docs[0].selector).toEqual('a,b,c');\n    expect(docs[0].exportAs).toEqual('someExport');\n    expect(docs[1].selector).toEqual('a,b,c');\n    expect(docs[1].exportAs).toEqual('someExport');\n    expect(docs[2].selector).toEqual('a,b,c');\n    expect(docs[2].exportAs).toEqual('someExport');\n  });\n\n  it('should extract inputs and outputs from the directive decorator', () => {\n    const docs = [{\n      docType: 'directive',\n      directiveOptions: {\n        inputs: ['in1:in2', 'in3', '  in4:in5  ', '  in6  '],\n        outputs: ['out1:out1', '  out2:out3  ', '  out4  ']\n      },\n      members: [\n        { name: 'in1' },\n        { name: 'in3' },\n        { name: 'in4' },\n        { name: 'in6' },\n        { name: 'out1' },\n        { name: 'out2' },\n        { name: 'out4' }\n      ]\n    }];\n    processorFactory().$process(docs);\n    expect(docs[0].inputs).toEqual([\n      { propertyName: 'in1', bindingName: 'in2', memberDoc: docs[0].members[0] },\n      { propertyName: 'in3', bindingName: 'in3', memberDoc: docs[0].members[1] },\n      { propertyName: 'in4', bindingName: 'in5', memberDoc: docs[0].members[2] },\n      { propertyName: 'in6', bindingName: 'in6', memberDoc: docs[0].members[3] }\n    ]);\n\n    expect(docs[0].outputs).toEqual([\n      { propertyName: 'out1', bindingName: 'out1', memberDoc: docs[0].members[4] },\n      { propertyName: 'out2', bindingName: 'out3', memberDoc: docs[0].members[5] },\n      { propertyName: 'out4', bindingName: 'out4', memberDoc: docs[0].members[6] }\n    ]);\n  });\n\n  it('should extract inputs and outputs from decorated properties', () => {\n    const docs = [{\n      docType: 'directive',\n      directiveOptions: {},\n      members: [\n        { name: 'a1', decorators: [{ name: 'Input', arguments: ['a2'] }] },\n        { name: 'b1', decorators: [{ name: 'Output', arguments: ['b2'] }] },\n        { name: 'c1', decorators: [{ name: 'Input', arguments: [] }] },\n        { name: 'd1', decorators: [{ name: 'Output', arguments: [] }] },\n      ]\n    }];\n    processorFactory().$process(docs);\n    expect(docs[0].inputs).toEqual([\n      { propertyName: 'a1', bindingName: 'a2', memberDoc: docs[0].members[0] },\n      { propertyName: 'c1', bindingName: 'c1', memberDoc: docs[0].members[2] }\n    ]);\n\n    expect(docs[0].outputs).toEqual([\n      { propertyName: 'b1', bindingName: 'b2', memberDoc: docs[0].members[1] },\n      { propertyName: 'd1', bindingName: 'd1', memberDoc: docs[0].members[3] }\n    ]);\n  });\n\n  it('should merge directive inputs/outputs with decorator property inputs/outputs', () => {\n    const docs = [{\n      docType: 'directive',\n      directiveOptions: {\n        inputs: ['a1:a2'],\n        outputs: ['b1:b2']\n      },\n      members: [\n        { name: 'a1' },\n        { name: 'a3', decorators: [{ name: 'Input', arguments: ['a4'] }] },\n        { name: 'b1' },\n        { name: 'b3', decorators: [{ name: 'Output', arguments: ['b4'] }] },\n      ]\n    }];\n    processorFactory().$process(docs);\n    expect(docs[0].inputs).toEqual([\n      { propertyName: 'a1', bindingName: 'a2', memberDoc: docs[0].members[0] },\n      { propertyName: 'a3', bindingName: 'a4', memberDoc: docs[0].members[1] }\n    ]);\n\n    expect(docs[0].outputs).toEqual([\n      { propertyName: 'b1', bindingName: 'b2', memberDoc: docs[0].members[2] },\n      { propertyName: 'b3', bindingName: 'b4', memberDoc: docs[0].members[3] }\n    ]);\n  });\n});\n"
  },
  {
    "path": "apps/rxjs.dev/tools/transforms/angular-api-package/processors/mergeDecoratorDocs.js",
    "content": "/**\n * Decorators in the Angular code base are made up from three code items:\n *\n * 1) An interface that represents the call signature of the decorator. E.g.\n *\n *   ```\n *   export interface ComponentDecorator {\n *     (obj: Component): TypeDecorator;\n *     new (obj: Component): Component;\n *   }\n *   ```\n *\n * 2) An interface that represents the members of the object that should be passed\n *   into the decorator. E.g.\n *\n *   ```\n *   export interface Component extends Directive {\n *     changeDetection?: ChangeDetectionStrategy;\n *     viewProviders?: Provider[];\n *     templateUrl?: string;\n *     ...\n *   }\n *   ```\n *\n * 3) A constant that is created by a call to a generic function, whose type parameter is\n *   the call signature interface of the decorator. E.g.\n *\n *   ```\n *   export const Component: ComponentDecorator =\n *     <ComponentDecorator>makeDecorator('Component', { ... }, Directive)\n *   ```\n *\n * This processor searches for these constants (3) by looking for a call to\n * `make...Decorator(...)`. (There are variations to the call for property and param\n * decorators). From this call we identify the `decoratorType` (e.g. `ComponentDecorator`).\n *\n * Calls to `make...Decorator<X>` will return an object of type X. This type is the document\n * referred to in (2). This is the primary doc that we care about for documenting the decorator.\n * It holds all of the members of the metadata that is passed to the decorator call.\n *\n * Finally we want to capture the documentation attached to the call signature interface of the\n * associated decorator (1). We copy across the properties that we care about from this call\n * signature (e.g. description, whatItDoes and howToUse).\n */\n\nmodule.exports = function mergeDecoratorDocs(log) {\n  return {\n    $runAfter: ['processing-docs'],\n    $runBefore: ['docs-processed'],\n    makeDecoratorCalls: [\n      {type: '', description: 'toplevel', functionName: 'makeDecorator'},\n      {type: 'Prop', description: 'property', functionName: 'makePropDecorator'},\n      {type: 'Param', description: 'parameter', functionName: 'makeParamDecorator'},\n    ],\n    $process: function(docs) {\n\n      var makeDecoratorCalls = this.makeDecoratorCalls;\n      var docsToMerge = Object.create(null);\n\n      docs.forEach(function(doc) {\n        const initializer = getInitializer(doc);\n        if (initializer) {\n          makeDecoratorCalls.forEach(function(call) {\n            // find all the decorators, signified by a call to `make...Decorator<Decorator>(metadata)`\n            if (initializer.expression && initializer.expression.text === call.functionName) {\n              log.debug('mergeDecoratorDocs: found decorator', doc.docType, doc.name);\n              doc.docType = 'decorator';\n              doc.decoratorLocation = call.description;\n              // Get the type of the decorator metadata from the first \"type\" argument of the call.\n              // For example the `X` of `createDecorator<X>(...)`.\n              doc.decoratorType = initializer.arguments[0].text;\n              // clear the symbol type named since it is not needed\n              doc.symbolTypeName = undefined;\n\n              // keep track of the names of the metadata interface that will need to be merged into this decorator doc\n              docsToMerge[doc.name + 'Decorator'] = doc;\n            }\n          });\n        }\n      });\n\n      // merge the metadata docs into the decorator docs\n      docs = docs.filter(function(doc) {\n        if (docsToMerge[doc.name]) {\n          // We have found an `XxxDecorator` document that will hold the call signature of the decorator\n          var decoratorDoc = docsToMerge[doc.name];\n          var callMember = doc.members.filter(function(member) { return member.isCallMember; })[0];\n          log.debug(\n            'mergeDecoratorDocs: merging', doc.name, 'into', decoratorDoc.name,\n            callMember.description.substring(0, 50));\n          // Merge the documentation found in this call signature into the original decorator\n          decoratorDoc.description = callMember.description;\n          decoratorDoc.howToUse = callMember.howToUse;\n          decoratorDoc.whatItDoes = callMember.whatItDoes;\n\n          // remove doc from its module doc's exports\n          doc.moduleDoc.exports =\n              doc.moduleDoc.exports.filter(function(exportDoc) { return exportDoc !== doc; });\n\n\n          // remove from the overall list of docs to be rendered\n          return false;\n        }\n        return true;\n      });\n    }\n  };\n};\n\nfunction getInitializer(doc) {\n  var initializer = doc.symbol && doc.symbol.valueDeclaration && doc.symbol.valueDeclaration.initializer;\n  // There appear to be two forms of initializer:\n  //    export var Injectable: InjectableFactory =\n  //    <InjectableFactory>makeDecorator(InjectableMetadata);\n  // and\n  //    export var RouteConfig: (configs: RouteDefinition[]) => ClassDecorator =\n  //    makeDecorator(RouteConfigAnnotation);\n  // In the first case, the type assertion `<InjectableFactory>` causes the AST to contain an\n  // extra level of expression\n  // to hold the new type of the expression.\n  if (initializer && initializer.expression && initializer.expression.expression) {\n    initializer = initializer.expression;\n  }\n  return initializer;\n}\n"
  },
  {
    "path": "apps/rxjs.dev/tools/transforms/angular-api-package/processors/mergeDecoratorDocs.spec.js",
    "content": "var testPackage = require('../../helpers/test-package');\nvar Dgeni = require('dgeni');\n\ndescribe('mergeDecoratorDocs processor', () => {\n  let processor, moduleDoc, decoratorDoc, metadataDoc, otherDoc;\n\n  beforeEach(() => {\n    const dgeni = new Dgeni([testPackage('angular-api-package')]);\n    const injector = dgeni.configureInjector();\n    processor = injector.get('mergeDecoratorDocs');\n\n    moduleDoc = {};\n\n    decoratorDoc = {\n      name: 'Component',\n      docType: 'const',\n      description: 'A description of the metadata for the Component decorator',\n      symbol: {\n        valueDeclaration: { initializer: { expression: { text: 'makeDecorator' }, arguments: [{ text: 'X' }] } }\n      },\n      members: [\n        { name: 'templateUrl', description: 'A description of the templateUrl property' }\n      ],\n      moduleDoc\n    };\n\n    metadataDoc = {\n      name: 'ComponentDecorator',\n      docType: 'interface',\n      description: 'A description of the interface for the call signature for the Component decorator',\n      members: [\n        {\n          isCallMember: true,\n          description: 'The actual description of the call signature',\n          whatItDoes: 'Does something cool...',\n          howToUse: 'Use it like this...'\n        },\n        {\n          description: 'Some other member'\n        }\n      ],\n      moduleDoc\n    };\n\n    otherDoc = {\n      name: 'Y',\n      docType: 'const',\n      symbol: {\n        valueDeclaration: { initializer: { expression: { text: 'otherCall' }, arguments: [{ text: 'param1' }] } }\n      },\n      moduleDoc\n    };\n\n    moduleDoc.exports = [decoratorDoc, metadataDoc, otherDoc];\n  });\n\n\n  it('should change the docType of only the docs that are initialized by a call to makeDecorator', () => {\n    processor.$process([decoratorDoc, metadataDoc, otherDoc]);\n    expect(decoratorDoc.docType).toEqual('decorator');\n    expect(otherDoc.docType).toEqual('const');\n  });\n\n  it('should extract the \"type\" of the decorator meta data', () => {\n    processor.$process([decoratorDoc, metadataDoc, otherDoc]);\n    expect(decoratorDoc.decoratorType).toEqual('X');\n  });\n\n  it('should copy across properties from the call signature doc', () => {\n    processor.$process([decoratorDoc, metadataDoc, otherDoc]);\n    expect(decoratorDoc.description).toEqual('The actual description of the call signature');\n    expect(decoratorDoc.whatItDoes).toEqual('Does something cool...');\n    expect(decoratorDoc.howToUse).toEqual('Use it like this...');\n  });\n\n  it('should remove the metadataDoc from the module exports', () => {\n    processor.$process([decoratorDoc, metadataDoc, otherDoc]);\n    expect(moduleDoc.exports).not.toContain(metadataDoc);\n  });\n\n  it('should cope with decorators that have type params', () => {\n    decoratorDoc.symbol.valueDeclaration.initializer.expression.type = {};\n    processor.$process([decoratorDoc, metadataDoc, otherDoc]);\n    expect(decoratorDoc.docType).toEqual('decorator');\n  });\n});\n"
  },
  {
    "path": "apps/rxjs.dev/tools/transforms/angular-api-package/processors/migrateLegacyJSDocTags.js",
    "content": "module.exports = function migrateLegacyJSDocTags(log, createDocMessage) {\n  return {\n    $runAfter: ['tags-extracted'],\n    $runBefore: ['processing-docs'],\n    $process(docs) {\n      let migrated = false;\n      docs.forEach(doc => {\n        if (doc.howToUse) {\n          if (doc.usageNotes) {\n            throw new Error(createDocMessage('`@usageNotes` and the deprecated `@howToUse` are not allowed on the same doc', doc));\n          }\n          log.debug(createDocMessage('Using deprecated `@howToUse` tag as though it was `@usageNotes` tag', doc));\n          doc.usageNotes = doc.howToUse;\n          doc.howToUse = null;\n          migrated = true;\n        }\n\n        if (doc.whatItDoes) {\n          log.debug(createDocMessage('Merging the content of `@whatItDoes` tag into the description.', doc));\n          if (doc.description) {\n            doc.description = `${doc.whatItDoes}\\n\\n${doc.description}`;\n          } else {\n            doc.description = doc.whatItDoes;\n          }\n          doc.whatItDoes = null;\n          migrated = true;\n        }\n      });\n\n      if (migrated) {\n        log.warn('Some deprecated tags were migrated.');\n        log.warn('This automatic handling will be removed in a future version of the doc generation.\\n');\n      }\n    }\n  };\n};\n"
  },
  {
    "path": "apps/rxjs.dev/tools/transforms/angular-api-package/processors/migrateLegacyJSDocTags.spec.js",
    "content": "const testPackage = require('../../helpers/test-package');\nconst processorFactory = require('./migrateLegacyJSDocTags');\nconst log = require('dgeni/lib/mocks/log')(false);\nconst createDocMessage = require('dgeni-packages/base/services/createDocMessage')();\nconst Dgeni = require('dgeni');\n\ndescribe('migrateLegacyJSDocTags processor', () => {\n\n  it('should be available on the injector', () => {\n    const dgeni = new Dgeni([testPackage('angular-api-package')]);\n    const injector = dgeni.configureInjector();\n    const processor = injector.get('migrateLegacyJSDocTags');\n    expect(processor.$process).toBeDefined();\n  });\n\n  it('should run before the correct processor', () => {\n    const processor = processorFactory(log, createDocMessage);\n    expect(processor.$runBefore).toEqual(['processing-docs']);\n  });\n\n  it('should run after the correct processor', () => {\n    const processor = processorFactory(log, createDocMessage);\n    expect(processor.$runAfter).toEqual(['tags-extracted']);\n  });\n\n  it('should migrate `howToUse` property to `usageNotes` property', () => {\n    const processor = processorFactory(log, createDocMessage);\n    const docs = [\n      { howToUse: 'this is how to use it' }\n    ];\n    processor.$process(docs);\n    expect(docs[0].howToUse).toBe(null);\n    expect(docs[0].usageNotes).toEqual('this is how to use it');\n  });\n\n  it('should migrate `whatItDoes` property to the `description`', () => {\n    const processor = processorFactory(log, createDocMessage);\n    const docs = [\n      { whatItDoes: 'what it does' },\n      { whatItDoes: 'what it does', description: 'the description' },\n      { description: 'the description' }\n    ];\n    processor.$process(docs);\n    expect(docs[0].whatItDoes).toBe(null);\n    expect(docs[0].description).toEqual('what it does');\n\n    expect(docs[1].whatItDoes).toBe(null);\n    expect(docs[1].description).toEqual('what it does\\n\\nthe description');\n\n    expect(docs[2].whatItDoes).toBeUndefined();\n    expect(docs[2].description).toEqual('the description');\n  });\n\n  it('should ignore docs that have neither `howToUse` nor `whatItDoes` properties', () => {\n    const processor = processorFactory(log, createDocMessage);\n    const docs = [\n      { },\n      { description: 'the description' }\n    ];\n    processor.$process(docs);\n    expect(docs).toEqual([\n      { },\n      { description: 'the description' }\n    ]);\n  });\n});"
  },
  {
    "path": "apps/rxjs.dev/tools/transforms/angular-api-package/processors/processClassLikeMembers.js",
    "content": "/**\n * A class like API doc contains members, but these can be either properties or method.\n * Separate the members into two new collections: `doc.properties` and `doc.methods`.\n */\nmodule.exports = function processClassLikeMembers() {\n  return {\n    $runAfter: ['filterContainedDocs'],\n    $runBefore: ['rendering-docs'],\n    $process(docs) {\n      docs.forEach(doc => {\n        if (doc.members) {\n          doc.properties = [];\n          doc.methods = [];\n          doc.members.forEach(member => {\n            if (isMethod(member)) {\n              doc.methods.push(member);\n              computeMemberDescription(member);\n            } else {\n              doc.properties.push(member);\n\n              if (!member.description) {\n                // Is this property defined as a constructor parameter e.g. `constructor(public property: string) { ... }`?\n                const constructorDoc = member.containerDoc.constructorDoc;\n                if (constructorDoc) {\n                  const matchingParameterDoc = constructorDoc.parameterDocs.filter(doc => doc.declaration === member.declaration)[0];\n                  member.constructorParamDoc = matchingParameterDoc;\n                }\n              }\n            }\n          });\n        }\n        if (doc.statics) {\n          doc.staticProperties = [];\n          doc.staticMethods = [];\n          doc.statics.forEach(member => {\n            if (isMethod(member)) {\n              doc.staticMethods.push(member);\n              computeMemberDescription(member);\n            } else {\n              doc.staticProperties.push(member);\n            }\n          });\n        }\n\n      });\n    }\n  };\n};\n\nfunction isMethod(doc) {\n  return doc.hasOwnProperty('parameters') && !doc.isGetAccessor && !doc.isSetAccessor;\n}\n\nfunction computeMemberDescription(member) {\n  if (!member.description && member.overloads) {\n    // Perhaps the description is on one of the overloads - take the first non-empty one\n    member.description = member.overloads.map(overload => overload.description).filter(description => !!description)[0];\n  }\n}"
  },
  {
    "path": "apps/rxjs.dev/tools/transforms/angular-api-package/processors/processClassLikeMembers.spec.js",
    "content": "const testPackage = require('../../helpers/test-package');\nconst processorFactory = require('./processClassLikeMembers');\nconst Dgeni = require('dgeni');\n\nconst property1 = { description: 'property 1' };\nconst property2 = { description: 'property 2' };\nconst getter1 = { parameters: [], isGetAccessor: true, description: 'getter 1' };\nconst setter1 = { parameters: [], isSetAccessor: true, description: 'setter 1' };\nconst method1 = { parameters: [] };\nconst method2 = { parameters: [] };\nconst method3 = { parameters: [] };\n\ndescribe('angular-api-package: processClassLikeMembers processor', () => {\n\n  it('should be available on the injector', () => {\n    const dgeni = new Dgeni([testPackage('angular-api-package')]);\n    const injector = dgeni.configureInjector();\n    const processor = injector.get('processClassLikeMembers');\n    expect(processor.$process).toBeDefined();\n    expect(processor.$runAfter).toEqual(['filterContainedDocs']);\n    expect(processor.$runBefore).toEqual(['rendering-docs']);\n  });\n\n  it('should copy instance members into properties and methods', () => {\n    const processor = processorFactory();\n    const docs = [\n      { members: [ property1, method1, getter1] },\n      { members: [ method2, property2, method3, setter1] },\n      { }\n    ];\n    processor.$process(docs);\n\n    expect(docs[0].properties).toEqual([property1, getter1]);\n    expect(docs[0].methods).toEqual([method1]);\n\n    expect(docs[1].properties).toEqual([property2, setter1]);\n    expect(docs[1].methods).toEqual([method2, method3]);\n\n    expect(docs[2].properties).toBeUndefined();\n    expect(docs[2].methods).toBeUndefined();\n  });\n\n  it('should copy static members into properties and methods', () => {\n    const processor = processorFactory();\n    const docs = [\n      { statics: [ property1, method1, getter1] },\n      { statics: [ method2, property2, method3, setter1] },\n      { }\n    ];\n    processor.$process(docs);\n\n    expect(docs[0].staticProperties).toEqual([property1, getter1]);\n    expect(docs[0].staticMethods).toEqual([method1]);\n\n    expect(docs[1].staticProperties).toEqual([property2, setter1]);\n    expect(docs[1].staticMethods).toEqual([method2, method3]);\n\n    expect(docs[2].staticProperties).toBeUndefined();\n    expect(docs[2].staticMethods).toBeUndefined();\n  });\n\n  it('should wire up properties that are declared as parameters on the constructor to its associated parameter doc', () => {\n    const processor = processorFactory();\n    const propertyDeclaration = {};\n    const parameterDoc1 = { declaration: {} };\n    const parameterDoc2 = { declaration: propertyDeclaration };\n    const parameterDoc3 = { declaration: {} };\n    const property = {\n      declaration: propertyDeclaration,\n      containerDoc: {\n        constructorDoc: {\n          parameterDocs: [ parameterDoc1, parameterDoc2, parameterDoc3 ]\n        }\n      }\n    };\n    const docs = [{ members: [ property] }];\n    processor.$process(docs);\n\n    expect(property.constructorParamDoc).toEqual(parameterDoc2);\n  });\n});\n"
  },
  {
    "path": "apps/rxjs.dev/tools/transforms/angular-api-package/processors/simplifyMemberAnchors.js",
    "content": "/**\n * Members that have overloads get long unwieldy anchors because they must be distinguished\n * by their parameter lists.\n * But the primary overload doesn't not need this distinction, so can just be the name of the member.\n */\nmodule.exports = function simplifyMemberAnchors() {\n  return {\n    $runAfter: ['paths-computed'],\n    $runBefore: ['rendering-docs'],\n    $process: function(docs) {\n      return docs.forEach(doc => {\n        if (doc.members) {\n          doc.members.forEach(member => {\n            member.anchor = computeAnchor(member);\n            member.path = doc.path + '#' + member.anchor;\n          });\n        }\n        if (doc.statics) {\n          doc.statics.forEach(member => {\n            member.anchor = computeAnchor(member);\n            member.path = doc.path + '#' + member.anchor;\n          });\n        }\n      });\n    }\n  };\n};\n\nfunction computeAnchor(member) {\n  // if the member is a \"call\" type then it has no name\n  return encodeURI(member.name.trim() || 'call');\n}\n"
  },
  {
    "path": "apps/rxjs.dev/tools/transforms/angular-api-package/processors/simplifyMemberAnchors.spec.js",
    "content": "const testPackage = require('../../helpers/test-package');\nconst processorFactory = require('./simplifyMemberAnchors');\nconst Dgeni = require('dgeni');\n\ndescribe('simplifyMemberAnchors processor', () => {\n\n  it('should be available on the injector', () => {\n    const dgeni = new Dgeni([testPackage('angular-api-package')]);\n    const injector = dgeni.configureInjector();\n    const processor = injector.get('simplifyMemberAnchors');\n    expect(processor.$process).toBeDefined();\n    expect(processor.$runAfter).toEqual(['paths-computed']);\n    expect(processor.$runBefore).toEqual(['rendering-docs']);\n  });\n\n  describe('$process', () => {\n    describe('docs without members', () => {\n      it('should ignore the docs', () => {\n        const processor = processorFactory();\n        const docs = [\n          { id: 'some-doc' },\n          { id: 'some-other' }\n        ];\n        processor.$process(docs);\n        expect(docs).toEqual([\n          { id: 'some-doc' },\n          { id: 'some-other' }\n        ]);\n      });\n    });\n\n    describe('docs with members', () => {\n      it('should compute an anchor for each instance member', () => {\n        const processor = processorFactory();\n        const docs = [\n          { id: 'some-doc', members: [ { name: 'foo' }, { name: 'new' }, { name: '' } ] }\n        ];\n        processor.$process(docs);\n        expect(docs[0].members.map(member => member.anchor)).toEqual(['foo', 'new', 'call']);\n      });\n\n      it('should compute a path for each instance member', () => {\n        const processor = processorFactory();\n        const docs = [\n          { id: 'some-doc', path: 'a/b/c', members: [ { name: 'foo' }, { name: 'new' }, { name: '' } ] }\n        ];\n        processor.$process(docs);\n        expect(docs[0].members.map(member => member.path)).toEqual(['a/b/c#foo', 'a/b/c#new', 'a/b/c#call']);\n      });\n    });\n\n    describe('docs with static members', () => {\n      it('should compute an anchor for each static member', () => {\n        const processor = processorFactory();\n        const docs = [\n          { id: 'some-doc', statics: [ { name: 'foo' }, { name: 'new' }, { name: '' } ] }\n        ];\n        processor.$process(docs);\n        expect(docs[0].statics.map(member => member.anchor)).toEqual(['foo', 'new', 'call']);\n      });\n\n      it('should compute a path for each static member', () => {\n        const processor = processorFactory();\n        const docs = [\n          { id: 'some-doc', path: 'a/b/c', statics: [ { name: 'foo' }, { name: 'new' }, { name: '' } ] }\n        ];\n        processor.$process(docs);\n        expect(docs[0].statics.map(member => member.path)).toEqual(['a/b/c#foo', 'a/b/c#new', 'a/b/c#call']);\n      });\n    });\n  });\n});\n"
  },
  {
    "path": "apps/rxjs.dev/tools/transforms/angular-api-package/processors/splitDescription.js",
    "content": "/**\n * Split the description (of selected docs) into:\n * * `shortDescription`: the first paragraph\n * * `description`: the rest of the paragraphs\n */\nmodule.exports = function splitDescription() {\n  return {\n    $runAfter: ['tags-extracted', 'migrateLegacyJSDocTags'],\n    $runBefore: ['processing-docs'],\n    docTypes: [],\n    $process(docs) {\n      docs.forEach(doc => {\n        if (this.docTypes.indexOf(doc.docType) !== -1 && doc.description !== undefined) {\n          const description = doc.description.trim();\n          const endOfParagraph = description.search(/\\n\\s*\\n/);\n          if (endOfParagraph === -1) {\n            doc.shortDescription = description;\n            doc.description = '';\n          } else {\n            doc.shortDescription = description.substr(0, endOfParagraph).trim();\n            doc.description = description.substr(endOfParagraph).trim();\n          }\n        }\n      });\n    }\n  };\n};\n\n"
  },
  {
    "path": "apps/rxjs.dev/tools/transforms/angular-api-package/processors/splitDescription.spec.js",
    "content": "const testPackage = require('../../helpers/test-package');\nconst processorFactory = require('./splitDescription');\nconst Dgeni = require('dgeni');\n\ndescribe('splitDescription processor', () => {\n\n  it('should be available on the injector', () => {\n    const dgeni = new Dgeni([testPackage('angular-api-package')]);\n    const injector = dgeni.configureInjector();\n    const processor = injector.get('splitDescription');\n    expect(processor.$process).toBeDefined();\n  });\n\n  it('should run before the correct processor', () => {\n    const processor = processorFactory();\n    expect(processor.$runBefore).toEqual(['processing-docs']);\n  });\n\n  it('should run after the correct processor', () => {\n    const processor = processorFactory();\n    expect(processor.$runAfter).toEqual(['tags-extracted', 'migrateLegacyJSDocTags']);\n  });\n\n  it('should split the `description` property into the first paragraph and other paragraphs', () => {\n    const processor = processorFactory();\n    processor.docTypes = ['test'];\n    const docs = [\n      { docType: 'test' },\n      { docType: 'test', description: '' },\n      { docType: 'test', description: 'abc' },\n      { docType: 'test', description: 'abc\\n' },\n      { docType: 'test', description: 'abc\\n\\n' },\n      { docType: 'test', description: 'abc\\ncde' },\n      { docType: 'test', description: 'abc\\ncde\\n' },\n      { docType: 'test', description: 'abc\\n\\ncde' },\n      { docType: 'test', description: 'abc\\n  \\ncde' },\n      { docType: 'test', description: 'abc\\n\\n\\ncde' },\n      { docType: 'test', description: 'abc\\n\\ncde\\nfgh' },\n      { docType: 'test', description: 'abc\\n\\ncde\\n\\nfgh' },\n    ];\n    processor.$process(docs);\n    expect(docs).toEqual([\n      { docType: 'test' },\n      { docType: 'test', shortDescription: '', description: '' },\n      { docType: 'test', shortDescription: 'abc', description: '' },\n      { docType: 'test', shortDescription: 'abc', description: '' },\n      { docType: 'test', shortDescription: 'abc', description: '' },\n      { docType: 'test', shortDescription: 'abc\\ncde', description: '' },\n      { docType: 'test', shortDescription: 'abc\\ncde', description: '' },\n      { docType: 'test', shortDescription: 'abc', description: 'cde' },\n      { docType: 'test', shortDescription: 'abc', description: 'cde' },\n      { docType: 'test', shortDescription: 'abc', description: 'cde' },\n      { docType: 'test', shortDescription: 'abc', description: 'cde\\nfgh' },\n      { docType: 'test', shortDescription: 'abc', description: 'cde\\n\\nfgh' },\n    ]);\n  });\n\n  it('should ignore docs that do not match the specified doc types', () => {\n    const processor = processorFactory();\n    processor.docTypes = ['test'];\n    const docs = [\n      { docType: 'test', description: 'abc\\n\\ncde' },\n      { docType: 'other', description: 'abc\\n\\ncde' }\n    ];\n    processor.$process(docs);\n    expect(docs).toEqual([\n      { docType: 'test', shortDescription: 'abc', description: 'cde' },\n      { docType: 'other', description: 'abc\\n\\ncde' }\n    ]);\n  });\n});"
  },
  {
    "path": "apps/rxjs.dev/tools/transforms/angular-api-package/tag-defs/deprecated.js",
    "content": "module.exports = function() {\n  return {name: 'deprecated'};\n};\n"
  },
  {
    "path": "apps/rxjs.dev/tools/transforms/angular-api-package/tag-defs/internal.js",
    "content": "/**\n * Use this tag to ensure that dgeni does not include this code item\n * in the rendered docs.\n *\n * The `@internal` tag indicates to the compiler not to include the\n * item in the public typings file.\n * Use the `@nodoc` alias if you only want to hide the item from the\n * docs but not from the typings file.\n */\nmodule.exports = function() {\n  return {\n    name: 'internal',\n    aliases: ['nodoc'],\n    transforms: function() { return true; }\n  };\n};\n"
  },
  {
    "path": "apps/rxjs.dev/tools/transforms/angular-api-package/tag-defs/throws.js",
    "content": "module.exports = function(extractTypeTransform, wholeTagTransform) {\n  return {\n    name: 'throws',\n    aliases: ['exception'],\n    multi: true,\n    transforms: [ extractTypeTransform, wholeTagTransform ]\n  };\n};"
  },
  {
    "path": "apps/rxjs.dev/tools/transforms/angular-base-package/ignore-words.json",
    "content": "[\n  \"a\",\n  \"able\",\n  \"about\",\n  \"above\",\n  \"abst\",\n  \"accordance\",\n  \"according\",\n  \"accordingly\",\n  \"across\",\n  \"act\",\n  \"actually\",\n  \"added\",\n  \"adj\",\n  \"adopted\",\n  \"affected\",\n  \"affecting\",\n  \"affects\",\n  \"after\",\n  \"afterwards\",\n  \"again\",\n  \"against\",\n  \"ah\",\n  \"all\",\n  \"almost\",\n  \"alone\",\n  \"along\",\n  \"already\",\n  \"also\",\n  \"although\",\n  \"always\",\n  \"am\",\n  \"among\",\n  \"amongst\",\n  \"an\",\n  \"and\",\n  \"announce\",\n  \"another\",\n  \"any\",\n  \"anybody\",\n  \"anyhow\",\n  \"anymore\",\n  \"anyone\",\n  \"anything\",\n  \"anyway\",\n  \"anyways\",\n  \"anywhere\",\n  \"apparently\",\n  \"approximately\",\n  \"are\",\n  \"aren\",\n  \"arent\",\n  \"arise\",\n  \"around\",\n  \"as\",\n  \"aside\",\n  \"ask\",\n  \"asking\",\n  \"at\",\n  \"auth\",\n  \"available\",\n  \"away\",\n  \"awfully\",\n  \"b\",\n  \"back\",\n  \"be\",\n  \"became\",\n  \"because\",\n  \"become\",\n  \"becomes\",\n  \"becoming\",\n  \"been\",\n  \"before\",\n  \"beforehand\",\n  \"begin\",\n  \"beginning\",\n  \"beginnings\",\n  \"begins\",\n  \"behind\",\n  \"being\",\n  \"believe\",\n  \"below\",\n  \"beside\",\n  \"besides\",\n  \"between\",\n  \"beyond\",\n  \"biol\",\n  \"both\",\n  \"brief\",\n  \"briefly\",\n  \"but\",\n  \"by\",\n  \"c\",\n  \"ca\",\n  \"came\",\n  \"can\",\n  \"cannot\",\n  \"can't\",\n  \"cant\",\n  \"cause\",\n  \"causes\",\n  \"certain\",\n  \"certainly\",\n  \"co\",\n  \"com\",\n  \"come\",\n  \"comes\",\n  \"contain\",\n  \"containing\",\n  \"contains\",\n  \"could\",\n  \"couldnt\",\n  \"d\",\n  \"date\",\n  \"did\",\n  \"didn't\",\n  \"didnt\",\n  \"different\",\n  \"do\",\n  \"does\",\n  \"doesn't\",\n  \"doesnt\",\n  \"doing\",\n  \"done\",\n  \"don't\",\n  \"dont\",\n  \"down\",\n  \"downwards\",\n  \"due\",\n  \"during\",\n  \"e\",\n  \"each\",\n  \"ed\",\n  \"edu\",\n  \"effect\",\n  \"eg\",\n  \"eight\",\n  \"eighty\",\n  \"either\",\n  \"else\",\n  \"elsewhere\",\n  \"end\",\n  \"ending\",\n  \"enough\",\n  \"especially\",\n  \"et\",\n  \"et-al\",\n  \"etc\",\n  \"even\",\n  \"ever\",\n  \"every\",\n  \"everybody\",\n  \"everyone\",\n  \"everything\",\n  \"everywhere\",\n  \"ex\",\n  \"except\",\n  \"f\",\n  \"far\",\n  \"few\",\n  \"ff\",\n  \"fifth\",\n  \"first\",\n  \"five\",\n  \"fix\",\n  \"followed\",\n  \"following\",\n  \"follows\",\n  \"for\",\n  \"former\",\n  \"formerly\",\n  \"forth\",\n  \"found\",\n  \"four\",\n  \"from\",\n  \"further\",\n  \"furthermore\",\n  \"g\",\n  \"gave\",\n  \"get\",\n  \"gets\",\n  \"getting\",\n  \"give\",\n  \"given\",\n  \"gives\",\n  \"giving\",\n  \"go\",\n  \"goes\",\n  \"gone\",\n  \"got\",\n  \"gotten\",\n  \"h\",\n  \"had\",\n  \"happens\",\n  \"hardly\",\n  \"has\",\n  \"hasn't\",\n  \"hasnt\",\n  \"have\",\n  \"haven't\",\n  \"havent\",\n  \"having\",\n  \"he\",\n  \"hed\",\n  \"hence\",\n  \"her\",\n  \"here\",\n  \"hereafter\",\n  \"hereby\",\n  \"herein\",\n  \"heres\",\n  \"hereupon\",\n  \"hers\",\n  \"herself\",\n  \"hes\",\n  \"hi\",\n  \"hid\",\n  \"him\",\n  \"himself\",\n  \"his\",\n  \"hither\",\n  \"home\",\n  \"how\",\n  \"howbeit\",\n  \"however\",\n  \"hundred\",\n  \"i\",\n  \"id\",\n  \"ie\",\n  \"if\",\n  \"i'll\",\n  \"ill\",\n  \"im\",\n  \"immediate\",\n  \"immediately\",\n  \"importance\",\n  \"important\",\n  \"in\",\n  \"inc\",\n  \"indeed\",\n  \"index\",\n  \"information\",\n  \"instead\",\n  \"into\",\n  \"invention\",\n  \"inward\",\n  \"is\",\n  \"isn't\",\n  \"isnt\",\n  \"it\",\n  \"itd\",\n  \"it'll\",\n  \"itll\",\n  \"its\",\n  \"itself\",\n  \"i've\",\n  \"ive\",\n  \"j\",\n  \"just\",\n  \"k\",\n  \"keep\",\n  \"keeps\",\n  \"kept\",\n  \"keys\",\n  \"kg\",\n  \"km\",\n  \"know\",\n  \"known\",\n  \"knows\",\n  \"l\",\n  \"largely\",\n  \"last\",\n  \"lately\",\n  \"later\",\n  \"latter\",\n  \"latterly\",\n  \"least\",\n  \"less\",\n  \"lest\",\n  \"let\",\n  \"lets\",\n  \"like\",\n  \"liked\",\n  \"likely\",\n  \"line\",\n  \"little\",\n  \"'ll\",\n  \"'ll\",\n  \"look\",\n  \"looking\",\n  \"looks\",\n  \"ltd\",\n  \"m\",\n  \"made\",\n  \"mainly\",\n  \"make\",\n  \"makes\",\n  \"many\",\n  \"may\",\n  \"maybe\",\n  \"me\",\n  \"mean\",\n  \"means\",\n  \"meantime\",\n  \"meanwhile\",\n  \"merely\",\n  \"mg\",\n  \"might\",\n  \"million\",\n  \"miss\",\n  \"ml\",\n  \"more\",\n  \"moreover\",\n  \"most\",\n  \"mostly\",\n  \"mr\",\n  \"mrs\",\n  \"much\",\n  \"mug\",\n  \"must\",\n  \"my\",\n  \"myself\",\n  \"n\",\n  \"na\",\n  \"name\",\n  \"namely\",\n  \"nay\",\n  \"nd\",\n  \"near\",\n  \"nearly\",\n  \"necessarily\",\n  \"necessary\",\n  \"need\",\n  \"needs\",\n  \"neither\",\n  \"never\",\n  \"nevertheless\",\n  \"new\",\n  \"next\",\n  \"nine\",\n  \"ninety\",\n  \"no\",\n  \"nobody\",\n  \"non\",\n  \"none\",\n  \"nonetheless\",\n  \"noone\",\n  \"nor\",\n  \"normally\",\n  \"nos\",\n  \"not\",\n  \"noted\",\n  \"nothing\",\n  \"now\",\n  \"nowhere\",\n  \"o\",\n  \"obtain\",\n  \"obtained\",\n  \"obviously\",\n  \"of\",\n  \"off\",\n  \"often\",\n  \"oh\",\n  \"ok\",\n  \"okay\",\n  \"old\",\n  \"omitted\",\n  \"on\",\n  \"once\",\n  \"one\",\n  \"ones\",\n  \"only\",\n  \"onto\",\n  \"or\",\n  \"ord\",\n  \"other\",\n  \"others\",\n  \"otherwise\",\n  \"ought\",\n  \"our\",\n  \"ours\",\n  \"ourselves\",\n  \"out\",\n  \"outside\",\n  \"over\",\n  \"overall\",\n  \"owing\",\n  \"own\",\n  \"p\",\n  \"page\",\n  \"pages\",\n  \"part\",\n  \"particular\",\n  \"particularly\",\n  \"past\",\n  \"per\",\n  \"perhaps\",\n  \"placed\",\n  \"please\",\n  \"plus\",\n  \"poorly\",\n  \"possible\",\n  \"possibly\",\n  \"potentially\",\n  \"pp\",\n  \"predominantly\",\n  \"present\",\n  \"previously\",\n  \"primarily\",\n  \"probably\",\n  \"promptly\",\n  \"proud\",\n  \"provides\",\n  \"put\",\n  \"q\",\n  \"que\",\n  \"quickly\",\n  \"quite\",\n  \"qv\",\n  \"r\",\n  \"ran\",\n  \"rather\",\n  \"rd\",\n  \"re\",\n  \"readily\",\n  \"really\",\n  \"recent\",\n  \"recently\",\n  \"ref\",\n  \"refs\",\n  \"regarding\",\n  \"regardless\",\n  \"regards\",\n  \"related\",\n  \"relatively\",\n  \"research\",\n  \"respectively\",\n  \"resulted\",\n  \"resulting\",\n  \"results\",\n  \"right\",\n  \"run\",\n  \"s\",\n  \"said\",\n  \"same\",\n  \"saw\",\n  \"say\",\n  \"saying\",\n  \"says\",\n  \"sec\",\n  \"section\",\n  \"see\",\n  \"seeing\",\n  \"seem\",\n  \"seemed\",\n  \"seeming\",\n  \"seems\",\n  \"seen\",\n  \"self\",\n  \"selves\",\n  \"sent\",\n  \"seven\",\n  \"several\",\n  \"shall\",\n  \"she\",\n  \"shed\",\n  \"she'll\",\n  \"shell\",\n  \"shes\",\n  \"should\",\n  \"shouldn't\",\n  \"shouldnt\",\n  \"show\",\n  \"showed\",\n  \"shown\",\n  \"showns\",\n  \"shows\",\n  \"significant\",\n  \"significantly\",\n  \"similar\",\n  \"similarly\",\n  \"since\",\n  \"six\",\n  \"slightly\",\n  \"so\",\n  \"some\",\n  \"somebody\",\n  \"somehow\",\n  \"someone\",\n  \"somethan\",\n  \"something\",\n  \"sometime\",\n  \"sometimes\",\n  \"somewhat\",\n  \"somewhere\",\n  \"soon\",\n  \"sorry\",\n  \"specifically\",\n  \"specified\",\n  \"specify\",\n  \"specifying\",\n  \"state\",\n  \"states\",\n  \"still\",\n  \"stop\",\n  \"strongly\",\n  \"sub\",\n  \"substantially\",\n  \"successfully\",\n  \"such\",\n  \"sufficiently\",\n  \"suggest\",\n  \"sup\",\n  \"sure\",\n  \"t\",\n  \"take\",\n  \"taken\",\n  \"taking\",\n  \"tell\",\n  \"tends\",\n  \"th\",\n  \"than\",\n  \"thank\",\n  \"thanks\",\n  \"thanx\",\n  \"that\",\n  \"that'll\",\n  \"thatll\",\n  \"thats\",\n  \"that've\",\n  \"thatve\",\n  \"the\",\n  \"their\",\n  \"theirs\",\n  \"them\",\n  \"themselves\",\n  \"then\",\n  \"thence\",\n  \"there\",\n  \"thereafter\",\n  \"thereby\",\n  \"thered\",\n  \"therefore\",\n  \"therein\",\n  \"there'll\",\n  \"therell\",\n  \"thereof\",\n  \"therere\",\n  \"theres\",\n  \"thereto\",\n  \"thereupon\",\n  \"there've\",\n  \"thereve\",\n  \"these\",\n  \"they\",\n  \"theyd\",\n  \"they'll\",\n  \"theyll\",\n  \"theyre\",\n  \"they've\",\n  \"theyve\",\n  \"think\",\n  \"this\",\n  \"those\",\n  \"thou\",\n  \"though\",\n  \"thoughh\",\n  \"thousand\",\n  \"throug\",\n  \"through\",\n  \"throughout\",\n  \"thru\",\n  \"thus\",\n  \"til\",\n  \"tip\",\n  \"to\",\n  \"together\",\n  \"too\",\n  \"took\",\n  \"toward\",\n  \"towards\",\n  \"tried\",\n  \"tries\",\n  \"truly\",\n  \"try\",\n  \"trying\",\n  \"ts\",\n  \"twice\",\n  \"two\",\n  \"u\",\n  \"un\",\n  \"under\",\n  \"unfortunately\",\n  \"unless\",\n  \"unlike\",\n  \"unlikely\",\n  \"until\",\n  \"unto\",\n  \"up\",\n  \"upon\",\n  \"ups\",\n  \"us\",\n  \"use\",\n  \"used\",\n  \"useful\",\n  \"usefully\",\n  \"usefulness\",\n  \"uses\",\n  \"using\",\n  \"usually\",\n  \"v\",\n  \"value\",\n  \"various\",\n  \"'ve\",\n  \"'ve\",\n  \"very\",\n  \"via\",\n  \"viz\",\n  \"vol\",\n  \"vols\",\n  \"vs\",\n  \"w\",\n  \"want\",\n  \"wants\",\n  \"was\",\n  \"wasn't\",\n  \"wasnt\",\n  \"way\",\n  \"we\",\n  \"wed\",\n  \"welcome\",\n  \"we'll\",\n  \"well\",\n  \"went\",\n  \"were\",\n  \"weren't\",\n  \"werent\",\n  \"we've\",\n  \"weve\",\n  \"what\",\n  \"whatever\",\n  \"what'll\",\n  \"whatll\",\n  \"whats\",\n  \"when\",\n  \"whence\",\n  \"whenever\",\n  \"where\",\n  \"whereafter\",\n  \"whereas\",\n  \"whereby\",\n  \"wherein\",\n  \"wheres\",\n  \"whereupon\",\n  \"wherever\",\n  \"whether\",\n  \"which\",\n  \"while\",\n  \"whim\",\n  \"whither\",\n  \"who\",\n  \"whod\",\n  \"whoever\",\n  \"whole\",\n  \"who'll\",\n  \"wholl\",\n  \"whom\",\n  \"whomever\",\n  \"whos\",\n  \"whose\",\n  \"why\",\n  \"widely\",\n  \"will\",\n  \"willing\",\n  \"wish\",\n  \"with\",\n  \"within\",\n  \"without\",\n  \"won't\",\n  \"wont\",\n  \"words\",\n  \"would\",\n  \"wouldn't\",\n  \"wouldnt\",\n  \"www\",\n  \"x\",\n  \"y\",\n  \"yes\",\n  \"yet\",\n  \"you\",\n  \"youd\",\n  \"you'll\",\n  \"youll\",\n  \"your\",\n  \"youre\",\n  \"yours\",\n  \"yourself\",\n  \"yourselves\",\n  \"you've\",\n  \"youve\",\n  \"z\",\n  \"zero\"\n]\n"
  },
  {
    "path": "apps/rxjs.dev/tools/transforms/angular-base-package/index.js",
    "content": "/**\n * @license\n * Copyright Google Inc. All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\nconst path = require('path');\nconst Package = require('dgeni').Package;\n\nconst jsdocPackage = require('dgeni-packages/jsdoc');\nconst nunjucksPackage = require('dgeni-packages/nunjucks');\nconst linksPackage = require('../links-package');\nconst remarkPackage = require('../remark-package');\nconst postProcessPackage = require('dgeni-packages/post-process-html');\n\nconst { PROJECT_ROOT, CONTENTS_PATH, OUTPUT_PATH, DOCS_OUTPUT_PATH, TEMPLATES_PATH, AIO_PATH, requireFolder } = require('../config');\n\n// prettier-ignore\nmodule.exports = new Package('angular-base', [\n  jsdocPackage,\n  nunjucksPackage,\n  linksPackage,\n  remarkPackage,\n  postProcessPackage,\n])\n\n  // Register the processors\n  .processor(require('./processors/generateKeywords'))\n  .processor(require('./processors/createSitemap'))\n  .processor(require('./processors/checkUnbalancedBackTicks'))\n  .processor(require('./processors/convertToJson'))\n  .processor(require('./processors/fixInternalDocumentLinks'))\n  .processor(require('./processors/copyContentAssets'))\n  .processor(require('./processors/renderLinkInfo'))\n\n  // overrides base packageInfo and returns the one for the 'angular/angular' repo.\n  .factory('packageInfo', function () {\n    return require(path.resolve(PROJECT_ROOT, './packages/rxjs/package.json'));\n  })\n  .factory(require('./readers/json'))\n  .factory(require('./services/copyFolder'))\n  .factory(require('./services/filterPipes'))\n  .factory(require('./services/filterAmbiguousDirectiveAliases'))\n  .factory(require('./services/filterFromInImports'))\n  .factory(require('./services/getImageDimensions'))\n\n  .factory(require('./post-processors/add-image-dimensions'))\n  .factory(require('./post-processors/auto-link-code'))\n\n  .config(function (checkAnchorLinksProcessor) {\n    // This is disabled here to prevent false negatives for the `docs-watch` task.\n    // It is re-enabled in the main `angular.io-package`\n    checkAnchorLinksProcessor.$enabled = false;\n  })\n\n  // Where do we get the source files?\n  .config(function (readFilesProcessor, generateKeywordsProcessor, jsonFileReader) {\n    readFilesProcessor.fileReaders.push(jsonFileReader);\n    readFilesProcessor.basePath = PROJECT_ROOT;\n    readFilesProcessor.sourceFiles = [];\n\n    generateKeywordsProcessor.ignoreWords = require(path.resolve(__dirname, 'ignore-words'));\n    generateKeywordsProcessor.docTypesToIgnore = [\n      undefined,\n      'json-doc',\n      'api-list-data',\n      'api-list-data',\n      'contributors-json',\n      'navigation-json',\n      'announcements-json',\n    ];\n    generateKeywordsProcessor.propertiesToIgnore = ['basePath', 'renderedContent', 'docType', 'searchTitle'];\n  })\n\n  // Where do we write the output files?\n  .config(function (writeFilesProcessor) {\n    writeFilesProcessor.outputFolder = DOCS_OUTPUT_PATH;\n  })\n\n  // Configure nunjucks rendering of docs via templates\n  .config(function (renderDocsProcessor, templateFinder, templateEngine, getInjectables) {\n    // Where to find the templates for the doc rendering\n    templateFinder.templateFolders = [TEMPLATES_PATH];\n\n    // Standard patterns for matching docs to templates\n    templateFinder.templatePatterns = [\n      '${ doc.template }',\n      '${ doc.id }.${ doc.docType }.template.html',\n      '${ doc.id }.template.html',\n      '${ doc.docType }.template.html',\n      '${ doc.id }.${ doc.docType }.template.js',\n      '${ doc.id }.template.js',\n      '${ doc.docType }.template.js',\n      '${ doc.id }.${ doc.docType }.template.json',\n      '${ doc.id }.template.json',\n      '${ doc.docType }.template.json',\n      'common.template.html',\n    ];\n\n    // Nunjucks and Angular conflict in their template bindings so change Nunjucks\n    templateEngine.config.tags = { variableStart: '{$', variableEnd: '$}' };\n\n    templateEngine.filters = templateEngine.filters.concat(getInjectables(requireFolder(__dirname, './rendering')));\n\n    // helpers are made available to the nunjucks templates\n    renderDocsProcessor.helpers.relativePath = function (from, to) {\n      return path.relative(from, to);\n    };\n  })\n\n  .config(function (copyContentAssetsProcessor) {\n    copyContentAssetsProcessor.assetMappings.push({ from: path.resolve(CONTENTS_PATH, 'images'), to: path.resolve(OUTPUT_PATH, 'images') });\n  })\n\n  // We are not going to be relaxed about ambiguous links\n  .config(function (getLinkInfo) {\n    getLinkInfo.useFirstAmbiguousLink = false;\n  })\n\n  .config(function (generateKeywordsProcessor) {\n    generateKeywordsProcessor.outputFolder = 'app';\n  })\n\n  .config(function (\n    postProcessHtml,\n    addImageDimensions,\n    autoLinkCode,\n    filterPipes,\n    filterAmbiguousDirectiveAliases,\n    filterFromInImports\n  ) {\n    addImageDimensions.basePath = path.resolve(AIO_PATH, 'src');\n    autoLinkCode.customFilters = [filterPipes, filterAmbiguousDirectiveAliases];\n    autoLinkCode.wordFilters = [filterFromInImports];\n    postProcessHtml.plugins = [\n      require('./post-processors/autolink-headings'),\n      addImageDimensions,\n      require('./post-processors/h1-checker'),\n      autoLinkCode,\n    ];\n  })\n\n  .config(function (convertToJsonProcessor) {\n    convertToJsonProcessor.docTypes = [];\n  });\n"
  },
  {
    "path": "apps/rxjs.dev/tools/transforms/angular-base-package/post-processors/add-image-dimensions.js",
    "content": "const visit = require('unist-util-visit');\nconst is = require('hast-util-is-element');\nconst source = require('unist-util-source');\n\n/**\n * Add the width and height of the image to the `img` tag if they are\n * not already provided. This helps prevent jank when the page is\n * rendered before the image has downloaded.\n *\n * If there is no `src` attribute on an image, or it is not possible\n * to load the image file indicated by the `src` then a warning is emitted.\n */\nmodule.exports = function addImageDimensions(getImageDimensions) {\n  return function addImageDimensionsImpl()  {\n    return (ast, file) => {\n      visit(ast, node => {\n\n        if (is(node, 'img')) {\n          const props = node.properties;\n          const src = props.src;\n          if (!src) {\n            file.message('Missing src in image tag `' + source(node, file) + '`');\n          } else {\n            try {\n              const dimensions = getImageDimensions(addImageDimensionsImpl.basePath, src);\n              if (props.width === undefined && props.height === undefined) {\n                props.width = '' + dimensions.width;\n                props.height = '' + dimensions.height;\n              }\n            } catch(e) {\n              if (e.code === 'ENOENT') {\n                file.message('Unable to load src in image tag `' + source(node, file) + '`');\n              } else {\n                file.fail(e.message);\n              }\n            }\n          }\n        }\n      });\n    };\n  };\n};\n"
  },
  {
    "path": "apps/rxjs.dev/tools/transforms/angular-base-package/post-processors/add-image-dimensions.spec.js",
    "content": "var createTestPackage = require('../../helpers/test-package');\nvar Dgeni = require('dgeni');\n\ndescribe('addImageDimensions post-processor', () => {\n  let processor, getImageDimensionsSpy, addImageDimensions, log;\n\n  beforeEach(() => {\n    const testPackage = createTestPackage('angular-base-package')\n      .factory('getImageDimensions', mockGetImageDimensions);\n    const dgeni = new Dgeni([testPackage]);\n    const injector = dgeni.configureInjector();\n    log = injector.get('log');\n    addImageDimensions = injector.get('addImageDimensions');\n    addImageDimensions.basePath = 'base/path';\n    getImageDimensionsSpy = injector.get('getImageDimensions');\n    processor = injector.get('postProcessHtml');\n    processor.docTypes = ['a'];\n    processor.plugins = [addImageDimensions];\n  });\n\n  it('should add the image dimensions into <img> tags', () => {\n    const docs = [{\n      docType: 'a',\n      renderedContent: `\n        <p>xxx</p>\n        <img src=\"a/b.jpg\">\n        <p>yyy</p>\n        <img src=\"c/d.png\">\n        <p>zzz</p>\n      `\n    }];\n    processor.$process(docs);\n    expect(getImageDimensionsSpy).toHaveBeenCalledWith('base/path', 'a/b.jpg');\n    expect(getImageDimensionsSpy).toHaveBeenCalledWith('base/path', 'c/d.png');\n    expect(docs).toEqual([jasmine.objectContaining({\n      docType: 'a',\n      renderedContent: `\n        <p>xxx</p>\n        <img src=\"a/b.jpg\" width=\"10\" height=\"20\">\n        <p>yyy</p>\n        <img src=\"c/d.png\" width=\"30\" height=\"40\">\n        <p>zzz</p>\n      `\n    })]);\n  });\n\n  it('should log a warning for images with no src attribute', () => {\n    const docs = [{\n      docType: 'a',\n      renderedContent: '<img attr=\"value\">'\n    }];\n    processor.$process(docs);\n    expect(getImageDimensionsSpy).not.toHaveBeenCalled();\n    expect(docs).toEqual([jasmine.objectContaining({\n      docType: 'a',\n      renderedContent: '<img attr=\"value\">'\n    })]);\n    expect(log.warn).toHaveBeenCalledWith('Missing src in image tag `<img attr=\"value\">` - doc (a) ');\n  });\n\n  it('should fail for images whose source cannot be loaded', () => {\n    getImageDimensionsSpy.and.callFake(() => {\n      const error = new Error('no such file or directory');\n      error.code = 'ENOENT';\n      throw error;\n    });\n    const docs = [{\n      docType: 'a',\n      renderedContent: '<img src=\"missing\">'\n    }];\n    processor.$process(docs);\n    expect(log.warn).toHaveBeenCalledWith('Unable to load src in image tag `<img src=\"missing\">` - doc (a) ');\n    expect(getImageDimensionsSpy).toHaveBeenCalledWith('base/path', 'missing');\n  });\n\n  it('should ignore images with width or height attributes', () => {\n    const docs = [{\n      docType: 'a',\n      renderedContent: `\n        <img src=\"a/b.jpg\" width=\"10\">\n        <img src=\"c/d.jpg\" height=\"10\">\n        <img src=\"e/f.jpg\" width=\"10\" height=\"10\">\n      `\n    }];\n    processor.$process(docs);\n    expect(docs).toEqual([jasmine.objectContaining({\n      docType: 'a',\n      renderedContent: `\n        <img src=\"a/b.jpg\" width=\"10\">\n        <img src=\"c/d.jpg\" height=\"10\">\n        <img src=\"e/f.jpg\" width=\"10\" height=\"10\">\n      `\n    })]);\n  });\n\n  function mockGetImageDimensions() {\n    const imageInfo = {\n      'a/b.jpg': { width: 10, height: 20 },\n      'c/d.png': { width: 30, height: 40 },\n    };\n    // eslint-disable-next-line jasmine/no-unsafe-spy\n    return jasmine.createSpy('getImageDimensions')\n      .and.callFake((base, url) => imageInfo[url]);\n  }\n});\n"
  },
  {
    "path": "apps/rxjs.dev/tools/transforms/angular-base-package/post-processors/auto-link-code.js",
    "content": "const visit = require('unist-util-visit-parents');\nconst is = require('hast-util-is-element');\nconst textContent = require('hast-util-to-string');\n\n/**\n * Automatically add in a link to the relevant document for code blocks.\n * E.g. `<code>MyClass</code>` becomes `<code><a href=\"path/to/myclass\">MyClass</a></code>`\n *\n * @property docTypes an array of strings.\n * Only docs that have one of these docTypes will be linked to.\n * Usually set to the API exported docTypes, e.g. \"class\", \"function\", \"directive\", etc.\n *\n * @property customFilters array of functions `(docs, words, wordIndex) => docs` that will filter\n * out docs where a word should not link to a doc.\n *   - `docs` is the array of docs that match the link `word`\n *   - `words` is the collection of words parsed from the code text\n *   - `wordIndex` is the index of the current `word` for which we are finding a link\n *\n * @property codeElements an array of strings.\n * Only text contained in these elements will be linked to.\n * Usually set to \"code\" but also \"code-example\" for angular.io.\n */\nmodule.exports = function autoLinkCode(getDocFromAlias) {\n  autoLinkCodeImpl.docTypes = [];\n  autoLinkCodeImpl.customFilters = [];\n  autoLinkCodeImpl.wordFilters = [];\n  autoLinkCodeImpl.codeElements = ['code'];\n  autoLinkCodeImpl.ignoredLanguages = ['bash', 'sh', 'shell', 'json', 'markdown'];\n  autoLinkCodeImpl.failOnMissingDocPath = false;\n\n  return autoLinkCodeImpl;\n\n  function autoLinkCodeImpl() {\n    return (ast, file) => {\n      visit(ast, 'element', (node, ancestors) => {\n        if (!isValidCodeElement(node, ancestors)) {\n          return;\n        }\n\n        visit(node, 'text', (node, ancestors) => {\n          const isInLink = isInsideLink(ancestors);\n          if (isInLink) {\n            return;\n          }\n\n          const parent = ancestors[ancestors.length - 1];\n          const index = parent.children.indexOf(node);\n\n          // Can we convert the whole text node into a doc link?\n          const docs = getFilteredDocsFromAlias([node.value], 0);\n          if (foundValidDoc(docs, node.value, file)) {\n            parent.children.splice(index, 1, createLinkNode(docs[0], node.value));\n          } else {\n            // Parse the text for words that we can convert to links\n            const nodes = getNodes(node, file);\n            // Replace the text node with the links and leftover text nodes\n            Array.prototype.splice.apply(parent.children, [index, 1].concat(nodes));\n            // Do not visit this node's children or the newly added nodes\n            return [visit.SKIP, index + nodes.length];\n          }\n        });\n      });\n    };\n  }\n\n  function isValidCodeElement(node, ancestors) {\n    // Only interested in code elements that:\n    // * do not have `no-auto-link` class\n    // * do not have an ignored language\n    // * are not inside links\n    const isCodeElement = autoLinkCodeImpl.codeElements.some(elementType => is(node, elementType));\n    const hasNoAutoLink =\n      node.properties.className && node.properties.className.includes('no-auto-link');\n    const isLanguageSupported =\n      !autoLinkCodeImpl.ignoredLanguages.includes(node.properties.language);\n    const isInLink = isInsideLink(ancestors);\n    return isCodeElement && !hasNoAutoLink && isLanguageSupported && !isInLink;\n  }\n\n  function isInsideLink(ancestors) {\n    return ancestors.some(ancestor => is(ancestor, 'a'));\n  }\n\n  function getFilteredDocsFromAlias(words, index) {\n    // Remove docs that fail the custom filter tests.\n    return autoLinkCodeImpl.customFilters.reduce(\n      (docs, filter) => filter(docs, words, index), getDocFromAlias(words[index]));\n  }\n\n  function shouldSkipFindingValidDoc(words, index) {\n    return autoLinkCodeImpl.wordFilters.reduce((skip, filter) => skip || filter(words, index), false);\n  }\n\n  function getNodes(node, file) {\n    return textContent(node)\n      .split(/([A-Za-z0-9_.-]+)/)\n      .filter(word => word.length)\n      .map((word, index, words) => {\n        const filteredDocs = getFilteredDocsFromAlias(words, index);\n        const skipFindingValidDoc = shouldSkipFindingValidDoc(words, index);\n\n        return !skipFindingValidDoc && foundValidDoc(filteredDocs, word, file) ?\n          // Create a link wrapping the text node.\n          createLinkNode(filteredDocs[0], word) :\n          // this is just text so push a new text node\n          {type: 'text', value: word};\n      });\n  }\n\n  /**\n   * Validates the docs to be used to generate the links. The validation ensures\n   * that the docs are not `internal` and that the `docType` is supported. The `path`\n   * can be empty when the `API` is not public.\n   *\n   * @param {Array<Object>} docs An array of objects containing the doc details\n   *\n   * @param {string} keyword The keyword the doc applies to\n   */\n  function foundValidDoc(docs, keyword, file) {\n    if (docs.length !== 1) {\n      return false;\n    }\n\n    var doc = docs[0];\n\n    const isInvalidDoc = doc.docType === 'member' && !keyword.includes('.');\n    if (isInvalidDoc) {\n      return false;\n    }\n\n    if (!doc.path) {\n      var message = `\n      autoLinkCode: Doc path is empty for \"${doc.id}\" - link will not be generated for \"${keyword}\".\n      Please make sure if the doc should be public. If not, it should probably not be referenced in the docs.`;\n\n      if (autoLinkCodeImpl.failOnMissingDocPath) {\n        file.fail(message);\n      } else {\n        file.message(message);\n      }\n      return false;\n    }\n\n    return !doc.internal && autoLinkCodeImpl.docTypes.includes(doc.docType);\n  }\n\n  function createLinkNode(doc, text) {\n    return {\n      type: 'element',\n      tagName: 'a',\n      properties: {href: doc.path, class: 'code-anchor'},\n      children: [{type: 'text', value: text}]\n    };\n  }\n};\n"
  },
  {
    "path": "apps/rxjs.dev/tools/transforms/angular-base-package/post-processors/auto-link-code.spec.js",
    "content": "var createTestPackage = require('../../helpers/test-package');\nvar Dgeni = require('dgeni');\n\ndescribe('autoLinkCode post-processor', () => {\n  let processor, autoLinkCode, aliasMap, filterPipes;\n\n  beforeEach(() => {\n    const testPackage = createTestPackage('angular-base-package');\n    const dgeni = new Dgeni([testPackage]);\n    const injector = dgeni.configureInjector();\n    autoLinkCode = injector.get('autoLinkCode');\n    autoLinkCode.docTypes = ['class', 'pipe', 'function', 'const', 'member'];\n    aliasMap = injector.get('aliasMap');\n    processor = injector.get('postProcessHtml');\n    processor.docTypes = ['test-doc'];\n    processor.plugins = [autoLinkCode];\n    filterPipes = injector.get('filterPipes');\n  });\n\n  it('should insert an anchor into every code item that matches the id of an API doc', () => {\n    aliasMap.addDoc({ docType: 'class', id: 'MyClass', aliases: ['MyClass'], path: 'a/b/myclass' });\n    const doc = { docType: 'test-doc', renderedContent: '<code>MyClass</code>' };\n    processor.$process([doc]);\n    expect(doc.renderedContent).toEqual('<code><a href=\"a/b/myclass\" class=\"code-anchor\">MyClass</a></code>');\n  });\n\n  it('should insert an anchor into every code item that matches an alias of an API doc', () => {\n    aliasMap.addDoc({ docType: 'class', id: 'MyClass', aliases: ['MyClass', 'foo.MyClass'], path: 'a/b/myclass' });\n    const doc = { docType: 'test-doc', renderedContent: '<code>foo.MyClass</code>' };\n    processor.$process([doc]);\n    expect(doc.renderedContent).toEqual('<code><a href=\"a/b/myclass\" class=\"code-anchor\">foo.MyClass</a></code>');\n  });\n\n  it('should match code items within a block of code that contain a dot in their identifier', () => {\n    aliasMap.addDoc({ docType: 'member', id: 'MyEnum.Value', aliases: ['Value', 'MyEnum.Value'], path: 'a/b/myenum' });\n    const doc = { docType: 'test-doc', renderedContent: '<code>someFn(): MyEnum.Value</code>' };\n    processor.$process([doc]);\n    expect(doc.renderedContent).toEqual('<code>someFn(): <a href=\"a/b/myenum\" class=\"code-anchor\">MyEnum.Value</a></code>');\n  });\n\n  it('should ignore code items that do not match a link to an API doc', () => {\n    aliasMap.addDoc({ docType: 'guide', id: 'MyClass', aliases: ['MyClass'], path: 'a/b/myclass' });\n    const doc = { docType: 'test-doc', renderedContent: '<code>MyClass</code>' };\n    processor.$process([doc]);\n    expect(doc.renderedContent).toEqual('<code>MyClass</code>');\n  });\n\n  it('should ignore code items that are already inside a link', () => {\n    aliasMap.addDoc({ docType: 'class', id: 'MyClass', aliases: ['MyClass'], path: 'a/b/myclass' });\n    const doc = { docType: 'test-doc', renderedContent: '<a href=\"...\"><div><code>MyClass</code></div></a>' };\n    processor.$process([doc]);\n    expect(doc.renderedContent).toEqual('<a href=\"...\"><div><code>MyClass</code></div></a>');\n  });\n\n  it('should ignore code items match an API doc but are not in the list of acceptable docTypes', () => {\n    aliasMap.addDoc({ docType: 'directive', id: 'MyClass', aliases: ['MyClass'], path: 'a/b/myclass' });\n    const doc = { docType: 'test-doc', renderedContent: '<code>MyClass</code>' };\n    processor.$process([doc]);\n    expect(doc.renderedContent).toEqual('<code>MyClass</code>');\n  });\n\n  it('should ignore code items that match an API doc but are attached to other text via a dash', () => {\n    aliasMap.addDoc({ docType: 'class', id: 'MyClass', aliases: ['MyClass'], path: 'a/b/myclass' });\n    const doc = { docType: 'test-doc', renderedContent: '<code>xyz-MyClass</code>' };\n    processor.$process([doc]);\n    expect(doc.renderedContent).toEqual('<code>xyz-MyClass</code>');\n  });\n\n  it('should ignore code items that are filtered out by custom filters', () => {\n    autoLinkCode.customFilters = [filterPipes];\n    aliasMap.addDoc({ docType: 'pipe', id: 'MyClass', aliases: ['MyClass', 'myClass'], path: 'a/b/myclass', pipeOptions: { name: '\\'myClass\\'' } });\n    const doc = { docType: 'test-doc', renderedContent: '<code>{ xyz | myClass } { xyz|myClass } MyClass myClass OtherClass|MyClass</code>' };\n    processor.$process([doc]);\n    expect(doc.renderedContent).toEqual('<code>' +\n                                        '{ xyz | <a href=\"a/b/myclass\" class=\"code-anchor\">myClass</a> } '  +\n                                        '{ xyz|<a href=\"a/b/myclass\" class=\"code-anchor\">myClass</a> } ' +\n                                        '<a href=\"a/b/myclass\" class=\"code-anchor\">MyClass</a> ' +\n                                        'myClass OtherClass|<a href=\"a/b/myclass\" class=\"code-anchor\">MyClass</a>' +\n                                        '</code>');\n  });\n\n  it('should insert anchors for individual text nodes within a code block', () => {\n    aliasMap.addDoc({ docType: 'class', id: 'MyClass', aliases: ['MyClass'], path: 'a/b/myclass' });\n    const doc = { docType: 'test-doc', renderedContent: '<code><span>MyClass</span><span>MyClass</span></code>' };\n    processor.$process([doc]);\n    expect(doc.renderedContent).toEqual('<code><span><a href=\"a/b/myclass\" class=\"code-anchor\">MyClass</a></span><span><a href=\"a/b/myclass\" class=\"code-anchor\">MyClass</a></span></code>');\n  });\n\n  it('should insert anchors for words that match within text nodes in a code block', () => {\n    aliasMap.addDoc({ docType: 'class', id: 'MyClass', aliases: ['MyClass'], path: 'a/b/myclass' });\n    aliasMap.addDoc({ docType: 'function', id: 'myFunc', aliases: ['myFunc'], path: 'ng/myfunc' });\n    aliasMap.addDoc({ docType: 'const', id: 'MY_CONST', aliases: ['MY_CONST'], path: 'ng/my_const' });\n    const doc = { docType: 'test-doc', renderedContent: '<code>myFunc() {\\n  return new MyClass(MY_CONST);\\n}</code>' };\n    processor.$process([doc]);\n    expect(doc.renderedContent).toEqual('<code><a href=\"ng/myfunc\" class=\"code-anchor\">myFunc</a>() {\\n  return new <a href=\"a/b/myclass\" class=\"code-anchor\">MyClass</a>(<a href=\"ng/my_const\" class=\"code-anchor\">MY_CONST</a>);\\n}</code>');\n  });\n\n  it('should work with custom elements', () => {\n    autoLinkCode.codeElements = ['code-example'];\n    aliasMap.addDoc({ docType: 'class', id: 'MyClass', aliases: ['MyClass'], path: 'a/b/myclass' });\n    const doc = { docType: 'test-doc', renderedContent: '<code-example>MyClass</code-example>' };\n    processor.$process([doc]);\n    expect(doc.renderedContent).toEqual('<code-example><a href=\"a/b/myclass\" class=\"code-anchor\">MyClass</a></code-example>');\n  });\n});\n"
  },
  {
    "path": "apps/rxjs.dev/tools/transforms/angular-base-package/post-processors/autolink-headings.js",
    "content": "const has = require('hast-util-has-property');\nconst is = require('hast-util-is-element');\nconst slug = require('rehype-slug');\nconst visit = require('unist-util-visit');\n\n/**\n * Get remark to add IDs to headings and inject anchors into them.\n * This is a stripped-down equivalent of [rehype-autolink-headings](https://github.com/wooorm/rehype-autolink-headings)\n * that supports ignoring headings with the `no-anchor` class.\n */\nconst HEADINGS = ['h1', 'h2', 'h3', 'h4', 'h5', 'h6'];\nconst NO_ANCHOR_CLASS = 'no-anchor';\n\nconst clone = obj => JSON.parse(JSON.stringify(obj));\nconst hasClass = (node, cls) => {\n  const className = node.properties.className;\n  return className && className.includes(cls);\n};\n\nconst link = options =>\n  tree => visit(tree, node => {\n    if (is(node, HEADINGS) && has(node, 'id') && !hasClass(node, NO_ANCHOR_CLASS)) {\n      node.children.push({\n        type: 'element',\n        tagName: 'a',\n        properties: Object.assign(clone(options.properties), {href: `#${node.properties.id}`}),\n        children: clone(options.content)\n      });\n    }\n  });\n\nmodule.exports = [\n  slug,\n  [link, {\n    properties: {\n      title: 'Link to this heading',\n      className: ['header-link'],\n      'aria-hidden': 'true'\n    },\n    content: [\n      {\n        type: 'element',\n        tagName: 'i',\n        properties: {className: ['material-icons']},\n        children: [{ type: 'text', value: 'link' }]\n      }\n    ]\n  }]\n];\n"
  },
  {
    "path": "apps/rxjs.dev/tools/transforms/angular-base-package/post-processors/autolink-headings.spec.js",
    "content": "var testPackage = require('../../helpers/test-package');\nvar Dgeni = require('dgeni');\nconst plugin = require('./autolink-headings');\n\ndescribe('autolink-headings postprocessor', () => {\n  let processor;\n\n  beforeEach(() => {\n    const dgeni = new Dgeni([testPackage('angular-base-package')]);\n    const injector = dgeni.configureInjector();\n    processor = injector.get('postProcessHtml');\n    processor.docTypes = ['a'];\n    processor.plugins = [plugin];\n  });\n\n  it('should add anchors to headings', () => {\n    const originalContent = `\n      <h1>Heading 1</h2>\n      <h2>Heading with <strong>bold</strong></h2>\n      <h3>Heading with encoded chars &#x26;</h3>\n    `;\n    const processedContent = `\n      <h1 id=\"heading-1\">Heading 1<a title=\"Link to this heading\" class=\"header-link\" aria-hidden=\"true\" href=\"#heading-1\"><i class=\"material-icons\">link</i></a></h1>\n      <h2 id=\"heading-with-bold\">Heading with <strong>bold</strong><a title=\"Link to this heading\" class=\"header-link\" aria-hidden=\"true\" href=\"#heading-with-bold\"><i class=\"material-icons\">link</i></a></h2>\n      <h3 id=\"heading-with-encoded-chars-\">Heading with encoded chars &#x26;<a title=\"Link to this heading\" class=\"header-link\" aria-hidden=\"true\" href=\"#heading-with-encoded-chars-\"><i class=\"material-icons\">link</i></a></h3>\n    `;\n\n    const docs = [{docType: 'a', renderedContent: originalContent}];\n    processor.$process(docs);\n    expect(docs[0].renderedContent).toBe(processedContent);\n  });\n\n  it('should ignore headings with the `no-anchor` class', () => {\n    const originalContent = `\n      <h1 class=\"no-anchor\">Heading 1</h2>\n      <h2 class=\"no-anchor\">Heading with <strong>bold</strong></h2>\n      <h3 class=\"no-anchor\">Heading with encoded chars &#x26;</h3>\n    `;\n    const processedContent = `\n      <h1 class=\"no-anchor\" id=\"heading-1\">Heading 1</h1>\n      <h2 class=\"no-anchor\" id=\"heading-with-bold\">Heading with <strong>bold</strong></h2>\n      <h3 class=\"no-anchor\" id=\"heading-with-encoded-chars-\">Heading with encoded chars &#x26;</h3>\n    `;\n\n    const docs = [{docType: 'a', renderedContent: originalContent}];\n    processor.$process(docs);\n    expect(docs[0].renderedContent).toBe(processedContent);\n  });\n});\n\n"
  },
  {
    "path": "apps/rxjs.dev/tools/transforms/angular-base-package/post-processors/h1-checker.js",
    "content": "const visit = require('unist-util-visit');\nconst is = require('hast-util-is-element');\nconst toString = require('hast-util-to-string');\nconst filter = require('unist-util-filter');\n\nmodule.exports = function h1CheckerPostProcessor() {\n  return (ast, file) => {\n    file.headings = {\n      h1: [],\n      h2: [],\n      h3: [],\n      h4: [],\n      h5: [],\n      h6: [],\n      hgroup: []\n    };\n    visit(ast, node => {\n      if (is(node, ['h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'hgroup'])) {\n        file.headings[node.tagName].push(getText(node));\n      }\n    });\n\n    file.title = file.headings.h1[0];\n    if (file.headings.h1.length > 1) {\n      file.fail(`More than one h1 found in ${file}`);\n    }\n  };\n};\n\nfunction getText(h1) {\n  // Remove the aria-hidden anchor from the h1 node\n  const cleaned = filter(h1, node => !(\n    is(node, 'a') && node.properties &&\n    (node.properties.ariaHidden === 'true' || node.properties['aria-hidden'] === 'true')\n  ));\n\n  return cleaned ? toString(cleaned) : '';\n}\n"
  },
  {
    "path": "apps/rxjs.dev/tools/transforms/angular-base-package/post-processors/h1-checker.spec.js",
    "content": "var testPackage = require('../../helpers/test-package');\nvar Dgeni = require('dgeni');\nconst plugin = require('./h1-checker');\n\ndescribe('h1Checker postprocessor', () => {\n  let processor, createDocMessage;\n\n  beforeEach(() => {\n    const dgeni = new Dgeni([testPackage('angular-base-package')]);\n    const injector = dgeni.configureInjector();\n    createDocMessage = injector.get('createDocMessage');\n    processor = injector.get('postProcessHtml');\n    processor.docTypes = ['a'];\n    processor.plugins = [plugin];\n  });\n\n  it('should complain if there is more than one h1 in a document', () => {\n    const doc = {\n      docType: 'a',\n      renderedContent: `\n        <h1>Heading 1</h2>\n        <h2>Heading 2</h2>\n        <h1>Heading 1a</h1>\n    `\n    };\n    expect(() => processor.$process([doc])).toThrowError(createDocMessage('More than one h1 found in ' + doc.renderedContent, doc));\n  });\n\n  it('should not complain if there is exactly one h1 in a document', () => {\n    const doc = {\n      docType: 'a',\n      renderedContent: `\n        <h1>Heading 1</h2>\n        <h2>Heading 2</h2>\n    `\n    };\n    expect(() => processor.$process([doc])).not.toThrow();\n  });\n\n  it('should not complain if there are no h1s in a document', () => {\n    const doc = {\n      docType: 'a',\n      renderedContent: `\n        <h2>Heading 2</h2>\n    `\n    };\n    expect(() => processor.$process([doc])).not.toThrow();\n  });\n\n  it('should attach the h1 text to the vFile', () => {\n    const doc = {\n      docType: 'a',\n      renderedContent: '<h1>Heading 1</h1>'\n    };\n    processor.$process([doc]);\n    expect(doc.vFile.title).toEqual('Heading 1');\n  });\n\n  it('should clean aria-hidden anchors from h1 text added to the vFile', () => {\n    const doc = {\n      docType: 'a',\n      renderedContent:\n        '<h1 class=\"no-toc\" id=\"what-is-angular\">' +\n          '<a title=\"Link to this heading\" class=\"header-link\" aria-hidden=\"true\" href=\"docs#what-is-angular\">' +\n            '<i class=\"material-icons\">link</i>' +\n          '</a>What is Angular?' +\n        '</h1>'\n    };\n    processor.$process([doc]);\n    expect(doc.vFile.title).toEqual('What is Angular?');\n  });\n\n  it('should not break if the h1 is empty (except for an aria-hidden anchor)', () => {\n    const doc = {\n      docType: 'a',\n      renderedContent: `\n        <h1><a aria-hidden=\"true\"></a></h1>\n      `\n    };\n    expect(() => processor.$process([doc])).not.toThrow();\n  });\n});\n"
  },
  {
    "path": "apps/rxjs.dev/tools/transforms/angular-base-package/processors/checkUnbalancedBackTicks.js",
    "content": "var _ = require('lodash');\n\n/**\n * @dgProcessor checkUnbalancedBackTicks\n * @description\n * Searches the rendered content for an odd number of (```) backticks,\n * which would indicate an unbalanced pair and potentially a typo in the\n * source content.\n */\nmodule.exports = function checkUnbalancedBackTicks(log, createDocMessage) {\n\n  var BACKTICK_REGEX = /^ *```/gm;\n\n  return {\n    // $runAfter: ['checkAnchorLinksProcessor'],\n    $runAfter: ['inlineTagProcessor'],\n    $runBefore: ['writeFilesProcessor'],\n    $process: function(docs) {\n      _.forEach(docs, function(doc) {\n        if (doc.renderedContent) {\n          var matches = doc.renderedContent.match(BACKTICK_REGEX);\n          if (matches && matches.length % 2 !== 0) {\n            doc.unbalancedBackTicks = true;\n            log.warn(createDocMessage(\n              'checkUnbalancedBackTicks processor: unbalanced backticks found in rendered content',\n              doc));\n            log.warn(doc.renderedContent);\n          }\n        }\n      });\n    }\n  };\n};"
  },
  {
    "path": "apps/rxjs.dev/tools/transforms/angular-base-package/processors/checkUnbalancedBackTicks.spec.js",
    "content": "var testPackage = require('../../helpers/test-package');\nvar Dgeni = require('dgeni');\n\ndescribe('checkUnbalancedBackTicks', function() {\n  var dgeni, injector, processor, log;\n\n  beforeEach(function() {\n    dgeni = new Dgeni([testPackage('angular-base-package')]);\n    injector = dgeni.configureInjector();\n    processor = injector.get('checkUnbalancedBackTicks');\n    log = injector.get('log');\n  });\n\n  it('should warn if there are an odd number of back ticks in the rendered content', function() {\n    var docs = [{\n      renderedContent: '```\\n' +\n          'code block\\n' +\n          '```\\n' +\n          '```\\n' +\n          'code block with missing closing back ticks\\n'\n    }];\n\n    processor.$process(docs);\n\n    expect(log.warn).toHaveBeenCalledWith(\n      'checkUnbalancedBackTicks processor: unbalanced backticks found in rendered content - doc');\n    expect(docs[0].unbalancedBackTicks).toBe(true);\n  });\n});\n"
  },
  {
    "path": "apps/rxjs.dev/tools/transforms/angular-base-package/processors/convertToJson.js",
    "content": "module.exports = function convertToJsonProcessor(log, createDocMessage) {\n\n  return {\n    $runAfter: ['checkUnbalancedBackTicks'],\n    $runBefore: ['writeFilesProcessor'],\n    docTypes: [],\n    $process: function(docs) {\n      const docTypes = this.docTypes;\n      docs.forEach((doc) => {\n        if (docTypes.indexOf(doc.docType) !== -1) {\n          let contents = doc.renderedContent || '';\n\n          let title = doc.title;\n\n          // We do allow an empty `title` but if it is `undefined` we resort to `vFile.title` and then `name`\n          if (title === undefined) {\n            title = (doc.vFile && doc.vFile.title);\n          }\n\n          if (title === undefined) {\n            title = doc.name;\n          }\n\n          // If there is still no title then log a warning\n          if (title === undefined) {\n            title = '';\n            log.warn(createDocMessage('Title property expected', doc));\n          }\n\n          doc.renderedContent = JSON.stringify({ id: doc.path, title, contents }, null, 2);\n        }\n      });\n    }\n  };\n\n};\n"
  },
  {
    "path": "apps/rxjs.dev/tools/transforms/angular-base-package/processors/convertToJson.spec.js",
    "content": "var testPackage = require('../../helpers/test-package');\nvar Dgeni = require('dgeni');\n\ndescribe('convertToJson processor', () => {\n  var dgeni, injector, processor, log;\n\n  beforeEach(function() {\n    dgeni = new Dgeni([testPackage('angular-base-package')]);\n    injector = dgeni.configureInjector();\n    processor = injector.get('convertToJsonProcessor');\n    log = injector.get('log');\n    processor.docTypes = ['test-doc'];\n  });\n\n  it('should be part of the dgeni package', () => {\n    expect(processor).toBeDefined();\n  });\n\n  it('should convert the renderedContent to JSON', () => {\n    const docs = [{\n      docType: 'test-doc',\n      title: 'The Title',\n      name: 'The Name',\n      path: 'test/doc',\n      renderedContent: 'Some Content'\n    }];\n    processor.$process(docs);\n    expect(JSON.parse(docs[0].renderedContent).id).toEqual('test/doc');\n    expect(JSON.parse(docs[0].renderedContent).title).toEqual('The Title');\n    expect(JSON.parse(docs[0].renderedContent).contents).toEqual('Some Content');\n  });\n\n  it('should get the title from name if no title is specified', () => {\n    const docs = [{ docType: 'test-doc', name: 'The Name' }];\n    processor.$process(docs);\n    expect(JSON.parse(docs[0].renderedContent).title).toEqual('The Name');\n  });\n\n  it('should accept an empty title', () => {\n    const docs = [{ docType: 'test-doc', title: '' }];\n    processor.$process(docs);\n    expect(JSON.parse(docs[0].renderedContent).title).toEqual('');\n    expect(log.warn).not.toHaveBeenCalled();\n  });\n\n  it('should accept an empty name if title is not provided', () => {\n    const docs = [{ docType: 'test-doc', name: '' }];\n    processor.$process(docs);\n    expect(JSON.parse(docs[0].renderedContent).title).toEqual('');\n    expect(log.warn).not.toHaveBeenCalled();\n  });\n\n  it('should get the title from the title extracted from the h1 in the rendered content if no title property is specified', () => {\n    const docs = [{\n      docType: 'test-doc',\n      vFile: { title: 'Some title' },\n      renderedContent: '<div><h1 class=\"title\">Some title</h1><article><h1>Article 1</h1></article></div>'\n    }];\n    processor.$process(docs);\n    expect(JSON.parse(docs[0].renderedContent).contents).toEqual('<div><h1 class=\"title\">Some title</h1><article><h1>Article 1</h1></article></div>');\n    expect(JSON.parse(docs[0].renderedContent).title).toEqual('Some title');\n  });\n\n  it('should set missing titles to empty', () => {\n    const docs = [{ docType: 'test-doc' }];\n    processor.$process(docs);\n    expect(JSON.parse(docs[0].renderedContent).title).toBe('');\n  });\n\n  it('should log a warning', () => {\n    const docs = [{ docType: 'test-doc' }];\n    processor.$process(docs);\n    expect(log.warn).toHaveBeenCalledWith('Title property expected - doc (test-doc) ');\n  });\n});"
  },
  {
    "path": "apps/rxjs.dev/tools/transforms/angular-base-package/processors/copyContentAssets.js",
    "content": "\nmodule.exports = function copyContentAssetsProcessor(copyFolder) {\n  return {\n    $runBefore: ['postProcessHtml'],\n    assetMappings: [],\n    $process() {\n      this.assetMappings.forEach(map => {\n        copyFolder(map.from, map.to);\n      });\n    }\n  };\n};\n"
  },
  {
    "path": "apps/rxjs.dev/tools/transforms/angular-base-package/processors/copyContentAssets.spec.js",
    "content": "const testPackage = require('../../helpers/test-package');\nconst Dgeni = require('dgeni');\nconst factory = require('./copyContentAssets');\n\ndescribe('extractDecoratedClasses processor', function() {\n  let dgeni, injector, processor;\n\n  beforeEach(function() {\n    dgeni = new Dgeni([testPackage('angular-content-package')]);\n    injector = dgeni.configureInjector();\n    processor = injector.get('copyContentAssetsProcessor');\n  });\n\n  it('should exist', () => {\n    expect(processor).toBeDefined();\n  });\n\n  it('should call copyFolder with each mapping', () => {\n    const mockCopyFolder = jasmine.createSpy();\n    processor = factory(mockCopyFolder);\n    processor.assetMappings.push({ from: 'a/b/c', to: 'x/y/z' });\n    processor.assetMappings.push({ from: '1/2/3', to: '4/5/6' });\n    processor.$process();\n    expect(mockCopyFolder).toHaveBeenCalledWith('a/b/c', 'x/y/z');\n    expect(mockCopyFolder).toHaveBeenCalledWith('1/2/3', '4/5/6');\n  });\n});\n"
  },
  {
    "path": "apps/rxjs.dev/tools/transforms/angular-base-package/processors/createSitemap.js",
    "content": "module.exports = function createSitemap() {\n  return {\n    blacklistedDocTypes: [\n      'navigation-json',\n      'contributors-json',\n      'resources-json',\n    ],\n    blacklistedPaths: [\n      'test',\n      'file-not-found',\n      'overview-dump'\n    ],\n    $runAfter: ['paths-computed'],\n    $runBefore: ['rendering-docs'],\n    $process(docs) {\n      docs.push({\n        id: 'sitemap.xml',\n        path: 'sitemap.xml',\n        outputPath: '../sitemap.xml',\n        template: 'sitemap.template.xml',\n        urls: docs\n          // Filter out docs that are not outputted\n          .filter(doc => doc.outputPath)\n          // Filter out unwanted docs\n          .filter(doc => this.blacklistedDocTypes.indexOf(doc.docType) === -1)\n          .filter(doc => this.blacklistedPaths.indexOf(doc.path) === -1)\n          // Filter out duplicate renamed exports\n          .filter(doc => !doc.duplicateOf)\n          // Capture the path of each doc\n          .map(doc => doc.path)\n          // Convert the homepage: `index` to `/`\n          .map(path => path === 'index' ? '' : path)\n      });\n    }\n  };\n};\n"
  },
  {
    "path": "apps/rxjs.dev/tools/transforms/angular-base-package/processors/createSitemap.spec.js",
    "content": "var testPackage = require('../../helpers/test-package');\nvar Dgeni = require('dgeni');\n\ndescribe('createSitemap processor', () => {\n  var injector, processor;\n\n  beforeEach(() => {\n    const dgeni = new Dgeni([testPackage('angular-base-package')]);\n\n    injector = dgeni.configureInjector();\n    processor = injector.get('createSitemap');\n  });\n\n  it('should be available from the injector', () => {\n    expect(processor).toBeDefined();\n  });\n\n  it('should run after \"paths-computed\"', () => {\n    expect(processor.$runAfter).toEqual(['paths-computed']);\n  });\n\n  it('should run before \"rendering-docs\"', () => {\n    expect(processor.$runBefore).toEqual(['rendering-docs']);\n  });\n\n  describe('$process', () => {\n    describe('should add a sitemap doc', () => {\n\n      it('with the correct id, path, outputPath and template properties', () => {\n        const docs = [];\n        processor.$process(docs);\n        expect(docs.pop()).toEqual(jasmine.objectContaining({\n          id: 'sitemap.xml',\n          path: 'sitemap.xml',\n          outputPath: '../sitemap.xml',\n          template: 'sitemap.template.xml'\n        }));\n      });\n\n      it('with an array of urls for each doc that has an outputPath', () => {\n        const docs = [\n          { path: 'abc', outputPath: 'abc' },\n          { path: 'cde' },\n          { path: 'fgh', outputPath: 'fgh' },\n        ];\n        processor.$process(docs);\n        expect(docs.pop().urls).toEqual(['abc', 'fgh']);\n      });\n\n      it('ignoring blacklisted doc types', () => {\n        const docs = [\n          { path: 'abc', outputPath: 'abc', docType: 'good' },\n          { path: 'cde', outputPath: 'cde', docType: 'bad' },\n          { path: 'fgh', outputPath: 'fgh', docType: 'good' },\n        ];\n        processor.blacklistedDocTypes = ['bad'];\n        processor.$process(docs);\n        expect(docs.pop().urls).toEqual(['abc', 'fgh']);\n      });\n\n      it('ignoring blacklisted paths', () => {\n        const docs = [\n          { path: 'abc', outputPath: 'abc' },\n          { path: 'cde', outputPath: 'cde' },\n          { path: 'fgh', outputPath: 'fgh' },\n        ];\n        processor.blacklistedPaths = ['cde'];\n        processor.$process(docs);\n        expect(docs.pop().urls).toEqual(['abc', 'fgh']);\n      });\n\n      it('mapping the home page\\'s path to `/`', () => {\n        const docs = [\n          { path: 'abc', outputPath: 'abc' },\n          { path: 'index', outputPath: 'index.json' },\n          { path: 'fgh', outputPath: 'fgh' },\n        ];\n        processor.$process(docs);\n        expect(docs.pop().urls).toEqual(['abc', '', 'fgh']);\n      });\n    });\n  });\n});"
  },
  {
    "path": "apps/rxjs.dev/tools/transforms/angular-base-package/processors/fixInternalDocumentLinks.js",
    "content": "/**\n * @dgProcessor fixInternalDocumentLinks\n * @description\n * Add in the document path to links that start with a hash.\n * This is important when the web app has a base href in place,\n * since links like: `<a href=\"#some-id\">` would get mapped to\n * the URL `base/#some-id` even if the current location is `base/some/doc`.\n */\nmodule.exports = function fixInternalDocumentLinks() {\n\n  var INTERNAL_LINK = /(<a [^>]*href=\")(#[^\"]*)/g;\n\n  return {\n    $runAfter: ['inlineTagProcessor'],\n    $runBefore: ['convertToJsonProcessor'],\n    $process: function(docs) {\n      docs.forEach(doc => {\n        doc.renderedContent = doc.renderedContent.replace(INTERNAL_LINK, (_, pre, hash) => {\n          return pre + doc.path + hash;\n        });\n      });\n    }\n  };\n};"
  },
  {
    "path": "apps/rxjs.dev/tools/transforms/angular-base-package/processors/fixInternalDocumentLinks.spec.js",
    "content": "const testPackage = require('../../helpers/test-package');\nconst processorFactory = require('./fixInternalDocumentLinks');\nconst Dgeni = require('dgeni');\n\ndescribe('fixInternalDocumentLinks processor', () => {\n\n  it('should be available on the injector', () => {\n    const dgeni = new Dgeni([testPackage('angular-base-package')]);\n    const injector = dgeni.configureInjector();\n    const processor = injector.get('fixInternalDocumentLinks');\n    expect(processor.$process).toBeDefined();\n  });\n\n  it('should run before the correct processor', () => {\n    const processor = processorFactory();\n    expect(processor.$runBefore).toEqual(['convertToJsonProcessor']);\n  });\n\n  it('should run after the correct processor', () => {\n    const processor = processorFactory();\n    expect(processor.$runAfter).toEqual(['inlineTagProcessor']);\n  });\n\n  it('should prefix internal hash links with the current doc path', () => {\n    const processor = processorFactory();\n    const docs = [\n      {\n        path: 'some/doc',\n        renderedContent: `\n          <a href=\"http://google.com#q=angular\">Google</a>\n          <a href=\"some/relative/path#some-id\">Some Id</a>\n          <a href=\"#some-internal-id\">Link to heading</a>\n          <a class=\"important\" href=\"#some-internal-id\">Link to heading</a>\n          <a href=\"#some-internal-id\" target=\"_blank\">Link to heading</a>\n        `\n      },\n    ];\n    processor.$process(docs);\n    expect(docs).toEqual([\n      {\n        path: 'some/doc',\n        renderedContent: `\n          <a href=\"http://google.com#q=angular\">Google</a>\n          <a href=\"some/relative/path#some-id\">Some Id</a>\n          <a href=\"some/doc#some-internal-id\">Link to heading</a>\n          <a class=\"important\" href=\"some/doc#some-internal-id\">Link to heading</a>\n          <a href=\"some/doc#some-internal-id\" target=\"_blank\">Link to heading</a>\n        `\n      },\n    ]);\n  });\n});\n"
  },
  {
    "path": "apps/rxjs.dev/tools/transforms/angular-base-package/processors/generateKeywords.js",
    "content": "\n/* eslint-disable */\n\n/**\n * @dgProcessor generateKeywordsProcessor\n * @description\n * This processor extracts all the keywords from each document and creates\n * a new document that will be rendered as a JavaScript file containing all\n * this data.\n */\nmodule.exports = function generateKeywordsProcessor(log) {\n  return {\n    ignoreWords: [],\n    propertiesToIgnore: [],\n    docTypesToIgnore: [],\n    outputFolder: '',\n    $validate: {\n      ignoreWords: {},\n      docTypesToIgnore: {},\n      propertiesToIgnore: {},\n      outputFolder: { presence: true },\n    },\n    $runAfter: ['postProcessHtml'],\n    $runBefore: ['writing-files'],\n    async $process(docs) {\n      const { stemmer: stem } = await import('stemmer');\n\n      const dictionary = new Map();\n\n      const emptySet = new Set();\n\n      // Keywords to ignore\n      const ignoreWords = new Set(this.ignoreWords);\n      log.debug('Words to ignore', ignoreWords);\n      const propertiesToIgnore = new Set(this.propertiesToIgnore);\n      log.debug('Properties to ignore', propertiesToIgnore);\n      const docTypesToIgnore = new Set(this.docTypesToIgnore);\n      log.debug('Doc types to ignore', docTypesToIgnore);\n\n      const filteredDocs = docs\n        // We are not interested in some docTypes\n        .filter((doc) => !docTypesToIgnore.has(doc.docType))\n        // Ignore internals and private exports (indicated by the ɵ prefix)\n        .filter((doc) => !doc.internal && !doc.privateExport)\n        // Ignore duplicates and remove the `/api/operators/` path entries from the search results\n        .filter((doc) => doc.path.indexOf('api/operators/') !== 0);\n\n      for (const doc of filteredDocs) {\n        // Search each top level property of the document for search terms\n        let mainTokens = [];\n        for (const key of Object.keys(doc)) {\n          const value = doc[key];\n          if (isString(value) && !propertiesToIgnore.has(key)) {\n            mainTokens.push(...tokenize(value, ignoreWords, dictionary));\n          }\n        }\n\n        const memberTokens = extractMemberTokens(doc, dictionary);\n\n        // Extract all the keywords from the headings\n        let headingTokens = [];\n        if (doc.vFile && doc.vFile.headings) {\n          for (const headingTag of Object.keys(doc.vFile.headings)) {\n            for (const headingText of doc.vFile.headings[headingTag]) {\n              headingTokens.push(...tokenize(headingText, ignoreWords, dictionary));\n            }\n          }\n        }\n\n        // Extract the title to use in searches\n        doc.searchTitle = doc.searchTitle || doc.title || (doc.vFile && doc.vFile.title) || doc.name || '';\n\n        // Attach all this search data to the document\n        doc.searchTerms = {};\n        if (headingTokens.length > 0) {\n          doc.searchTerms.headings = headingTokens;\n        }\n        if (mainTokens.length > 0) {\n          doc.searchTerms.keywords = mainTokens;\n        }\n        if (memberTokens.length > 0) {\n          doc.searchTerms.members = memberTokens;\n        }\n        if (doc.searchKeywords) {\n          doc.searchTerms.topics = doc.searchKeywords.trim();\n        }\n      }\n\n      // Now process all the search data and collect it up to be used in creating a new document\n      const searchData = {\n        dictionary: Array.from(dictionary.keys()).join(' '),\n        pages: filteredDocs.map((page) => {\n          // Copy the properties from the searchTerms object onto the search data object\n          const searchObj = {\n            path: page.path,\n            title: page.searchTitle,\n            type: page.docType,\n          };\n          if (page.deprecated) {\n            searchObj.deprecated = true;\n          }\n          return Object.assign(searchObj, page.searchTerms);\n        }),\n      };\n\n      docs.push({\n        docType: 'json-doc',\n        id: 'search-data-json',\n        path: this.outputFolder + '/search-data.json',\n        outputPath: this.outputFolder + '/search-data.json',\n        data: searchData,\n        renderedContent: JSON.stringify(searchData),\n      });\n\n      return docs;\n\n      // Helpers\n      function tokenize(text, ignoreWords, dictionary) {\n        // Split on whitespace and things that are likely to be HTML tags (this is not exhaustive but reduces the unwanted tokens that are indexed).\n        const rawTokens = text.split(\n          new RegExp(\n            '[\\\\s/]+' + // whitespace\n              '|' + // or\n              '</?[a-z]+(?:\\\\s+\\\\w+(?:=\"[^\"]+\")?)*/?>', // simple HTML tags (e.g. <td>, <hr/>, </table>, etc.)\n            'ig'\n          )\n        );\n        const tokens = [];\n        for (let token of rawTokens) {\n          token = token.trim();\n\n          // Trim unwanted trivia characters from the start and end of the token\n          const TRIVIA_CHARS = '[\\\\s_\"\\'`({[<$*)}\\\\]>.,-]';\n          // Tokens can contain letters, numbers, underscore, dot or hyphen but not at the start or end.\n          // The leading TRIVIA_CHARS will capture any leading `.`, '-`' or `_` so we don't have to avoid them in this regular expression.\n          // But we do need to ensure we don't capture the at the end of the token.\n          const POSSIBLE_TOKEN = '[a-z0-9_.-]*[a-z0-9]';\n          token = token.replace(new RegExp(`^${TRIVIA_CHARS}*(${POSSIBLE_TOKEN})${TRIVIA_CHARS}*$`, 'i'), '$1');\n\n          // Skip if blank or in the ignored words list\n          if (token === '' || ignoreWords.has(token.toLowerCase())) {\n            continue;\n          }\n\n          // Skip tokens that contain weird characters\n          if (!/^\\w[\\w.-]*$/.test(token)) {\n            continue;\n          }\n\n          storeToken(token, tokens, dictionary);\n          if (token.startsWith('ng')) {\n            // Strip off `ng`, `ng-`, `ng1`, `ng2`, etc\n            storeToken(token.replace(/^ng[-12]*/, ''), tokens, dictionary);\n          }\n        }\n\n        return tokens;\n      }\n\n      function storeToken(token, tokens, dictionary) {\n        token = stem(token);\n        if (!dictionary.has(token)) {\n          dictionary.set(token, dictionary.size);\n        }\n        tokens.push(dictionary.get(token));\n      }\n\n      function extractMemberTokens(doc, dictionary) {\n        if (!doc) return [];\n\n        let memberContent = [];\n\n        if (doc.members) {\n          doc.members.forEach((member) => memberContent.push(...tokenize(member.name, emptySet, dictionary)));\n        }\n        if (doc.statics) {\n          doc.statics.forEach((member) => memberContent.push(...tokenize(member.name, emptySet, dictionary)));\n        }\n        if (doc.extendsClauses) {\n          doc.extendsClauses.forEach((clause) => memberContent.push(...extractMemberTokens(clause.doc, dictionary)));\n        }\n        if (doc.implementsClauses) {\n          doc.implementsClauses.forEach((clause) => memberContent.push(...extractMemberTokens(clause.doc, dictionary)));\n        }\n\n        return memberContent;\n      }\n    },\n  };\n};\n\nfunction isString(value) {\n  return typeof value == 'string';\n}\n"
  },
  {
    "path": "apps/rxjs.dev/tools/transforms/angular-base-package/processors/generateKeywords.spec.js",
    "content": "const path = require('canonical-path');\nconst Dgeni = require('dgeni');\n\nconst testPackage = require('../../helpers/test-package');\nconst mockLogger = require('dgeni/lib/mocks/log')(false);\nconst processorFactory = require('./generateKeywords');\n\nconst mockReadFilesProcessor = {\n  basePath: 'base/path',\n};\n\nconst ignoreWords = require(path.resolve(__dirname, '../ignore-words'));\n\nfunction createProcessor() {\n  const processor = processorFactory(mockLogger, mockReadFilesProcessor);\n  processor.ignoreWords = ignoreWords;\n  return processor;\n}\n\ndescribe('generateKeywords processor', () => {\n  it('should be available on the injector', () => {\n    const dgeni = new Dgeni([testPackage('angular-base-package'), testPackage('angular-api-package')]);\n    const injector = dgeni.configureInjector();\n    const processor = injector.get('generateKeywordsProcessor');\n    expect(processor.$process).toBeDefined();\n  });\n\n  it('should run after the correct processor', () => {\n    const processor = createProcessor();\n    expect(processor.$runAfter).toEqual(['postProcessHtml']);\n  });\n\n  it('should run before the correct processor', () => {\n    const processor = createProcessor();\n    expect(processor.$runBefore).toEqual(['writing-files']);\n  });\n\n  it('should ignore internal and private exports', async () => {\n    const processor = createProcessor();\n    const docs = await processor.$process([\n      { docType: 'class', name: 'PublicExport', path: '' },\n      { docType: 'class', name: 'PrivateExport', privateExport: true, path: '' },\n      { docType: 'class', name: 'InternalExport', internal: true, path: '' },\n    ]);\n    expect(docs[docs.length - 1].data.pages).toEqual([jasmine.objectContaining({ title: 'PublicExport', type: 'class' })]);\n  });\n\n  it('should ignore docs that are in the `docTypesToIgnore` list', async () => {\n    const processor = createProcessor();\n    processor.docTypesToIgnore = ['interface'];\n    const docs = await processor.$process([\n      { docType: 'class', name: 'Class', path: '' },\n      { docType: 'interface', name: 'Interface', path: '' },\n      { docType: 'content', name: 'Guide', path: '' },\n    ]);\n    expect(docs[docs.length - 1].data.pages).toEqual([\n      jasmine.objectContaining({ title: 'Class', type: 'class' }),\n      jasmine.objectContaining({ title: 'Guide', type: 'content' }),\n    ]);\n  });\n\n  it('should not collect keywords from properties that are in the `propertiesToIgnore` list', async () => {\n    const processor = createProcessor();\n    processor.propertiesToIgnore = ['docType', 'ignore'];\n    const docs = await processor.$process([\n      { docType: 'class', name: 'FooClass', ignore: 'ignore this content', path: '' },\n      { docType: 'interface', name: 'BarInterface', capture: 'capture this content', path: '' },\n    ]);\n    expect(docs[docs.length - 1].data).toEqual({\n      dictionary: 'fooclass barinterfac captur content',\n      pages: [\n        jasmine.objectContaining({ title: 'FooClass', type: 'class', keywords: [0] }),\n        jasmine.objectContaining({ title: 'BarInterface', type: 'interface', keywords: [1, 2, 3] }),\n      ],\n    });\n  });\n\n  it('should not collect keywords that look like HTML tags', async () => {\n    const processor = createProcessor();\n    const docs = await processor.$process([\n      {\n        docType: 'class',\n        name: 'FooClass',\n        content: `\n      <table id=\"foo\">\n        <tr class=\"moo\" id=\"bar\">\n          <td>Content inside a table</td>\n        </tr>\n      </table>`,\n        path: '',\n      },\n    ]);\n    expect(docs[docs.length - 1].data).toEqual({\n      dictionary: 'class fooclass content insid tabl',\n      pages: [jasmine.objectContaining({ keywords: [0, 1, 2, 3, 4] })],\n    });\n  });\n\n  it('should compute `doc.searchTitle` from the doc properties if not already provided', async () => {\n    const processor = createProcessor();\n    const docs = await processor.$process([\n      { docType: 'class', name: 'A', searchTitle: 'searchTitle A', title: 'title A', vFile: { headings: { h1: ['vFile A'] } }, path: '' },\n      { docType: 'class', name: 'B', title: 'title B', vFile: { headings: { h1: ['vFile B'] } }, path: '' },\n      { docType: 'class', name: 'C', vFile: { title: 'vFile C', headings: { h1: ['vFile C'] } }, path: '' },\n      { docType: 'class', name: 'D', path: '' },\n    ]);\n    expect(docs[docs.length - 1].data.pages).toEqual([\n      jasmine.objectContaining({ title: 'searchTitle A' }),\n      jasmine.objectContaining({ title: 'title B' }),\n      jasmine.objectContaining({ title: 'vFile C' }),\n      jasmine.objectContaining({ title: 'D' }),\n    ]);\n  });\n\n  it('should use `doc.searchTitle` as the title in the search index', async () => {\n    const processor = createProcessor();\n    const docs = await processor.$process([{ docType: 'class', name: 'PublicExport', searchTitle: 'class PublicExport', path: '' }]);\n    const keywordsDoc = docs[docs.length - 1];\n    expect(keywordsDoc.data.pages).toEqual([jasmine.objectContaining({ title: 'class PublicExport', type: 'class' })]);\n  });\n\n  it('should add heading words to the search terms', async () => {\n    const processor = createProcessor();\n    const docs = await processor.$process([\n      {\n        docType: 'class',\n        name: 'PublicExport',\n        searchTitle: 'class PublicExport',\n        vFile: { headings: { h2: ['Important heading', 'Secondary heading'] } },\n        path: '',\n      },\n    ]);\n    const keywordsDoc = docs[docs.length - 1];\n    expect(keywordsDoc.data).toEqual({\n      dictionary: 'class publicexport head secondari',\n      pages: [jasmine.objectContaining({ headings: [2, 3, 2] })],\n    });\n  });\n\n  it('should add member doc properties to the search terms', async () => {\n    const processor = createProcessor();\n    const docs = await processor.$process([\n      {\n        docType: 'class',\n        name: 'PublicExport',\n        searchTitle: 'class PublicExport',\n        vFile: { headings: { h2: ['heading A'] } },\n        content: 'Some content with ngClass in it.',\n        members: [{ name: 'instanceMethodA' }, { name: 'instancePropertyA' }, { name: 'instanceMethodB' }, { name: 'instancePropertyB' }],\n        statics: [{ name: 'staticMethodA' }, { name: 'staticPropertyA' }, { name: 'staticMethodB' }, { name: 'staticPropertyB' }],\n        path: '',\n      },\n    ]);\n    const keywordsDoc = docs[docs.length - 1];\n    expect(keywordsDoc.data).toEqual({\n      dictionary:\n        'class publicexport content ngclass instancemethoda instancepropertya instancemethodb instancepropertyb staticmethoda staticpropertya staticmethodb staticpropertyb head',\n      pages: [\n        jasmine.objectContaining({\n          members: [4, 5, 6, 7, 8, 9, 10, 11],\n        }),\n      ],\n    });\n  });\n\n  it('should add member doc properties contained in the ignored word list to the search terms', async () => {\n    const processor = createProcessor();\n    const docs = await processor.$process([\n      {\n        docType: 'class',\n        name: 'PublicExport',\n        searchTitle: 'class PublicExport',\n        vFile: { headings: { h2: ['heading A'] } },\n        content: 'Some content with ngClass in it.',\n        members: [{ name: 'some' }, { name: 'none' }, { name: 'get' }, { name: 'put' }],\n        statics: [{ name: 'zero' }, { name: 'one' }, { name: 'next' }, { name: 'index' }],\n        path: '',\n      },\n    ]);\n    const keywordsDoc = docs[docs.length - 1];\n    expect(keywordsDoc.data).toEqual({\n      dictionary: 'class publicexport content ngclass some none get put zero on next index head',\n      pages: [\n        jasmine.objectContaining({\n          members: [4, 5, 6, 7, 8, 9, 10, 11],\n        }),\n      ],\n    });\n  });\n\n  it('should add inherited member doc properties to the search terms', async () => {\n    const processor = createProcessor();\n    const parentClass = {\n      docType: 'class',\n      name: 'ParentClass',\n      members: [{ name: 'parentMember1' }],\n      statics: [{ name: 'parentMember2' }],\n      path: '',\n    };\n    const parentInterface = {\n      docType: 'interface',\n      name: 'ParentInterface',\n      members: [{ name: 'parentMember3' }],\n      path: '',\n    };\n\n    const childClass = {\n      docType: 'class',\n      name: 'Child',\n      members: [{ name: 'childMember1' }],\n      statics: [{ name: 'childMember2' }],\n      extendsClauses: [{ doc: parentClass }],\n      implementsClauses: [{ doc: parentInterface }],\n      path: '',\n    };\n    const docs = await processor.$process([childClass, parentClass, parentInterface]);\n    const keywordsDoc = docs[docs.length - 1];\n    expect(keywordsDoc.data).toEqual({\n      dictionary: 'class child childmember1 childmember2 parentmember1 parentmember2 parentmember3 parentclass interfac parentinterfac',\n      pages: [\n        jasmine.objectContaining({\n          title: 'Child',\n          members: [2, 3, 4, 5, 6],\n        }),\n        jasmine.objectContaining({\n          title: 'ParentClass',\n          members: [4, 5],\n        }),\n        jasmine.objectContaining({\n          title: 'ParentInterface',\n          members: [6],\n        }),\n      ],\n    });\n  });\n\n  it('should add inherited member doc properties contained in the ignored word list to the search terms', async () => {\n    const processor = createProcessor();\n    const parentClass = {\n      docType: 'class',\n      name: 'ParentClass',\n      members: [{ name: 'one' }],\n      statics: [{ name: 'zero' }],\n      path: '',\n    };\n    const parentInterface = {\n      docType: 'interface',\n      name: 'ParentInterface',\n      members: [{ name: 'index' }],\n      path: '',\n    };\n\n    const childClass = {\n      docType: 'class',\n      name: 'Child',\n      members: [{ name: 'next' }],\n      statics: [{ name: 'get' }],\n      extendsClauses: [{ doc: parentClass }],\n      implementsClauses: [{ doc: parentInterface }],\n      path: '',\n    };\n    const docs = await processor.$process([childClass, parentClass, parentInterface]);\n    const keywordsDoc = docs[docs.length - 1];\n    expect(keywordsDoc.data).toEqual({\n      dictionary: 'class child next get on zero index parentclass interfac parentinterfac',\n      pages: [\n        jasmine.objectContaining({\n          title: 'Child',\n          members: [2, 3, 4, 5, 6],\n        }),\n        jasmine.objectContaining({\n          title: 'ParentClass',\n          members: [4, 5],\n        }),\n        jasmine.objectContaining({\n          title: 'ParentInterface',\n          members: [6],\n        }),\n      ],\n    });\n  });\n\n  it('should include both stripped and unstripped \"ng\" prefixed tokens', async () => {\n    const processor = createProcessor();\n    const docs = await processor.$process([\n      {\n        docType: 'class',\n        name: 'PublicExport',\n        searchTitle: 'ngController',\n        vFile: { headings: { h2: ['ngModel'] } },\n        content: 'Some content with ngClass in it.',\n        path: '',\n      },\n    ]);\n    const keywordsDoc = docs[docs.length - 1];\n    expect(keywordsDoc.data).toEqual({\n      dictionary: 'class publicexport ngcontrol control content ngclass ngmodel model',\n      pages: [\n        jasmine.objectContaining({\n          headings: [6, 7],\n          keywords: [0, 1, 2, 3, 4, 5, 0],\n        }),\n      ],\n    });\n  });\n\n  it('should generate compressed encoded renderedContent property', async () => {\n    const processor = createProcessor();\n    const docs = await processor.$process([\n      {\n        docType: 'class',\n        name: 'SomeClass',\n        description: 'The is the documentation for the SomeClass API.',\n        vFile: { headings: { h1: ['SomeClass'], h2: ['Some heading'] } },\n        path: '',\n      },\n      {\n        docType: 'class',\n        name: 'SomeClass2',\n        description: 'description',\n        members: [{ name: 'member1' }],\n        deprecated: true,\n        path: '',\n      },\n    ]);\n    const keywordsDoc = docs[docs.length - 1];\n    expect(JSON.parse(keywordsDoc.renderedContent)).toEqual({\n      dictionary: 'class someclass document api head someclass2 descript member1',\n      pages: [\n        {\n          path: '',\n          title: 'SomeClass',\n          type: 'class',\n          headings: [1, 4],\n          keywords: [0, 1, 2, 1, 3],\n        },\n        {\n          path: '',\n          title: 'SomeClass2',\n          type: 'class',\n          keywords: [0, 5, 6],\n          members: [7],\n          deprecated: true,\n        },\n      ],\n    });\n  });\n});\n"
  },
  {
    "path": "apps/rxjs.dev/tools/transforms/angular-base-package/processors/renderLinkInfo.js",
    "content": "/**\n * @dgProcessor renderLinkInfo\n * @description For each doc that has one of the specified docTypes,\n * add HTML comments that describe the links to and from the doc.\n */\nmodule.exports = function renderLinkInfo(extractLinks) {\n  return {\n    docTypes: [],\n    $runBefore: ['convertToJsonProcessor'],\n    $runAfter: ['fixInternalDocumentLinks'],\n    $process(docs) {\n      const toLinks = {};\n      const fromLinks = {};\n      const docsToCheck = docs.filter(doc => this.docTypes.indexOf(doc.docType) !==  -1);\n\n      // Extract and store all links found in each doc in hashes\n      docsToCheck.forEach(doc => {\n        const linksFromDoc = extractLinks(doc.renderedContent).hrefs;\n        // Update the hashes\n        fromLinks[doc.path] = linksFromDoc;\n        linksFromDoc.forEach(linkPath => {\n          linkPath = linkPath.match(/^[^#?]+/)[0]; // remove the query and hash from the link\n          (toLinks[linkPath] = toLinks[linkPath] || []).push(doc.path);\n        });\n      });\n\n      // Add HTML comments to the end of the rendered content that list the links found above\n      docsToCheck.forEach(doc => {\n        const linksFromDoc = getLinks(fromLinks, doc.path);\n        const linksToDoc = getLinks(toLinks, doc.path);\n        doc.renderedContent +=\n        `\\n<!-- links to this doc:${linksToDoc.map(link => `\\n - ${link}`).join('')}\\n-->\\n` +\n        `<!-- links from this doc:${linksFromDoc.map(link => `\\n - ${link}`).join('')}\\n-->`;\n      });\n    }\n  };\n};\n\nfunction getLinks(hash, docPath) {\n  const links = (hash[docPath] || []).filter(link => link !== docPath);\n  const internal = {};\n  const external = {};\n  links.forEach(link => {\n    if (/^[^:/#?]+:/.test(link)) {\n      external[link] = true;\n    } else {\n      internal[link] = true;\n    }\n  });\n  return Object.keys(internal).sort()\n    .concat(Object.keys(external).sort());\n}\n"
  },
  {
    "path": "apps/rxjs.dev/tools/transforms/angular-base-package/processors/renderLinkInfo.spec.js",
    "content": "const testPackage = require('../../helpers/test-package');\nconst processorFactory = require('./renderLinkInfo');\nconst extractLinks = require('dgeni-packages/base/services/extractLinks')();\nconst Dgeni = require('dgeni');\n\ndescribe('renderLinkInfo processor', () => {\n\n  it('should be available on the injector', () => {\n    const dgeni = new Dgeni([testPackage('angular-base-package')]);\n    const injector = dgeni.configureInjector();\n    const processor = injector.get('renderLinkInfo');\n    expect(processor.$process).toBeDefined();\n  });\n\n  it('should run before the correct processor', () => {\n    const processor = processorFactory(extractLinks);\n    expect(processor.$runBefore).toEqual(['convertToJsonProcessor']);\n  });\n\n  it('should run after the correct processor', () => {\n    const processor = processorFactory(extractLinks);\n    expect(processor.$runAfter).toEqual(['fixInternalDocumentLinks']);\n  });\n\n  it('should add HTML comments for links out of docs', () => {\n    const processor = processorFactory(extractLinks);\n    processor.docTypes = ['test'];\n    const docs = [\n      { path: 'test-1', docType: 'test', renderedContent: '<a href=\"a/b/c\"></a><a href=\"x/y/z\"></a>' },\n      { path: 'test-2', docType: 'test', renderedContent: '<a href=\"foo\"></a><a href=\"bar\"></a>' },\n    ];\n    processor.$process(docs);\n    expect(docs).toEqual([\n      {\n        path: 'test-1',\n        docType: 'test',\n        renderedContent: '<a href=\"a/b/c\"></a><a href=\"x/y/z\"></a>\\n' +\n                         '<!-- links to this doc:\\n-->\\n' +\n                         '<!-- links from this doc:\\n - a/b/c\\n - x/y/z\\n-->'\n      },\n      {\n        path: 'test-2',\n        docType: 'test',\n        renderedContent: '<a href=\"foo\"></a><a href=\"bar\"></a>\\n' +\n                         '<!-- links to this doc:\\n-->\\n' +\n                         '<!-- links from this doc:\\n - bar\\n - foo\\n-->'\n      },\n    ]);\n  });\n\n  it('should order links alphabetically', () => {\n    const processor = processorFactory(extractLinks);\n    processor.docTypes = ['test'];\n    const docs = [\n      { path: 'test-1', docType: 'test', renderedContent: '<a href=\"orange\"></a><a href=\"apple\"></a><a href=\"banana\"></a>' },\n    ];\n    processor.$process(docs);\n    expect(docs).toEqual([\n      {\n        path: 'test-1',\n        docType: 'test',\n        renderedContent: '<a href=\"orange\"></a><a href=\"apple\"></a><a href=\"banana\"></a>\\n' +\n                         '<!-- links to this doc:\\n-->\\n' +\n                         '<!-- links from this doc:\\n - apple\\n - banana\\n - orange\\n-->'\n      },\n    ]);\n  });\n\n  it('should list repeated links only once', () => {\n    const processor = processorFactory(extractLinks);\n    processor.docTypes = ['test'];\n    const docs = [\n      { path: 'test-1', docType: 'test', renderedContent: '<a href=\"banana\"></a><a href=\"apple\"></a><a href=\"banana\"></a>' },\n    ];\n    processor.$process(docs);\n    expect(docs).toEqual([\n      {\n        path: 'test-1',\n        docType: 'test',\n        renderedContent: '<a href=\"banana\"></a><a href=\"apple\"></a><a href=\"banana\"></a>\\n' +\n                         '<!-- links to this doc:\\n-->\\n' +\n                         '<!-- links from this doc:\\n - apple\\n - banana\\n-->'\n      },\n    ]);\n  });\n\n  it('should list internal links before external', () => {\n    const processor = processorFactory(extractLinks);\n    processor.docTypes = ['test'];\n    const docs = [\n      { path: 'test-1', docType: 'test', renderedContent: '<a href=\"https://www.google.com\"></a><a href=\"apple\"></a><a href=\"ftp://myfile.org\"></a>' },\n    ];\n    processor.$process(docs);\n    expect(docs).toEqual([\n      {\n        path: 'test-1',\n        docType: 'test',\n        renderedContent: '<a href=\"https://www.google.com\"></a><a href=\"apple\"></a><a href=\"ftp://myfile.org\"></a>\\n' +\n                         '<!-- links to this doc:\\n-->\\n' +\n                         '<!-- links from this doc:\\n - apple\\n - ftp://myfile.org\\n - https://www.google.com\\n-->'\n      },\n    ]);\n  });\n\n  it('should ignore docs that do not have the specified docType', () => {\n    const processor = processorFactory(extractLinks);\n    processor.docTypes = ['test'];\n    const docs = [\n      { path: 'test-1', docType: 'test', renderedContent: '<a href=\"a/b/c\"></a><a href=\"x/y/z\"></a>' },\n      { path: 'test-2', docType: 'test2', renderedContent: '<a href=\"foo\"></a><a href=\"bar\"></a>' },\n    ];\n    processor.$process(docs);\n    expect(docs).toEqual([\n      {\n        path: 'test-1',\n        docType: 'test',\n        renderedContent: '<a href=\"a/b/c\"></a><a href=\"x/y/z\"></a>\\n' +\n                         '<!-- links to this doc:\\n-->\\n' +\n                         '<!-- links from this doc:\\n - a/b/c\\n - x/y/z\\n-->'\n      },\n      {\n        path: 'test-2',\n        docType: 'test2',\n        renderedContent: '<a href=\"foo\"></a><a href=\"bar\"></a>'\n      },\n    ]);\n  });\n\n  it('should add HTML comments for links into docs', () => {\n    const processor = processorFactory(extractLinks);\n    processor.docTypes = ['test'];\n    const docs = [\n      { path: 'test-1', docType: 'test', renderedContent: '<a href=\"test-2\"></a>' },\n      { path: 'test-2', docType: 'test', renderedContent: '<a href=\"test-1\"></a><a href=\"test-3\"></a>' },\n      { path: 'test-3', docType: 'test', renderedContent: '<a href=\"test-1\"></a><a href=\"test-2\"></a>' },\n    ];\n    processor.$process(docs);\n    expect(docs).toEqual([\n      {\n        path: 'test-1',\n        docType: 'test',\n        renderedContent: '<a href=\"test-2\"></a>\\n' +\n        '<!-- links to this doc:\\n - test-2\\n - test-3\\n-->\\n' +\n        '<!-- links from this doc:\\n - test-2\\n-->'\n      },\n      {\n        path: 'test-2',\n        docType: 'test',\n        renderedContent: '<a href=\"test-1\"></a><a href=\"test-3\"></a>\\n' +\n        '<!-- links to this doc:\\n - test-1\\n - test-3\\n-->\\n' +\n        '<!-- links from this doc:\\n - test-1\\n - test-3\\n-->'\n      },\n      {\n        path: 'test-3',\n        docType: 'test',\n        renderedContent: '<a href=\"test-1\"></a><a href=\"test-2\"></a>\\n' +\n        '<!-- links to this doc:\\n - test-2\\n-->\\n' +\n        '<!-- links from this doc:\\n - test-1\\n - test-2\\n-->'\n      },\n    ]);\n  });\n\n  it('should not include links to themselves', () => {\n    const processor = processorFactory(extractLinks);\n    processor.docTypes = ['test'];\n    const docs = [\n      { path: 'test-1', docType: 'test', renderedContent: '<a href=\"test-2\"></a>' },\n      { path: 'test-2', docType: 'test', renderedContent: '<a href=\"test-1\"></a><a href=\"test-2\"></a>' },\n    ];\n    processor.$process(docs);\n    expect(docs).toEqual([\n      {\n        path: 'test-1',\n        docType: 'test',\n        renderedContent: '<a href=\"test-2\"></a>\\n' +\n        '<!-- links to this doc:\\n - test-2\\n-->\\n' +\n        '<!-- links from this doc:\\n - test-2\\n-->'\n      },\n      {\n        path: 'test-2',\n        docType: 'test',\n        renderedContent: '<a href=\"test-1\"></a><a href=\"test-2\"></a>\\n' +\n        '<!-- links to this doc:\\n - test-1\\n-->\\n' +\n        '<!-- links from this doc:\\n - test-1\\n-->'\n      },\n    ]);\n  });\n\n  it('should match links that contain fragments or queries', () => {\n    const processor = processorFactory(extractLinks);\n    processor.docTypes = ['test'];\n    const docs = [\n      { path: 'test-1', docType: 'test', renderedContent: '<a href=\"test-2#foo\"></a>' },\n      { path: 'test-2', docType: 'test', renderedContent: '<a href=\"test-1?some-query\"></a>' },\n      { path: 'test-3', docType: 'test', renderedContent: '<a href=\"test-1?some-query#foo\"></a>' },\n    ];\n    processor.$process(docs);\n    expect(docs).toEqual([\n      {\n        path: 'test-1',\n        docType: 'test',\n        renderedContent: '<a href=\"test-2#foo\"></a>\\n' +\n        '<!-- links to this doc:\\n - test-2\\n - test-3\\n-->\\n' +\n        '<!-- links from this doc:\\n - test-2#foo\\n-->'\n      },\n      {\n        path: 'test-2',\n        docType: 'test',\n        renderedContent: '<a href=\"test-1?some-query\"></a>\\n' +\n        '<!-- links to this doc:\\n - test-1\\n-->\\n' +\n        '<!-- links from this doc:\\n - test-1?some-query\\n-->'\n      },\n      {\n        path: 'test-3',\n        docType: 'test',\n        renderedContent: '<a href=\"test-1?some-query#foo\"></a>\\n' +\n        '<!-- links to this doc:\\n-->\\n' +\n        '<!-- links from this doc:\\n - test-1?some-query#foo\\n-->'\n      },\n    ]);\n  });\n});\n"
  },
  {
    "path": "apps/rxjs.dev/tools/transforms/angular-base-package/readers/json.js",
    "content": "/**\n * Read in JSON files\n */\nmodule.exports = function jsonFileReader() {\n  return {\n    name: 'jsonFileReader',\n    getDocs: function(fileInfo) {\n\n      // We return a single element array because content files only contain one document\n      return [{\n        docType: fileInfo.baseName + '-json',\n        data: JSON.parse(fileInfo.content),\n        template: 'json-doc.template.json',\n        id: fileInfo.baseName,\n        aliases: [fileInfo.baseName, fileInfo.relativePath]\n      }];\n    }\n  };\n};"
  },
  {
    "path": "apps/rxjs.dev/tools/transforms/angular-base-package/rendering/filterByPropertyValue.js",
    "content": "module.exports = function filterBy() {\n  return {\n    name: 'filterByPropertyValue',\n    process: function(list, property, value) {\n      if (!list) return list;\n      return list.filter(item => item[property] === value);\n    }\n  };\n};"
  },
  {
    "path": "apps/rxjs.dev/tools/transforms/angular-base-package/rendering/filterByPropertyValue.spec.js",
    "content": "const factory = require('./filterByPropertyValue');\n\ndescribe('filterByPropertyValue filter', () => {\n  let filter;\n\n  beforeEach(function() { filter = factory(); });\n\n  it('should be called \"filterByPropertyValue\"', function() { expect(filter.name).toEqual('filterByPropertyValue'); });\n\n  it('should filter out items that do not match the given property value', function() {\n    expect(filter.process([{ a: 1 }, { a: 2 }, { b: 1 }, { a: 1, b: 2 }, { a: null }, { a: undefined }], 'a', 1))\n      .toEqual([{ a: 1 }, { a: 1, b: 2 }]);\n  });\n});"
  },
  {
    "path": "apps/rxjs.dev/tools/transforms/angular-base-package/rendering/toId.js",
    "content": "module.exports = function toId() {\n  return {\n    name: 'toId',\n    process: function(str) { return str.replace(/[^(a-z)(A-Z)(0-9)._-]/g, '-'); }\n  };\n};"
  },
  {
    "path": "apps/rxjs.dev/tools/transforms/angular-base-package/rendering/toId.spec.js",
    "content": "var factory = require('./toId');\n\ndescribe('toId filter', function() {\n  var filter;\n\n  beforeEach(function() { filter = factory(); });\n\n  it('should be called \"toId\"', function() { expect(filter.name).toEqual('toId'); });\n\n  it('should convert a string to make it appropriate for use as an HTML id', function() {\n    expect(filter.process('This is a big string with €bad#characters¢\\nAnd even NewLines'))\n      .toEqual('This-is-a-big-string-with--bad-characters--And-even-NewLines');\n  });\n});"
  },
  {
    "path": "apps/rxjs.dev/tools/transforms/angular-base-package/rendering/trimBlankLines.js",
    "content": "module.exports = function() {\n  return {\n    name: 'trimBlankLines',\n    process: function(str) {\n      var lines = str.split(/\\r?\\n/);\n      while (lines.length && (lines[0].trim() === '')) {\n        lines.shift();\n      }\n      while (lines.length && (lines[lines.length - 1].trim() === '')) {\n        lines.pop();\n      }\n      return lines.join('\\n');\n    }\n  };\n};"
  },
  {
    "path": "apps/rxjs.dev/tools/transforms/angular-base-package/rendering/trimBlankLines.spec.js",
    "content": "var factory = require('./trimBlankLines');\n\ndescribe('trimBlankLines filter', function() {\n  var filter;\n\n  beforeEach(function() { filter = factory(); });\n\n  it('should be called \"trimBlankLines\"',\n    function() { expect(filter.name).toEqual('trimBlankLines'); });\n\n  it('should remove empty lines from the start and end of the string', function() {\n    expect(filter.process('\\n  \\n\\nsome text\\n  \\nmore text\\n  \\n'))\n      .toEqual('some text\\n  \\nmore text');\n  });\n});"
  },
  {
    "path": "apps/rxjs.dev/tools/transforms/angular-base-package/rendering/truncateCode.js",
    "content": "module.exports = function() {\n  return {\n    name: 'truncateCode',\n    process: function(str, lines) {\n      if (lines === undefined) return str;\n\n      const parts = str && str.split && str.split(/\\r?\\n/);\n      if (parts && parts.length > lines) {\n        return balance(parts[0] + '...', ['{', '(', '['], ['}', ')', ']']);\n      } else {\n        return str;\n      }\n    }\n  };\n};\n\n/**\n * Try to balance the brackets by adding closers on to the end of a string\n * for every bracket that is left open.\n * The chars at each index in the openers and closers should match (i.e openers = ['{', '('], closers = ['}', ')'])\n *\n * @param {string} str The string to balance\n * @param {string[]} openers an array of chars that open a bracket\n * @param {string[]} closers an array of chars that close a brack\n * @returns the balanced string\n */\nfunction balance(str, openers, closers) {\n  const stack = [];\n\n  // Add each open bracket to the stack, removing them when there is a matching closer\n  str.split('').forEach(function(char) {\n    const closerIndex = closers.indexOf(char);\n    if (closerIndex !== -1 && stack[stack.length-1] === closerIndex) {\n      stack.pop();\n    } else {\n      const openerIndex = openers.indexOf(char);\n      if (openerIndex !== -1) {\n        stack.push(openerIndex);\n      }\n    }\n  });\n\n  // Now the stack should contain all the unclosed brackets\n  while(stack.length) {\n    str += closers[stack.pop()];\n  }\n\n  return str;\n}"
  },
  {
    "path": "apps/rxjs.dev/tools/transforms/angular-base-package/rendering/truncateCode.spec.js",
    "content": "var factory = require('./truncateCode');\n\ndescribe('truncateCode filter', function() {\n  var filter;\n\n  beforeEach(function() { filter = factory(); });\n\n  it('should be called \"truncateCode\"',\n    function() { expect(filter.name).toEqual('truncateCode'); });\n\n  it('should return the whole string given lines is undefined', function() {\n    expect(filter.process('some text\\n  \\nmore text\\n  \\n'))\n      .toEqual('some text\\n  \\nmore text\\n  \\n');\n  });\n\n  it('should return the whole string if less than the given number of lines', function() {\n    expect(filter.process('this is a pretty long string that only exists on one line', 1))\n      .toEqual('this is a pretty long string that only exists on one line');\n\n    expect(filter.process('this is a pretty long string\\nthat exists on two lines', 2))\n      .toEqual('this is a pretty long string\\nthat exists on two lines');\n  });\n\n  it('should return the specified number of lines and an ellipsis if there are more lines', function() {\n    expect(filter.process('some text\\n  \\nmore text\\n  \\n', 1)).toEqual('some text...');\n  });\n\n  it('should add closing brackets for all the unclosed opening brackets after truncating', function() {\n    expect(filter.process('()[]{}\\nsecond line', 1)).toEqual('()[]{}...');\n    expect(filter.process('([]{}\\nsecond line', 1)).toEqual('([]{}...)');\n    expect(filter.process('()[{}\\nsecond line', 1)).toEqual('()[{}...]');\n    expect(filter.process('()[]{\\nsecond line', 1)).toEqual('()[]{...}');\n    expect(filter.process('([{\\nsecond line', 1)).toEqual('([{...}])');\n  });\n});"
  },
  {
    "path": "apps/rxjs.dev/tools/transforms/angular-base-package/services/copyFolder.js",
    "content": "const {copySync} = require('fs-extra');\n\nmodule.exports = function copyFolder() {\n  return (from, to) => copySync(from, to);\n};\n"
  },
  {
    "path": "apps/rxjs.dev/tools/transforms/angular-base-package/services/filterAmbiguousDirectiveAliases.js",
    "content": "\n/**\n * This service is used by the autoLinkCode post-processor to filter out ambiguous directive\n * docs where the matching word is a directive selector.\n * E.g. `ngModel`, which is a selector for a number of directives, where we are only really\n * interested in the `NgModel` class.\n */\nmodule.exports = function filterAmbiguousDirectiveAliases() {\n  return (docs, words, index) => {\n    const word = words[index];\n\n    // we are only interested if there are multiple matching docs\n    if (docs.length > 1) {\n      if (docs.every(doc =>\n        // We are only interested if they are all either directives or components\n        (doc.docType === 'directive' || doc.docType === 'component') &&\n        // and the matching word is in the selector for all of them\n        doc[doc.docType + 'Options'].selector.indexOf(word) != -1\n      )) {\n        // find the directive whose class name matches the word (case-insensitive)\n        return docs.filter(doc => doc.name.toLowerCase() === word.toLowerCase());\n      }\n    }\n    return docs;\n  };\n};\n"
  },
  {
    "path": "apps/rxjs.dev/tools/transforms/angular-base-package/services/filterAmbiguousDirectiveAliases.spec.js",
    "content": "const filterAmbiguousDirectiveAliases = require('./filterAmbiguousDirectiveAliases')();\n\nconst words = ['Http', 'ngModel', 'NgModel', 'NgControlStatus'];\n\ndescribe('filterAmbiguousDirectiveAliases(docs, words, index)', () => {\n  it('should not try to filter the docs, if the docs are not all directives or components', () => {\n    const docs = [\n      { docType: 'class', name: 'Http' },\n      { docType: 'directive', name: 'NgModel', directiveOptions: { selector: '[ngModel]' } },\n      { docType: 'component', name: 'NgModel', componentOptions: { selector: '[ngModel]' } }\n    ];\n    // take a copy to prove `docs` was not modified\n    const filteredDocs = docs.slice(0);\n    expect(filterAmbiguousDirectiveAliases(docs, words, 1)).toEqual(filteredDocs);\n    expect(filterAmbiguousDirectiveAliases(docs, words, 2)).toEqual(filteredDocs);\n  });\n\n  describe('(where all the docs are components or directives', () => {\n    describe('and do not all contain the matching word in their selector)', () => {\n      it('should not try to filter the docs', () => {\n        const docs = [\n          { docType: 'directive', name: 'NgModel', ['directiveOptions']: { selector: '[ngModel]' } },\n          { docType: 'component', name: 'NgControlStatus', ['componentOptions']: { selector: '[ngControlStatus]' } }\n        ];\n        // take a copy to prove `docs` was not modified\n        const filteredDocs = docs.slice(0);\n        expect(filterAmbiguousDirectiveAliases(docs, words, 1)).toEqual(filteredDocs);\n        expect(filterAmbiguousDirectiveAliases(docs, words, 2)).toEqual(filteredDocs);\n\n        // Also test that the check is case-sensitive\n        docs[1].componentOptions.selector = '[ngModel]';\n        filteredDocs[1].componentOptions.selector = '[ngModel]';\n        expect(filterAmbiguousDirectiveAliases(docs, words, 2)).toEqual(filteredDocs);\n      });\n    });\n\n    describe('and do all contain the matching word in there selector)', () => {\n      it('should filter out docs whose class name is not (case-insensitively) equal to the matching word', () => {\n        const docs = [\n          { docType: 'directive', name: 'NgModel', ['directiveOptions']: { selector: '[ngModel],[ngControlStatus]' } },\n          { docType: 'component', name: 'NgControlStatus', ['componentOptions']: { selector: '[ngModel],[ngControlStatus]' } }\n        ];\n        const filteredDocs = [\n          { docType: 'directive', name: 'NgModel', ['directiveOptions']: { selector: '[ngModel],[ngControlStatus]' } }\n        ];\n        expect(filterAmbiguousDirectiveAliases(docs, words, 1)).toEqual(filteredDocs);\n      });\n    });\n  });\n});\n"
  },
  {
    "path": "apps/rxjs.dev/tools/transforms/angular-base-package/services/filterFromInImports.spec.js",
    "content": "const filterFromInImports = require('./filterFromInImports')();\n\nconst words = ['import', ' { ', 'from', ' } ', 'from', ' \\'', 'rxjs', '\\';'];\nconst words2 = [' } ', 'from', '(', 'of'];\n\ndescribe('filterFromInImports(words, index)', () => {\n  it('should not filter the word, if the word is not \"from\"', () => {\n    expect(filterFromInImports(words, 0)).toEqual(false);\n  });\n\n  it('should not filter the word, if the word \"from\" is not positioned between } and \\' signs', () => {\n    expect(filterFromInImports(words, 2)).toEqual(false);\n  });\n\n  it('should filter \"from\" when \"from\" is positioned between } and \\' signs', () => {\n    expect(filterFromInImports(words, 4)).toEqual(true);\n  });\n\n  it('should not filter \"from\" when \"from\" is after } but not before \\'', () => {\n    expect(filterFromInImports(words2, 1)).toEqual(false);\n  });\n});\n"
  },
  {
    "path": "apps/rxjs.dev/tools/transforms/angular-base-package/services/filterFromInImports.ts",
    "content": "/**\n * This filter is filtering word 'from' in ES6 import statements.\n * For example, next line:\n *\n * ```\n * import { interval, from } from 'rxjs';\n * ```\n *\n * will filter the second occurrence of the word 'from' leaving\n * it without the link, but the first occurrence will remain\n * unfiltered, thus it will get the link to\n * /api/index/function/from\n */\nmodule.exports = function filterFromInImports(): (words: string[], index: number) => boolean {\n  return (words: string[], index: number) => {\n    const previousWord = words[index - 1];\n    const nextWord = words[index + 1];\n\n    return words[index] === 'from' && /}/.test(previousWord) && /'/.test(nextWord);\n  };\n};\n"
  },
  {
    "path": "apps/rxjs.dev/tools/transforms/angular-base-package/services/filterPipes.js",
    "content": "\n/**\n * This service is used by the autoLinkCode post-processors to filter out pipe docs\n * where the matching word is the pipe name and is not preceded by a pipe\n */\nmodule.exports = function filterPipes() {\n  return (docs, words, index) =>\n    docs.filter(doc =>\n      doc.docType !== 'pipe' ||\n      doc.pipeOptions.name !== '\\'' + words[index] + '\\'' ||\n      index > 0 && words[index - 1].trim() === '|');\n};\n"
  },
  {
    "path": "apps/rxjs.dev/tools/transforms/angular-base-package/services/filterPipes.spec.js",
    "content": "const filterPipes = require('./filterPipes')();\n\ndescribe('filterPipes', () => {\n  it('should ignore docs that are not pipes', () => {\n    const docs = [{ docType: 'class', name: 'B', pipeOptions: { name: '\\'b\\'' } }];\n    const words = ['A', 'b', 'B', 'C'];\n    const filteredDocs = [{ docType: 'class', name: 'B', pipeOptions: { name: '\\'b\\'' } }];\n    expect(filterPipes(docs, words, 1)).toEqual(filteredDocs);\n    expect(filterPipes(docs, words, 2)).toEqual(filteredDocs);\n  });\n\n  it('should ignore docs that are pipes but do not match the pipe name', () => {\n    const docs = [{ docType: 'pipe', name: 'B', pipeOptions: { name: '\\'b\\'' } }];\n    const words = ['A', 'B', 'C'];\n    const filteredDocs = [{ docType: 'pipe', name: 'B', pipeOptions: { name: '\\'b\\'' } }];\n    expect(filterPipes(docs, words, 1)).toEqual(filteredDocs);\n  });\n\n  it('should ignore docs that are pipes, match the pipe name and are preceded by a pipe character', () => {\n    const docs = [{ docType: 'pipe', name: 'B', pipeOptions: { name: '\\'b\\'' } }];\n    const words = ['A', '|', 'b', 'C'];\n    const filteredDocs = [{ docType: 'pipe', name: 'B', pipeOptions: { name: '\\'b\\'' } }];\n    expect(filterPipes(docs, words, 2)).toEqual(filteredDocs);\n  });\n\n  it('should filter out docs that are pipes, match the pipe name but are not preceded by a pipe character', () => {\n    const docs = [\n      { docType: 'pipe', name: 'B', pipeOptions: { name: '\\'b\\'' } },\n      { docType: 'class', name: 'B' }\n    ];\n    const words = ['A', 'b', 'C'];\n    const index = 1;\n    const filteredDocs = [{ docType: 'class', name: 'B' }];\n    expect(filterPipes(docs, words, index)).toEqual(filteredDocs);\n  });\n});\n"
  },
  {
    "path": "apps/rxjs.dev/tools/transforms/angular-base-package/services/getImageDimensions.js",
    "content": "const { resolve } = require('canonical-path');\nconst sizeOf = require('image-size');\n\nmodule.exports = function getImageDimensions() {\n  return (basePath, path) => sizeOf(resolve(basePath, path));\n};\n"
  },
  {
    "path": "apps/rxjs.dev/tools/transforms/angular-content-package/index.js",
    "content": "/**\n * @license\n * Copyright Google Inc. All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\nconst Package = require('dgeni').Package;\nconst basePackage = require('../angular-base-package');\nconst contentPackage = require('../content-package');\n\nconst { CONTENTS_PATH } = require('../config');\n\nmodule.exports = new Package('angular-content', [basePackage, contentPackage])\n\n  // Where do we get the source files?\n  .config(function(readFilesProcessor) {\n\n    readFilesProcessor.sourceFiles = readFilesProcessor.sourceFiles.concat([\n      {\n        basePath: CONTENTS_PATH,\n        include: CONTENTS_PATH + '/{deprecations,guide,tutorial}/**/*.md',\n        fileReader: 'contentFileReader'\n      },\n      {\n        basePath: CONTENTS_PATH + '/marketing',\n        include: CONTENTS_PATH + '/marketing/**/*.{html,md}',\n        fileReader: 'contentFileReader'\n      },\n      {\n        basePath: CONTENTS_PATH,\n        include: CONTENTS_PATH + '/*.md',\n        exclude: [CONTENTS_PATH + '/index.md'],\n        fileReader: 'contentFileReader'\n      },\n      {\n        basePath: CONTENTS_PATH,\n        include: CONTENTS_PATH + '/navigation.json',\n        fileReader: 'jsonFileReader'\n      },\n      {\n        basePath: CONTENTS_PATH,\n        include: CONTENTS_PATH + '/marketing/contributors.json',\n        fileReader: 'jsonFileReader'\n      },\n      {\n        basePath: CONTENTS_PATH,\n        include: CONTENTS_PATH + '/marketing/announcements.json',\n        fileReader: 'jsonFileReader'\n      },\n    ]);\n\n  })\n\n\n  // Configure jsdoc-style tag parsing\n  .config(function(inlineTagProcessor) {\n    inlineTagProcessor.inlineTagDefinitions.push(require('./inline-tag-defs/anchor'));\n  })\n\n\n  .config(function(computePathsProcessor) {\n\n    // Replace any path templates inherited from other packages\n    // (we want full and transparent control)\n    computePathsProcessor.pathTemplates = computePathsProcessor.pathTemplates.concat([\n      {\n        docTypes: ['content'],\n        getPath: (doc) => `${doc.id.replace(/\\/index$/, '')}`,\n        outputPathTemplate: '${path}.json'\n      },\n      {docTypes: ['navigation-json'], pathTemplate: '${id}', outputPathTemplate: '../${id}.json'},\n      {docTypes: ['contributors-json'], pathTemplate: '${id}', outputPathTemplate: '../${id}.json'},\n      {docTypes: ['announcements-json'], pathTemplate: '${id}', outputPathTemplate: '../${id}.json'}\n    ]);\n  })\n\n  // We want the content files to be converted\n  .config(function(convertToJsonProcessor, postProcessHtml) {\n    convertToJsonProcessor.docTypes.push('content');\n    postProcessHtml.docTypes.push('content');\n  });\n"
  },
  {
    "path": "apps/rxjs.dev/tools/transforms/angular-content-package/inline-tag-defs/anchor.js",
    "content": "module.exports = {\n  name: 'a',\n  description: 'A shorthand for creating heading anchors. Usage: `{@a some-id}`',\n  handler: function(doc, tagName, tagDescription) {\n    return '<a id=\"' + tagDescription.trim() + '\"></a>';\n  }\n};\n"
  },
  {
    "path": "apps/rxjs.dev/tools/transforms/angular.io-package/index.js",
    "content": "/**\n * @license\n * Copyright Google Inc. All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\nconst Package = require('dgeni').Package;\nconst gitPackage = require('dgeni-packages/git');\nconst apiPackage = require('../angular-api-package');\nconst contentPackage = require('../angular-content-package');\nconst { extname, resolve } = require('canonical-path');\nconst { existsSync } = require('fs');\nconst { SRC_PATH, DOCS_OUTPUT_PATH, DECISION_TREE_PATH } = require('../config');\n// prettier-ignore\nmodule.exports = new Package('angular.io', [gitPackage, apiPackage, contentPackage])\n\n  // This processor relies upon the versionInfo. See below...\n  .processor(require('./processors/processNavigationMap'))\n  .processor(require('./processors/createOverviewDump'))\n  .processor(require('./processors/cleanGeneratedFiles'))\n  .processor(require('../rxjs-decision-tree-generator'))\n\n  // We don't include this in the angular-base package because the `versionInfo` stuff\n  // accesses the file system and git, which is slow.\n  .config(function(renderDocsProcessor, versionInfo) {\n    // Add the version data to the renderer, for use in things like github links\n    renderDocsProcessor.extraData.versionInfo = versionInfo;\n  })\n\n  .config(function(checkAnchorLinksProcessor, linkInlineTagDef) {\n\n    // Fail the processing if there is an invalid link\n    linkInlineTagDef.failOnBadLink = false;\n\n    checkAnchorLinksProcessor.$enabled = false;\n    // since we encode the HTML to JSON we need to ensure that this processor runs before that encoding happens.\n    checkAnchorLinksProcessor.$runBefore = ['convertToJsonProcessor'];\n    checkAnchorLinksProcessor.$runAfter = ['fixInternalDocumentLinks'];\n    // We only want to check docs that are going to be output as JSON docs.\n    checkAnchorLinksProcessor.checkDoc = (doc) => doc.path && doc.outputPath && extname(doc.outputPath) === '.json';\n    // Since we have a `base[href=\"/\"]` arrangement all links are relative to that and not relative to the source document's path\n    checkAnchorLinksProcessor.base = '/';\n    // Ignore links to local assets\n    // (This is not optimal in terms of performance without making changes to dgeni-packages there is no other way.\n    //  That being said do this only add 500ms onto the ~30sec doc-gen run - so not a huge issue)\n    checkAnchorLinksProcessor.ignoredLinks.push({\n      test(url) {\n        return (existsSync(resolve(SRC_PATH, url)));\n      }\n    });\n    checkAnchorLinksProcessor.pathVariants = ['', '/', '.html', '/index.html', '#top-of-page'];\n    checkAnchorLinksProcessor.errorOnUnmatchedLinks = false;\n  })\n\n  .config(function(renderLinkInfo, postProcessHtml) {\n    renderLinkInfo.docTypes = postProcessHtml.docTypes;\n  })\n  .config(function(decisionTreeGenerator) {\n    decisionTreeGenerator.outputFolder = DOCS_OUTPUT_PATH + '/app';\n    decisionTreeGenerator.decisionTreeFile = DECISION_TREE_PATH;\n  });\n"
  },
  {
    "path": "apps/rxjs.dev/tools/transforms/angular.io-package/processors/cleanGeneratedFiles.js",
    "content": "const rimraf = require('rimraf');\nmodule.exports = function cleanGeneratedFiles() {\n  return {\n    $runAfter: ['writing-files'],\n    $runBefore: ['writeFilesProcessor'],\n    $process: function() {\n      rimraf.sync('src/generated/{*.json}');\n    }\n  };\n};\n"
  },
  {
    "path": "apps/rxjs.dev/tools/transforms/angular.io-package/processors/createOverviewDump.js",
    "content": "var _ = require('lodash');\n\nmodule.exports = function createOverviewDump() {\n\n  return {\n    $runAfter: ['processing-docs'],\n    $runBefore: ['docs-processed'],\n    $process: function(docs) {\n      var overviewDoc = {\n        id: 'overview-dump',\n        aliases: ['overview-dump'],\n        path: 'overview-dump',\n        outputPath: 'overview-dump.html',\n        modules: []\n      };\n      _.forEach(docs, function(doc) {\n        if (doc.docType === 'module') {\n          overviewDoc.modules.push(doc);\n        }\n      });\n      docs.push(overviewDoc);\n    }\n  };\n};"
  },
  {
    "path": "apps/rxjs.dev/tools/transforms/angular.io-package/processors/processNavigationMap.js",
    "content": "module.exports = function processNavigationMap(versionInfo, log) {\n  return {\n    $runAfter: ['paths-computed'],\n    $runBefore: ['rendering-docs'],\n    $process: function(docs) {\n\n      const navigationDoc = docs.find(doc => doc.docType === 'navigation-json');\n\n      if (!navigationDoc) {\n        throw new Error(\n          'Missing navigation map document (docType=\"navigation-json\").' +\n          'Did you forget to add it to the readFileProcessor?');\n      }\n\n      // Verify that all the navigation paths are to valid docs\n      const pathMap = {};\n      docs.forEach(doc => pathMap[doc.path] = true);\n      const errors = walk(navigationDoc.data, pathMap, []);\n\n      if (errors.length) {\n        log.error(`Navigation doc: ${navigationDoc.fileInfo.relativePath} contains invalid urls`);\n        // eslint-disable-next-line no-console\n        console.log(errors);\n        // TODO(petebd): fail if there are errors: throw new Error('processNavigationMap failed');\n      }\n\n      // Add in the version data in a \"secret\" field to be extracted in the docs app\n      navigationDoc.data['__versionInfo'] = versionInfo.currentVersion;\n    }\n  };\n};\n\nfunction walk(node, map, path) {\n  let errors = [];\n  for(const key in node) {\n    const child = node[key];\n    if (child !== null) { // null is allowed\n      if (key === 'url') {\n        const url = child.replace(/#.*$/, ''); // strip hash\n        if (isRelative(url) && !map[url]) {\n          errors.push({ path: path.join('.'), url });\n        }\n      } else if (typeof child !== 'string') {\n        errors = errors.concat(walk(child, map, path.concat([key])));\n      }\n    }\n  }\n  return errors;\n}\n\nfunction isRelative(url) {\n  return !/^(https?:)?\\/\\//.test(url);\n}\n"
  },
  {
    "path": "apps/rxjs.dev/tools/transforms/authors-package/api-package.js",
    "content": "/**\n * @license\n * Copyright Google Inc. All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\nconst Package = require('dgeni').Package;\nconst apiPackage = require('../angular-api-package');\nconst { API_SOURCE_PATH } = require('../config');\n\nconst packageMap = {\n  animations: ['animations/index.ts', 'animations/browser/index.ts', 'animations/browser/testing/index.ts'],\n  common: ['common/index.ts', 'common/testing/index.ts', 'common/http/index.ts', 'common/http/testing/index.ts'],\n  core: ['core/index.ts', 'core/testing/index.ts'],\n  elements: ['elements/index.ts'],\n  forms: ['forms/index.ts'],\n  http: ['http/index.ts', 'http/testing/index.ts'],\n  'platform-browser': ['platform-browser/index.ts', 'platform-browser/animations/index.ts', 'platform-browser/testing/index.ts'],\n  'platform-browser-dynamic': ['platform-browser-dynamic/index.ts', 'platform-browser-dynamic/testing/index.ts'],\n  'platform-server': ['platform-server/index.ts', 'platform-server/testing/index.ts'],\n  'platform-webworker': ['platform-webworker/index.ts'],\n  'platform-webworker-dynamic': ['platform-webworker-dynamic/index.ts'],\n  router: ['router/index.ts', 'router/testing/index.ts', 'router/upgrade/index.ts'],\n  'service-worker': ['service-worker/index.ts'],\n  upgrade: ['upgrade/index.ts', 'upgrade/static/index.ts']\n};\n\n\nfunction createPackage(packageName) {\n\n  return new Package('author-api', [apiPackage])\n    .config(function(readTypeScriptModules) {\n      readTypeScriptModules.sourceFiles = packageMap[packageName];\n    })\n    .config(function(readFilesProcessor) {\n      readFilesProcessor.sourceFiles = [\n        {\n          basePath: API_SOURCE_PATH,\n          include: `${API_SOURCE_PATH}/examples/${packageName}/**/*`,\n          fileReader: 'exampleFileReader'\n        }\n      ];\n    });\n}\n\n\nmodule.exports = {\n  createPackage\n};\n"
  },
  {
    "path": "apps/rxjs.dev/tools/transforms/authors-package/guide-package.js",
    "content": "/**\n * @license\n * Copyright Google Inc. All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\n/* eslint no-console: \"off\" */\n\nconst Package = require('dgeni').Package;\nconst contentPackage = require('../angular-content-package');\nconst { readFileSync } = require('fs');\nconst { resolve } = require('canonical-path');\nconst { CONTENTS_PATH } = require('../config');\n\nfunction createPackage(guideName) {\n\n  const guideFilePath = `${CONTENTS_PATH}/guide/${guideName}.md`;\n  const guideFile = readFileSync(guideFilePath, 'utf8');\n  const examples = [];\n  guideFile.replace(/<code-(?:pane|example) [^>]*path=\"([^\"]+)\"/g, (_, path) => examples.push('examples/' + path));\n\n  if (examples.length) {\n    console.log('The following example files are referenced in this guide:');\n    console.log(examples.map(example => ' - ' + example).join('\\n'));\n  }\n\n  return new Package('author-guide', [contentPackage])\n    .config(function(readFilesProcessor) {\n      readFilesProcessor.sourceFiles = [\n        {\n          basePath: CONTENTS_PATH,\n          include: guideFilePath,\n          fileReader: 'contentFileReader'\n        },\n        {\n          basePath: CONTENTS_PATH,\n          include: examples.map(example => resolve(CONTENTS_PATH, example)),\n          fileReader: 'exampleFileReader'\n        }\n      ];\n    });\n}\n\nmodule.exports = { createPackage };"
  },
  {
    "path": "apps/rxjs.dev/tools/transforms/authors-package/index.js",
    "content": "/**\n * @license\n * Copyright Google Inc. All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n/* eslint no-console: \"off\" */\n\nfunction createPackage(changedFile) {\n  const marketingMatch = /^apps\\/rxjs.dev\\/content\\/marketing\\/(.*)/.exec(changedFile);\n  if (marketingMatch) {\n    console.log('Building marketing docs');\n    return require('./marketing-package').createPackage();\n  }\n\n  const tutorialMatch = /^apps\\/rxjs.dev\\/content\\/tutorial\\/([^.]+)\\.md/.exec(changedFile);\n  const tutorialExampleMatch = /^apps\\/rxjs.dev\\/content\\/examples\\/(toh-[^/]+)\\//.exec(changedFile);\n  if (tutorialMatch || tutorialExampleMatch) {\n    const tutorialName = (tutorialMatch && tutorialMatch[1]) || tutorialExampleMatch[1];\n    console.log('Building tutorial docs');\n    return require('./tutorial-package').createPackage(tutorialName);\n  }\n\n  const guideMatch = /^apps\\/rxjs.dev\\/content\\/guide\\/([^.]+)\\.md/.exec(changedFile);\n  const exampleMatch = /^apps\\/rxjs.dev\\/content\\/examples\\/(?:cb-)?([^/]+)\\//.exec(changedFile);\n  if (guideMatch || exampleMatch) {\n    const guideName = (guideMatch && guideMatch[1]) || exampleMatch[1];\n    console.log(`Building guide doc: ${guideName}.md`);\n    return require('./guide-package').createPackage(guideName);\n  }\n}\n\nmodule.exports = {\n  generateDocs: function (changedFile, options = {}) {\n    const { Dgeni } = require('dgeni');\n    const package = createPackage(changedFile);\n    if (options.silent) {\n      package.config(function (log) {\n        log.level = 'error';\n      });\n    }\n    var dgeni = new Dgeni([package]);\n    const start = Date.now();\n    return dgeni.generate().then(\n      () => console.log('Generated docs in ' + (Date.now() - start) / 1000 + ' secs'),\n      (err) => console.log('Error generating docs', err)\n    );\n  },\n};\n"
  },
  {
    "path": "apps/rxjs.dev/tools/transforms/authors-package/index.spec.js",
    "content": "/* eslint jasmine/prefer-toHaveBeenCalledWith:0 */\nconst fs = require('fs/promises');\nconst { resolve } = require('canonical-path');\nconst { generateDocs } = require('./index.js');\nconst { DOCS_OUTPUT_PATH } = require('../config');\n\ndescribe('authors-package (integration tests)', () => {\n  let originalJasmineTimeout;\n  let files;\n\n  beforeAll(() => {\n    originalJasmineTimeout = jasmine.DEFAULT_TIMEOUT_INTERVAL;\n    jasmine.DEFAULT_TIMEOUT_INTERVAL = 10000;\n  });\n\n  afterAll(() => (jasmine.DEFAULT_TIMEOUT_INTERVAL = originalJasmineTimeout));\n\n  beforeEach(() => {\n    files = [];\n    spyOn(fs, 'writeFile').and.callFake((file) => {\n      files.push(file);\n      return Promise.resolve();\n    });\n  });\n\n  it('should generate marketing docs if the \"fileChanged\" is a marketing doc', (done) => {\n    generateDocs('apps/rxjs.dev/content/marketing/team.html', { silent: true })\n      .then(() => {\n        expect(fs.writeFile).toHaveBeenCalled();\n        expect(files).toContain(resolve(DOCS_OUTPUT_PATH, 'team.json'));\n        expect(files).toContain(resolve(DOCS_OUTPUT_PATH, '../navigation.json'));\n        expect(files).toContain(resolve(DOCS_OUTPUT_PATH, '../contributors.json'));\n        done();\n      })\n      .catch(done.fail);\n  });\n\n  it('should generate guide doc if the \"fileChanged\" is a guide doc', (done) => {\n    generateDocs('apps/rxjs.dev/content/guide/subject.md', { silent: true })\n      .then(() => {\n        expect(fs.writeFile).toHaveBeenCalled();\n        expect(files).toContain(resolve(DOCS_OUTPUT_PATH, 'guide/subject.json'));\n        done();\n      })\n      .catch(done.fail);\n  });\n});\n"
  },
  {
    "path": "apps/rxjs.dev/tools/transforms/authors-package/marketing-package.js",
    "content": "/**\n * @license\n * Copyright Google Inc. All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\nconst Package = require('dgeni').Package;\nconst contentPackage = require('../angular-content-package');\nconst { CONTENTS_PATH } = require('../config');\n\nfunction createPackage() {\n  return new Package('author-marketing', [contentPackage])\n    .config(function(readFilesProcessor) {\n      readFilesProcessor.sourceFiles = [\n        {\n          basePath: CONTENTS_PATH + '/marketing',\n          include: CONTENTS_PATH + '/marketing/**/*.{html,md}',\n          fileReader: 'contentFileReader'\n        },\n        {\n          basePath: CONTENTS_PATH,\n          include: CONTENTS_PATH + '/*.md',\n          exclude: [CONTENTS_PATH + '/index.md'],\n          fileReader: 'contentFileReader'\n        },\n        {\n          basePath: CONTENTS_PATH,\n          include: CONTENTS_PATH + '/marketing/*.json',\n          fileReader: 'jsonFileReader'\n        },\n        {\n          basePath: CONTENTS_PATH,\n          include: CONTENTS_PATH + '/navigation.json',\n          fileReader: 'jsonFileReader'\n        },\n      ];\n    });\n}\n\n\nmodule.exports = { createPackage };"
  },
  {
    "path": "apps/rxjs.dev/tools/transforms/authors-package/tutorial-package.js",
    "content": "/**\n * @license\n * Copyright Google Inc. All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nconst Package = require('dgeni').Package;\nconst contentPackage = require('../angular-content-package');\nconst { readFileSync } = require('fs');\nconst { resolve } = require('canonical-path');\nconst { CONTENTS_PATH } = require('../config');\n\n/* eslint no-console: \"off\" */\n\nfunction createPackage(tutorialName) {\n\n  const tutorialFilePath = `${CONTENTS_PATH}/tutorial/${tutorialName}.md`;\n  const tutorialFile = readFileSync(tutorialFilePath, 'utf8');\n  const examples = [];\n  tutorialFile.replace(/<code-(?:pane|example) [^>]*path=\"([^\"]+)\"/g, (_, path) => examples.push('examples/' + path));\n\n  if (examples.length) {\n    console.log('The following example files are referenced in this tutorial:');\n    console.log(examples.map(example => ' - ' + example).join('\\n'));\n  }\n\n  return new Package('author-tutorial', [contentPackage])\n    .config(function(readFilesProcessor) {\n      readFilesProcessor.sourceFiles = [\n        {\n          basePath: CONTENTS_PATH,\n          include: tutorialFilePath,\n          fileReader: 'contentFileReader'\n        },\n        {\n          basePath: CONTENTS_PATH,\n          include: examples.map(example => resolve(CONTENTS_PATH, example)),\n          fileReader: 'exampleFileReader'\n        }\n      ];\n    });\n}\n\n\nmodule.exports = { createPackage };"
  },
  {
    "path": "apps/rxjs.dev/tools/transforms/authors-package/watchr.js",
    "content": "/* eslint no-console: \"off\" */\nconst watchr = require('watchr');\nconst {relative} = require('canonical-path');\nconst {generateDocs} = require('./index.js');\nconst { PROJECT_ROOT, CONTENTS_PATH, API_SOURCE_PATH } = require('../config');\n\nfunction listener(changeType, fullPath) {\n  try {\n    const relativePath = relative(PROJECT_ROOT, fullPath);\n    console.log('The file', relativePath, `was ${changeType}d at`, new Date().toUTCString());\n    generateDocs(relativePath);\n  } catch(err) {\n    console.log('Error generating docs', err);\n  }\n}\n\nfunction next(error) {\n  if (error) {\n    console.log(error);\n  }\n}\n\nlet p = Promise.resolve();\n\nif (process.argv.indexOf('--watch-only') === -1) {\n  console.log('================================================================');\n  console.log('Running initial doc generation');\n  console.log('----------------------------------------------------------------');\n  console.log('Skip the full doc-gen by running: `yarn docs-watch --watch-only`');\n  console.log('================================================================');\n  const {Dgeni} = require('dgeni');\n  const dgeni = new Dgeni([require('../angular.io-package')]);\n\n  // Turn off all the potential failures for this doc-gen one-off run.\n  // This enables authors to run `docs-watch` while the docs are still in an unstable state.\n  const injector = dgeni.configureInjector();\n  injector.get('linkInlineTagDef').failOnBadLink = false;\n  injector.get('checkAnchorLinksProcessor').$enabled = false;\n  injector.get('renderExamples').ignoreBrokenExamples = true;\n\n  p = dgeni.generate();\n}\n\np.then(() => {\n  console.log('===================================================================');\n  console.log('Started watching files in:');\n  console.log(' - ', CONTENTS_PATH);\n  console.log(' - ', API_SOURCE_PATH);\n  console.log('Doc gen will run when you change a file in either of these folders.');\n  console.log('===================================================================');\n\n  watchr.open(CONTENTS_PATH, listener, next);\n  watchr.open(API_SOURCE_PATH, listener, next);\n\n});\n"
  },
  {
    "path": "apps/rxjs.dev/tools/transforms/config.js",
    "content": "const { resolve } = require('path');\nconst { readdirSync } = require('fs');\n\nconst PROJECT_ROOT = resolve(__dirname, '../../../..');\nconst AIO_PATH = resolve(PROJECT_ROOT, 'apps/rxjs.dev');\nconst TEMPLATES_PATH = resolve(AIO_PATH, 'tools/transforms/templates');\nconst API_TEMPLATES_PATH = resolve(TEMPLATES_PATH, 'api');\nconst CONTENTS_PATH = resolve(AIO_PATH, 'content');\nconst SRC_PATH = resolve(AIO_PATH, 'src');\nconst OUTPUT_PATH = resolve(SRC_PATH, 'generated');\nconst DOCS_OUTPUT_PATH = resolve(OUTPUT_PATH, 'docs');\nconst API_SOURCE_PATH = resolve(PROJECT_ROOT, 'packages/rxjs/src');\nconst MARBLE_IMAGES_PATH = resolve(SRC_PATH, 'assets/images/marble-diagrams');\nconst MARBLE_IMAGES_WEB_PATH = 'assets/images/marble-diagrams';\nconst DECISION_TREE_PATH = resolve(CONTENTS_PATH, 'operator-decision-tree.yml');\n\nfunction requireFolder(dirname, folderPath) {\n  const absolutePath = resolve(dirname, folderPath);\n  return readdirSync(absolutePath)\n    .filter((p) => !/[._]spec\\.js$/.test(p)) // ignore spec files\n    .map((p) => require(resolve(absolutePath, p)));\n}\n\nmodule.exports = {\n  PROJECT_ROOT,\n  AIO_PATH,\n  TEMPLATES_PATH,\n  API_TEMPLATES_PATH,\n  CONTENTS_PATH,\n  SRC_PATH,\n  OUTPUT_PATH,\n  DOCS_OUTPUT_PATH,\n  API_SOURCE_PATH,\n  MARBLE_IMAGES_PATH,\n  MARBLE_IMAGES_WEB_PATH,\n  DECISION_TREE_PATH,\n  requireFolder,\n};\n"
  },
  {
    "path": "apps/rxjs.dev/tools/transforms/content-package/index.js",
    "content": "var Package = require('dgeni').Package;\nvar jsdocPackage = require('dgeni-packages/jsdoc');\nvar linksPackage = require('../links-package');\nvar { requireFolder } = require('../config');\n\n// Define the dgeni package for generating the docs\nmodule.exports = new Package('content', [jsdocPackage, linksPackage])\n\n  // Register the services and file readers\n  .factory(require('./readers/content'))\n\n  // Configure file reading\n  .config(function(readFilesProcessor, contentFileReader) {\n    readFilesProcessor.fileReaders.push(contentFileReader);\n  })\n\n  .config(function(parseTagsProcessor, getInjectables) {\n    parseTagsProcessor.tagDefinitions = parseTagsProcessor.tagDefinitions.concat(\n      getInjectables(requireFolder(__dirname, './tag-defs')));\n  })\n\n  // Configure ids and paths\n  .config(function(computeIdsProcessor) {\n\n    computeIdsProcessor.idTemplates.push({\n      docTypes: ['content'],\n      getId: function(doc) {\n        return doc.fileInfo\n          .relativePath\n        // path should be relative to `modules` folder\n          .replace(/.*\\/?modules\\//, '')\n        // path should not include `/docs/`\n          .replace(/\\/docs\\//, '/')\n        // path should not have a suffix\n          .replace(/\\.\\w*$/, '');\n      },\n      getAliases: function(doc) { return [doc.id]; }\n    });\n  });\n"
  },
  {
    "path": "apps/rxjs.dev/tools/transforms/content-package/readers/content.js",
    "content": "/**\n * @dgService\n * @description\n * This file reader will pull the contents from a text file (by default .md)\n *\n * The doc will initially have the form:\n * ```\n * {\n *   content: 'the content of the file',\n *   startingLine: 1\n * }\n * ```\n */\nmodule.exports = function contentFileReader() {\n  return {\n    name: 'contentFileReader',\n    defaultPattern: /\\.md$/,\n    getDocs: function(fileInfo) {\n\n      // We return a single element array because content files only contain one document\n      return [{docType: 'content', content: fileInfo.content, startingLine: 1}];\n    }\n  };\n};\n"
  },
  {
    "path": "apps/rxjs.dev/tools/transforms/content-package/readers/content.spec.js",
    "content": "var testPackage = require('../../helpers/test-package');\nvar Dgeni = require('dgeni');\nvar path = require('canonical-path');\n\ndescribe('contentFileReader', function() {\n  var dgeni, injector, fileReader;\n\n  beforeEach(function() {\n    dgeni = new Dgeni([testPackage('content-package', true)]);\n    injector = dgeni.configureInjector();\n    fileReader = injector.get('contentFileReader');\n  });\n\n  var createFileInfo = function(file, content, basePath) {\n    return {\n      fileReader: fileReader.name,\n      filePath: file,\n      baseName: path.basename(file, path.extname(file)),\n      extension: path.extname(file).replace(/^\\./, ''),\n      basePath: basePath,\n      relativePath: path.relative(basePath, file),\n      content: content\n    };\n  };\n\n  describe('defaultPattern', function() {\n    it('should match .md files', function() {\n      expect(fileReader.defaultPattern.test('abc.md')).toBeTruthy();\n      expect(fileReader.defaultPattern.test('abc.js')).toBeFalsy();\n    });\n  });\n\n\n  describe('getDocs', function() {\n    it('should return an object containing info about the file and its contents', function() {\n      var fileInfo = createFileInfo(\n        'project/path/modules/someModule/foo/docs/subfolder/bar.ngdoc', 'A load of content',\n        'project/path');\n      expect(fileReader.getDocs(fileInfo)).toEqual([\n        {docType: 'content', content: 'A load of content', startingLine: 1}\n      ]);\n    });\n  });\n});\n"
  },
  {
    "path": "apps/rxjs.dev/tools/transforms/content-package/tag-defs/intro.js",
    "content": "module.exports = function() {\n  return {name: 'intro'};\n};\n"
  },
  {
    "path": "apps/rxjs.dev/tools/transforms/content-package/tag-defs/title.js",
    "content": "module.exports = function() {\n  return {name: 'title'};\n};\n"
  },
  {
    "path": "apps/rxjs.dev/tools/transforms/helpers/test-package.js",
    "content": "/**\n * @license\n * Copyright Google Inc. All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nconst path = require('canonical-path');\n\nconst Package = require('dgeni').Package;\n\nmodule.exports = function testPackage(packageName, mockTemplateEngine) {\n\n  const pkg = new Package('mock_' + packageName, [require('../' + packageName)]);\n\n  // provide a mock log service\n  pkg.factory('log', function() { return require('dgeni/lib/mocks/log')(false); });\n\n  // overrides base packageInfo and returns the one for the 'angular/angular' repo.\n  const PROJECT_ROOT = path.resolve(__dirname, '../../../..');\n  pkg.factory('packageInfo', function() { return require(path.resolve(PROJECT_ROOT, 'package.json')); });\n\n\n  if (mockTemplateEngine) {\n    pkg.factory('templateEngine', function() { return {}; });\n  }\n\n  return pkg;\n};\n"
  },
  {
    "path": "apps/rxjs.dev/tools/transforms/helpers/utils.js",
    "content": "module.exports = {\n  /**\n   * Transform the values of an object via a mapper function\n   * @param {Object} obj\n   * @param {Function} mapper\n   */\n  mapObject(obj, mapper) {\n    const mappedObj = {};\n    Object.keys(obj).forEach(key => { mappedObj[key] = mapper(key, obj[key]); });\n    return mappedObj;\n  },\n\n  /**\n   * Parses the attributes from a string taken from an HTML element start tag\n   * E.g. ` a=\"one\" b=\"two\" `\n   * @param {string} str\n   */\n  parseAttributes(str) {\n    const attrMap = {};\n    let index = 0;\n\n    skipSpace();\n\n    while(index < str.length) {\n      takeAttribute();\n      skipSpace();\n    }\n\n    function takeAttribute() {\n      const key = takeKey();\n      skipSpace();\n      if (tryEquals()) {\n        skipSpace();\n        const quote = tryQuote();\n        attrMap[key] = takeValue(quote);\n        // skip the closing quote or whitespace\n        index++;\n      } else {\n        attrMap[key] = true;\n      }\n    }\n\n\n    function skipSpace() {\n      while(index < str.length && /\\s/.test(str[index])) {\n        index++;\n      }\n    }\n\n    function tryEquals() {\n      if (str[index] === '=') {\n        index++;\n        return true;\n      }\n    }\n\n    function takeKey() {\n      let startIndex = index;\n      while(index < str.length && /[^\\s=]/.test(str[index])) {\n        index++;\n      }\n      return str.substring(startIndex, index);\n    }\n\n    function tryQuote() {\n      const quote = str[index];\n      if (['\"', '\\''].indexOf(quote) !== -1) {\n        index++;\n        return quote;\n      }\n    }\n\n    function takeValue(quote) {\n      let startIndex = index;\n\n      if (quote) {\n        while(index < str.length && str[index] !== quote) {\n          index++;\n        }\n        if (index >= str.length) {\n          throw new Error(`Unterminated quoted attribute value in \\`${str}\\`. Starting at ${startIndex}. Expected a ${quote} but got \"end of string\".`);\n        }\n      } else {\n        while(index < str.length && /\\S/.test(str[index])) {\n          index++;\n        }\n      }\n      return str.substring(startIndex, index);\n    }\n\n    return attrMap;\n  },\n\n  renderAttributes(attrMap) {\n    return Object.keys(attrMap).map(key =>\n      attrMap[key] === false ? '' :\n        attrMap[key] === true ? ` ${key}` :\n          ` ${key}=\"${attrMap[key].replace(/\"/g, '&quot;')}\"`).join('');\n  }\n};\n"
  },
  {
    "path": "apps/rxjs.dev/tools/transforms/helpers/utils.spec.js",
    "content": "const { mapObject, parseAttributes, renderAttributes } = require('./utils');\n\ndescribe('utils', () => {\n  describe('mapObject', () => {\n    it('creates a new object', () => {\n      const testObj = { a: 1 };\n      const mappedObj = mapObject(testObj, (key, value) => value);\n      expect(mappedObj).toEqual(testObj);\n      expect(mappedObj).not.toBe(testObj);\n    });\n\n    it('maps the values via the mapper function', () => {\n      const testObj = { a: 1, b: 2 };\n      const mappedObj = mapObject(testObj, (key, value) => value * 2);\n      expect(mappedObj).toEqual({ a: 2, b: 4 });\n    });\n  });\n\n  describe('parseAttributes', () => {\n    it('should parse empty string', () => {\n      const attrs = parseAttributes('');\n      expect(attrs).toEqual({ });\n    });\n\n    it('should parse blank string', () => {\n      const attrs = parseAttributes('  ');\n      expect(attrs).toEqual({ });\n    });\n\n    it('should parse double quoted attributes', () => {\n      const attrs = parseAttributes('a=\"one\" b=\"two\"');\n      expect(attrs).toEqual({ a: 'one', b: 'two' });\n    });\n\n    it('should parse empty quoted attributes', () => {\n      const attrs = parseAttributes('a=\"\" b=\"two\"');\n      expect(attrs).toEqual({ a: '', b: 'two' });\n    });\n\n    it('should parse single quoted attributes', () => {\n      const attrs = parseAttributes('a=\\'one\\' b=\\'two\\'');\n      expect(attrs).toEqual({ a: 'one', b: 'two' });\n    });\n\n    it('should ignore whitespace', () => {\n      const attrs = parseAttributes('   a = \"one\"   b  =  \"two\"   ');\n      expect(attrs).toEqual({ a: 'one', b: 'two' });\n    });\n\n    it('should parse attributes with quotes within quotes', () => {\n      const attrs = parseAttributes('a=\\'o\"n\"e\\' b=\"t\\'w\\'o\"');\n      expect(attrs).toEqual({ a: 'o\"n\"e', b: 't\\'w\\'o' });\n    });\n\n    it('should parse attributes with spaces in their values', () => {\n      const attrs = parseAttributes('a=\"one and two\" b=\"three and four\"');\n      expect(attrs).toEqual({ a: 'one and two', b: 'three and four' });\n    });\n\n    it('should parse empty attributes', () => {\n      const attrs = parseAttributes('a b=\"two\"');\n      expect(attrs).toEqual({ a: true, b: 'two' });\n    });\n\n    it('should parse unquoted attributes', () => {\n      const attrs = parseAttributes('a=one b=two');\n      expect(attrs).toEqual({ a: 'one', b: 'two' });\n    });\n\n    it('should complain if a quoted attribute is not closed', () => {\n      expect(() => parseAttributes('a=\"\" b=\"two')).toThrowError(\n        'Unterminated quoted attribute value in `a=\"\" b=\"two`. Starting at 8. Expected a \" but got \"end of string\".'\n      );\n    });\n  });\n\n  describe('renderAttributes', () => {\n    it('should convert key-value map to a strong that can be used in HTML', () => {\n      expect(renderAttributes({ foo: 'bar', moo: 'car' })).toEqual(' foo=\"bar\" moo=\"car\"');\n    });\n\n    it('should handle boolean values', () => {\n      expect(renderAttributes({ foo: 'bar', loo: true, moo: false }))\n        .toEqual(' foo=\"bar\" loo');\n    });\n\n    it('should escape double quotes inside the value', () => {\n      expect(renderAttributes({ foo: 'bar \"car\"' })).toEqual(' foo=\"bar &quot;car&quot;\"');\n    });\n\n    it('should not escape single quotes inside the value', () => {\n      expect(renderAttributes({ foo: 'bar \\'car\\'' })).toEqual(' foo=\"bar \\'car\\'\"');\n    });\n\n    it('should handle an empty object', () => {\n      expect(renderAttributes({ })).toEqual('');\n    });\n  });\n});\n"
  },
  {
    "path": "apps/rxjs.dev/tools/transforms/links-package/index.js",
    "content": "var Package = require('dgeni').Package;\nvar jsdocPackage = require('dgeni-packages/jsdoc');\n\nmodule.exports = new Package('links', [jsdocPackage])\n\n  .factory(require('./inline-tag-defs/link'))\n  .factory(require('./services/getAliases'))\n  .factory(require('./services/getDocFromAlias'))\n  .factory(require('./services/getLinkInfo'))\n  .factory(require('./services/disambiguators/disambiguateByDeprecated'))\n  .factory(require('./services/disambiguators/disambiguateByNonMember'))\n  .factory(require('./services/disambiguators/disambiguateByModule'))\n  .factory(require('./services/disambiguators/disambiguateByNonOperator'))\n\n  .config(function (inlineTagProcessor, linkInlineTagDef) {\n    inlineTagProcessor.inlineTagDefinitions.push(linkInlineTagDef);\n  })\n\n  .config(function (getDocFromAlias, disambiguateByDeprecated, disambiguateByNonMember, disambiguateByModule, disambiguateByNonOperator) {\n    getDocFromAlias.disambiguators = [disambiguateByDeprecated, disambiguateByNonMember, disambiguateByModule, disambiguateByNonOperator];\n  });\n"
  },
  {
    "path": "apps/rxjs.dev/tools/transforms/links-package/inline-tag-defs/link.js",
    "content": "var INLINE_LINK = /(\\S+)(?:\\s+([\\s\\S]+))?/;\n\n/**\n * @dgService linkInlineTagDef\n * @description\n * Process inline link tags (of the form {@link some/uri Some Title}), replacing them with HTML anchors\n * @kind function\n * @param  {Object} url   The url to match\n * @param  {Function} docs error message\n * @return {String}  The html link information\n *\n * @property {boolean} failOnBadLink Whether to throw an error (aborting the processing) if a link is invalid.\n */\nmodule.exports = function linkInlineTagDef(getLinkInfo, createDocMessage, log) {\n  return {\n    name: 'link',\n    aliases: ['linkDocs'],\n    failOnBadLink: false,\n    description:\n        'Process inline link tags (of the form {@link some/uri Some Title}), replacing them with HTML anchors',\n    handler(doc, tagName, tagDescription) {\n\n      // Parse out the uri and title\n      return tagDescription.replace(INLINE_LINK, (match, uri, title) => {\n\n        var linkInfo = getLinkInfo(uri, title, doc);\n\n        if (!linkInfo.valid) {\n          const message = createDocMessage(`Error in {@${tagName} ${tagDescription}} - ${linkInfo.error}`, doc);\n          if (this.failOnBadLink) {\n            throw new Error(message);\n          } else {\n            log.warn(message);\n          }\n        }\n\n        return '<a href=\\'' + linkInfo.url + '\\'>' + linkInfo.title + '</a>';\n      });\n    }\n  };\n};"
  },
  {
    "path": "apps/rxjs.dev/tools/transforms/links-package/inline-tag-defs/link.spec.js",
    "content": "var testPackageFactory = require('../../helpers/test-package');\nvar Dgeni = require('dgeni');\n\ndescribe('link inline-tag-def', function() {\n  let injector, tag, getLinkInfo, log;\n\n  beforeEach(() => {\n    getLinkInfo = jasmine.createSpy('getLinkInfo');\n    const testPackage = testPackageFactory('links-package', true)\n      .factory('getLinkInfo', function() { return getLinkInfo; });\n    getLinkInfo.disambiguators = [];\n\n    const dgeni = new Dgeni([testPackage]);\n    injector = dgeni.configureInjector();\n    tag = injector.get('linkInlineTagDef');\n    log = injector.get('log');\n  });\n\n  it('should be available as a service', () => {\n    expect(tag).toBeDefined();\n    expect(tag.name).toEqual('link');\n    expect(tag.aliases).toEqual(['linkDocs']);\n  });\n\n  it('should call getLinkInfo', () => {\n    const doc = {};\n    const tagName = 'link';\n    const tagDescription = 'doc-id link text';\n    getLinkInfo.and.returnValue({ url: 'url/to/doc', title: 'link text' });\n    tag.handler(doc, tagName, tagDescription);\n    expect(getLinkInfo).toHaveBeenCalledWith('doc-id', 'link text', doc);\n  });\n\n  it('should return an HTML anchor tag', () => {\n    const doc = {};\n    const tagName = 'link';\n    const tagDescription = 'doc-id link text';\n    getLinkInfo.and.returnValue({ url: 'url/to/doc', title: 'link text' });\n    const result = tag.handler(doc, tagName, tagDescription);\n    expect(result).toEqual('<a href=\\'url/to/doc\\'>link text</a>');\n  });\n\n  it('should log a warning if not failOnBadLink and the link is \"bad\"', () => {\n    const doc = {};\n    const tagName = 'link';\n    const tagDescription = 'doc-id link text';\n    getLinkInfo.and.returnValue({ valid: false, error: 'Error message', errorType: 'error' });\n    expect(() => tag.handler(doc, tagName, tagDescription)).not.toThrow();\n    expect(log.warn).toHaveBeenCalledWith('Error in {@link doc-id link text} - Error message - doc');\n  });\n\n  it('should throw an error if failOnBadLink and the link is \"bad\"', () => {\n    const doc = {};\n    const tagName = 'link';\n    const tagDescription = 'doc-id link text';\n    getLinkInfo.and.returnValue({ valid: false, error: 'Error message', errorType: 'error' });\n    tag.failOnBadLink = true;\n    expect(() => tag.handler(doc, tagName, tagDescription)).toThrowError('Error in {@link doc-id link text} - Error message - doc');\n  });\n});\n\n"
  },
  {
    "path": "apps/rxjs.dev/tools/transforms/links-package/services/disambiguators/disambiguateByDeprecated.js",
    "content": "module.exports = function disambiguateByDeprecated() {\n  return (alias, originatingDoc, docs) => {\n    const filteredDocs = docs.filter((doc) => doc.deprecated === undefined);\n    return filteredDocs.length > 0 ? filteredDocs : docs;\n  };\n};\n"
  },
  {
    "path": "apps/rxjs.dev/tools/transforms/links-package/services/disambiguators/disambiguateByDeprecated.spec.js",
    "content": "const disambiguateByDeprecated = require('./disambiguateByDeprecated')();\nconst doc1 = { id: 'doc1' };\nconst doc2 = { id: 'doc2', deprecated: true };\nconst doc3 = { id: 'doc3', deprecated: '' };\nconst doc4 = { id: 'doc4' };\nconst doc5 = { id: 'doc5', deprecated: 'Some text' };\n\ndescribe('disambiguateByDeprecated', () => {\n  it('should filter out docs whose `deprecated` property is defined', () => {\n    expect(disambiguateByDeprecated('alias', {}, [doc1, doc2, doc3, doc4, doc5])).toEqual([doc1, doc4]);\n  });\n\n  it('should not filter docs if all of them are `deprecated`', () => {\n    expect(disambiguateByDeprecated('alias', {}, [doc2, doc3, doc5])).toEqual([doc2, doc3, doc5]);\n  });\n});\n"
  },
  {
    "path": "apps/rxjs.dev/tools/transforms/links-package/services/disambiguators/disambiguateByModule.js",
    "content": "module.exports = function disambiguateByModule() {\n  return (alias, originatingDoc, docs) => {\n    const originatingModule = originatingDoc && originatingDoc.moduleDoc;\n    if (originatingModule) {\n      const filteredDocs = docs.filter(doc => doc.moduleDoc === originatingModule);\n      if (filteredDocs.length > 0) {\n        return filteredDocs;\n      }\n    }\n    return docs;\n  };\n};\n"
  },
  {
    "path": "apps/rxjs.dev/tools/transforms/links-package/services/disambiguators/disambiguateByModule.spec.js",
    "content": "const disambiguateByModule = require('./disambiguateByModule')();\nconst moduleA = { name: 'a' };\nconst moduleB = { name: 'b' };\nconst docs = [\n  { id: 'doc1', moduleDoc: moduleA },\n  { id: 'doc2', moduleDoc: moduleA },\n  { id: 'doc3', moduleDoc: moduleB },\n];\n\ndescribe('disambiguateByModule', () => {\n  it('should return all docs if the originating doc has no moduleDoc', () => {\n    expect(disambiguateByModule('alias', { }, docs)).toEqual(docs);\n  });\n\n  it('should return all docs if no docs match the originating doc moduleDoc', () => {\n    expect(disambiguateByModule('alias', { moduleDoc: { name: 'c' } }, docs)).toEqual(docs);\n  });\n\n  it('should return only docs that match the moduleDoc of the originating doc', () => {\n    expect(disambiguateByModule('alias', { moduleDoc: moduleA }, docs)).toEqual([\n      { id: 'doc1', moduleDoc: moduleA },\n      { id: 'doc2', moduleDoc: moduleA },\n    ]);\n\n    expect(disambiguateByModule('alias', { moduleDoc: moduleB }, docs)).toEqual([\n      { id: 'doc3', moduleDoc: moduleB },\n    ]);\n  });\n});"
  },
  {
    "path": "apps/rxjs.dev/tools/transforms/links-package/services/disambiguators/disambiguateByNonMember.js",
    "content": "/**\n * This link disambiguator will remove all the members from the list of ambiguous links\n * if there is at least one link to a doc that is not a member.\n *\n * The heuristic is that exports are more important than members when linking, and that\n * in general members will be linked to via a more explicit code links such as\n * `MyClass.member` rather than simply `member`.\n */\nmodule.exports = function disambiguateByNonMember() {\n  return (alias, originatingDoc, docs) => {\n    const filteredDocs = docs.filter(doc => doc.docType !== 'member');\n    return filteredDocs.length > 0 ? filteredDocs : docs;\n  };\n};\n"
  },
  {
    "path": "apps/rxjs.dev/tools/transforms/links-package/services/disambiguators/disambiguateByNonMember.spec.js",
    "content": "const disambiguateByNonMember = require('./disambiguateByNonMember')();\nconst doc1 = { id: 'doc1', docType: 'function', containerDoc: {} };\nconst doc2 = { id: 'doc2', docType: 'member', containerDoc: {} };\nconst doc3 = { id: 'doc3', docType: 'member', containerDoc: {} };\nconst doc4 = { id: 'doc4', docType: 'class', containerDoc: {} };\nconst doc5 = { id: 'doc5', docType: 'member', containerDoc: {} };\n\ndescribe('disambiguateByNonMember', () => {\n  it('should filter out docs that are not members', () => {\n    const docs = [doc1, doc2, doc3, doc4, doc5];\n    expect(disambiguateByNonMember('alias', {}, docs)).toEqual([doc1, doc4]);\n  });\n\n  it('should return all docs if there are no members', () => {\n    const docs = [doc1, doc4];\n    expect(disambiguateByNonMember('alias', {}, docs)).toEqual([doc1, doc4]);\n  });\n\n  it('should return all docs if there are only members', () => {\n    const docs = [doc2, doc3, doc5];\n    expect(disambiguateByNonMember('alias', {}, docs)).toEqual([doc2, doc3, doc5]);\n  });\n});\n"
  },
  {
    "path": "apps/rxjs.dev/tools/transforms/links-package/services/disambiguators/disambiguateByNonOperator.js",
    "content": "/**\n * This link disambiguator will remove all the members from the list of ambiguous links\n * if there is at least one link to a doc that does not belong to 'operators' module.\n * TODO Remove this disambiguator once 'rxjs/operators' export is removed\n */\nmodule.exports = function disambiguateByNonOperator() {\n  return (alias, originatingDoc, docs) => {\n    const filteredDocs = docs.filter((doc) => doc.moduleDoc?.id !== 'operators');\n    return filteredDocs.length > 0 ? filteredDocs : docs;\n  };\n};\n"
  },
  {
    "path": "apps/rxjs.dev/tools/transforms/links-package/services/disambiguators/disambiguateByNonOperator.spec.js",
    "content": "const disambiguateByNonOperator = require('./disambiguateByNonOperator')();\nconst indexModule = { id: 'index' };\nconst operatorsModule = { id: 'operators' };\nconst doc1 = { id: 'doc1', moduleDoc: indexModule };\nconst doc2 = { id: 'doc2', moduleDoc: operatorsModule };\nconst doc3 = { id: 'doc3', moduleDoc: operatorsModule };\nconst doc4 = { id: 'doc4', moduleDoc: indexModule };\n\ndescribe('disambiguateByNonOperator', () => {\n  it('should filter out docs that are not operators', () => {\n    const docs = [doc1, doc2];\n    expect(disambiguateByNonOperator('alias', {}, docs)).toEqual([doc1]);\n  });\n\n  it('should return all docs if there are no operators', () => {\n    const docs = [doc1, doc4];\n    expect(disambiguateByNonOperator('alias', {}, docs)).toEqual([doc1, doc4]);\n  });\n\n  it('should return all docs if there are only operators', () => {\n    const docs = [doc2, doc3];\n    expect(disambiguateByNonOperator('alias', {}, docs)).toEqual([doc2, doc3]);\n  });\n});\n"
  },
  {
    "path": "apps/rxjs.dev/tools/transforms/links-package/services/getAliases.js",
    "content": "\nfunction parseCodeName(codeName) {\n  var parts = [];\n  var currentPart;\n\n  codeName.split('.').forEach(function(part) {\n    var subParts = part.split(':');\n\n    var name = subParts.pop();\n    var modifier = subParts.pop();\n\n    if (!modifier && currentPart) {\n      currentPart.name += '.' + name;\n    } else {\n      currentPart = {name: name, modifier: modifier};\n      parts.push(currentPart);\n    }\n  });\n  return parts;\n}\n\n/**\n * @dgService getAliases\n * @description\n * Get a list of all the aliases that can be made from the doc\n * @param  {Object} doc A doc from which to extract aliases\n * @return {Array}      A collection of aliases\n */\nmodule.exports = function getAliases() {\n\n  return function(doc) {\n\n    var codeNameParts = parseCodeName(doc.id);\n\n    var methodName;\n    var aliases = [];\n    // Add the last part to the list of aliases\n    var part = codeNameParts.pop();\n\n    // If the name contains a # then it is a member and that should be included in the aliases\n    if (part.name.indexOf('#') !== -1) {\n      methodName = part.name.split('#')[1];\n    }\n    // Add the part name and modifier, if provided\n    aliases.push(part.name);\n    if (part.modifier) {\n      aliases.push(part.modifier + ':' + part.name);\n    }\n\n    // Continue popping off the parts of the codeName and work forward collecting up each alias\n    aliases = codeNameParts.reduceRight(function(aliases, part) {\n\n      // Add this part to each of the aliases we have so far\n      aliases.forEach(function(name) {\n        // Add the part name and modifier, if provided\n        aliases.push(part.name + '.' + name);\n        if (part.modifier) {\n          aliases.push(part.modifier + ':' + part.name + '.' + name);\n        }\n      });\n\n      return aliases;\n    }, aliases);\n\n    if (methodName) {\n      aliases.push(methodName);\n    }\n\n    return aliases;\n  };\n};"
  },
  {
    "path": "apps/rxjs.dev/tools/transforms/links-package/services/getAliases.spec.js",
    "content": "var getAliasesFactory = require('./getAliases');\n\ndescribe('getAliases', function() {\n\n  it('should extract all the parts from a code name', function() {\n\n    var getAliases = getAliasesFactory();\n\n    expect(getAliases({id: 'module:ng.service:$http#get'})).toEqual([\n      '$http#get', 'service:$http#get', 'ng.$http#get', 'module:ng.$http#get',\n      'ng.service:$http#get', 'module:ng.service:$http#get', 'get'\n    ]);\n  });\n});\n"
  },
  {
    "path": "apps/rxjs.dev/tools/transforms/links-package/services/getDocFromAlias.js",
    "content": "/**\n * @dgService getDocFromAlias\n * @description Get an array of docs that match this alias, relative to the originating doc.\n *\n * @property {Array<(alias: string, originatingDoc: Doc, ambiguousDocs: Doc[]) => Doc[]>} disambiguators\n *           a collection of functions that attempt to resolve ambiguous links. Each disambiguator returns\n *           a new collection of docs with unwanted ambiguous docs removed (see links-package/service/disambiguators\n *           for examples).\n */\nmodule.exports = function getDocFromAlias(aliasMap) {\n\n  getDocFromAlias.disambiguators = [];\n  return getDocFromAlias;\n\n  function getDocFromAlias(alias, originatingDoc) {\n    return getDocFromAlias.disambiguators.reduce(\n      // Run the disambiguators while there is more than 1 doc found\n      (docs, disambiguator) => docs.length > 1 ? disambiguator(alias, originatingDoc, docs) : docs,\n      // Start with the docs that match the alias\n      aliasMap.getDocs(alias)\n    );\n  }\n};\n"
  },
  {
    "path": "apps/rxjs.dev/tools/transforms/links-package/services/getDocFromAlias.spec.js",
    "content": "var testPackage = require('../../helpers/test-package');\nvar Dgeni = require('dgeni');\n\nvar getDocFromAlias, aliasMap;\n\ndescribe('getDocFromAlias', () => {\n  beforeEach(() => {\n    var dgeni = new Dgeni([testPackage('links-package', true)]);\n    var injector = dgeni.configureInjector();\n    aliasMap = injector.get('aliasMap');\n    getDocFromAlias = injector.get('getDocFromAlias');\n  });\n\n  it('should return an array of docs that match the alias', () => {\n    var doc1 = {aliases: ['a', 'b', 'c']};\n    var doc2 = {aliases: ['a', 'b']};\n    var doc3 = {aliases: ['a']};\n    aliasMap.addDoc(doc1);\n    aliasMap.addDoc(doc2);\n    aliasMap.addDoc(doc3);\n\n    expect(getDocFromAlias('a')).toEqual([doc1, doc2, doc3]);\n    expect(getDocFromAlias('b')).toEqual([doc1, doc2]);\n    expect(getDocFromAlias('c')).toEqual([doc1]);\n  });\n\n  it('should filter ambiguous docs by calling each disambiguator', () => {\n    getDocFromAlias.disambiguators = [\n      (alias, originatingDoc, docs) => docs.filter(doc => doc.name.indexOf('X') !== -1), // only if X appears in name\n      (alias, originatingDoc, docs) => docs.filter(doc => doc.name.indexOf('Y') !== -1)  // only if Y appears in name\n    ];\n\n    var doc1 = {name: 'X', aliases: ['a', 'b', 'c']};\n    var doc2 = {name: 'Y', aliases: ['a', 'b']};\n    var doc3 = {name: 'XY', aliases: ['a', 'c']};\n    aliasMap.addDoc(doc1);\n    aliasMap.addDoc(doc2);\n    aliasMap.addDoc(doc3);\n\n    // doc1 and doc2 get removed as they don't both have X and Y in name\n    expect(getDocFromAlias('a')).toEqual([doc3]);\n    // doc2 gets removed as it has no X; then we have only one doc left so second disambiguator never runs\n    expect(getDocFromAlias('b')).toEqual([doc1]);\n    // doc1 gets removed as it has no Y; then we have only one doc left (which would anyway pass 2nd disambiguator)\n    expect(getDocFromAlias('c')).toEqual([doc3]);\n  });\n});"
  },
  {
    "path": "apps/rxjs.dev/tools/transforms/links-package/services/getLinkInfo.js",
    "content": "var path = require('canonical-path');\n\n/**\n * @dgService getLinkInfo\n * @description\n * Get link information to a document that matches the given url\n * @kind function\n * @param  {String} url   The url to match\n * @param  {String} title An optional title to return in the link information\n * @return {Object}       The link information\n *\n * @property {boolean} relativeLinks Whether we expect the links to be relative to the originating doc\n */\nmodule.exports = function getLinkInfo(getDocFromAlias, encodeCodeBlock, log) {\n\n  return getLinkInfoImpl;\n\n  function getLinkInfoImpl(url, title, currentDoc) {\n    var linkInfo = {url: url, type: 'url', valid: true, title: title || url};\n\n    if (!url) {\n      throw new Error('Invalid url');\n    }\n\n    var docs = getDocFromAlias(url, currentDoc);\n\n    if (!getLinkInfoImpl.useFirstAmbiguousLink && docs.length > 1) {\n      linkInfo.valid = false;\n      linkInfo.errorType = 'ambiguous';\n      linkInfo.error = 'Ambiguous link: \"' + url + '\".\\n' + docs.reduce(function(msg, doc) {\n        return msg + '\\n  \"' + doc.id + '\" (' + doc.docType + ') : (' + doc.path + ' / ' +\n            doc.fileInfo.relativePath + ')';\n      }, 'Matching docs: ');\n\n    } else if (docs.length >= 1) {\n      linkInfo.url = docs[0].path;\n      linkInfo.title = title || docs[0].title || docs[0].name && encodeCodeBlock(docs[0].name, true);\n      linkInfo.type = 'doc';\n\n      if (getLinkInfoImpl.relativeLinks && currentDoc && currentDoc.path) {\n        var currentFolder = path.dirname(currentDoc.path);\n        var docFolder = path.dirname(linkInfo.url);\n        var relativeFolder =\n            path.relative(path.join('/', currentFolder), path.join('/', docFolder));\n        linkInfo.url = path.join(relativeFolder, path.basename(linkInfo.url));\n        log.debug(currentDoc.path, docs[0].path, linkInfo.url);\n      }\n\n    } else if (url.indexOf('#') > 0) {\n      var pathAndHash = url.split('#');\n      linkInfo = getLinkInfoImpl(pathAndHash[0], title, currentDoc);\n      linkInfo.url = linkInfo.url + '#' + pathAndHash[1];\n      return linkInfo;\n\n    } else if (url.indexOf('/') === -1 && url.indexOf('#') !== 0) {\n      linkInfo.valid = false;\n      linkInfo.errorType = 'missing';\n      linkInfo.error = 'Invalid link (does not match any doc): \"' + url + '\"';\n\n    } else {\n      linkInfo.title =\n          title || ((url.indexOf('#') === 0) ? url.substring(1) : path.basename(url, '.html'));\n    }\n\n    if (linkInfo.title === undefined) {\n      linkInfo.valid = false;\n      linkInfo.errorType = 'no-title';\n      linkInfo.error = 'The link is missing a title';\n    }\n\n    return linkInfo;\n  }\n};\n"
  },
  {
    "path": "apps/rxjs.dev/tools/transforms/links-package/services/getLinkInfo.spec.js",
    "content": "const testPackage = require('../../helpers/test-package');\nconst Dgeni = require('dgeni');\n\nlet getLinkInfo, aliasMap;\n\ndescribe('getLinkInfo', () => {\n  beforeEach(function() {\n    var dgeni = new Dgeni([testPackage('links-package', true)]);\n    var injector = dgeni.configureInjector();\n    aliasMap = injector.get('aliasMap');\n    getLinkInfo = injector.get('getLinkInfo');\n  });\n\n  it('should use the title if specified', () => {\n    aliasMap.addDoc({ docType: 'guide', title: 'Browser Support', name: 'browser-support', id: 'guide/browser-support', aliases: ['guide/browser-support', 'browser-support'], path: 'guide/browser-support' });\n    const currentDoc = { };\n    const linkInfo = getLinkInfo('browser-support', '\"Browser Support Guide\"', currentDoc);\n    expect(linkInfo.title).toBe('\"Browser Support Guide\"');\n  });\n\n  it('should set the link to invalid if the title is `undefined`', () => {\n    aliasMap.addDoc({ docType: 'guide', id: 'guide/browser-support', aliases: ['guide/browser-support', 'browser-support'], path: 'guide/browser-support' });\n    const currentDoc = { };\n    const linkInfo = getLinkInfo('browser-support', undefined, currentDoc);\n    expect(linkInfo.valid).toBe(false);\n    expect(linkInfo.errorType).toEqual('no-title');\n    expect(linkInfo.error).toEqual('The link is missing a title');\n  });\n\n  it('should use the target document title if available and no title is specified', () => {\n    aliasMap.addDoc({ docType: 'guide', title: 'Browser Support', id: 'guide/browser-support', aliases: ['guide/browser-support', 'browser-support'], path: 'guide/browser-support' });\n    const currentDoc = { };\n    const linkInfo = getLinkInfo('browser-support', undefined, currentDoc);\n    expect(linkInfo.valid).toBe(true);\n    expect(linkInfo.title).toEqual('Browser Support');\n  });\n\n  it('should prefer the target doc title over name if available and no title is specified', () => {\n    aliasMap.addDoc({ docType: 'guide', title: 'Browser Support', name: 'browser-support', id: 'guide/browser-support', aliases: ['guide/browser-support', 'browser-support'], path: 'guide/browser-support' });\n    const currentDoc = { };\n    const linkInfo = getLinkInfo('browser-support', undefined, currentDoc);\n    expect(linkInfo.valid).toBe(true);\n    expect(linkInfo.title).toEqual('Browser Support');\n  });\n\n  it('should use the target document name as a code block if available and no title is specified', () => {\n    aliasMap.addDoc({ docType: 'api', name: 'CurrencyPipe', id: 'common/CurrencyPipe', aliases: ['common/CurrencyPipe', 'CurrencyPipe'], path: 'api/common/CurrencyPipe' });\n    const currentDoc = { };\n    const linkInfo = getLinkInfo('CurrencyPipe', undefined, currentDoc);\n    expect(linkInfo.valid).toBe(true);\n    expect(linkInfo.title).toEqual('<code>CurrencyPipe</code>');\n  });\n});"
  },
  {
    "path": "apps/rxjs.dev/tools/transforms/remark-package/index.js",
    "content": "var Package = require('dgeni').Package;\n\n/**\n * @dgPackage remark\n * @description Overrides the renderMarkdown service with an implementation based on remark\n */\nmodule.exports = new Package('remark', ['nunjucks'])\n  .factory(require('./services/markedNunjucksFilter'))\n  .factory(require('./services/renderMarkdown'));\n"
  },
  {
    "path": "apps/rxjs.dev/tools/transforms/remark-package/services/handlers/code.js",
    "content": "/**\n * Render markdown code blocks as `<code-example>` tags\n */\nmodule.exports = function code(h, node) {\n  var value = node.value ? ('\\n' + node.value + '\\n') : '';\n  var lang = node.lang && node.lang.match(/^[^ \\t]+(?=[ \\t]|$)/);\n  var props = {};\n\n  if (lang) {\n    props.language = lang;\n  }\n\n  return h(node, 'code-example', props, [{ type: 'text', value }]);\n};\n"
  },
  {
    "path": "apps/rxjs.dev/tools/transforms/remark-package/services/markedNunjucksFilter.js",
    "content": "/**\n * Convert the value, as markdown, into HTML\n * @param headingMappings A map of headings to convert (e.g. from h3 to h4).\n */\nmodule.exports = function markedNunjucksFilter(renderMarkdown) {\n  return {\n    name: 'marked',\n    process: function(str, headingMappings) {\n      return str && renderMarkdown(str, headingMappings);\n    }\n  };\n};\n"
  },
  {
    "path": "apps/rxjs.dev/tools/transforms/remark-package/services/plugins/mapHeadings.js",
    "content": "const visit = require('unist-util-visit');\n\nfunction headingToLevel(heading) {\n  const match = /^h(\\d+)/.exec(heading);\n  return match ? match[1] : '0';\n}\n\nfunction parseMappings(mappings) {\n  const mapping = {};\n  Object.keys(mappings).forEach(key => mapping[headingToLevel(key)] = headingToLevel(mappings[key]));\n  return mapping;\n}\n\nmodule.exports = function mapHeadings(mappings) {\n  const headings = parseMappings(mappings || {});\n  return () => ast => {\n    const nodesToFix = [];\n    Object.keys(headings).forEach(heading => {\n      visit(ast, 'heading', node => {\n        if (node.depth === Number(heading)) {\n          nodesToFix.push(node);\n        }\n      });\n    });\n\n    // Update the depth of the matched nodes\n    nodesToFix.forEach(node => node.depth = headings[node.depth]);\n\n    return ast;\n  };\n};\n"
  },
  {
    "path": "apps/rxjs.dev/tools/transforms/remark-package/services/renderMarkdown.js",
    "content": "const remark = require('remark');\nconst html = require('remark-html');\nconst code = require('./handlers/code');\nconst mapHeadings = require('./plugins/mapHeadings');\n\n/**\n * @dgService renderMarkdown\n * @description\n * Render the markdown in the given string as HTML.\n * @param headingMap A map of headings to convert.\n *                   E.g. `{h3: 'h4'} will map heading 3 level into heading 4.\n */\nmodule.exports = function renderMarkdown() {\n  return function renderMarkdownImpl(content, headingMap) {\n\n    const renderer = remark()\n      .use(inlineTagDefs)\n      .use(noIndentedCodeBlocks)\n      .use(plainHTMLBlocks)\n      // USEFUL DEBUGGING CODE\n      // .use(() => tree => {\n      //   console.log(require('util').inspect(tree, { colors: true, depth: 4 }));\n      // })\n      .use(mapHeadings(headingMap))\n      .use(html, { handlers: { code }, sanitize: false });\n\n    return renderer.processSync(content).toString();\n  };\n\n  /**\n   * Teach remark not to render indented codeblocks\n   */\n  function noIndentedCodeBlocks() {\n    const blockMethods = this.Parser.prototype.blockMethods;\n    blockMethods.splice(blockMethods.indexOf('indentedCode'), 1);\n  }\n\n\n  /**\n   * Teach remark about inline tags, so that it neither wraps block level\n   * tags in paragraphs nor processes the text within the tag.\n   */\n  function inlineTagDefs() {\n    const Parser = this.Parser;\n    const inlineTokenizers = Parser.prototype.inlineTokenizers;\n    const inlineMethods = Parser.prototype.inlineMethods;\n    const blockTokenizers = Parser.prototype.blockTokenizers;\n    const blockMethods = Parser.prototype.blockMethods;\n\n    blockTokenizers.inlineTag = tokenizeInlineTag;\n    blockMethods.splice(blockMethods.indexOf('paragraph'), 0, 'inlineTag');\n\n    inlineTokenizers.inlineTag = tokenizeInlineTag;\n    inlineMethods.splice(blockMethods.indexOf('text'), 0, 'inlineTag');\n    tokenizeInlineTag.notInLink = true;\n    tokenizeInlineTag.locator = inlineTagLocator;\n\n    function tokenizeInlineTag(eat, value, silent) {\n      const match = /^\\{@[^\\s}]+[^}]*\\}/.exec(value);\n\n      if (match) {\n        if (silent) {\n          return true;\n        }\n        return eat(match[0])({\n          'type': 'inlineTag',\n          'value': match[0]\n        });\n      }\n    }\n\n    function inlineTagLocator(value, fromIndex) {\n      return value.indexOf('{@', fromIndex);\n    }\n  }\n\n  /**\n   * Teach remark that some HTML blocks never include markdown\n   */\n  function plainHTMLBlocks() {\n\n    const plainBlocks = ['code-example', 'code-tabs'];\n\n    // Create matchers for each block\n    const anyBlockMatcher = new RegExp('^' + createOpenMatcher(`(${plainBlocks.join('|')})`));\n\n    const Parser = this.Parser;\n    const blockTokenizers = Parser.prototype.blockTokenizers;\n    const blockMethods = Parser.prototype.blockMethods;\n\n    blockTokenizers.plainHTMLBlocks = tokenizePlainHTMLBlocks;\n    blockMethods.splice(blockMethods.indexOf('html'), 0, 'plainHTMLBlocks');\n\n    function tokenizePlainHTMLBlocks(eat, value, silent) {\n      const openMatch = anyBlockMatcher.exec(value);\n      if (openMatch) {\n        const blockName = openMatch[1];\n        try {\n          const fullMatch = matchRecursiveRegExp(value, createOpenMatcher(blockName), createCloseMatcher(blockName))[0];\n          if (silent || !fullMatch) {\n            // either we are not eating (silent) or the match failed\n            return !!fullMatch;\n          }\n          return eat(fullMatch[0])({\n            type: 'html',\n            value: fullMatch[0]\n          });\n        } catch(e) {\n          this.file.fail('Unmatched plain HTML block tag ' + e.message);\n        }\n      }\n    }\n  }\n};\n\n/**\n * matchRecursiveRegExp\n *\n * (c) 2007 Steven Levithan <stevenlevithan.com>\n * MIT License\n *\n * Accepts a string to search, a left and right format delimiter\n * as regex patterns, and optional regex flags. Returns an array\n * of matches, allowing nested instances of left/right delimiters.\n * Use the \"g\" flag to return all matches, otherwise only the\n * first is returned. Be careful to ensure that the left and\n * right format delimiters produce mutually exclusive matches.\n * Backreferences are not supported within the right delimiter\n * due to how it is internally combined with the left delimiter.\n * When matching strings whose format delimiters are unbalanced\n * to the left or right, the output is intentionally as a\n * conventional regex library with recursion support would\n * produce, e.g. \"<<x>\" and \"<x>>\" both produce [\"x\"] when using\n * \"<\" and \">\" as the delimiters (both strings contain a single,\n * balanced instance of \"<x>\").\n *\n * examples:\n * matchRecursiveRegExp(\"test\", \"\\\\(\", \"\\\\)\")\n * returns: []\n * matchRecursiveRegExp(\"<t<<e>><s>>t<>\", \"<\", \">\", \"g\")\n * returns: [\"t<<e>><s>\", \"\"]\n * matchRecursiveRegExp(\"<div id=\\\"x\\\">test</div>\", \"<div\\\\b[^>]*>\", \"</div>\", \"gi\")\n * returns: [\"test\"]\n */\nfunction matchRecursiveRegExp(str, left, right, flags) {\n  'use strict';\n\n  const matchPos = rgxFindMatchPos(str, left, right, flags);\n  const results = [];\n\n  for (var i = 0; i < matchPos.length; ++i) {\n    results.push([\n      str.slice(matchPos[i].wholeMatch.start, matchPos[i].wholeMatch.end),\n      str.slice(matchPos[i].match.start, matchPos[i].match.end),\n      str.slice(matchPos[i].left.start, matchPos[i].left.end),\n      str.slice(matchPos[i].right.start, matchPos[i].right.end)\n    ]);\n  }\n  return results;\n}\n\nfunction rgxFindMatchPos(str, left, right, flags) {\n  'use strict';\n  flags = flags || '';\n  const global = flags.indexOf('g') > -1;\n  const bothMatcher = new RegExp(left + '|' + right, 'g' + flags.replace(/g/g, ''));\n  const leftMatcher = new RegExp(left, flags.replace(/g/g, ''));\n  const pos = [];\n  let index, match, start, end;\n  let count = 0;\n\n  while ((match = bothMatcher.exec(str))) {\n    if (leftMatcher.test(match[0])) {\n      if (!(count++)) {\n        index = bothMatcher.lastIndex;\n        start = index - match[0].length;\n      }\n    } else if (count) {\n      if (!--count) {\n        end = match.index + match[0].length;\n        var obj = {\n          left: {start: start, end: index},\n          match: {start: index, end: match.index},\n          right: {start: match.index, end: end},\n          wholeMatch: {start: start, end: end}\n        };\n        pos.push(obj);\n        if (!global) {\n          return pos;\n        }\n      }\n    }\n  }\n\n  if (count) {\n    throw new Error(str.slice(start, index));\n  }\n\n  return pos;\n}\n\nfunction createOpenMatcher(elementNameMatcher) {\n  const attributeName = '[a-zA-Z_:][a-zA-Z0-9:._-]*';\n  const unquoted = '[^\"\\'=<>`\\\\u0000-\\\\u0020]+';\n  const singleQuoted = '\\'[^\\']*\\'';\n  const doubleQuoted = '\"[^\"]*\"';\n  const attributeValue = '(?:' + unquoted + '|' + singleQuoted + '|' + doubleQuoted + ')';\n  const attribute = '(?:\\\\s+' + attributeName + '(?:\\\\s*=\\\\s*' + attributeValue + ')?)';\n  return `<${elementNameMatcher}${attribute}*\\\\s*>`;\n}\n\nfunction createCloseMatcher(elementNameMatcher) {\n  return `</${elementNameMatcher}>`;\n}\n"
  },
  {
    "path": "apps/rxjs.dev/tools/transforms/remark-package/services/renderMarkdown.spec.js",
    "content": "const renderMarkdownFactory = require('./renderMarkdown');\n\n// prettier-ignore\ndescribe('remark: renderMarkdown service', () => {\n  let renderMarkdown;\n  beforeEach(() => {\n    renderMarkdown = renderMarkdownFactory();\n  });\n\n  it('should convert markdown to HTML', () => {\n    const content = '# heading 1\\n' +\n        '\\n' +\n        'A paragraph with **bold** and _italic_.\\n' +\n        '\\n' +\n        '* List item 1\\n' +\n        '* List item 2';\n    const output = renderMarkdown(content);\n\n    expect(output).toEqual(\n      '<h1>heading 1</h1>\\n' +\n        '<p>A paragraph with <strong>bold</strong> and <em>italic</em>.</p>\\n' +\n        '<ul>\\n' +\n        '<li>List item 1</li>\\n' +\n        '<li>List item 2</li>\\n' +\n        '</ul>\\n');\n  });\n\n  it('should not process markdown inside inline tags', () => {\n    const content = '* list item {@link some_url_path}';\n    const output = renderMarkdown(content);\n    expect(output).toEqual('<ul>\\n<li>list item {@link some_url_path}</li>\\n</ul>\\n');\n  });\n\n  it('should not format the contents of tags marked as unformatted ', () => {\n    const content = '<code-example>\\n\\n  **abc**\\n\\n  def\\n</code-example>\\n\\n<code-tabs><code-pane>\\n\\n  **abc**\\n\\n  def\\n</code-pane></code-tabs>';\n    const output = renderMarkdown(content);\n    expect(output).toEqual('<code-example>\\n\\n  **abc**\\n\\n  def\\n</code-example>\\n<code-tabs><code-pane>\\n\\n  **abc**\\n\\n  def\\n</code-pane></code-tabs>\\n');\n  });\n\n  it('should handle recursive tags marked as unformatted', () => {\n    const content = '<code-example>\\n\\n  <code-example>\\n\\n  **abc**\\n\\n  def\\n\\n</code-example>\\n\\n</code-example>\\n\\nhij\\n\\n<code-example>\\n\\nklm</code-example>';\n    const output = renderMarkdown(content);\n    expect(output).toEqual('<code-example>\\n\\n  <code-example>\\n\\n  **abc**\\n\\n  def\\n\\n</code-example>\\n\\n</code-example>\\n<p>hij</p>\\n<code-example>\\n\\nklm</code-example>\\n');\n  });\n\n  it('should raise an error if a tag marked as unformatted is not closed', () => {\n    const content = '<code-example path=\"xxx\">\\n\\n  **abc**\\n\\n  def\\n<code-example>\\n\\n\\n\\n  **abc**\\n\\n  def\\n</code-example>';\n    expect(() => renderMarkdown(content)).toThrowError('Unmatched plain HTML block tag <code-example path=\"xxx\">');\n  });\n\n  it('should not remove spaces after anchor tags', () => {\n    var input =\n        'A aa aaa aaaa aaaaa aaaaaa aaaaaaa aaaaaaaa aaaaaaaaa aaaaaaaaaa aaaaaaaaaaa\\n' +\n        '[foo](path/to/foo) bbb.';\n    var output =\n        '<p>' +\n        'A aa aaa aaaa aaaaa aaaaaa aaaaaaa aaaaaaaa aaaaaaaaa aaaaaaaaaa aaaaaaaaaaa\\n' +\n        '<a href=\"path/to/foo\">foo</a> bbb.' +\n        '</p>\\n';\n\n    expect(renderMarkdown(input)).toEqual(output);\n  });\n\n  it('should not format indented text as code', () => {\n    const content = 'some text\\n\\n    indented text\\n\\nother text';\n    const output = renderMarkdown(content);\n    expect(output).toEqual('<p>some text</p>\\n<p>    indented text</p>\\n<p>other text</p>\\n');\n  });\n\n  it('should format triple backtick code blocks as `code-example` tags', () => {\n    const content =\n    '```ts\\n' +\n    '  class MyClass {\\n' +\n    '    method1() { ... }\\n' +\n    '  }\\n' +\n    '```';\n    const output = renderMarkdown(content);\n    expect(output).toEqual(\n      '<code-example language=\"ts\">\\n' +\n    '  class MyClass {\\n' +\n    '    method1() { ... }\\n' +\n    '  }\\n' +\n    '</code-example>\\n'\n    );\n  });\n});\n"
  },
  {
    "path": "apps/rxjs.dev/tools/transforms/rxjs-decision-tree-generator/README.md",
    "content": "# Decision Tree Generator\n\n## Purpose\n\nManage a decision tree in YAML for choosing an operator and generate JSON to be consumed by the docs web app.\n\n## Goals\n\n- Port the first version of the decision-tree-widget into Angular\n- Flatten the JSON structure and make it easy to work with in the docs web app\n- Consume URI paths and other relevant from the docs generation task vai Dgeni\n- Keep the decision tree work scalable and easy to work with by keeping the linked list structure in the YAML tree\n\n## Prior Art\n\nVersion 1 was in the old docs site and used YAML, snabbdom, RxJS, and hyperscript-helpers. The YAML for version 1 version was ported into the new version with minor tweaks.\n\n## Tech\n\n- Node\n- TypeScript\n- TS-Node\n- Jest\n- YAML\n\n## Dependencies\n\nGenerating the JSON requires:\n\n- The decision tree YAML, located in `/src`\n- The generated `api-list.json`, which can be generated by running `yarn docs` at the root level of the `apps/rxjs.dev`\n\n## Setup & Build\n\n```shell\nnpm i && yarn build\n```\n\n## Development\n\nAny changes to the YAML tree or any of the TypeScript scripts will generate a new JSON tree\n\n```shell\nyarn watch\n```\n\n## Distribution\n\nAfter a `yarn build` the JSON is output to `apps/rxjs.dev/src/generated/app/decision-tree-data.json` to be consumed by the web application.\n\nThere's also an npm script at the root level of the `apps/rxjs.dev` to generate the JSON tree: `docs-decision-tree`.\n\n## Testing\n\nRun a watch task when writing tests\n\n```shell\nyarn test:watch\n```\n\nFull test\n\n```shell\nyarn test\n```\n\nRun coverage\n\n```shell\nyarn test:coverage\nyarn test:watch:coverage\n```\n\n## TODO\n\n- Consider moving this work into a Dgeni package so it can be generated in the same way the other doc information is generated\n"
  },
  {
    "path": "apps/rxjs.dev/tools/transforms/rxjs-decision-tree-generator/index.ts",
    "content": "import { readFile } from 'fs/promises';\nimport { parse } from 'yamljs';\n\nimport { TreeNodeRaw, build, flattenApiList } from './src/lib';\n\nmodule.exports = function decisionTreeGenerator(log: { warn: (message: string) => void }) {\n  return {\n    $runBefore: ['rendering-docs'],\n    $runAfter: ['generateApiListDoc'],\n    $validate: {\n      decisionTreeFile: { presence: true },\n      outputFolder: { presence: true },\n    },\n    $process: async function (this: any, docs: any[]) {\n      const apiListDoc = docs.find((doc) => doc.docType === 'api-list-data');\n\n      if (!apiListDoc) {\n        throw new Error('Can not find api-list-data for decision tree generation');\n      }\n\n      const yamlContent = await readFile(this.decisionTreeFile, { encoding: 'utf8' });\n      const decisionTreeJson: TreeNodeRaw[] = parse(yamlContent);\n\n      const flattenedApiList = flattenApiList(apiListDoc.data);\n      const jsonContent = build(flattenedApiList, decisionTreeJson, log);\n\n      docs.push({\n        docType: 'decision-tree-data',\n        template: 'json-doc.template.json',\n        path: this.outputFolder + '/decision-tree-data.json',\n        outputPath: this.outputFolder + '/decision-tree-data.json',\n        data: jsonContent,\n      });\n      return docs;\n    },\n  };\n};\n"
  },
  {
    "path": "apps/rxjs.dev/tools/transforms/rxjs-decision-tree-generator/src/lib/addUniqueId.spec.ts",
    "content": "import { addUniqueId } from './addUniqueId';\nimport { TreeNode } from './interfaces';\nimport { mockRawTreeNodes } from './fixtures';\n\ndescribe('addUniqueId', () => {\n  describe('when called with three raw nodes', () => {\n    let tree: TreeNode[];\n    const baseProperties = jasmine.objectContaining({\n      id: jasmine.any(String),\n      label: jasmine.any(String),\n      depth: jasmine.any(Number),\n    });\n\n    beforeEach(() => {\n      tree = addUniqueId(mockRawTreeNodes);\n    });\n\n    describe('and one of the nodes is a child of another', () => {\n      it('should not flatten the tree and return the same number of top level nodes', () => {\n        expect(tree.length).toBe(mockRawTreeNodes.length);\n      });\n      it('should return an array of tree nodes that have unique ids', () => {\n        tree.forEach((node) => {\n          expect(node).toEqual(baseProperties);\n\n          if (!node.children) {\n            expect(node.options).toBeUndefined();\n          } else {\n            expect(node).toEqual(\n              jasmine.objectContaining({\n                children: jasmine.any(Array),\n                options: jasmine.any(Array),\n              })\n            );\n            node.children.forEach((child) => {\n              expect(child).toEqual(baseProperties);\n            });\n          }\n        });\n      });\n    });\n  });\n});\n"
  },
  {
    "path": "apps/rxjs.dev/tools/transforms/rxjs-decision-tree-generator/src/lib/addUniqueId.ts",
    "content": "import { TreeNode, TreeNodeRaw } from './interfaces';\nimport { generateUniqueId } from './generateUniqueId';\n\n/**\n * Recursively walks the tree and adds unique ids.\n * It also aggregates nested nodes new unique IDs in an options field.\n * Depth is added to better determine later if it's an inital question\n *\n * @export\n * @param {Tree} tree\n * @param {number} [depth=0]\n * @requires generateUniqueId\n * @returns {Tree}\n */\nexport function addUniqueId(tree: TreeNodeRaw[], depth = 0): TreeNode[] {\n  return tree.map(node => {\n    let treeNode: TreeNode;\n    treeNode = {\n      label: node.label,\n      id: generateUniqueId(),\n      depth // used later in extractInitialSequence to determine the initial options\n    };\n\n    if (node.children) {\n      const children = addUniqueId(node.children, depth + 1);\n      treeNode = {\n        ...treeNode,\n        children,\n        options: children.map(({ id }) => id)\n      };\n    }\n\n    if (node.method) {\n      treeNode = {\n        ...treeNode,\n        method: node.method\n      };\n    }\n\n    return treeNode;\n  });\n}\n"
  },
  {
    "path": "apps/rxjs.dev/tools/transforms/rxjs-decision-tree-generator/src/lib/build.spec.ts",
    "content": "import { build } from './build';\nimport { mockFlatApiList, mockRawTreeNodes } from './fixtures';\nimport { treeNodeCount } from './helpers';\n\ndescribe('build', () => {\n  const tree = build(mockFlatApiList, mockRawTreeNodes, {warn: () => {}});\n  it('should return a flat map of all nodes and one additional initial node', () => {\n    expect(tree.initial).toBeDefined()\n    expect(Object.keys(tree).length).toBe(treeNodeCount(mockRawTreeNodes) + 1);\n  });\n});\n"
  },
  {
    "path": "apps/rxjs.dev/tools/transforms/rxjs-decision-tree-generator/src/lib/build.ts",
    "content": "import { addUniqueId } from './addUniqueId';\nimport { extractInitialSequence } from './extractInitialSequence';\nimport { FlattenedApiList, DecisionTree, TreeNodeRaw } from './interfaces';\nimport { decisionTreeReducer } from './decisionTreeReducer';\n\n/**\n * Main build script, outputs the decision tree.\n *\n * @export\n * @param {FlattenedApiList} apiList\n * @param {Tree} tree\n * @requires addUniqueId\n * @requires extractInitialSequence\n * @requires decisionTreeReducer\n * @returns {DecisionTree}\n */\nexport function build(apiList: FlattenedApiList, tree: TreeNodeRaw[], log: { warn: (message: string) => void }): DecisionTree {\n  const nodesWithUniqueIds = addUniqueId(tree);\n  const initialOption = extractInitialSequence(nodesWithUniqueIds);\n\n  return {\n    ...decisionTreeReducer(nodesWithUniqueIds, apiList, log),\n    [initialOption.id]: { ...initialOption },\n  };\n}\n"
  },
  {
    "path": "apps/rxjs.dev/tools/transforms/rxjs-decision-tree-generator/src/lib/decisionTreeReducer.spec.ts",
    "content": "import { decisionTreeReducer } from './decisionTreeReducer';\nimport { mockFlatApiList, mockRawTreeNodes } from './fixtures';\nimport { addUniqueId } from './addUniqueId';\nimport { rawNodesWithMethodCount } from './helpers';\n\ndescribe('decisionTreeReducer', () => {\n  const tree = decisionTreeReducer(addUniqueId(mockRawTreeNodes), mockFlatApiList, { warn: jasmine.createSpy() });\n  describe('all nodes', () => {\n    const baseProperties = jasmine.objectContaining({\n      id: jasmine.any(String),\n      label: jasmine.any(String),\n    });\n\n    it('should have base properties', () => {\n      for (const key in tree) {\n        if (tree.hasOwnProperty(key)) {\n          expect(tree[key]).toEqual(baseProperties);\n        }\n      }\n    });\n\n    describe('that have options', () => {\n      it('should have an options property that is an array of strings', () => {\n        for (const key in tree) {\n          if (tree.hasOwnProperty(key) && tree[key].options) {\n            tree[key].options?.forEach((option) => {\n              expect(typeof option).toBe('string');\n            });\n          }\n        }\n      });\n    });\n\n    describe('when a node does not have options', () => {\n      it('should not have an options property', () => {\n        for (const key in tree) {\n          if (tree.hasOwnProperty(key) && !tree[key].options) {\n            expect(tree[key].options).toBeUndefined();\n          }\n        }\n      });\n      it('should have a docType and a path', () => {\n        for (const key in tree) {\n          if (tree.hasOwnProperty(key) && !tree[key].options) {\n            expect(tree[key].docType).toBeDefined();\n            expect(tree[key].path).toBeDefined();\n          }\n        }\n      });\n\n      describe('and the node does not exist in the API list', () => {\n        const treeNodesMissingInApiList = [\n          ...mockRawTreeNodes,\n          {\n            label: 'foo',\n          },\n        ];\n        it('should call a console.log', () => {\n          const spy = jasmine.createSpy('warn');\n          decisionTreeReducer(addUniqueId(treeNodesMissingInApiList), mockFlatApiList, { warn: spy });\n          expect(spy).toHaveBeenCalled();\n        });\n      });\n    });\n\n    describe('when any raw node had a method', () => {\n      const rawCount = rawNodesWithMethodCount(mockRawTreeNodes);\n      it('should have a method property', () => {\n        let count = 0;\n        for (const key in tree) {\n          if (tree.hasOwnProperty(key) && tree[key].method) {\n            count++;\n          }\n        }\n        expect(count).toBe(rawCount);\n      });\n    });\n  });\n});\n"
  },
  {
    "path": "apps/rxjs.dev/tools/transforms/rxjs-decision-tree-generator/src/lib/decisionTreeReducer.ts",
    "content": "import { DecisionTree, FlattenedApiList, FlattenedApiNode, TreeNode } from './interfaces';\n\n/**\n * Recursively walks the tree and pulls relevant information from the API list.\n * Helps build the view model.\n *\n * @export\n * @param {Tree} tree\n * @param {FlattenedApiList} apiList\n * @returns {DecisionTree}\n */\nexport function decisionTreeReducer(tree: TreeNode[], apiList: FlattenedApiList, log: { warn: (message: string) => void }): DecisionTree {\n  return tree.reduce((acc, curr) => {\n    let nested;\n    let treeNode: TreeNode = {\n      // there might not be options, grab what we know is available\n      id: curr.id,\n      label: curr.label,\n    };\n\n    if (curr.options) {\n      // we are still deciding\n      treeNode = {\n        ...treeNode,\n        options: curr.options,\n      };\n    }\n\n    if (!curr.options) {\n      // we found the function/operator we want to use\n      const apiNode: FlattenedApiNode = apiList[treeNode.label! as keyof FlattenedApiList];\n      if (!apiNode) {\n        log.warn(`Decision Tree Generator - (reducer) - warning: Label does not exist in API List: ${treeNode.label}`);\n      }\n\n      treeNode = {\n        ...treeNode,\n        ...apiNode, // helps to build uri, used in Angular template\n      };\n    }\n\n    if (curr.method) {\n      // if we need to point at a method of a class, like Observable.create, helps to build uri\n      treeNode = {\n        ...treeNode,\n        method: curr.method,\n      };\n    }\n\n    if (curr.children) {\n      // there are children of the current node, recursively walk the paths to continue building the decision tree data\n      nested = decisionTreeReducer(curr.children, apiList, log);\n    }\n\n    return {\n      ...acc,\n      ...nested,\n      [treeNode.id]: treeNode,\n    };\n  }, {});\n}\n"
  },
  {
    "path": "apps/rxjs.dev/tools/transforms/rxjs-decision-tree-generator/src/lib/extractInitialSequence.spec.ts",
    "content": "import { extractInitialSequence } from './extractInitialSequence';\nimport { addUniqueId } from './addUniqueId';\nimport { mockRawTreeNodes } from './fixtures';\n\nconst tree = addUniqueId(mockRawTreeNodes);\nconst initialSequence = extractInitialSequence(tree);\n\ndescribe('extractInitialSequence', () => {\n  describe('when given a tree that has passed through addUniqueId', () => {\n    it('will return an object that has an id of initial', () => {\n      expect(initialSequence).toEqual({\n        id: 'initial',\n        options: jasmine.any(Array)\n      });\n    });\n\n    it('it will return a number of options equal to the length of the original tree', () => {\n      expect(initialSequence.options.length).toBe(mockRawTreeNodes.length);\n    });\n  });\n});\n"
  },
  {
    "path": "apps/rxjs.dev/tools/transforms/rxjs-decision-tree-generator/src/lib/extractInitialSequence.ts",
    "content": "import { TreeNode } from './interfaces';\n\n/**\n * Strip out initial sequence and add to tree\n *\n * @export\n * @param {Tree} tree\n * @returns {{id: string, options: string[]}}\n */\nexport function extractInitialSequence(tree: TreeNode[]): {id: string, options: string[]} {\n  return {\n    id: 'initial',\n    options: tree.filter(node => !node.depth).map(node => node.id)\n  };\n}\n"
  },
  {
    "path": "apps/rxjs.dev/tools/transforms/rxjs-decision-tree-generator/src/lib/fixtures.ts",
    "content": "import { TreeNodeRaw, FlattenedApiList, ApiListNode } from './interfaces';\n\nexport const mockRawTreeNodes: TreeNodeRaw[] = [\n  {\n    label: 'map'\n  },\n  {\n    label: 'just a label',\n    children: [\n      {\n        label: 'yet another label',\n        children: [\n          {\n            label: 'concat'\n          }\n        ]\n      }\n    ]\n  },\n  {\n    label: 'Observable',\n    method: 'fakeMethod'\n  }\n];\n\nexport const mockFlatApiList = {\n  map: {\n    docType: 'function',\n    path: 'fakePath'\n  },\n  mapTo: {\n    docType: 'function',\n    path: 'fakePath'\n  },\n  concat: {\n    docType: 'function',\n    path: 'fakePath'\n  },\n  Observable: {\n    docType: 'class',\n    path: 'fakePath'\n  }\n} as FlattenedApiList;\n\n// TODO consider using the real API list\nexport const mockRawApiListWithDeprecatedRefs: ApiListNode[] = [\n  {\n    name: 'foo',\n    title: 'foo',\n    items: [\n      {\n        name: 'empty',\n        title: 'EMPTY',\n        path: 'api/index/function/empty',\n        docType: 'function',\n        stability: 'deprecated',\n        securityRisk: false\n      },\n      {\n        name: 'empty',\n        title: 'EMPTY',\n        path: 'api/index/const/EMPTY',\n        docType: 'const',\n        stability: '',\n        securityRisk: false\n      },\n      {\n        name: 'concat',\n        title: 'concat',\n        path: 'api/index/function/concat',\n        docType: 'function',\n        stability: '',\n        securityRisk: false\n      }\n    ]\n  },\n  {\n    name: 'bar',\n    title: 'bar',\n    items: [\n      {\n        name: 'never',\n        title: 'NEVER',\n        path: 'api/index/function/never',\n        docType: 'function',\n        stability: 'deprecated',\n        securityRisk: false\n      },\n      {\n        name: 'never',\n        title: 'NEVER',\n        path: 'api/index/const/NEVER',\n        docType: 'const',\n        stability: '',\n        securityRisk: false\n      },\n      {\n        name: 'map',\n        title: 'map',\n        path: 'api/index/function/map',\n        docType: 'function',\n        stability: '',\n        securityRisk: false\n      }\n    ]\n  }\n];\n"
  },
  {
    "path": "apps/rxjs.dev/tools/transforms/rxjs-decision-tree-generator/src/lib/flattenApiList.spec.ts",
    "content": "import { flattenApiList } from './flattenApiList';\nimport { mockRawApiListWithDeprecatedRefs } from './fixtures';\nimport { validApiRefCount } from './helpers';\n\ndescribe('flattenApiList', () => {\n  describe('when a API reference is deprecated', () => {\n    const flattenedApiList = flattenApiList(mockRawApiListWithDeprecatedRefs);\n    const validRefCount = validApiRefCount(mockRawApiListWithDeprecatedRefs);\n    it('should return a flat list with only stable refs', () => {\n      expect(Object.keys(flattenedApiList).length).toBe(validRefCount);\n    });\n  });\n});\n\n\n"
  },
  {
    "path": "apps/rxjs.dev/tools/transforms/rxjs-decision-tree-generator/src/lib/flattenApiList.ts",
    "content": "import { ApiListNode, FlattenedApiList } from './interfaces';\nimport { isStable } from './helpers';\n\n/**\n * Flattens API List from the docs generation into a map with relevant properties.\n * Makes navigation easier.\n *\n * @export\n * @param {ApiListNode[]} [apiList=[]]\n * @requires isStable\n * @returns {FlattenedApiList}\n * @todo create better type lenses - inference is not working well here\n */\nexport function flattenApiList(apiList: ApiListNode[]): FlattenedApiList {\n  return apiList.reduce((acc, curr): FlattenedApiList => {\n    return {\n      ...acc,\n      ...curr.items.reduce((acc, curr): FlattenedApiList => {\n        if (isStable(curr.stability)) {\n          return {\n            ...acc,\n            [curr.title]: {\n              path: curr.path,\n              docType: curr.docType,\n            }\n          };\n        }\n\n        return {\n          ...acc,\n        };\n      }, {} as FlattenedApiList),\n    };\n  }, {} as FlattenedApiList);\n}\n"
  },
  {
    "path": "apps/rxjs.dev/tools/transforms/rxjs-decision-tree-generator/src/lib/generateUniqueId.spec.ts",
    "content": "import { generateUniqueId } from './generateUniqueId';\n\ndescribe('generateUniqueId', () => {\n  describe('when called', () => {\n    it('will generate a unique string', () => {\n      const x = generateUniqueId();\n      expect(x).not.toBe(generateUniqueId());\n      expect(typeof x).toBe('string');\n    });\n  });\n});\n"
  },
  {
    "path": "apps/rxjs.dev/tools/transforms/rxjs-decision-tree-generator/src/lib/generateUniqueId.ts",
    "content": "import { randomBytes } from 'crypto';\n\n/**\n * Generates a unique ID for the decision tree nodes\n *\n * @export\n * @requires crypto:randomByes\n * @returns {string}\n */\nexport function generateUniqueId(): string {\n  return randomBytes(2).toString('hex');\n}\n"
  },
  {
    "path": "apps/rxjs.dev/tools/transforms/rxjs-decision-tree-generator/src/lib/helpers.spec.ts",
    "content": "import { isStable } from './helpers';\n\ndescribe('isStable', () => {\n  describe('when passed anything but the string \"deprecated\"', () => {\n    it('will return true', () => {\n      expect(isStable('')).toBeTruthy();\n    });\n  });\n  describe('when passed the string \"deprecated\"', () => {\n    it('will return false', () => {\n      expect(isStable('deprecated')).toBeFalsy();\n    });\n  });\n});\n"
  },
  {
    "path": "apps/rxjs.dev/tools/transforms/rxjs-decision-tree-generator/src/lib/helpers.ts",
    "content": "import { ApiListNode, TreeNodeRaw } from './interfaces';\n\nexport type Omit<T, K extends keyof T> = Pick<T, Exclude<keyof T, K>>;\n\n/**\n * The model for an API list item has a stability property.\n * If the API reference is deprecated it will not be stable.\n * We don't want to point people to deprecated API references.\n *\n * @export\n * @param {string} stability\n * @returns {boolean}\n */\nexport function isStable(stability: string): boolean {\n  return stability !== 'deprecated';\n}\n\n/**\n * Recursively count the number of tree nodes\n *\n * @export\n * @param {*} tree\n * @returns\n */\nexport function treeNodeCount(tree: TreeNodeRaw[]) {\n  return tree.reduce((acc: number, curr) => {\n    let childSum: number;\n    if (curr.children) {\n      childSum = treeNodeCount(curr.children);\n      return ++acc + childSum;\n    }\n\n    return ++acc;\n  }, 0);\n}\n\n/**\n * Recursively count the number of nodes with a method\n *\n * @export\n * @param {*} tree\n * @returns\n */\nexport function rawNodesWithMethodCount(tree: TreeNodeRaw[]): number {\n  return tree.filter((node) => {\n    let childHadMethod = false;\n\n    if (node.method) {\n      return node;\n    }\n\n    if (node.children) {\n      childHadMethod = rawNodesWithMethodCount(node.children) > 0;\n    }\n\n    return childHadMethod;\n  }).length;\n}\n\n/**\n * Recursively count valid API references\n * Deprecated API refs are invalid\n *\n * @export\n * @param {*} apiList\n * @returns\n */\nexport function validApiRefCount(apiList: ApiListNode[]): number {\n  return apiList.reduce((acc, curr) => {\n    const itemCount = curr.items.reduce((a, node) => {\n      if (node.stability === 'deprecated') {\n        return a;\n      }\n\n      return ++a;\n    }, 0);\n\n    return acc + itemCount;\n  }, 0);\n}\n"
  },
  {
    "path": "apps/rxjs.dev/tools/transforms/rxjs-decision-tree-generator/src/lib/index.ts",
    "content": "export * from './addUniqueId';\nexport * from './build';\nexport * from './extractInitialSequence';\nexport * from './flattenApiList';\nexport * from './generateUniqueId';\nexport * from './interfaces';\nexport * from './decisionTreeReducer';\n"
  },
  {
    "path": "apps/rxjs.dev/tools/transforms/rxjs-decision-tree-generator/src/lib/interfaces.ts",
    "content": "import { Omit } from './helpers';\n\nexport type DocType =\n  | 'all'\n  | 'class'\n  | 'const'\n  | 'enum'\n  | 'function'\n  | 'interface'\n  | 'type-alias';\n\nexport type ApiUnion =\n  | 'audit'\n  | 'auditTime'\n  | 'bindCallback'\n  | 'bindNodeCallback'\n  | 'buffer'\n  | 'bufferCount'\n  | 'bufferTime'\n  | 'bufferToggle'\n  | 'bufferWhen'\n  | 'catchError'\n  | 'combineLatest'\n  | 'concat'\n  | 'concatMap'\n  | 'concatMapTo'\n  | 'count'\n  | 'debounce'\n  | 'debounceTime'\n  | 'defer'\n  | 'delay'\n  | 'delayWhen'\n  | 'distinct'\n  | 'distinctUntilChanged'\n  | 'distinctUntilKeyChanged'\n  | 'elementAt'\n  | 'EMPTY'\n  | 'exhaustMap'\n  | 'expand'\n  | 'filter'\n  | 'finalize'\n  | 'first'\n  | 'forkJoin'\n  | 'from'\n  | 'fromEvent'\n  | 'fromEventPattern'\n  | 'generate'\n  | 'groupBy'\n  | 'ignoreElements'\n  | 'interval'\n  | 'last'\n  | 'map'\n  | 'mapTo'\n  | 'materialize'\n  | 'merge'\n  | 'mergeMap'\n  | 'mergeMapTo'\n  | 'mergeScan'\n  | 'NEVER'\n  | 'Observable'\n  | 'observeOn'\n  | 'of'\n  | 'pairwise'\n  | 'partition'\n  | 'pipe'\n  | 'race'\n  | 'range'\n  | 'reduce'\n  | 'repeat'\n  | 'repeatWhen'\n  | 'retry'\n  | 'retryWhen'\n  | 'scan'\n  | 'share'\n  | 'single'\n  | 'skip'\n  | 'skipLast'\n  | 'skipUntil'\n  | 'skipWhile'\n  | 'startWith'\n  | 'subscribeOn'\n  | 'switchMap'\n  | 'switchMapTo'\n  | 'take'\n  | 'takeLast'\n  | 'takeUntil'\n  | 'takeWhile'\n  | 'tap'\n  | 'throttle'\n  | 'throttleTime'\n  | 'throwError'\n  | 'timeInterval'\n  | 'timeout'\n  | 'timeoutWith'\n  | 'timer'\n  | 'toArray'\n  | 'window'\n  | 'windowCount'\n  | 'windowTime'\n  | 'windowToggle'\n  | 'windowWhen'\n  | 'withLatestFrom'\n  | 'zip';\n\nexport interface ApiListItem {\n  docType: DocType;\n  name: string;\n  path: string;\n  securityRisk: boolean;\n  stability: string;\n  title: ApiUnion;\n}\n\nexport interface ApiListNode {\n  items: ApiListItem[];\n  name: string;\n  title: string;\n}\n\nexport interface FlattenedApiNode {\n  docType: DocType;\n  path: string;\n}\n\nexport type FlattenedApiList = {\n  [K in ApiUnion]: FlattenedApiNode;\n};\n\nexport interface TreeNodeRaw {\n  label: string;\n  children?: TreeNodeRaw[];\n  method?: string;\n}\n\nexport interface TreeNode {\n  id: string;\n  label?: string;\n  children?: TreeNode[];\n  depth?: number;\n  docType?: DocType;\n  method?: string;\n  options?: string[];\n  path?: string;\n}\n\nexport interface DecisionTree {\n  [key: string]: Omit<TreeNode, 'depth' | 'children'>;\n}\n"
  },
  {
    "path": "apps/rxjs.dev/tools/transforms/templates/README.md",
    "content": "This folder contains the dgeni templates that are used to generate the API docs\n\nGenerally there is a template for each docType. Templates can extend and/or include\nother templates. Templates can also import macros from other template files.\n\n# Template inheritance\n\nWhen extending a template, parent must declare blocks that can be overridden by the\nchild. The template extension hierarchy looks like this (with declared blocks in parentheses):\n\n- layout/base.template.html (base)\n  - module.template.html\n  - layout/api-base.template.html (jumpNav, jumpNavLinks, whatItDoes, infoBar, securityConsiderations,\n    deprecationNotes, howToUse, details)\n    - class.template.html\n      - directive.template.html\n      - enum.template.html\n    - var.template.html\n      - const.template.html\n      - let.template.html\n    - decorator.template.html\n    - function.template.html\n    - interface.template.html\n      - type-alias.template.html\n    - pipe.template.html\n\n# Doc Properties\n\nIt is useful to know what properties are available on each doc type when working with the templates.\nThe `typescript` Dgeni package is now written in TypeScript and there is a class for each of the types of\nAPI document. See https://github.com/angular/dgeni-packages/tree/master/typescript/src/api-doc-types.\nThis is a good place to go to see what properties you can use in the templates."
  },
  {
    "path": "apps/rxjs.dev/tools/transforms/templates/api/base.template.html",
    "content": "{% import \"lib/githubLinks.html\" as github -%}\n{% set comma = joiner(',') %}\n{% set slash = joiner('/') %}\n<article>\n  <div class=\"page-actions\">\n    <a href=\"{$ github.githubEditHref(doc, versionInfo) $}\" aria-label=\"Suggest Edits\" title=\"Suggest Edits\"><i class=\"material-icons\" aria-hidden=\"true\" role=\"img\">mode_edit</i></a>\n    <a href=\"{$ github.githubViewHref(doc, versionInfo) $}\" aria-label=\"View Source\" title=\"View Source\"><i class=\"material-icons\" aria-hidden=\"true\" role=\"img\">code</i></a>\n  </div>\n  <div class=\"breadcrumb\">\n    <script type=\"application/ld+json\">\n      {\n        \"@context\": \"http://schema.org\",\n        \"@type\": \"BreadcrumbList\",\n        \"itemListElement\": [\n          {%- for crumb in doc.breadCrumbs %}{$ comma() $}\n          { \"@type\": \"ListItem\", \"position\": {$ loop.index $}, \"item\": { \"@id\": \"https://angular.io/{$ crumb.path $}\", \"name\": \"{$ crumb.text $}\" } }{% endfor %}\n        ]\n      }\n    </script>\n    {% for crumb in doc.breadCrumbs %}{% if not loop.last %} {$ slash() $} {% if crumb.path %}<a href=\"{$ crumb.path $}\">{$ crumb.text $}</a>{% else %}{$ crumb.text $}{% endif %}{% endif %}{% endfor %}\n  </div>\n  <header class=\"api-header\">\n    <h1>{$ doc.name $}</h1>\n    <label class=\"api-type-label {$ doc.docType $}\">{$ doc.docType $}</label>\n    {% if doc.deprecated !== undefined %}<label class=\"api-status-label deprecated\">deprecated</label>{% endif %}\n    {% if doc.experimental !== undefined %}<label class=\"api-status-label experimental\">experimental</label>{% endif %}\n    {% if doc.stable !== undefined %}<label class=\"api-status-label stable\">stable</label>{% endif %}\n    {% if doc.pipeOptions.pure === 'false' %}<label class=\"api-status-label impure-pipe\">impure</label>{% endif %}\n    {% if doc.isOperator %}<label class=\"api-status-label operator\">operator</label>{% endif %}\n  </header>\n  <aio-toc class=\"embedded\"></aio-toc>\n\n  <div class=\"api-body\">\n    {% block body %}{% endblock %}\n  </div>\n</article>\n"
  },
  {
    "path": "apps/rxjs.dev/tools/transforms/templates/api/class.template.html",
    "content": "{% import \"lib/memberHelpers.html\" as memberHelpers -%}\n{% import \"lib/descendants.html\" as descendants -%}\n{% import \"lib/paramList.html\" as params -%}\n{% extends 'export-base.template.html' -%}\n\n{% block overview %}\n  {% include \"includes/class-overview.html\" %}\n{% endblock %}\n{% block details %}\n  {% block additional %}{% endblock %}\n  {% include \"includes/description.html\" %}\n  {$ memberHelpers.renderProperties(doc.staticProperties, 'static-properties', 'static-property', 'Static Properties') $}\n  {$ memberHelpers.renderMethodDetails(doc.staticMethods, 'static-methods', 'static-method', 'Static Methods') $}\n  {% if doc.constructorDoc %}\n  <h2>Constructor</h2>\n  {$ memberHelpers.renderMethodDetail(doc.constructorDoc, 'constructor') $}{% endif %}\n\n  {$ memberHelpers.renderProperties(doc.properties, 'instance-properties', 'instance-property', 'Properties') $}\n\n  {$ memberHelpers.renderMethodDetails(doc.methods, 'instance-methods', 'instance-method', 'Methods') $}\n\n  {% block annotations %}{% include \"includes/annotations.html\" %}{% endblock %}\n{% endblock %}\n"
  },
  {
    "path": "apps/rxjs.dev/tools/transforms/templates/api/const.template.html",
    "content": "{% extends 'var.template.html' -%}"
  },
  {
    "path": "apps/rxjs.dev/tools/transforms/templates/api/decorator.template.html",
    "content": "{% import \"lib/memberHelpers.html\" as memberHelper -%}\n{% import \"lib/paramList.html\" as params -%}\n{% extends 'export-base.template.html' %}\n\n{% block overview %}{% include \"includes/decorator-overview.html\" %}{% endblock %}\n{% block details %}\n  {% include \"includes/description.html\" %}\n  {$ memberHelper.renderProperties(doc.members, 'metadata-members', 'metadata-member', 'Options') $}\n{% endblock %}\n"
  },
  {
    "path": "apps/rxjs.dev/tools/transforms/templates/api/deprecation.template.html",
    "content": "{% block overview %}\r\n<section class=\"deprecations\">\r\n  <h1>Deprecations</h1>\r\n  <p class=\"important\">The API listed below will be removed in the next major release!</p>\r\n  <table>\r\n{% for deprecation in doc.data %}\r\n    <tr>\r\n        <td>\r\n            <a href=\"{$ deprecation.path $}\">{$ deprecation.name $}</a>\r\n        </td>\r\n        <td>\r\n            {$ deprecation.text $}\r\n        </td>\r\n    </tr>\r\n    {% endfor %}\r\n  </table>\r\n</section>\r\n{% endblock %}\r\n\r\n\r\n"
  },
  {
    "path": "apps/rxjs.dev/tools/transforms/templates/api/directive.template.html",
    "content": "{% import \"lib/directiveHelpers.html\" as directiveHelper -%}\n{% import \"lib/paramList.html\" as params -%}\n{% extends 'class.template.html' -%}\n\n{% block overview %}{% include \"includes/directive-overview.html\" %}{% endblock %}\n{% block additional -%}\n  {% include \"includes/selectors.html\" %}\n  {$ directiveHelper.renderBindings(doc.inputs, 'inputs', 'input', 'Inputs') $}\n  {$ directiveHelper.renderBindings(doc.outputs, 'outputs', 'output', 'Outputs') $}\n  {% include \"includes/export-as.html\" %}\n{% endblock %}\n\n{% block annotations %}{% endblock %}\n"
  },
  {
    "path": "apps/rxjs.dev/tools/transforms/templates/api/enum.template.html",
    "content": "{% extends 'class.template.html' -%}"
  },
  {
    "path": "apps/rxjs.dev/tools/transforms/templates/api/export-base.template.html",
    "content": "{% extends 'base.template.html' -%}\n\n{% block body %}\n  {% include \"includes/renamed-exports.html\" %}\n  <p class=\"short-description\">{$ doc.shortDescription | marked $}</p>\n  {% include \"includes/security-notes.html\" %}\n  {% include \"includes/deprecation.html\" %}\n  {% block overview %}{% endblock %}\n  {% block details %}{% endblock %}\n  {% include \"includes/usageNotes.html\" %}\n  {% include \"includes/see-also.html\" %}\n{% endblock %}\n"
  },
  {
    "path": "apps/rxjs.dev/tools/transforms/templates/api/function.template.html",
    "content": "{% import \"lib/memberHelpers.html\" as memberHelpers -%}\n{% import \"lib/paramList.html\" as params -%}\n{% extends 'export-base.template.html' -%}\n\n{% block overview %}\n{% if doc.overloads.length > 0 and doc.overloads.length < 3 -%}\n  {% for overload in doc.overloads -%}\n    {$ memberHelpers.renderOverloadInfo(overload, 'function-overload', doc) $}\n    {% if not loop.last %}<hr class=\"hr-margin fullwidth\">{% endif %}\n  {% endfor -%}\n{% else %}\n  {$ memberHelpers.renderOverloadInfo(doc, 'function-overload', doc) $}\n{% endif %}\n{% endblock %}\n\n\n{% block details %}\n{% include \"includes/description.html\" %}\n{% if doc.overloads.length >= 3 %}\n<section class=\"overloads\">\n  <h2>Overloads</h2>\n  <table>\n  {% for overload in doc.overloads %}\n  <tr>\n    <td>\n      {$ memberHelpers.renderOverloadInfo(overload, 'function-overload', doc) $}\n    </td>\n  </tr>\n  {% endfor %}\n  </table>\n</section>\n{% endif %}\n{% endblock %}"
  },
  {
    "path": "apps/rxjs.dev/tools/transforms/templates/api/includes/annotations.html",
    "content": "{%- if doc.decorators.length %}\n<section class=\"annotations\">\n  <h2>Annotations</h2>\n  {%- for decorator in doc.decorators %}\n    <code-example language=\"ts\" hideCopy=\"true\" class=\"no-box api-heading\">@{$ decorator.name $}({$ decorator.arguments $})</code-example>\n    {% if not decorator.notYetDocumented %}{$ decorator.description | marked $}{% endif %}\n  {% endfor %}\n</section>\n{% endif %}\n"
  },
  {
    "path": "apps/rxjs.dev/tools/transforms/templates/api/includes/class-overview.html",
    "content": "{% import \"lib/memberHelpers.html\" as memberHelper -%}\n\n<section class=\"{$ doc.docType $}-overview\">\n<code-example language=\"ts\" hideCopy=\"true\">\n{% if doc.isAbstract %}abstract {% endif%}{$ doc.docType $} {$ doc.name $}{$ doc.typeParams | escape $}{$ memberHelper.renderHeritage(doc) $} {{$ memberHelper.renderMembers(doc) $}\n}\n</code-example>\n{$ descendants.renderDescendants(doc, 'class', 'Subclasses') $}\n</section>\n"
  },
  {
    "path": "apps/rxjs.dev/tools/transforms/templates/api/includes/decorator-overview.html",
    "content": "{% import \"lib/memberHelpers.html\" as memberHelper -%}\n\n{% if doc.members.length %}\n<section class=\"decorator-overview\">\n<code-example language=\"ts\" hideCopy=\"true\">\n@{$ doc.name $}{$ doc.typeParams | escape $}({ {$ memberHelper.renderMembers(doc) $}\n})\n</code-example>\n</section>\n{% endif %}"
  },
  {
    "path": "apps/rxjs.dev/tools/transforms/templates/api/includes/deprecation.html",
    "content": "{% if doc.deprecated %}\n<section class=\"deprecated\">\n  <h2>Deprecation Notes</h2>\n  {$ doc.deprecated | marked $}\n</section>\n{% endif %}"
  },
  {
    "path": "apps/rxjs.dev/tools/transforms/templates/api/includes/description.html",
    "content": "{% if doc.description %}\n<section class=\"description\">\n  <h2>Description</h2>\n  {$ doc.description | trimBlankLines | marked $}\n</section>\n{% endif %}"
  },
  {
    "path": "apps/rxjs.dev/tools/transforms/templates/api/includes/directive-overview.html",
    "content": "{% import \"lib/memberHelpers.html\" as memberHelper -%}\n\n<section class=\"{$ doc.docType $}-overview\">\n<code-example language=\"ts\" hideCopy=\"true\">{% for decorator in doc.decorators %}\n@{$ decorator.name $}({$ decorator.arguments $}){% endfor %}\nclass {$ doc.name $}{$ doc.typeParams | escape $}{$ memberHelper.renderHeritage(doc) $} {\n{%- if doc.statics.length %}{% for member in doc.statics %}{% if not member.internal %}\n  <a class=\"code-anchor\" href=\"#{$ member.anchor | urlencode $}\">{$ memberHelper.renderMemberSyntax(member, 1) $}</a>{% endif %}{% endfor %}{% endif -%}\n{$ memberHelper.renderMembers(doc) $}\n}\n</code-example>\n</section>\n"
  },
  {
    "path": "apps/rxjs.dev/tools/transforms/templates/api/includes/export-as.html",
    "content": "{%- if doc.exportAs %}\n<section class=\"export-as\">\n  <h2>Exported as</h2>\n  <div>\n    <code>{$ doc.exportAs $}</code>\n  </div>\n</section>\n{% endif %}\n"
  },
  {
    "path": "apps/rxjs.dev/tools/transforms/templates/api/includes/info-bar.html",
    "content": "{% import \"lib/githubLinks.html\" as github -%}\n\n<!-- INFO BAR -->\n<section class=\"info-bar\">\n\n<table class=\"is-full-width\">\n<tbody>\n<tr>\n  <th>npm Package</th>\n  <td><a href=\"https://www.npmjs.com/package/@angular/{$ doc.moduleDoc.id.split('/')[0] $}\">@angular/{$ doc.moduleDoc.id.split('/')[0] $}</a></td>\n</tr>\n<tr>\n  <th>Module</th>\n  <td><code>import { {$ doc.name $} } from <a href=\"{$ doc.moduleDoc.path $}\">'@angular/{$ doc.moduleDoc.id $}'</a>;</code></td>\n</tr>\n<tr>\n  <th>Source</th>\n  <td>{$ github.githubViewLink(doc, versionInfo) $}</td>\n</tr>\n{% if doc.ngModule %}\n<tr>\n  <th>NgModule</th>\n  <td>{@link {$ doc.ngModule $}}</td>\n</tr>\n{% endif %}\n</tbody>\n</table>\n"
  },
  {
    "path": "apps/rxjs.dev/tools/transforms/templates/api/includes/interface-overview.html",
    "content": "{% import \"lib/memberHelpers.html\" as memberHelper -%}\n\n<section class=\"interface-overview\">\n<code-example language=\"ts\" hideCopy=\"true\">\ninterface {$ doc.name $}{$ doc.typeParams | escape $}{$ memberHelper.renderHeritage(doc) $} {{$ memberHelper.renderMembers(doc) $}\n}\n</code-example>\n{$ descendants.renderDescendants(doc, 'interface', 'Child Interfaces') $}\n{$ descendants.renderDescendants(doc, 'class', 'Class Implementations') $}\n</section>"
  },
  {
    "path": "apps/rxjs.dev/tools/transforms/templates/api/includes/metadata.html",
    "content": "{% if doc.members.length %}\n<section class=\"meta-data\">\n  <h2>Metadata Properties</h2>\n    {% for metadata in doc.members %}{% if not metadata.internal %}\n    <div class=\"metadata-member\">\n      <a name=\"{$ metadata.name $}\" class=\"anchor-offset\"></a>\n      <code-example language=\"ts\" hideCopy=\"true\">{$ metadata.name $}{$ params.paramList(metadata.parameters) | trim $}{$ params.returnType(metadata.type) $}</code-example>\n      {%- if not metadata.notYetDocumented %}{$ metadata.description | marked $}{% endif -%}\n    </div>\n    {% if not loop.last %}<hr class=\"hr-margin\">{% endif %}\n  {% endif %}{% endfor %}\n</section>\n{% endif %}\n"
  },
  {
    "path": "apps/rxjs.dev/tools/transforms/templates/api/includes/pipe-overview.html",
    "content": "{% import \"lib/memberHelpers.html\" as memberHelpers -%}\n{% import \"lib/paramList.html\" as params -%}\n\n<section class=\"{$ doc.docType $}-overview\">\n  <code-example hideCopy=\"true\" class=\"no-box api-heading\">{{ {$ doc.valueParam.name $}_expression | <span class=\"kwd nocode\">{$ doc.pipeName $}</span>\n    {%- for param in doc.pipeParams %}\n      {%- if param.isOptional or param.defaultValue !== undefined %} [{% endif %} : {$ param.name $}\n    {%- endfor %}\n    {%- for param in doc.pipeParams %}\n      {%- if param.isOptional or param.defaultValue !== undefined %} ]{% endif %}\n    {%- endfor %} }}</code-example>\n\n  {% if doc.valueParam.type %}\n  <h2>Input Value</h2>\n  {$ params.renderParameters([doc.valueParam], 'pipe-parameters', 'pipe-parameter', true) $}\n  {% endif %}\n  {% if doc.pipeParams.length %}\n  <h2>Parameters</h2>\n  {$ params.renderParameters(doc.pipeParams, 'pipe-parameters', 'pipe-parameter', true) $}\n  {% endif %}\n</section>\n"
  },
  {
    "path": "apps/rxjs.dev/tools/transforms/templates/api/includes/renamed-exports.html",
    "content": "{% if doc.renamedDuplicates %}\n<section class=\"renamed-duplicates\">\n  Aliased as\n  {% for d in doc.renamedDuplicates %}\n    <i>{$ d.name $}</i>{% if not loop.last %}, {% endif %}\n  {% endfor %}\n</section>\n{% endif %}\n"
  },
  {
    "path": "apps/rxjs.dev/tools/transforms/templates/api/includes/security-notes.html",
    "content": "{% if doc.security %}\n<section \"security\">\n  <h2>Security Risk</h2>\n  {$ doc.security | marked $}\n</section>\n{% endif %}"
  },
  {
    "path": "apps/rxjs.dev/tools/transforms/templates/api/includes/see-also.html",
    "content": "{%- if doc.see.length %}\n<section class=\"see-also\">\n  <h2>See Also</h2>\n  <ul>\n  {% for see in doc.see %}\n    <li>{$ see | marked $}</li>{% endfor %}\n  </ul>\n</section>\n{% endif %}\n"
  },
  {
    "path": "apps/rxjs.dev/tools/transforms/templates/api/includes/selectors.html",
    "content": "{%- if doc.selector %}\n<section class=\"selectors\">\n  <h2>Selectors</h2>\n  <code-example hideCopy=\"true\" class=\"no-box api-heading selector\">\n  {%- for selector in doc.selector.split(',') %}\n  {$ selector $}{% endfor %}\n  </code-example>\n</section>\n{% endif %}\n"
  },
  {
    "path": "apps/rxjs.dev/tools/transforms/templates/api/includes/usageNotes.html",
    "content": "{% if doc.usageNotes %}\n<section class=\"usage-notes\">\n  <h2>Usage Notes</h2>\n  {$ doc.usageNotes | marked $}\n</section>\n{% endif %}\n"
  },
  {
    "path": "apps/rxjs.dev/tools/transforms/templates/api/interface.template.html",
    "content": "{% import \"lib/paramList.html\" as params -%}\n{% import \"lib/memberHelpers.html\" as memberHelper -%}\n{% import \"lib/descendants.html\" as descendants -%}\n{% extends 'export-base.template.html' -%}\n\n{% block overview %}{% include \"includes/interface-overview.html\" %}{% endblock %}\n{% block details %}\n  {% include \"includes/description.html\" %}\n  {$ memberHelper.renderProperties(doc.properties, 'instance-properties', 'instance-property', 'Properties') $}\n  {$ memberHelper.renderMethodDetails(doc.methods, 'instance-methods', 'instance-method', 'Methods') $}\n{% endblock %}\n"
  },
  {
    "path": "apps/rxjs.dev/tools/transforms/templates/api/let.template.html",
    "content": "{% extends 'var.template.html' -%}"
  },
  {
    "path": "apps/rxjs.dev/tools/transforms/templates/api/lib/descendants.html",
    "content": "{% macro renderDescendantList(descendants, docType, recursed) %}\n{% if descendants.length %}\n<ul>\n  {% for descendant in descendants %}\n    <li>\n      <code>{$ descendant.name $}</code>\n      {$ renderDescendantList(descendant.descendants | filterByPropertyValue('docType', docType), docType, recursed) $}\n    </li>\n  {% endfor %}\n</ul>\n{% endif %}\n{% endmacro -%}\n\n{%- macro renderDescendants(doc, docType, title='', recursed=true) %}\n  {% set descendants = doc.descendants | filterByPropertyValue('docType', docType) %}\n  {% if descendants.length %}\n  <div class=\"descendants {$ docType $}\">\n    {% if title %}<h2>{$ title $}</h2>{% endif %}\n    {$ renderDescendantList(descendants, docType, recursed) $}\n  </div>\n  {% endif %}\n{% endmacro %}"
  },
  {
    "path": "apps/rxjs.dev/tools/transforms/templates/api/lib/directiveHelpers.html",
    "content": "{% macro renderBindings(bindings, cssContainerClass, cssItemClass, title) -%}\n{% if bindings.length %}\n<section class=\"{$ cssContainerClass $}\">\n  <h2>{$ title $}</h2>\n  {% for binding in bindings %}\n  <div class=\"{$ cssItemClass $}\">\n    <code>{$ binding.bindingName $}</code>&nbsp;bound to&nbsp;<code>{$ binding.memberDoc.containerDoc.name $}.{$ binding.propertyName $}</code>\n    {#{$ binding.memberDoc.description | trimBlankLines | marked $}#}\n  </div>\n  {% endfor %}\n</section>\n{% endif %}\n{%- endmacro %}"
  },
  {
    "path": "apps/rxjs.dev/tools/transforms/templates/api/lib/githubLinks.html",
    "content": "{% macro githubViewHref(doc, versionInfo) -%}\nhttps://github.com/{$ versionInfo.gitRepoInfo.owner $}/{$ versionInfo.gitRepoInfo.repo $}/tree/{$ versionInfo.currentVersion.isSnapshot and versionInfo.currentVersion.SHA or versionInfo.currentVersion.raw $}/src/{$ doc.fileInfo.realProjectRelativePath $}#L{$ doc.startingLine + 1 $}-L{$ doc.endingLine + 1 $}\n{%- endmacro %}\n\n\n{% macro githubEditHref(doc, versionInfo) -%}\nhttps://github.com/{$ versionInfo.gitRepoInfo.owner $}/{$ versionInfo.gitRepoInfo.repo $}/edit/master/src/{$ doc.fileInfo.realProjectRelativePath $}?message=docs(\n  {%- if doc.moduleDoc %}{$ doc.moduleDoc.id.split('/')[0] $}\n  {%- elseif doc.docType === 'module' %}{$ doc.id.split('/')[0] $}\n  {%- else %}...{%- endif -%}\n)%3A%20describe%20your%20change...#L{$ doc.startingLine + 1 $}-L{$ doc.endingLine + 1 $}\n{%- endmacro %}"
  },
  {
    "path": "apps/rxjs.dev/tools/transforms/templates/api/lib/memberHelpers.html",
    "content": "{% import \"lib/paramList.html\" as params -%}\n\n{%- macro renderHeritage(exportDoc) -%}\n  {%- if exportDoc.extendsClauses.length %} extends {% for clause in exportDoc.extendsClauses -%}\n  {$ clause.text | escape $}{% if not loop.last %}, {% endif -%}\n  {% endfor %}{% endif %}\n  {%- if exportDoc.implementsClauses.length %} implements {% for clause in exportDoc.implementsClauses -%}\n  {$ clause.text | escape $}{% if not loop.last %}, {% endif -%}\n  {% endfor %}{% endif %}\n{%- endmacro -%}\n\n{%- macro renderMembers(doc) -%}\n  {%- for member in doc.staticProperties %}{% if not member.internal %}\n  <a class=\"code-anchor{% if member.deprecated %} deprecated-api-item{% endif %}\" href=\"{$ doc.path $}#{$ member.anchor | urlencode $}\">{$ renderMemberSyntax(member, 1) $}</a>{% endif %}{% endfor -%}\n  {% for member in doc.staticMethods %}{% if not member.internal %}\n  <a class=\"code-anchor{% if member.deprecated %} deprecated-api-item{% endif %}\" href=\"{$ doc.path $}#{$ member.anchor | urlencode $}\">{$ renderMemberSyntax(member, 1) $}</a>{% endif %}{% endfor -%}\n  {% if doc.constructorDoc and not doc.constructorDoc.internal %}\n  <a class=\"code-anchor{% if member.deprecated %} deprecated-api-item{% endif %}\" href=\"{$ doc.path $}#{$ doc.constructorDoc.anchor | urlencode $}\">{$ renderMemberSyntax(doc.constructorDoc, 1) $}</a>{% endif -%}\n  {% for member in doc.properties %}{% if not member.internal %}\n  <a class=\"code-anchor{% if member.deprecated %} deprecated-api-item{% endif %}\" href=\"{$ doc.path $}#{$ member.anchor | urlencode $}\">{$ renderMemberSyntax(member, 1) $}</a>{% endif %}{% endfor -%}\n  {% for member in doc.methods %}{% if not member.internal %}\n  <a class=\"code-anchor{% if member.deprecated %} deprecated-api-item{% endif %}\" href=\"{$ doc.path $}#{$ member.anchor | urlencode $}\">{$ renderMemberSyntax(member, 1) $}</a>{% endif %}{% endfor -%}\n\n  {%- for ancestor in doc.extendsClauses %}{% if ancestor.doc %}\n\n  // inherited from <a class=\"code-anchor\" href=\"{$ ancestor.doc.path $}\">{$ ancestor.doc.id $}</a>{$ renderMembers(ancestor.doc) $}{% endif %}{% endfor -%}\n{%- endmacro -%}\n\n{%- macro renderMemberSyntax(member, truncateLines) -%}\n    {%- if member.accessibility !== 'public' %}{$ member.accessibility $} {% endif -%}\n    {%- if member.isAbstract %}abstract {% endif -%}\n    {%- if member.isStatic %}static {% endif -%}\n    {%- if (member.isGetAccessor or member.isReadonly) and not member.isSetAccessor %}get {% endif -%}\n    {%- if member.isSetAccessor and not member.isGetAccessor %}set {% endif -%}\n    {$ member.name $}{$ member.typeParameters | escape $}{% if not member.isGetAccessor %}{$ params.paramList(member.parameters, truncateLines) | trim $}{% endif %}\n    {%- if member.isOptional  %}?{% endif -%}\n    {$ params.returnType(member.type) | trim | truncateCode(truncateLines) $}\n{%- endmacro -%}\n\n{%- macro renderOverloadInfo(overload, cssClass, method) -%}\n\n<code-example language=\"ts\" hideCopy=\"true\" class=\"no-box api-heading{% if overload.deprecated %} deprecated-api-item{% endif %}\">{$ renderMemberSyntax(overload) $}</code-example>\n\n{% if overload.shortDescription and (overload.shortDescription != method.shortDescription) %}\n<div class=\"short-description\">\n  {$ overload.shortDescription | marked $}\n</div>{% endif %}\n\n<h4 class=\"no-anchor\">Parameters</h4>\n{$ params.renderParameters(overload.parameterDocs, cssClass + '-parameters', cssClass + '-parameter', true) $}\n\n{% if overload.type or overload.returns.type %}\n<h4 class=\"no-anchor\">Returns</h4>\n{% marked %}`{$ (overload.type or overload.returns.type) $}`{% if overload.returns %}: {$ overload.returns.description $}{% endif %}{% endmarked %}\n{% endif %}\n\n\n{% if overload.throws.length %}\n<h4 class=\"no-anchor\">Throws</h4>\n{% for error in overload.throws %}\n{% marked %}`{$ (error.typeList or 'Error') $}` {$ error.description $}{% endmarked %}\n{% endfor %}\n{% endif %}\n\n{% if overload.description and (overload.description != method.description) -%}\n<div class=\"description\">\n  {$ overload.description | marked $}\n</div>\n{%- endif %}\n{%- endmacro -%}\n\n{%- macro renderMethodDetail(method, cssClass) -%}\n<a id=\"{$ method.anchor $}\"></a>\n<table class=\"is-full-width method-table {$ cssClass $}\">\n  {% if method.name !== 'constructor' %}<thead><tr><th><h3>\n    {% if method.isCallMember %}<i>call signature</i>\n    {% elseif method.isNewMember %}<i>construct signature</i>\n    {% else %}{$ method.name $}()\n    {% endif %}\n  </h3></th></tr></thead>{% endif %}\n  <tbody>\n    {% if method.shortDescription %}<tr>\n      <td class=\"short-description\">\n        {$ method.shortDescription | marked $}\n      </td>\n    </tr>{% endif %}\n  {% if method.overloads.length == 0 %}\n    <tr>\n      <td>\n        {$ renderOverloadInfo(method, cssClass + '-overload', method) $}\n      </td>\n    </tr>\n  {% elseif method.overloads.length < 3 -%}\n    {% for overload in method.overloads -%}\n    <tr>\n      <td>\n        {$ renderOverloadInfo(overload, cssClass + '-overload', method) $}\n      </td>\n    </tr>\n    {% endfor -%}\n  {% else -%}\n    <tr>\n      <td>\n        <details class=\"overloads\">\n          <summary><h4 class=\"no-anchor\">{$ method.overloads.length $} overloads...</h4></summary>\n          <div class=\"detail-contents\">\n              {% for overload in method.overloads %}\n                {$ renderOverloadInfo(overload, cssClass + '-overload', method) $}\n                {% if not loop.last %}<hr class=\"hr-margin fullwidth\">{% endif %}\n              {% endfor %}\n          </div>\n        </details>\n      </td>\n    </tr>\n  {% endif %}\n  {% if method.description %}<tr>\n      <td class=\"description\">\n        {$ method.description | marked $}\n      </td>\n    </tr>{% endif %}\n  </tbody>\n</table>\n{% endmacro -%}\n\n{%- macro renderMethodDetails(methods, containerClass, itemClass, headingText) -%}\n{% set nonInternalMethods = methods | filterByPropertyValue('internal', undefined) %}\n{% if nonInternalMethods.length %}\n<section class=\"{$ containerClass $}\">\n  <h2>{$ headingText $}</h2>\n  {% for member in nonInternalMethods %}\n    {$ renderMethodDetail(member, itemClass) $}\n  {% endfor %}\n</section>\n{% endif %}\n{%- endmacro -%}\n\n\n{%- macro renderProperties(properties, containerClass, propertyClass, headingText) -%}\n{% set nonInternalProperties = properties | filterByPropertyValue('internal', undefined) %}\n{% if nonInternalProperties.length -%}\n<section class=\"{$ containerClass $}\">\n  <h2>{$ headingText $}</h2>\n  <table class=\"is-full-width list-table properties-table\">\n    <thead>\n      <tr><th>Property</th><th>Type</th><th>Description</th></tr>\n    </thead>\n    <tbody>\n    {% for property in nonInternalProperties %}\n      <tr class=\"{$ propertyClass $}\">\n        <td><a id=\"{$ property.anchor $}\"></a><code class=\"{% if property.deprecated %} deprecated-api-item{% endif %}\">{$ property.name $}</code></td>\n        <td><label class=\"property-type-label\"><code>{$ property.type | escape $}</code></label></td>\n        <td>\n          {%- if (property.isGetAccessor or property.isReadonly) and not property.isSetAccessor %}<span class='read-only-property'>Read-only.</span>{% endif %}\n          {% if property.shortDescription %}{$ property.shortDescription | marked $}{% endif %}\n          {$ (property.description or property.constructorParamDoc.description) | marked $}\n          {% if property.constructorParamDoc %} <span class='from-constructor'>Declared in constructor.</span>{% endif %}\n        </td>\n    </tr>\n    {% endfor %}\n    </tbody>\n  </table>\n</section>\n{%- endif -%}\n{%- endmacro -%}\n"
  },
  {
    "path": "apps/rxjs.dev/tools/transforms/templates/api/lib/paramList.html",
    "content": "{% macro paramList(params, truncateLines) -%}\n  {%- if params -%}\n    ({%- for param in params -%}\n      {$ param | escape | truncateCode(truncateLines) $}{% if not loop.last %}, {% endif %}\n    {%- endfor %})\n  {%- endif %}\n{%- endmacro -%}\n\n\n{% macro returnType(returnType) -%}\n  {%- if returnType %}: {$ returnType | escape $}{% endif -%}\n{%- endmacro -%}\n\n{%- macro renderParameters(parameters, containerClass, parameterClass, showType) -%}\n{%- if parameters.length -%}\n<table class=\"is-full-width list-table parameters-table {$ containerClass $}\">\n  <tbody>\n  {% for parameter in parameters %}\n    <tr class=\"{$ parameterClass $}\">\n      <td class=\"param-name\">\n        <a id=\"{$ parameter.anchor or parameter.name $}\"></a>\n        <code>{$ parameter.name $}</code>\n      </td>\n      {% if showType %}<td class=\"param-type\"><code>{$ parameter.type | escape $}</code></td>{% endif %}\n      <td class=\"param-description\">\n      {% marked %}\n        {% if parameter.isOptional or parameter.defaultValue !== undefined %}Optional. Default is `{$ parameter.defaultValue === undefined and 'undefined' or parameter.defaultValue $}`.{% endif %}\n\n        {% if parameter.description | trim %}{$ parameter.description $}\n        {% elseif not showType and parameter.type %}<p>Type: <code>{$ parameter.type | escape $}</code>.</p>\n        {% endif %}\n      {% endmarked %}\n      </td>\n    </tr>{% endfor %}\n  </tbody>\n</table>\n{%- else -%}\n<p>There are no parameters.</p>\n{%- endif -%}\n{%- endmacro -%}\n"
  },
  {
    "path": "apps/rxjs.dev/tools/transforms/templates/api/module.template.html",
    "content": "{% extends 'base.template.html' -%}\n\n{% block body -%}\n\n{% include \"includes/deprecation.html\" %}\n{% include \"includes/description.html\" %}\n\n<section class=\"export-list\">\n  <ul>\n    {% for export in doc.exports -%}\n      {% if not export.duplicateOf %}\n        <li><a{% if export.deprecated %} class=\"deprecated\"{% endif %} href=\"{$ export.path $}\">{$ export.name $}</a></li>\n      {% endif %}\n    {%- endfor %}\n  </ul>\n</section>\n\n{%- endblock %}\n"
  },
  {
    "path": "apps/rxjs.dev/tools/transforms/templates/api/pipe.template.html",
    "content": "{% extends 'export-base.template.html' -%}\n\n{% block overview %}\n{% include \"includes/pipe-overview.html\" %}\n{% endblock %}\n{% block details %}\n{% include \"includes/description.html\" %}\n{% endblock %}\n"
  },
  {
    "path": "apps/rxjs.dev/tools/transforms/templates/api/type-alias.template.html",
    "content": "{% extends 'export-base.template.html' %}\n\n{% block overview %}\n  <section class=\"{$ doc.docType $}-overview\">\n    <code-example language=\"ts\" hideCopy=\"true\">\n    type {$ doc.name $}{$ doc.typeParameters | escape $}{% if doc.typeDefinition %} = {$ doc.typeDefinition | escape $}{% endif %};\n    </code-example>\n  </section>\n{% endblock %}\n\n{% block details %}\n  {% include \"includes/description.html\" %}\n{% endblock %}\n"
  },
  {
    "path": "apps/rxjs.dev/tools/transforms/templates/api/value-module.template.html",
    "content": "{% extends 'interface.template.html' %}"
  },
  {
    "path": "apps/rxjs.dev/tools/transforms/templates/api/var.template.html",
    "content": "{% extends 'export-base.template.html' %}\n\n{% block overview %}\n  <code-example language=\"ts\" hideCopy=\"true\" class=\"no-box api-heading\">\n  const {$ doc.name $}: {$ (doc.type | escape) or 'any' $};\n  </code-example>\n{% endblock %}\n\n{% block details %}\n  {% include \"includes/description.html\" %}\n{% endblock %}\n"
  },
  {
    "path": "apps/rxjs.dev/tools/transforms/templates/content.template.html",
    "content": "{% if doc.title %}{$ ('# ' + doc.title.trim()) | marked $}{% endif %}\n<div class=\"content\">\n{$ doc.description | marked $}\n</div>"
  },
  {
    "path": "apps/rxjs.dev/tools/transforms/templates/data-module.template.js",
    "content": "/* tslint:disable quotemark */\n/* TODO: rework this so that it has single quotes */\nexport const {$ doc.serviceName $} = {$ doc.value | json $};\n"
  },
  {
    "path": "apps/rxjs.dev/tools/transforms/templates/example-region.template.html",
    "content": "{$ doc.contents | escape $}\n"
  },
  {
    "path": "apps/rxjs.dev/tools/transforms/templates/json-doc.template.json",
    "content": "{$ doc.data | json $}"
  },
  {
    "path": "apps/rxjs.dev/tools/transforms/templates/overview-dump.template.html",
    "content": "{% import \"api/lib/githubLinks.html\" as github -%}\n{% import \"api/lib/memberHelpers.html\" as members -%}\n{% macro goToCode(doc) %}<a href=\"{$ github.githubViewHref(doc, versionInfo) $}\" class=\"go-to-code\" title=\"Go to source code\"><i class=\"material-icons\" aria-hidden=\"true\" role=\"img\">code</i></a>{% endmacro %}\n{% macro label(test, class, text) %}{% if test %}<label class=\"{$ class $}\">{$ text $}</label>{% endif %}{% endmacro %}\n{% macro renderLabels(doc) -%}\n  {$ label(doc.notYetDocumented, 'no-doc', 'UNDOCUMENTED') $}\n  {%- for tag in doc.tags.tags %}{$ label(tag.tagDef.deprecated, 'deprecated', '@' + tag.tagDef.name + ' deprecated') $}{% endfor %}\n{% endmacro %}\n{% macro renderMember(member) -%}\n  <div class=\"member\">{$ goToCode(member) $}\n  <h4><code>{$ members.renderMemberSyntax(member, 1) $}</code></h4>\n    {$ renderLabels(member) $}\n  </div>\n{% endmacro -%}\n\n<!DOCTYPE html>\n<html>\n<head>\n  <title></title>\n  <link href=\"https://fonts.googleapis.com/icon?family=Material+Icons\" rel=\"stylesheet\">\n  <style>\n    body {\n      margin: 0 50px;\n    }\n    details {\n      margin: 10px;\n      padding: 0 10px;\n      border: solid black 1px;\n    }\n    details details {\n      border: none;\n      margin: 0;\n    }\n\n    .member:nth-child(odd) {\n      background-color: #eee;\n    }\n    h2, h3, h4 {\n      display: inline-block;\n      margin: 0;\n    }\n    h3 {\n      padding-left: 15px;\n    }\n    h4 {\n      padding: 10px 0 0 30px;\n    }\n    div {\n      position: relative;\n    }\n\n    label {\n      border-radius: 4px;\n      padding: 4px 8px;\n      display: inline-block;\n      font-size: 12px;\n      color: #fff;\n      margin: 0 8px;\n      font-weight: bold;\n      font-family: Arial, Helvetica, sans-serif;\n    }\n\n    .no-doc {\n      background-color: red;\n    }\n\n    .deprecated {\n      background-color: orange;\n      color: black;\n    }\n\n    a.go-to-code {\n      position: absolute;\n      top: 10px;\n      right: 10px;\n    }\n  </style>\n</head>\n<body>\n\n\n<h1>Documentation Status Report</h1>\n\n{% for module in doc.modules %}\n<details>\n  <summary><h2><code>{$ module.id $}{%- if module.public %} (public){% endif %}</code></h2></summary>\n\n  {% for export in module.exports %}\n  <div class=\"export\">{$ goToCode(export) $}\n    <details>\n      <summary><h3><code>{$ export.docType $} {$ export.name $}</code></h3>{$ renderLabels(export) $}</summary>\n\n      {%- for member in export.staticProperties %}{% if not member.internal %}\n      {$ renderMember(member) $}</a>{% endif %}{% endfor -%}\n      {% for member in export.staticMethods %}{% if not member.internal %}\n      {$ renderMember(member) $}</a>{% endif %}{% endfor -%}\n      {% if export.constructorDoc and not export.constructorexport.internal %}\n      {$ renderMember(export.constructorDoc) $}</a>{% endif -%}\n      {% for member in export.properties %}{% if not member.internal %}\n      {$ renderMember(member) $}</a>{% endif %}{% endfor -%}\n      {% for member in export.methods %}{% if not member.internal %}\n      {$ renderMember(member) $}</a>{% endif %}{% endfor -%}\n\n    </details>\n  </div>\n  {% endfor %}\n</details>\n{% endfor %}\n</body>\n</html>\n"
  },
  {
    "path": "apps/rxjs.dev/tools/transforms/templates/sitemap.template.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<urlset xmlns=\"http://www.sitemaps.org/schemas/sitemap/0.9\">\n  {%- for url in doc.urls %}\n  <url>\n    <loc>https://rxjs.dev/{$ url $}</loc>\n  </url>{% endfor %}\n</urlset>"
  },
  {
    "path": "apps/rxjs.dev/tools/transforms/test.js",
    "content": "/*\n * Use this script to run the tests for the doc generation\n * We cannot use the Jasmine CLI directly because it doesn't seem to\n * understand the glob and only runs one spec file.\n *\n * Equally we cannot use a jasmine.json config file because it doesn't\n * allow us to set the projectBaseDir, which means that you have to run\n * jasmine CLI from this directory.\n *\n * Using a file like this gives us full control and keeps the package.json\n * file clean and simple.\n */\n\nconst Jasmine = require('jasmine');\nconst jasmine = new Jasmine({ projectBaseDir: __dirname });\njasmine.loadConfig({ spec_files: ['**/*.spec.{js,ts}'] });\njasmine.execute();\n"
  },
  {
    "path": "apps/rxjs.dev/tsconfig.app.json",
    "content": "{\n    \"extends\": \"./tsconfig.json\",\n    \"compilerOptions\": {\n      \"noPropertyAccessFromIndexSignature\": false,\n      \"outDir\": \"./out-tsc/app\",\n      \"types\": [\n        \"trusted-types\"\n      ],\n      \"plugins\": [\n        {\n          \"name\": \"tsec\",\n          \"exemptionConfig\": \"./security-exemptions.json\"\n        }\n      ]\n    },\n    \"files\": [\n      \"src/main.ts\",\n      \"src/polyfills.ts\"\n    ],\n    \"include\": [\n      \"src/**/*.d.ts\"\n    ]\n  }"
  },
  {
    "path": "apps/rxjs.dev/tsconfig.docs.json",
    "content": "{\n  \"extends\": \"./tsconfig.json\",\n  \"compilerOptions\": {\n    \"module\": \"commonjs\",\n    \"noUnusedParameters\": false,\n    \"noUnusedLocals\": false,\n    \"target\": \"es6\"\n  }\n}\n"
  },
  {
    "path": "apps/rxjs.dev/tsconfig.json",
    "content": "/* To learn more about this file see: https://angular.io/config/tsconfig. */\n{\n  \"compileOnSave\": false,\n  \"compilerOptions\": {\n    \"baseUrl\": \"src\",\n    \"outDir\": \"./out-tsc\",\n    \"forceConsistentCasingInFileNames\": true,\n    \"strict\": true,\n    \"noImplicitOverride\": true,\n    // NOTE: Intentionally deviate from default Angular CLI settings\n    //       (due to many violations and uglier syntax).\n    \"noPropertyAccessFromIndexSignature\": false,\n    \"noImplicitReturns\": true,\n    \"noFallthroughCasesInSwitch\": true,\n    \"noUnusedLocals\": true,\n    \"noUnusedParameters\": true,\n    \"sourceMap\": true,\n    \"declaration\": false,\n    \"downlevelIteration\": true,\n    \"experimentalDecorators\": true,\n    \"moduleResolution\": \"node\",\n    \"importHelpers\": true,\n    \"target\": \"es2017\",\n    \"module\": \"es2020\",\n    \"lib\": [\n      \"es2020\",\n      \"dom\"\n    ],\n    \"skipLibCheck\": true,\n    // disabled because this is on by default in tsc 2.7 breaking our codebase - we need to refactor\n    \"strictPropertyInitialization\": false\n  },\n  \"exclude\": [\n    \"aio-builds-setup\",\n    \"content\",\n    \"dist\",\n    \"node_modules\",\n    \"out-tsc\",\n    \"scripts\"\n  ],\n  \"angularCompilerOptions\": {\n    \"enableI18nLegacyMessageIdFormat\": false,\n    \"disableTypeScriptVersionCheck\": true,\n    \"strictInjectionParameters\": true,\n    \"strictInputAccessModifiers\": true,\n    \"strictTemplates\": true\n  }\n}"
  },
  {
    "path": "apps/rxjs.dev/tsconfig.spec.json",
    "content": "{\n  \"extends\": \"./tsconfig.json\",\n  \"compilerOptions\": {\n    \"noUnusedParameters\": false,\n    \"outDir\": \"./out-tsc/spec\",\n    \"types\": [\n      \"jasmine\",\n      \"node\"\n    ]\n  },\n  \"files\": [\n    \"src/test.ts\",\n    \"src/polyfills.ts\"\n  ],\n  \"include\": [\n    \"src/testing/**/*.ts\",\n    \"src/**/*.spec.ts\",\n    \"src/**/*.d.ts\"\n  ]\n}"
  },
  {
    "path": "apps/rxjs.dev/tsconfig.worker.json",
    "content": "{\n  \"extends\": \"./tsconfig.json\",\n  \"compilerOptions\": {\n    \"outDir\": \"./out-tsc/worker\",\n    \"types\": [\n      \"lunr\"\n    ],\n    \"lib\": [\n      \"es2018\",\n      \"webworker\"\n    ]\n  },\n  \"include\": [\n    \"src/**/*.worker.ts\"\n  ]\n}\n"
  },
  {
    "path": "nx.json",
    "content": "{\n  \"affected\": {\n    \"defaultBase\": \"master\"\n  },\n  \"nxCloudAccessToken\": \"OWE4MTMzMTEtNDZlZi00MWMwLWJkYmEtN2EwYTQ1ZWNjMzRkfHJlYWQ=\",\n  \"targetDefaults\": {\n    \"build\": {\n      \"dependsOn\": [\"^build\"],\n      \"inputs\": [\"production\", \"^production\"],\n      \"cache\": true\n    },\n    \"test:circular\": {\n      \"dependsOn\": [\"build\"]\n    },\n    \"test\": {\n      \"cache\": true\n    },\n    \"lint\": {\n      \"inputs\": [\"default\", \"{workspaceRoot}/.eslintrc.json\", \"{workspaceRoot}/tools/eslint-rules/**/*\"],\n      \"cache\": true\n    }\n  },\n  \"namedInputs\": {\n    \"default\": [\"{projectRoot}/**/*\", \"sharedGlobals\"],\n    \"production\": [\"default\", \"!{projectRoot}/**/?(*.)+(spec|test).[jt]s?(x)?(.snap)\", \"!{projectRoot}/.eslintrc.json\"],\n    \"sharedGlobals\": [\n      \"{workspaceRoot}/github/workflows/*.yml\",\n      {\n        \"runtime\": \"node -e 'console.log(`${process.platform}-${process.arch}`)'\"\n      },\n      {\n        \"runtime\": \"node --version\"\n      },\n      {\n        \"runtime\": \"npm --version\"\n      },\n      {\n        \"runtime\": \"yarn --version\"\n      }\n    ]\n  },\n  \"release\": {\n    \"projects\": [\"packages/*\"],\n    \"releaseTagPattern\": \"{version}\",\n    \"changelog\": {\n      \"workspaceChangelog\": {\n        \"createRelease\": \"github\",\n        \"file\": false\n      },\n      \"projectChangelogs\": true\n    },\n    \"version\": {\n      \"generatorOptions\": {\n        \"currentVersionResolver\": \"git-tag\",\n        \"specifierSource\": \"conventional-commits\"\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "package.json",
    "content": "{\n  \"private\": true,\n  \"workspaces\": {\n    \"packages\": [\n      \"packages/*\",\n      \"apps/rxjs.dev\"\n    ],\n    \"nohoist\": [\n      \"**/@types/jasmine\",\n      \"**/@types/jasminewd2\",\n      \"**/@types/mocha\",\n      \"**/core-js\"\n    ]\n  },\n  \"license\": \"Apache-2.0\",\n  \"engines\": {\n    \"node\": \"^18.13.0 || ^20.9.0\"\n  },\n  \"packageManager\": \"yarn@1.22.21\",\n  \"scripts\": {\n    \"prepare-packages\": \"yarn nx test @rxjs/observable && yarn nx run-many -t build,lint,test:circular,dtslint,copy_common_package_files --exclude rxjs.dev\",\n    \"release\": \"node scripts/release.js\"\n  },\n  \"devDependencies\": {\n    \"@nx/eslint-plugin\": \"17.3.2\",\n    \"@nx/js\": \"17.3.2\",\n    \"@typescript-eslint/eslint-plugin\": \"^6.19.0\",\n    \"@typescript-eslint/parser\": \"^6.19.0\",\n    \"cz-conventional-changelog\": \"1.2.0\",\n    \"eslint\": \"^8.56.0\",\n    \"husky\": \"^4.2.5\",\n    \"lint-staged\": \"^10.2.11\",\n    \"nx\": \"17.3.2\",\n    \"ts-node\": \"^10.9.2\",\n    \"tshy\": \"^1.11.0\",\n    \"typescript\": \"~5.3.3\",\n    \"validate-commit-msg\": \"2.14.0\",\n    \"vitest\": \"^1.2.1\"\n  },\n  \"husky\": {\n    \"hooks\": {\n      \"pre-commit\": \"lint-staged\",\n      \"commit-msg\": \"validate-commit-msg\"\n    }\n  },\n  \"config\": {\n    \"commitizen\": {\n      \"path\": \"cz-conventional-changelog\"\n    }\n  },\n  \"lint-staged\": {\n    \"*.js\": \"eslint --cache --fix\",\n    \"(src|spec)/**/*.ts\": [\n      \"eslint --fix\",\n      \"prettier --write\"\n    ],\n    \"*.{js,css,md}\": \"prettier --write\"\n  }\n}\n\n"
  },
  {
    "path": "packages/observable/.eslintrc.json",
    "content": "{\n  \"extends\": [\"../../.eslintrc.json\"],\n  \"ignorePatterns\": [\"!**/*\"],\n  \"overrides\": [\n    {\n      \"files\": [\"*.ts\", \"*.tsx\", \"*.js\", \"*.jsx\"],\n      \"parserOptions\": {\n        \"project\": [\"./packages/observable/tsconfig.json\"]\n      },\n      \"rules\": {}\n    },\n    {\n      \"files\": [\"*.ts\", \"*.tsx\"],\n      \"rules\": {}\n    },\n    {\n      \"files\": [\"*.js\", \"*.jsx\"],\n      \"rules\": {}\n    },\n    {\n      \"files\": [\"./package.json\"],\n      \"parser\": \"jsonc-eslint-parser\",\n      \"rules\": {\n        \"@nx/dependency-checks\": [\"error\"]\n      }\n    }\n  ]\n}\n"
  },
  {
    "path": "packages/observable/.tshy/browser.json",
    "content": "{\n  \"extends\": \"./build.json\",\n  \"include\": [\n    \"../src/**/*.ts\",\n    \"../src/**/*.mts\",\n    \"../src/**/*.tsx\"\n  ],\n  \"exclude\": [],\n  \"compilerOptions\": {\n    \"outDir\": \"../.tshy-build/browser\"\n  }\n}\n"
  },
  {
    "path": "packages/observable/.tshy/build.json",
    "content": "{\n  \"extends\": \"../tsconfig.json\",\n  \"compilerOptions\": {\n    \"rootDir\": \"../src\",\n    \"target\": \"es2022\",\n    \"module\": \"nodenext\",\n    \"moduleResolution\": \"nodenext\"\n  }\n}\n"
  },
  {
    "path": "packages/observable/.tshy/commonjs.json",
    "content": "{\n  \"extends\": \"./build.json\",\n  \"include\": [\n    \"../src/**/*.ts\",\n    \"../src/**/*.cts\",\n    \"../src/**/*.tsx\"\n  ],\n  \"exclude\": [\n    \"../src/**/*.mts\"\n  ],\n  \"compilerOptions\": {\n    \"outDir\": \"../.tshy-build/commonjs\"\n  }\n}\n"
  },
  {
    "path": "packages/observable/.tshy/esm.json",
    "content": "{\n  \"extends\": \"./build.json\",\n  \"include\": [\n    \"../src/**/*.ts\",\n    \"../src/**/*.mts\",\n    \"../src/**/*.tsx\"\n  ],\n  \"exclude\": [],\n  \"compilerOptions\": {\n    \"outDir\": \"../.tshy-build/esm\"\n  }\n}\n"
  },
  {
    "path": "packages/observable/.tshy/webpack.json",
    "content": "{\n  \"extends\": \"./build.json\",\n  \"include\": [\n    \"../src/**/*.ts\",\n    \"../src/**/*.cts\",\n    \"../src/**/*.tsx\"\n  ],\n  \"exclude\": [\n    \"../src/**/*.mts\"\n  ],\n  \"compilerOptions\": {\n    \"outDir\": \"../.tshy-build/webpack\"\n  }\n}\n"
  },
  {
    "path": "packages/observable/package.json",
    "content": "{\n  \"name\": \"@rxjs/observable\",\n  \"version\": \"8.0.0-alpha.14\",\n  \"license\": \"Apache-2.0\",\n  \"bugs\": {\n    \"url\": \"https://github.com/ReactiveX/RxJS/issues\"\n  },\n  \"homepage\": \"https://rxjs.dev\",\n  \"author\": \"Ben Lesh <ben@benlesh.com>\",\n  \"files\": [\n    \"dist\"\n  ],\n  \"main\": \"./dist/commonjs/index.js\",\n  \"types\": \"./dist/commonjs/index.d.ts\",\n  \"type\": \"module\",\n  \"scripts\": {\n    \"build\": \"tshy\",\n    \"lint\": \"eslint ./src\",\n    \"test\": \"vitest --run\",\n    \"test:watch\": \"vitest\"\n  },\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"https://github.com/ReactiveX/rxjs.git\",\n    \"directory\": \"packages/observable\"\n  },\n  \"keywords\": [\n    \"Rx\",\n    \"RxJS\",\n    \"ReactiveX\",\n    \"ReactiveExtensions\",\n    \"Streams\",\n    \"Observables\",\n    \"Observable\",\n    \"Stream\"\n  ],\n  \"tshy\": {\n    \"exports\": {\n      \"./package.json\": \"./package.json\",\n      \".\": \"./src/index.ts\"\n    },\n    \"esmDialects\": [\n      \"browser\"\n    ],\n    \"commonjsDialects\": [\n      \"webpack\"\n    ]\n  },\n  \"exports\": {\n    \"./package.json\": \"./package.json\",\n    \".\": {\n      \"browser\": {\n        \"types\": \"./dist/browser/index.d.ts\",\n        \"default\": \"./dist/browser/index.js\"\n      },\n      \"webpack\": {\n        \"types\": \"./dist/webpack/index.d.ts\",\n        \"default\": \"./dist/webpack/index.js\"\n      },\n      \"import\": {\n        \"types\": \"./dist/esm/index.d.ts\",\n        \"default\": \"./dist/esm/index.js\"\n      },\n      \"require\": {\n        \"types\": \"./dist/commonjs/index.d.ts\",\n        \"default\": \"./dist/commonjs/index.js\"\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "packages/observable/src/index.ts",
    "content": "export { Observable, Subscriber, Subscription, UnsubscriptionError, config, from, isObservable, operate } from './observable.js';\nexport type { GlobalConfig, SubscriberOverrides } from './observable.js';\n\n// TODO: reevaluate these as part of public API of @rxjs/observable? They aren't exported from rxjs so feel more internal?\nexport {\n  COMPLETE_NOTIFICATION,\n  ObservableInputType,\n  createNotification,\n  errorNotification,\n  fromArrayLike,\n  getObservableInputType,\n  isArrayLike,\n  isFunction,\n  isPromise,\n  nextNotification,\n  readableStreamLikeToAsyncGenerator,\n  subscribeToArray,\n} from './observable.js';\n"
  },
  {
    "path": "packages/observable/src/observable.spec.ts",
    "content": "import { describe, expect, it, vi } from 'vitest';\nimport { Observable, Subscription, config } from './observable.js';\n\nfunction expectFullObserver(val: any) {\n  expect(val).to.be.a('object');\n  expect(val.next).to.be.a('function');\n  expect(val.error).to.be.a('function');\n  expect(val.complete).to.be.a('function');\n  expect(val.closed).to.be.a('boolean');\n}\n\n/** @test {Observable} */\ndescribe('Observable', () => {\n  it('should be constructed with a subscriber function', () =>\n    new Promise<void>((done) => {\n      const source = new Observable<number>(function (observer) {\n        expectFullObserver(observer);\n        observer.next(1);\n        observer.complete();\n      });\n\n      source.subscribe({\n        next: function (x) {\n          expect(x).to.equal(1);\n        },\n        complete: done,\n      });\n    }));\n\n  it('should send errors thrown in the constructor down the error path', () =>\n    new Promise<void>((done) => {\n      new Observable<number>(() => {\n        throw new Error('this should be handled');\n      }).subscribe({\n        error(err) {\n          expect(err).to.exist.and.be.instanceof(Error).and.have.property('message', 'this should be handled');\n          done();\n        },\n      });\n    }));\n\n  describe('forEach', () => {\n    it('should handle a synchronous throw from the next handler', () => {\n      const expected = new Error('I told, you Bobby Boucher, threes are the debil!');\n      const syncObservable = new Observable<number>((observer) => {\n        observer.next(1);\n        observer.next(2);\n        observer.next(3);\n        observer.next(4);\n      });\n\n      const results: Array<number | Error> = [];\n\n      return syncObservable\n        .forEach((x) => {\n          results.push(x);\n          if (x === 3) {\n            throw expected;\n          }\n        })\n        .then(\n          () => {\n            throw new Error('should not be called');\n          },\n          (err) => {\n            results.push(err);\n            // The error should unsubscribe from the source, meaning we\n            // should not see the number 4.\n            expect(results).to.deep.equal([1, 2, 3, expected]);\n          }\n        );\n    });\n\n    it('should handle an asynchronous throw from the next handler and tear down', () => {\n      const expected = new Error('I told, you Bobby Boucher, twos are the debil!');\n      const asyncObservable = new Observable<number>((observer) => {\n        let i = 1;\n        const id = setInterval(() => observer.next(i++), 1);\n\n        return () => {\n          clearInterval(id);\n        };\n      });\n\n      const results: Array<number | Error> = [];\n\n      return asyncObservable\n        .forEach((x) => {\n          results.push(x);\n          if (x === 2) {\n            throw expected;\n          }\n        })\n        .then(\n          () => {\n            throw new Error('should not be called');\n          },\n          (err) => {\n            results.push(err);\n            expect(results).to.deep.equal([1, 2, expected]);\n          }\n        );\n    });\n  });\n\n  describe('subscribe', () => {\n    it('should be synchronous', () => {\n      let subscribed = false;\n      let nexted: string;\n      let completed: boolean;\n      const source = new Observable<string>((observer) => {\n        subscribed = true;\n        observer.next('wee');\n        expect(nexted).to.equal('wee');\n        observer.complete();\n        expect(completed).to.be.true;\n      });\n\n      expect(subscribed).to.be.false;\n\n      let mutatedByNext = false;\n      let mutatedByComplete = false;\n\n      source.subscribe({\n        next: (x) => {\n          nexted = x;\n          mutatedByNext = true;\n        },\n        complete: () => {\n          completed = true;\n          mutatedByComplete = true;\n        },\n      });\n\n      expect(mutatedByNext).to.be.true;\n      expect(mutatedByComplete).to.be.true;\n    });\n\n    it('should work when subscribe is called with no arguments', () => {\n      const source = new Observable<string>((subscriber) => {\n        subscriber.next('foo');\n        subscriber.complete();\n      });\n\n      source.subscribe();\n    });\n\n    it('should run unsubscription logic when an error is sent asynchronously and subscribe is called with no arguments', () =>\n      new Promise<void>((done, fail) => {\n        const fakeTimer = vi.useFakeTimers();\n\n        let unsubscribeCalled = false;\n        const source = new Observable<number>((observer) => {\n          const id = setInterval(() => {\n            observer.error(0);\n          }, 1);\n          return () => {\n            clearInterval(id);\n            unsubscribeCalled = true;\n          };\n        });\n\n        source.subscribe({\n          error() {\n            /* noop: expected error */\n          },\n        });\n\n        setTimeout(() => {\n          let err;\n          let errHappened = false;\n          try {\n            expect(unsubscribeCalled).to.be.true;\n          } catch (e) {\n            err = e;\n            errHappened = true;\n          } finally {\n            if (!errHappened) {\n              done();\n            } else {\n              fail(err);\n            }\n          }\n        }, 100);\n\n        fakeTimer.advanceTimersByTime(110);\n        vi.useRealTimers();\n      }));\n\n    it('should return a Subscription that calls the unsubscribe function returned by the subscriber', () => {\n      let unsubscribeCalled = false;\n\n      const source = new Observable<number>(() => {\n        return () => {\n          unsubscribeCalled = true;\n        };\n      });\n\n      const sub = source.subscribe(() => {\n        //noop\n      });\n      expect(sub instanceof Subscription).to.be.true;\n      expect(unsubscribeCalled).to.be.false;\n      expect(sub.unsubscribe).to.be.a('function');\n\n      sub.unsubscribe();\n      expect(unsubscribeCalled).to.be.true;\n    });\n\n    it('should finalize even with a synchronous thrown error', () => {\n      let called = false;\n      const badObservable = new Observable((subscriber) => {\n        subscriber.add(() => {\n          called = true;\n        });\n\n        throw new Error('bad');\n      });\n\n      badObservable.subscribe({\n        error: () => {\n          /* do nothing */\n        },\n      });\n\n      expect(called).to.be.true;\n    });\n\n    it('should handle empty string sync errors', () => {\n      const badObservable = new Observable(() => {\n        throw '';\n      });\n\n      let caught = false;\n      badObservable.subscribe({\n        error: (err) => {\n          caught = true;\n          expect(err).to.equal('');\n        },\n      });\n      expect(caught).to.be.true;\n    });\n  });\n\n  it('should emit an error for unhandled synchronous exceptions from something like a stack overflow', () => {\n    const source = new Observable(() => {\n      const boom = (): unknown => boom();\n      boom();\n    });\n\n    let thrownError: any = undefined;\n    source.subscribe({\n      error: (err) => (thrownError = err),\n    });\n\n    expect(thrownError).to.be.an.instanceOf(RangeError);\n    expect(thrownError.message).to.equal('Maximum call stack size exceeded');\n  });\n\n  describe('pipe', () => {\n    it('should not swallow internal errors', () =>\n      new Promise<void>((done) => {\n        config.onStoppedNotification = (notification) => {\n          expect(notification.kind).to.equal('E');\n          expect(notification).to.have.property('error', 'bad');\n          config.onStoppedNotification = null;\n          done();\n        };\n\n        new Observable((subscriber) => {\n          subscriber.error('test');\n          throw 'bad';\n        }).subscribe({\n          error: (err) => {\n            expect(err).to.equal('test');\n          },\n        });\n      }));\n  });\n\n  describe('As an async iterable', () => {\n    it('should be able to be used with for-await-of', async () => {\n      const source = new Observable<number>((subscriber) => {\n        subscriber.next(1);\n        subscriber.next(2);\n        subscriber.next(3);\n        subscriber.complete();\n      });\n\n      const results: number[] = [];\n      for await (const value of source) {\n        results.push(value);\n      }\n\n      expect(results).to.deep.equal([1, 2, 3]);\n    });\n\n    it('should unsubscribe if the for-await-of loop is broken', async () => {\n      let activeSubscriptions = 0;\n\n      const source = new Observable<number>((subscriber) => {\n        activeSubscriptions++;\n\n        subscriber.next(1);\n        subscriber.next(2);\n\n        // NOTE that we are NOT calling `subscriber.complete()` here.\n        // therefore the teardown below would never be called naturally\n        // by the observable unless it was unsubscribed.\n        return () => {\n          activeSubscriptions--;\n        };\n      });\n\n      const results: number[] = [];\n      for await (const value of source) {\n        results.push(value);\n        break;\n      }\n\n      expect(results).to.deep.equal([1]);\n      expect(activeSubscriptions).to.equal(0);\n    });\n\n    it('should unsubscribe if the for-await-of loop is broken with a thrown error', async () => {\n      const source = new Observable<number>((subscriber) => {\n        subscriber.next(1);\n        subscriber.next(2);\n        subscriber.next(3);\n        subscriber.complete();\n      });\n\n      const results: number[] = [];\n\n      try {\n        for await (const value of source) {\n          results.push(value);\n          throw new Error('wee');\n        }\n      } catch {\n        // Ignore\n      }\n\n      expect(results).to.deep.equal([1]);\n    });\n\n    it('should cause the async iterator to throw if the observable errors', async () => {\n      const source = new Observable<number>((subscriber) => {\n        subscriber.next(1);\n        subscriber.next(2);\n        subscriber.error(new Error('wee'));\n      });\n\n      const results: number[] = [];\n      let thrownError: any;\n\n      try {\n        for await (const value of source) {\n          results.push(value);\n        }\n      } catch (err: any) {\n        thrownError = err;\n      }\n\n      expect(thrownError?.message).to.equal('wee');\n      expect(results).to.deep.equal([1, 2]);\n    });\n\n    it('should unsubscribe from the source observable if `return` is called on the generator returned by Symbol.asyncIterator', async () => {\n      let state = 'idle';\n      const source = new Observable<number>((subscriber) => {\n        state = 'subscribed';\n        return () => {\n          state = 'unsubscribed';\n        };\n      });\n\n      const asyncIterator = source[Symbol.asyncIterator]();\n      expect(state).to.equal('idle');\n      asyncIterator.next();\n      expect(state).to.equal('subscribed');\n      asyncIterator.return();\n      expect(state).to.equal('unsubscribed');\n    });\n\n    it('should unsubscribe from the source observable if `throw` is called on the generator returned by Symbol.asyncIterator', async () => {\n      let state = 'idle';\n      const source = new Observable<number>((subscriber) => {\n        state = 'subscribed';\n        subscriber.next(0);\n        return () => {\n          state = 'unsubscribed';\n        };\n      });\n\n      const asyncIterator = source[Symbol.asyncIterator]();\n      expect(state).to.equal('idle');\n      await asyncIterator.next();\n      expect(state).to.equal('subscribed');\n      try {\n        await asyncIterator.throw(new Error('wee!'));\n      } catch (err: any) {\n        expect(err.message).to.equal('wee!');\n      }\n      expect(state).to.equal('unsubscribed');\n    });\n  });\n});\n"
  },
  {
    "path": "packages/observable/src/observable.ts",
    "content": "import type {\n  TeardownLogic,\n  UnaryFunction,\n  Subscribable,\n  Observer,\n  OperatorFunction,\n  Unsubscribable,\n  SubscriptionLike,\n  ObservableNotification,\n  ObservableInput,\n  ObservedValueOf,\n  ReadableStreamLike,\n  InteropObservable,\n  CompleteNotification,\n  ErrorNotification,\n  NextNotification,\n} from './types.js';\n\n/**\n * An error thrown when one or more errors have occurred during the\n * `unsubscribe` of a {@link Subscription}.\n */\nexport class UnsubscriptionError extends Error {\n  /**\n   * @deprecated Internal implementation detail. Do not construct error instances.\n   * Cannot be tagged as internal: https://github.com/ReactiveX/rxjs/issues/6269\n   */\n  constructor(public errors: any[]) {\n    super(\n      errors\n        ? `${errors.length} errors occurred during unsubscription:\n  ${errors.map((err, i) => `${i + 1}) ${err.toString()}`).join('\\n  ')}`\n        : ''\n    );\n    this.name = 'UnsubscriptionError';\n  }\n}\n\n/**\n * Represents a disposable resource, such as the execution of an Observable. A\n * Subscription has one important method, `unsubscribe`, that takes no argument\n * and just disposes the resource held by the subscription.\n *\n * Additionally, subscriptions may be grouped together through the `add()`\n * method, which will attach a child Subscription to the current Subscription.\n * When a Subscription is unsubscribed, all its children (and its grandchildren)\n * will be unsubscribed as well.\n */\nexport class Subscription implements SubscriptionLike {\n  public static EMPTY = (() => {\n    const empty = new Subscription();\n    empty.closed = true;\n    return empty;\n  })();\n\n  /**\n   * A flag to indicate whether this Subscription has already been unsubscribed.\n   */\n  public closed = false;\n\n  /**\n   * The list of registered finalizers to execute upon unsubscription. Adding and removing from this\n   * list occurs in the {@link #add} and {@link #remove} methods.\n   */\n  private _finalizers: Set<Exclude<TeardownLogic, void>> | null = null;\n\n  /**\n   * @param initialTeardown A function executed first as part of the finalization\n   * process that is kicked off when {@link #unsubscribe} is called.\n   */\n  constructor(private initialTeardown?: () => void) {}\n\n  /**\n   * Disposes the resources held by the subscription. May, for instance, cancel\n   * an ongoing Observable execution or cancel any other type of work that\n   * started when the Subscription was created.\n   */\n  unsubscribe(): void {\n    let errors: any[] | undefined;\n\n    if (!this.closed) {\n      this.closed = true;\n\n      const { initialTeardown: initialFinalizer } = this;\n      if (isFunction(initialFinalizer)) {\n        try {\n          initialFinalizer();\n        } catch (e) {\n          errors = e instanceof UnsubscriptionError ? e.errors : [e];\n        }\n      }\n\n      const { _finalizers } = this;\n      if (_finalizers) {\n        this._finalizers = null;\n        for (const finalizer of _finalizers) {\n          try {\n            execFinalizer(finalizer);\n          } catch (err) {\n            errors = errors ?? [];\n            if (err instanceof UnsubscriptionError) {\n              errors.push(...err.errors);\n            } else {\n              errors.push(err);\n            }\n          }\n        }\n      }\n\n      if (errors) {\n        throw new UnsubscriptionError(errors);\n      }\n    }\n  }\n\n  /**\n   * Adds a finalizer to this subscription, so that finalization will be unsubscribed/called\n   * when this subscription is unsubscribed. If this subscription is already {@link #closed},\n   * because it has already been unsubscribed, then whatever finalizer is passed to it\n   * will automatically be executed (unless the finalizer itself is also a closed subscription).\n   *\n   * Closed Subscriptions cannot be added as finalizers to any subscription. Adding a closed\n   * subscription to a any subscription will result in no operation. (A noop).\n   *\n   * Adding a subscription to itself, or adding `null` or `undefined` will not perform any\n   * operation at all. (A noop).\n   *\n   * `Subscription` instances that are added to this instance will automatically remove themselves\n   * if they are unsubscribed. Functions and {@link Unsubscribable} objects that you wish to remove\n   * will need to be removed manually with {@link #remove}\n   *\n   * @param teardown The finalization logic to add to this subscription.\n   */\n  add(teardown: TeardownLogic): void {\n    // Only add the finalizer if it's not undefined\n    // and don't add a subscription to itself.\n    if (teardown && teardown !== this) {\n      if (this.closed) {\n        // If this subscription is already closed,\n        // execute whatever finalizer is handed to it automatically.\n        execFinalizer(teardown);\n      } else {\n        if (teardown && 'add' in teardown) {\n          // If teardown is a subscription, we can make sure that if it\n          // unsubscribes first, it removes itself from this subscription.\n          teardown.add(() => {\n            this.remove(teardown);\n          });\n        }\n\n        this._finalizers ??= new Set();\n        this._finalizers.add(teardown);\n      }\n    }\n  }\n\n  /**\n   * Removes a finalizer from this subscription that was previously added with the {@link #add} method.\n   *\n   * Note that `Subscription` instances, when unsubscribed, will automatically remove themselves\n   * from every other `Subscription` they have been added to. This means that using the `remove` method\n   * is not a common thing and should be used thoughtfully.\n   *\n   * If you add the same finalizer instance of a function or an unsubscribable object to a `Subscription` instance\n   * more than once, you will need to call `remove` the same number of times to remove all instances.\n   *\n   * All finalizer instances are removed to free up memory upon unsubscription.\n   *\n   * TIP: In instances you're adding and removing _Subscriptions from other Subscriptions_, you should\n   * be sure to unsubscribe or otherwise get rid of the child subscription reference as soon as you remove it.\n   * The child subscription has a reference to the parent it was added to via closure. In most cases, this\n   * a non-issue, as child subscriptions are rarely long-lived.\n   *\n   * @param teardown The finalizer to remove from this subscription\n   */\n  remove(teardown: Exclude<TeardownLogic, void>): void {\n    this._finalizers?.delete(teardown);\n  }\n}\n\n// Even though Subscription only conditionally implements `Symbol.dispose`\n// if it's available, we still need to declare it here so that TypeScript\n// knows that it exists on the prototype when it is available.\nexport interface Subscription {\n  [Symbol.dispose](): void;\n}\n\nif (typeof Symbol.dispose === 'symbol') {\n  Subscription.prototype[Symbol.dispose] = Subscription.prototype.unsubscribe;\n}\n\nfunction execFinalizer(finalizer: Unsubscribable | (() => void)) {\n  if (isFunction(finalizer)) {\n    finalizer();\n  } else {\n    finalizer.unsubscribe();\n  }\n}\n\nexport interface SubscriberOverrides<T> {\n  /**\n   * If provided, this function will be called whenever the {@link Subscriber}'s\n   * `next` method is called, with the value that was passed to that call. If\n   * an error is thrown within this function, it will be handled and passed to\n   * the destination's `error` method.\n   * @param value The value that is being observed from the source.\n   */\n  next?: (value: T) => void;\n  /**\n   * If provided, this function will be called whenever the {@link Subscriber}'s\n   * `error` method is called, with the error that was passed to that call. If\n   * an error is thrown within this function, it will be handled and passed to\n   * the destination's `error` method.\n   * @param err An error that has been thrown by the source observable.\n   */\n  error?: (err: any) => void;\n  /**\n   * If provided, this function will be called whenever the {@link Subscriber}'s\n   * `complete` method is called. If an error is thrown within this function, it\n   * will be handled and passed to the destination's `error` method.\n   */\n  complete?: () => void;\n  /**\n   * If provided, this function will be called after all teardown has occurred\n   * for this {@link Subscriber}. This is generally used for cleanup purposes\n   * during operator development.\n   */\n  finalize?: () => void;\n}\n\n/**\n * Implements the {@link Observer} interface and extends the\n * {@link Subscription} class. While the {@link Observer} is the public API for\n * consuming the values of an {@link Observable}, all Observers get converted to\n * a Subscriber, in order to provide Subscription-like capabilities such as\n * `unsubscribe`. Subscriber is a common type in RxJS, and crucial for\n * implementing operators, but it is rarely used as a public API.\n */\nexport class Subscriber<T> extends Subscription implements Observer<T> {\n  /** @internal */\n  protected isStopped: boolean = false;\n  /** @internal */\n  protected destination: Observer<T>;\n\n  /** @internal */\n  protected readonly _nextOverride: ((value: T) => void) | null = null;\n  /** @internal */\n  protected readonly _errorOverride: ((err: any) => void) | null = null;\n  /** @internal */\n  protected readonly _completeOverride: (() => void) | null = null;\n  /** @internal */\n  protected readonly _onFinalize: (() => void) | null = null;\n\n  /**\n   * @deprecated Do not create instances of `Subscriber` directly. Use {@link operate} instead.\n   */\n  constructor(destination?: Subscriber<T> | Partial<Observer<T>> | ((value: T) => void) | null);\n\n  /**\n   * @internal\n   */\n  constructor(destination: Subscriber<any> | Partial<Observer<any>> | ((value: any) => void) | null, overrides: SubscriberOverrides<T>);\n\n  /**\n   * Creates an instance of an RxJS Subscriber. This is the workhorse of the library.\n   *\n   * If another instance of Subscriber is passed in, it will automatically wire up unsubscription\n   * between this instance and the passed in instance.\n   *\n   * If a partial or full observer is passed in, it will be wrapped and appropriate safeguards will be applied.\n   *\n   * If a next-handler function is passed in, it will be wrapped and appropriate safeguards will be applied.\n   *\n   * @param destination A subscriber, partial observer, or function that receives the next value.\n   * @deprecated Do not create instances of `Subscriber` directly. Use {@link operate} instead.\n   */\n  constructor(destination?: Subscriber<T> | Partial<Observer<T>> | ((value: T) => void) | null, overrides?: SubscriberOverrides<T>) {\n    super();\n\n    // The only way we know that error reporting safety has been applied is if we own it.\n    this.destination = destination instanceof Subscriber ? destination : createSafeObserver(destination);\n\n    this._nextOverride = overrides?.next ?? null;\n    this._errorOverride = overrides?.error ?? null;\n    this._completeOverride = overrides?.complete ?? null;\n    this._onFinalize = overrides?.finalize ?? null;\n\n    // It's important - for performance reasons - that all of this class's\n    // members are initialized and that they are always initialized in the same\n    // order. This will ensure that all Subscriber instances have the\n    // same hidden class in V8. This, in turn, will help keep the number of\n    // hidden classes involved in property accesses within the base class as\n    // low as possible. If the number of hidden classes involved exceeds four,\n    // the property accesses will become megamorphic and performance penalties\n    // will be incurred - i.e. inline caches won't be used.\n    //\n    // The reasons for ensuring all instances have the same hidden class are\n    // further discussed in this blog post from Benedikt Meurer:\n    // https://benediktmeurer.de/2018/03/23/impact-of-polymorphism-on-component-based-frameworks-like-react/\n    this._next = this._nextOverride ? overrideNext : this._next;\n    this._error = this._errorOverride ? overrideError : this._error;\n    this._complete = this._completeOverride ? overrideComplete : this._complete;\n\n    // Automatically chain subscriptions together here.\n    // if destination appears to be one of our subscriptions, we'll chain it.\n    if (hasAddAndUnsubscribe(destination)) {\n      destination.add(this);\n    }\n  }\n\n  /**\n   * The {@link Observer} callback to receive notifications of type `next` from\n   * the Observable, with a value. The Observable may call this method 0 or more\n   * times.\n   * @param value The `next` value.\n   */\n  next(value: T): void {\n    if (this.isStopped) {\n      handleStoppedNotification(nextNotification(value), this);\n    } else {\n      this._next(value!);\n    }\n  }\n\n  /**\n   * The {@link Observer} callback to receive notifications of type `error` from\n   * the Observable, with an attached `Error`. Notifies the Observer that\n   * the Observable has experienced an error condition.\n   * @param err The `error` exception.\n   */\n  error(err?: any): void {\n    if (this.isStopped) {\n      handleStoppedNotification(errorNotification(err), this);\n    } else {\n      this.isStopped = true;\n      this._error(err);\n    }\n  }\n\n  /**\n   * The {@link Observer} callback to receive a valueless notification of type\n   * `complete` from the Observable. Notifies the Observer that the Observable\n   * has finished sending push-based notifications.\n   */\n  complete(): void {\n    if (this.isStopped) {\n      handleStoppedNotification(COMPLETE_NOTIFICATION, this);\n    } else {\n      this.isStopped = true;\n      this._complete();\n    }\n  }\n\n  unsubscribe(): void {\n    if (!this.closed) {\n      this.isStopped = true;\n      super.unsubscribe();\n      this._onFinalize?.();\n    }\n  }\n\n  protected _next(value: T): void {\n    this.destination.next(value);\n  }\n\n  protected _error(err: any): void {\n    try {\n      this.destination.error(err);\n    } finally {\n      this.unsubscribe();\n    }\n  }\n\n  protected _complete(): void {\n    try {\n      this.destination.complete();\n    } finally {\n      this.unsubscribe();\n    }\n  }\n}\n\n/**\n * The {@link GlobalConfig} object for RxJS. It is used to configure things\n * like how to react on unhandled errors.\n */\nexport const config: GlobalConfig = {\n  onUnhandledError: null,\n  onStoppedNotification: null,\n};\n\n/**\n * The global configuration object for RxJS, used to configure things\n * like how to react on unhandled errors. Accessible via {@link config}\n * object.\n */\nexport interface GlobalConfig {\n  /**\n   * A registration point for unhandled errors from RxJS. These are errors that\n   * cannot were not handled by consuming code in the usual subscription path. For\n   * example, if you have this configured, and you subscribe to an observable without\n   * providing an error handler, errors from that subscription will end up here. This\n   * will _always_ be called asynchronously on another job in the runtime. This is because\n   * we do not want errors thrown in this user-configured handler to interfere with the\n   * behavior of the library.\n   */\n  onUnhandledError: ((err: any) => void) | null;\n\n  /**\n   * A registration point for notifications that cannot be sent to subscribers because they\n   * have completed, errored or have been explicitly unsubscribed. By default, next, complete\n   * and error notifications sent to stopped subscribers are noops. However, sometimes callers\n   * might want a different behavior. For example, with sources that attempt to report errors\n   * to stopped subscribers, a caller can configure RxJS to throw an unhandled error instead.\n   * This will _always_ be called asynchronously on another job in the runtime. This is because\n   * we do not want errors thrown in this user-configured handler to interfere with the\n   * behavior of the library.\n   */\n  onStoppedNotification: ((notification: ObservableNotification<any>, subscriber: Subscriber<any>) => void) | null;\n}\n\nfunction overrideNext<T>(this: Subscriber<T>, value: T): void {\n  try {\n    this._nextOverride!(value);\n  } catch (error) {\n    this.destination.error(error);\n  }\n}\n\nfunction overrideError(this: Subscriber<unknown>, err: any): void {\n  try {\n    this._errorOverride!(err);\n  } catch (error) {\n    this.destination.error(error);\n  } finally {\n    this.unsubscribe();\n  }\n}\n\nfunction overrideComplete(this: Subscriber<unknown>): void {\n  try {\n    this._completeOverride!();\n  } catch (error) {\n    this.destination.error(error);\n  } finally {\n    this.unsubscribe();\n  }\n}\n\nclass ConsumerObserver<T> implements Observer<T> {\n  constructor(private partialObserver: Partial<Observer<T>>) {}\n\n  next(value: T): void {\n    const { partialObserver } = this;\n    if (partialObserver.next) {\n      try {\n        partialObserver.next(value);\n      } catch (error) {\n        reportUnhandledError(error);\n      }\n    }\n  }\n\n  error(err: any): void {\n    const { partialObserver } = this;\n    if (partialObserver.error) {\n      try {\n        partialObserver.error(err);\n      } catch (error) {\n        reportUnhandledError(error);\n      }\n    } else {\n      reportUnhandledError(err);\n    }\n  }\n\n  complete(): void {\n    const { partialObserver } = this;\n    if (partialObserver.complete) {\n      try {\n        partialObserver.complete();\n      } catch (error) {\n        reportUnhandledError(error);\n      }\n    }\n  }\n}\n\nfunction createSafeObserver<T>(observerOrNext?: Partial<Observer<T>> | ((value: T) => void) | null): Observer<T> {\n  return new ConsumerObserver(!observerOrNext || isFunction(observerOrNext) ? { next: observerOrNext ?? undefined } : observerOrNext);\n}\n\n/**\n * A handler for notifications that cannot be sent to a stopped subscriber.\n * @param notification The notification being sent.\n * @param subscriber The stopped subscriber.\n */\nfunction handleStoppedNotification(notification: ObservableNotification<any>, subscriber: Subscriber<any>) {\n  const { onStoppedNotification } = config;\n  onStoppedNotification && setTimeout(() => onStoppedNotification(notification, subscriber));\n}\n\nfunction hasAddAndUnsubscribe(value: any): value is Subscription {\n  return value && isFunction(value.unsubscribe) && isFunction(value.add);\n}\n\nexport interface OperateConfig<In, Out> extends SubscriberOverrides<In> {\n  /**\n   * The destination subscriber to forward notifications to. This is also the\n   * subscriber that will receive unhandled errors if your `next`, `error`, or `complete`\n   * overrides throw.\n   */\n  destination: Subscriber<Out>;\n}\n\n/**\n * Creates a new {@link Subscriber} instance that passes notifications on to the\n * supplied `destination`. The overrides provided in the `config` argument for\n * `next`, `error`, and `complete` will be called in such a way that any\n * errors are caught and forwarded to the destination's `error` handler. The returned\n * `Subscriber` will be \"chained\" to the `destination` such that when `unsubscribe` is\n * called on the `destination`, the returned `Subscriber` will also be unsubscribed.\n *\n * Advanced: This ensures that subscriptions are properly wired up prior to starting the\n * subscription logic. This prevents \"synchronous firehose\" scenarios where an\n * inner observable from a flattening operation cannot be stopped by a downstream\n * terminal operator like `take`.\n *\n * This is a utility designed to be used to create new operators for observables.\n *\n * For examples, please see our code base.\n *\n * @param config The configuration for creating a new subscriber for an operator.\n * @returns A new subscriber that is chained to the destination.\n */\nexport function operate<In, Out>({ destination, ...subscriberOverrides }: OperateConfig<In, Out>) {\n  return new Subscriber(destination, subscriberOverrides);\n}\n\n// Ensure that `Symbol.dispose` is defined in TypeScript\ndeclare global {\n  interface SymbolConstructor {\n    readonly dispose: unique symbol;\n  }\n}\n\n/**\n * A representation of any set of values over any amount of time. This is the most basic building block\n * of RxJS.\n */\nexport class Observable<T> implements Subscribable<T> {\n  /**\n   * @param subscribe The function that is called when the Observable is\n   * initially subscribed to. This function is given a Subscriber, to which new values\n   * can be `next`ed, or an `error` method can be called to raise an error, or\n   * `complete` can be called to notify of a successful completion.\n   */\n  constructor(subscribe?: (this: Observable<T>, subscriber: Subscriber<T>) => TeardownLogic) {\n    if (subscribe) {\n      this._subscribe = subscribe;\n    }\n  }\n\n  /**\n   * Invokes an execution of an Observable and registers Observer handlers for notifications it will emit.\n   *\n   * <span class=\"informal\">Use it when you have all these Observables, but still nothing is happening.</span>\n   *\n   * `subscribe` is not a regular operator, but a method that calls Observable's internal `subscribe` function. It\n   * might be for example a function that you passed to Observable's constructor, but most of the time it is\n   * a library implementation, which defines what will be emitted by an Observable, and when it be will emitted. This means\n   * that calling `subscribe` is actually the moment when Observable starts its work, not when it is created, as it is often\n   * the thought.\n   *\n   * Apart from starting the execution of an Observable, this method allows you to listen for values\n   * that an Observable emits, as well as for when it completes or errors. You can achieve this in two\n   * of the following ways.\n   *\n   * The first way is creating an object that implements {@link Observer} interface. It should have methods\n   * defined by that interface, but note that it should be just a regular JavaScript object, which you can create\n   * yourself in any way you want (ES6 class, classic function constructor, object literal etc.). In particular, do\n   * not attempt to use any RxJS implementation details to create Observers - you don't need them. Remember also\n   * that your object does not have to implement all methods. If you find yourself creating a method that doesn't\n   * do anything, you can simply omit it. Note however, if the `error` method is not provided and an error happens,\n   * it will be thrown asynchronously. Errors thrown asynchronously cannot be caught using `try`/`catch`. Instead,\n   * use the {@link onUnhandledError} configuration option or use a runtime handler (like `window.onerror` or\n   * `process.on('error)`) to be notified of unhandled errors. Because of this, it's recommended that you provide\n   * an `error` method to avoid missing thrown errors.\n   *\n   * The second way is to give up on Observer object altogether and simply provide callback functions in place of its methods.\n   * This means you can provide three functions as arguments to `subscribe`, where the first function is equivalent\n   * of a `next` method, the second of an `error` method and the third of a `complete` method. Just as in case of an Observer,\n   * if you do not need to listen for something, you can omit a function by passing `undefined` or `null`,\n   * since `subscribe` recognizes these functions by where they were placed in function call. When it comes\n   * to the `error` function, as with an Observer, if not provided, errors emitted by an Observable will be thrown asynchronously.\n   *\n   * You can, however, subscribe with no parameters at all. This may be the case where you're not interested in terminal events\n   * and you also handled emissions internally by using operators (e.g. using `tap`).\n   *\n   * Whichever style of calling `subscribe` you use, in both cases it returns a Subscription object.\n   * This object allows you to call `unsubscribe` on it, which in turn will stop the work that an Observable does and will clean\n   * up all resources that an Observable used. Note that cancelling a subscription will not call `complete` callback\n   * provided to `subscribe` function, which is reserved for a regular completion signal that comes from an Observable.\n   *\n   * Remember that callbacks provided to `subscribe` are not guaranteed to be called asynchronously.\n   * It is an Observable itself that decides when these functions will be called. For example {@link of}\n   * by default emits all its values synchronously. Always check documentation for how given Observable\n   * will behave when subscribed and if its default behavior can be modified with a `scheduler`.\n   *\n   * #### Examples\n   *\n   * Subscribe with an {@link guide/observer Observer}\n   *\n   * ```ts\n   * import { of } from 'rxjs';\n   *\n   * const sumObserver = {\n   *   sum: 0,\n   *   next(value) {\n   *     console.log('Adding: ' + value);\n   *     this.sum = this.sum + value;\n   *   },\n   *   error() {\n   *     // We actually could just remove this method,\n   *     // since we do not really care about errors right now.\n   *   },\n   *   complete() {\n   *     console.log('Sum equals: ' + this.sum);\n   *   }\n   * };\n   *\n   * of(1, 2, 3) // Synchronously emits 1, 2, 3 and then completes.\n   *   .subscribe(sumObserver);\n   *\n   * // Logs:\n   * // 'Adding: 1'\n   * // 'Adding: 2'\n   * // 'Adding: 3'\n   * // 'Sum equals: 6'\n   * ```\n   *\n   * Subscribe with functions ({@link deprecations/subscribe-arguments deprecated})\n   *\n   * ```ts\n   * import { of } from 'rxjs'\n   *\n   * let sum = 0;\n   *\n   * of(1, 2, 3).subscribe(\n   *   value => {\n   *     console.log('Adding: ' + value);\n   *     sum = sum + value;\n   *   },\n   *   undefined,\n   *   () => console.log('Sum equals: ' + sum)\n   * );\n   *\n   * // Logs:\n   * // 'Adding: 1'\n   * // 'Adding: 2'\n   * // 'Adding: 3'\n   * // 'Sum equals: 6'\n   * ```\n   *\n   * Cancel a subscription\n   *\n   * ```ts\n   * import { interval } from 'rxjs';\n   *\n   * const subscription = interval(1000).subscribe({\n   *   next(num) {\n   *     console.log(num)\n   *   },\n   *   complete() {\n   *     // Will not be called, even when cancelling subscription.\n   *     console.log('completed!');\n   *   }\n   * });\n   *\n   * setTimeout(() => {\n   *   subscription.unsubscribe();\n   *   console.log('unsubscribed!');\n   * }, 2500);\n   *\n   * // Logs:\n   * // 0 after 1s\n   * // 1 after 2s\n   * // 'unsubscribed!' after 2.5s\n   * ```\n   *\n   * @param observerOrNext Either an {@link Observer} with some or all callback methods,\n   * or the `next` handler that is called for each value emitted from the subscribed Observable.\n   * @return A subscription reference to the registered handlers.\n   */\n  subscribe(observerOrNext?: Partial<Observer<T>> | ((value: T) => void) | null): Subscription {\n    const subscriber = observerOrNext instanceof Subscriber ? observerOrNext : new Subscriber(observerOrNext);\n    subscriber.add(this._trySubscribe(subscriber));\n    return subscriber;\n  }\n\n  /** @internal */\n  protected _trySubscribe(sink: Subscriber<T>): TeardownLogic {\n    try {\n      return this._subscribe(sink);\n    } catch (err) {\n      // We don't need to return anything in this case,\n      // because it's just going to try to `add()` to a subscription\n      // above.\n      sink.error(err);\n    }\n  }\n\n  /**\n   * Used as a NON-CANCELLABLE means of subscribing to an observable, for use with\n   * APIs that expect promises, like `async/await`. You cannot unsubscribe from this.\n   *\n   * **WARNING**: Only use this with observables you *know* will complete. If the source\n   * observable does not complete, you will end up with a promise that is hung up, and\n   * potentially all of the state of an async function hanging out in memory. To avoid\n   * this situation, look into adding something like {@link timeout}, {@link take},\n   * {@link takeWhile}, or {@link takeUntil} amongst others.\n   *\n   * #### Example\n   *\n   * ```ts\n   * import { interval, take } from 'rxjs';\n   *\n   * const source$ = interval(1000).pipe(take(4));\n   *\n   * async function getTotal() {\n   *   let total = 0;\n   *\n   *   await source$.forEach(value => {\n   *     total += value;\n   *     console.log('observable -> ' + value);\n   *   });\n   *\n   *   return total;\n   * }\n   *\n   * getTotal().then(\n   *   total => console.log('Total: ' + total)\n   * );\n   *\n   * // Expected:\n   * // 'observable -> 0'\n   * // 'observable -> 1'\n   * // 'observable -> 2'\n   * // 'observable -> 3'\n   * // 'Total: 6'\n   * ```\n   *\n   * @param next A handler for each value emitted by the observable.\n   * @return A promise that either resolves on observable completion or\n   * rejects with the handled error.\n   */\n  forEach(next: (value: T) => void): Promise<void> {\n    return new Promise<void>((resolve, reject) => {\n      const subscriber = new Subscriber({\n        next: (value: T) => {\n          try {\n            next(value);\n          } catch (err) {\n            reject(err);\n            subscriber.unsubscribe();\n          }\n        },\n        error: reject,\n        complete: resolve,\n      });\n      this.subscribe(subscriber);\n    });\n  }\n\n  /** @internal */\n  protected _subscribe(_subscriber: Subscriber<any>): TeardownLogic {\n    return;\n  }\n\n  /**\n   * An interop point defined by the es7-observable spec https://github.com/zenparsing/es-observable\n   * @return This instance of the observable.\n   */\n  [Symbol.observable ?? '@@observable']() {\n    return this;\n  }\n\n  pipe(): Observable<T>;\n  pipe<A>(op1: UnaryFunction<Observable<T>, A>): A;\n  pipe<A, B>(op1: UnaryFunction<Observable<T>, A>, op2: UnaryFunction<A, B>): B;\n  pipe<A, B, C>(op1: UnaryFunction<Observable<T>, A>, op2: UnaryFunction<A, B>, op3: UnaryFunction<B, C>): C;\n  pipe<A, B, C, D>(op1: UnaryFunction<Observable<T>, A>, op2: UnaryFunction<A, B>, op3: UnaryFunction<B, C>, op4: UnaryFunction<C, D>): D;\n  pipe<A, B, C, D, E>(\n    op1: UnaryFunction<Observable<T>, A>,\n    op2: UnaryFunction<A, B>,\n    op3: UnaryFunction<B, C>,\n    op4: UnaryFunction<C, D>,\n    op5: UnaryFunction<D, E>\n  ): E;\n  pipe<A, B, C, D, E, F>(\n    op1: UnaryFunction<Observable<T>, A>,\n    op2: UnaryFunction<A, B>,\n    op3: UnaryFunction<B, C>,\n    op4: UnaryFunction<C, D>,\n    op5: UnaryFunction<D, E>,\n    op6: UnaryFunction<E, F>\n  ): F;\n  pipe<A, B, C, D, E, F, G>(\n    op1: UnaryFunction<Observable<T>, A>,\n    op2: UnaryFunction<A, B>,\n    op3: UnaryFunction<B, C>,\n    op4: UnaryFunction<C, D>,\n    op5: UnaryFunction<D, E>,\n    op6: UnaryFunction<E, F>,\n    op7: UnaryFunction<F, G>\n  ): G;\n  pipe<A, B, C, D, E, F, G, H>(\n    op1: UnaryFunction<Observable<T>, A>,\n    op2: UnaryFunction<A, B>,\n    op3: UnaryFunction<B, C>,\n    op4: UnaryFunction<C, D>,\n    op5: UnaryFunction<D, E>,\n    op6: UnaryFunction<E, F>,\n    op7: UnaryFunction<F, G>,\n    op8: UnaryFunction<G, H>\n  ): H;\n  pipe<A, B, C, D, E, F, G, H, I>(\n    op1: UnaryFunction<Observable<T>, A>,\n    op2: UnaryFunction<A, B>,\n    op3: UnaryFunction<B, C>,\n    op4: UnaryFunction<C, D>,\n    op5: UnaryFunction<D, E>,\n    op6: UnaryFunction<E, F>,\n    op7: UnaryFunction<F, G>,\n    op8: UnaryFunction<G, H>,\n    op9: UnaryFunction<H, I>\n  ): I;\n  pipe<A, B, C, D, E, F, G, H, I>(\n    op1: UnaryFunction<Observable<T>, A>,\n    op2: UnaryFunction<A, B>,\n    op3: UnaryFunction<B, C>,\n    op4: UnaryFunction<C, D>,\n    op5: UnaryFunction<D, E>,\n    op6: UnaryFunction<E, F>,\n    op7: UnaryFunction<F, G>,\n    op8: UnaryFunction<G, H>,\n    op9: UnaryFunction<H, I>,\n    ...operations: OperatorFunction<any, any>[]\n  ): Observable<unknown>;\n  pipe<A, B, C, D, E, F, G, H, I>(\n    op1: UnaryFunction<Observable<T>, A>,\n    op2: UnaryFunction<A, B>,\n    op3: UnaryFunction<B, C>,\n    op4: UnaryFunction<C, D>,\n    op5: UnaryFunction<D, E>,\n    op6: UnaryFunction<E, F>,\n    op7: UnaryFunction<F, G>,\n    op8: UnaryFunction<G, H>,\n    op9: UnaryFunction<H, I>,\n    ...operations: UnaryFunction<any, any>[]\n  ): unknown;\n\n  /**\n   * Used to stitch together functional operators into a chain.\n   *\n   * ## Example\n   *\n   * ```ts\n   * import { interval, filter, map, scan } from 'rxjs';\n   *\n   * interval(1000)\n   *   .pipe(\n   *     filter(x => x % 2 === 0),\n   *     map(x => x + x),\n   *     scan((acc, x) => acc + x)\n   *   )\n   *   .subscribe(x => console.log(x));\n   * ```\n   *\n   * @return The Observable result of all the operators having been called\n   * in the order they were passed in.\n   */\n  pipe(...operations: UnaryFunction<any, any>[]): unknown {\n    return operations.reduce(pipeReducer, this as any);\n  }\n\n  /**\n   * Observable is async iterable, so it can be used in `for await` loop. This method\n   * of subscription is cancellable by breaking the for await loop. Although it's not\n   * recommended to use Observable's AsyncIterable contract outside of `for await`, if\n   * you're consuming the Observable as an AsyncIterable, and you're _not_ using `for await`,\n   * you can use the `throw` or `return` methods on the `AsyncGenerator` we return to\n   * cancel the subscription. Note that the subscription to the observable does not start\n   * until the first value is requested from the AsyncIterable.\n   *\n   * Functionally, this is equivalent to using a {@link concatMap} with an `async` function.\n   * That means that while the body of the `for await` loop is executing, any values that arrive\n   * from the observable source will be queued up, so they can be processed by the `for await`\n   * loop in order. So, like {@link concatMap} it's important to understand the speed your\n   * source emits at, and the speed of the body of your `for await` loop.\n   *\n   * ## Example\n   *\n   * ```ts\n   * import { interval } from 'rxjs';\n   *\n   * async function main() {\n   *  // Subscribe to the observable using for await.\n   *  for await (const value of interval(1000)) {\n   *    console.log(value);\n   *\n   *    if (value > 5) {\n   *      // Unsubscribe from the interval if we get a value greater than 5\n   *      break;\n   *    }\n   *  }\n   * }\n   *\n   * main();\n   * ```\n   */\n  [Symbol.asyncIterator](): AsyncGenerator<T, void, void> {\n    let subscription: Subscription | undefined;\n    let hasError = false;\n    let error: unknown;\n    let completed = false;\n    const values: T[] = [];\n    const deferreds: [(value: IteratorResult<T>) => void, (reason: unknown) => void][] = [];\n\n    const handleError = (err: unknown) => {\n      hasError = true;\n      error = err;\n      while (deferreds.length) {\n        const [_, reject] = deferreds.shift()!;\n        reject(err);\n      }\n    };\n\n    const handleComplete = () => {\n      completed = true;\n      while (deferreds.length) {\n        const [resolve] = deferreds.shift()!;\n        resolve({ value: undefined, done: true });\n      }\n    };\n\n    return {\n      next: (): Promise<IteratorResult<T>> => {\n        if (!subscription) {\n          // We only want to start the subscription when the user starts iterating.\n          subscription = this.subscribe({\n            next: (value) => {\n              if (deferreds.length) {\n                const [resolve] = deferreds.shift()!;\n                resolve({ value, done: false });\n              } else {\n                values.push(value);\n              }\n            },\n            error: handleError,\n            complete: handleComplete,\n          });\n        }\n\n        // If we already have some values in our buffer, we'll return the next one.\n        if (values.length) {\n          return Promise.resolve({ value: values.shift()!, done: false });\n        }\n\n        // This was already completed, so we're just going to return a done result.\n        if (completed) {\n          return Promise.resolve({ value: undefined, done: true });\n        }\n\n        // There was an error, so we're going to return an error result.\n        if (hasError) {\n          return Promise.reject(error);\n        }\n\n        // Otherwise, we need to make them wait for a value.\n        return new Promise((resolve, reject) => {\n          deferreds.push([resolve, reject]);\n        });\n      },\n      throw: (err): Promise<IteratorResult<T>> => {\n        subscription?.unsubscribe();\n        // NOTE: I did some research on this, and as of Feb 2023, Chrome doesn't seem to do\n        // anything with pending promises returned from `next()` when `throw()` is called.\n        // However, for consumption of observables, I don't want RxJS taking the heat for that\n        // quirk/leak of the type. So we're going to reject all pending promises we've nexted out here.\n        handleError(err);\n        return Promise.reject(err);\n      },\n      return: (): Promise<IteratorResult<T>> => {\n        subscription?.unsubscribe();\n        // NOTE: I did some research on this, and as of Feb 2023, Chrome doesn't seem to do\n        // anything with pending promises returned from `next()` when `throw()` is called.\n        // However, for consumption of observables, I don't want RxJS taking the heat for that\n        // quirk/leak of the type. So we're going to resolve all pending promises we've nexted out here.\n        handleComplete();\n        return Promise.resolve({ value: undefined, done: true });\n      },\n      [Symbol.asyncIterator]() {\n        return this;\n      },\n    };\n  }\n}\n\nfunction pipeReducer(prev: any, fn: UnaryFunction<any, any>) {\n  return fn(prev);\n}\n\n/**\n * Handles an error on another job either with the user-configured {@link onUnhandledError},\n * or by throwing it on that new job so it can be picked up by `window.onerror`, `process.on('error')`, etc.\n *\n * This should be called whenever there is an error that is out-of-band with the subscription\n * or when an error hits a terminal boundary of the subscription and no error handler was provided.\n *\n * @param err the error to report\n */\nexport function reportUnhandledError(err: any) {\n  setTimeout(() => {\n    const { onUnhandledError } = config;\n    if (onUnhandledError) {\n      // Execute the user-configured error handler.\n      onUnhandledError(err);\n    } else {\n      // Throw so it is picked up by the runtime's uncaught error mechanism.\n      throw err;\n    }\n  });\n}\n\n/**\n * Creates an Observable from an Array, an array-like object, a Promise, an iterable object, or an Observable-like object.\n *\n * <span class=\"informal\">Converts almost anything to an Observable.</span>\n *\n * ![](from.png)\n *\n * `from` converts various other objects and data types into Observables. It also converts a Promise, an array-like, or an\n * <a href=\"https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Iteration_protocols#iterable\" target=\"_blank\">iterable</a>\n * object into an Observable that emits the items in that promise, array, or iterable. A String, in this context, is treated\n * as an array of characters. Observable-like objects (contains a function named with the ES2015 Symbol for Observable) can also be\n * converted through this operator.\n *\n * ## Examples\n *\n * Converts an array to an Observable\n *\n * ```ts\n * import { from } from 'rxjs';\n *\n * const array = [10, 20, 30];\n * const result = from(array);\n *\n * result.subscribe(x => console.log(x));\n *\n * // Logs:\n * // 10\n * // 20\n * // 30\n * ```\n *\n * Convert an infinite iterable (from a generator) to an Observable\n *\n * ```ts\n * import { from, take } from 'rxjs';\n *\n * function* generateDoubles(seed) {\n *    let i = seed;\n *    while (true) {\n *      yield i;\n *      i = 2 * i; // double it\n *    }\n * }\n *\n * const iterator = generateDoubles(3);\n * const result = from(iterator).pipe(take(10));\n *\n * result.subscribe(x => console.log(x));\n *\n * // Logs:\n * // 3\n * // 6\n * // 12\n * // 24\n * // 48\n * // 96\n * // 192\n * // 384\n * // 768\n * // 1536\n * ```\n *\n * @see {@link fromEvent}\n * @see {@link fromEventPattern}\n * @see {@link scheduled}\n *\n * @param input A subscription object, a Promise, an Observable-like,\n * an Array, an iterable, async iterable, or an array-like object to be converted.\n */\n\nexport function from<O extends ObservableInput<any>>(input: O): Observable<ObservedValueOf<O>>;\nexport function from<T>(input: ObservableInput<T>): Observable<T> {\n  const type = getObservableInputType(input);\n  switch (type) {\n    case ObservableInputType.Own:\n      return input as Observable<T>;\n    case ObservableInputType.InteropObservable:\n      return fromInteropObservable(input);\n    case ObservableInputType.ArrayLike:\n      return fromArrayLike(input as ArrayLike<T>);\n    case ObservableInputType.Promise:\n      return fromPromise(input as PromiseLike<T>);\n    case ObservableInputType.AsyncIterable:\n      return fromAsyncIterable(input as AsyncIterable<T>);\n    case ObservableInputType.Iterable:\n      return fromIterable(input as Iterable<T>);\n    case ObservableInputType.ReadableStreamLike:\n      return fromReadableStreamLike(input as ReadableStreamLike<T>);\n  }\n}\n\n/**\n * Creates an RxJS Observable from an object that implements `Symbol.observable`.\n * @param obj An object that properly implements `Symbol.observable`.\n */\nfunction fromInteropObservable<T>(obj: any) {\n  return new Observable((subscriber: Subscriber<T>) => {\n    const obs = obj[Symbol.observable ?? '@@observable']();\n    if (isFunction(obs.subscribe)) {\n      return obs.subscribe(subscriber);\n    }\n    // Should be caught by observable subscribe function error handling.\n    throw new TypeError('Provided object does not correctly implement Symbol.observable');\n  });\n}\n\n/**\n * Synchronously emits the values of an array like and completes.\n * This is exported because there are creation functions and operators that need to\n * make direct use of the same logic, and there's no reason to make them run through\n * `from` conditionals because we *know* they're dealing with an array.\n * @param array The array to emit values from\n */\nexport function fromArrayLike<T>(array: ArrayLike<T>) {\n  return new Observable((subscriber: Subscriber<T>) => {\n    subscribeToArray(array, subscriber);\n  });\n}\n\nexport function fromPromise<T>(promise: PromiseLike<T>) {\n  return new Observable((subscriber: Subscriber<T>) => {\n    promise\n      .then(\n        (value) => {\n          if (!subscriber.closed) {\n            subscriber.next(value);\n            subscriber.complete();\n          }\n        },\n        (err: any) => subscriber.error(err)\n      )\n      .then(null, reportUnhandledError);\n  });\n}\n\nfunction fromIterable<T>(iterable: Iterable<T>) {\n  return new Observable((subscriber: Subscriber<T>) => {\n    for (const value of iterable) {\n      subscriber.next(value);\n      if (subscriber.closed) {\n        return;\n      }\n    }\n    subscriber.complete();\n  });\n}\n\nfunction fromAsyncIterable<T>(asyncIterable: AsyncIterable<T>) {\n  return new Observable((subscriber: Subscriber<T>) => {\n    process(asyncIterable, subscriber).catch((err) => subscriber.error(err));\n  });\n}\n\nfunction fromReadableStreamLike<T>(readableStream: ReadableStreamLike<T>) {\n  return fromAsyncIterable(readableStreamLikeToAsyncGenerator(readableStream));\n}\n\nasync function process<T>(asyncIterable: AsyncIterable<T>, subscriber: Subscriber<T>) {\n  for await (const value of asyncIterable) {\n    subscriber.next(value);\n    // A side-effect may have closed our subscriber,\n    // check before the next iteration.\n    if (subscriber.closed) {\n      return;\n    }\n  }\n  subscriber.complete();\n}\n\n/**\n * Subscribes to an ArrayLike with a subscriber\n * @param array The array or array-like to subscribe to\n * @param subscriber\n */\nexport function subscribeToArray<T>(array: ArrayLike<T>, subscriber: Subscriber<T>) {\n  // Loop over the array and emit each value. Note two things here:\n  // 1. We're making sure that the subscriber is not closed on each loop.\n  //    This is so we don't continue looping over a very large array after\n  //    something like a `take`, `takeWhile`, or other synchronous unsubscription\n  //    has already unsubscribed.\n  // 2. In this form, reentrant code can alter that array we're looping over.\n  //    This is a known issue, but considered an edge case. The alternative would\n  //    be to copy the array before executing the loop, but this has\n  //    performance implications.\n  const length = array.length;\n  for (let i = 0; i < length; i++) {\n    if (subscriber.closed) {\n      return;\n    }\n    // TODO(JamesHenry): discuss this added ! with Ben\n    subscriber.next(array[i]!);\n  }\n  subscriber.complete();\n}\n\nexport enum ObservableInputType {\n  Own,\n  InteropObservable,\n  ArrayLike,\n  Promise,\n  AsyncIterable,\n  Iterable,\n  ReadableStreamLike,\n}\n\nexport function getObservableInputType(input: unknown): ObservableInputType {\n  if (input instanceof Observable) {\n    return ObservableInputType.Own;\n  }\n  if (isInteropObservable(input)) {\n    return ObservableInputType.InteropObservable;\n  }\n  if (isArrayLike(input)) {\n    return ObservableInputType.ArrayLike;\n  }\n  if (isPromise(input)) {\n    return ObservableInputType.Promise;\n  }\n  if (isAsyncIterable(input)) {\n    return ObservableInputType.AsyncIterable;\n  }\n  if (isIterable(input)) {\n    return ObservableInputType.Iterable;\n  }\n  if (isReadableStreamLike(input)) {\n    return ObservableInputType.ReadableStreamLike;\n  }\n  throw new TypeError(\n    `You provided ${\n      input !== null && typeof input === 'object' ? 'an invalid object' : `'${input}'`\n    } where a stream was expected. You can provide an Observable, Promise, ReadableStream, Array, AsyncIterable, or Iterable.`\n  );\n}\n\n/**\n * Returns true if the object is a function.\n * @param value The value to check\n */\nexport function isFunction(value: any): value is (...args: any[]) => any {\n  return typeof value === 'function';\n}\n\nfunction isAsyncIterable<T>(obj: any): obj is AsyncIterable<T> {\n  return Symbol.asyncIterator && isFunction(obj?.[Symbol.asyncIterator]);\n}\n\nexport async function* readableStreamLikeToAsyncGenerator<T>(readableStream: ReadableStreamLike<T>): AsyncGenerator<T> {\n  const reader = readableStream.getReader();\n  try {\n    while (true) {\n      const { value, done } = await reader.read();\n      if (done) {\n        return;\n      }\n      yield value!;\n    }\n  } finally {\n    reader.releaseLock();\n  }\n}\n\nfunction isReadableStreamLike<T>(obj: any): obj is ReadableStreamLike<T> {\n  // We don't want to use instanceof checks because they would return\n  // false for instances from another Realm, like an <iframe>.\n  return isFunction(obj?.getReader);\n}\n\n/**\n * Tests to see if the object is \"thennable\".\n * @param value the object to test\n */\nexport function isPromise(value: any): value is PromiseLike<any> {\n  return isFunction(value?.then);\n}\n\n/** Identifies an input as being Observable (but not necessary an Rx Observable) */\nfunction isInteropObservable(input: any): input is InteropObservable<any> {\n  return isFunction(input[Symbol.observable ?? '@@observable']);\n}\n\n/** Identifies an input as being an Iterable */\nfunction isIterable(input: any): input is Iterable<any> {\n  return isFunction(input?.[Symbol.iterator]);\n}\n\nexport function isArrayLike<T>(x: any): x is ArrayLike<T> {\n  return x && typeof x.length === 'number' && !isFunction(x);\n}\n\n/**\n * Tests to see if the object is an RxJS {@link Observable}\n * @param obj the object to test\n */\nexport function isObservable(obj: any): obj is Observable<unknown> {\n  // The !! is to ensure that this publicly exposed function returns\n  // `false` if something like `null` or `0` is passed.\n  return !!obj && (obj instanceof Observable || (isFunction(obj.lift) && isFunction(obj.subscribe)));\n}\n\n/**\n * A completion object optimized for memory use and created to be the\n * same \"shape\" as other notifications in v8.\n * @internal\n */\nexport const COMPLETE_NOTIFICATION = (() => createNotification('C', undefined, undefined) as CompleteNotification)();\n\n/**\n * Internal use only. Creates an optimized error notification that is the same \"shape\"\n * as other notifications.\n * @internal\n */\nexport function errorNotification(error: any): ErrorNotification {\n  return createNotification('E', undefined, error) as any;\n}\n\n/**\n * Internal use only. Creates an optimized next notification that is the same \"shape\"\n * as other notifications.\n * @internal\n */\nexport function nextNotification<T>(value: T) {\n  return createNotification('N', value, undefined) as NextNotification<T>;\n}\n\nexport function createNotification<T>(kind: 'N', value: T, error: undefined): { kind: 'N'; value: T; error: undefined };\nexport function createNotification<T>(kind: 'E', value: undefined, error: any): { kind: 'E'; value: undefined; error: any };\nexport function createNotification<T>(kind: 'C', value: undefined, error: undefined): { kind: 'C'; value: undefined; error: undefined };\nexport function createNotification<T>(\n  kind: 'N' | 'E' | 'C',\n  value: T | undefined,\n  error: any\n): { kind: 'N' | 'E' | 'C'; value: T | undefined; error: any };\n\n/**\n * Ensures that all notifications created internally have the same \"shape\" in v8.\n *\n * TODO: This is only exported to support a crazy legacy test in `groupBy`.\n * @internal\n */\nexport function createNotification<T>(kind: 'N' | 'E' | 'C', value: T | undefined, error: any) {\n  return {\n    kind,\n    value,\n    error,\n  };\n}\n"
  },
  {
    "path": "packages/observable/src/types.ts",
    "content": "// https://github.com/microsoft/TypeScript/issues/40462#issuecomment-689879308\n/// <reference lib=\"esnext.asynciterable\" />\n\nimport type { Observable, Subscription } from './observable.js';\n\n/**\n * Note: This will add Symbol.observable globally for all TypeScript users,\n * however, we are no longer polyfilling Symbol.observable\n */\ndeclare global {\n  interface SymbolConstructor {\n    readonly observable: symbol;\n  }\n}\n\n/* OPERATOR INTERFACES */\n\n/**\n * A function type interface that describes a function that accepts one parameter `T`\n * and returns another parameter `R`.\n *\n * Usually used to describe {@link OperatorFunction} - it always takes a single\n * parameter (the source Observable) and returns another Observable.\n */\nexport interface UnaryFunction<T, R> {\n  (source: T): R;\n}\n\nexport interface OperatorFunction<T, R> extends UnaryFunction<Observable<T>, Observable<R>> {}\n\nexport type FactoryOrValue<T> = T | (() => T);\n\n/**\n * A function type interface that describes a function that accepts and returns a parameter of the same type.\n *\n * Used to describe {@link OperatorFunction} with the only one type: `OperatorFunction<T, T>`.\n *\n */\nexport interface MonoTypeOperatorFunction<T> extends OperatorFunction<T, T> {}\n\n/**\n * A value and the time at which it was emitted.\n *\n * Emitted by the `timestamp` operator\n *\n * @see {@link timestamp}\n */\nexport interface Timestamp<T> {\n  value: T;\n  /**\n   * The timestamp. By default, this is in epoch milliseconds.\n   * Could vary based on the timestamp provider passed to the operator.\n   */\n  timestamp: number;\n}\n\n/**\n * A value emitted and the amount of time since the last value was emitted.\n *\n * Emitted by the `timeInterval` operator.\n *\n * @see {@link timeInterval}\n */\nexport interface TimeInterval<T> {\n  value: T;\n\n  /**\n   * The amount of time between this value's emission and the previous value's emission.\n   * If this is the first emitted value, then it will be the amount of time since subscription\n   * started.\n   */\n  interval: number;\n}\n\n/* SUBSCRIPTION INTERFACES */\n\nexport interface Unsubscribable {\n  unsubscribe(): void;\n}\n\nexport type TeardownLogic = Subscription | Unsubscribable | (() => void) | void;\n\nexport interface SubscriptionLike extends Unsubscribable {\n  unsubscribe(): void;\n  readonly closed: boolean;\n}\n\n/* OBSERVABLE INTERFACES */\n\nexport interface Subscribable<T> {\n  subscribe(observer: Partial<Observer<T>>): Unsubscribable;\n}\n\n/**\n * Valid types that can be converted to observables.\n */\nexport type ObservableInput<T> =\n  | Observable<T>\n  | InteropObservable<T>\n  | AsyncIterable<T>\n  | PromiseLike<T>\n  | ArrayLike<T>\n  | Iterable<T>\n  | ReadableStreamLike<T>;\n\n/**\n * An object that implements the `Symbol.observable` interface.\n */\nexport interface InteropObservable<T> {\n  [Symbol.observable]: () => Subscribable<T>;\n}\n\n/* NOTIFICATIONS */\n\n/**\n * A notification representing a \"next\" from an observable.\n * Can be used with {@link dematerialize}.\n */\nexport interface NextNotification<T> {\n  /** The kind of notification. Always \"N\" */\n  kind: 'N';\n  /** The value of the notification. */\n  value: T;\n}\n\n/**\n * A notification representing an \"error\" from an observable.\n * Can be used with {@link dematerialize}.\n */\nexport interface ErrorNotification {\n  /** The kind of notification. Always \"E\" */\n  kind: 'E';\n  error: any;\n}\n\n/**\n * A notification representing a \"completion\" from an observable.\n * Can be used with {@link dematerialize}.\n */\nexport interface CompleteNotification {\n  kind: 'C';\n}\n\n/**\n * Valid observable notification types.\n */\nexport type ObservableNotification<T> = NextNotification<T> | ErrorNotification | CompleteNotification;\n\n/* OBSERVER INTERFACES */\n\nexport interface NextObserver<T> {\n  closed?: boolean;\n  next: (value: T) => void;\n  error?: (err: any) => void;\n  complete?: () => void;\n}\n\nexport interface ErrorObserver<T> {\n  closed?: boolean;\n  next?: (value: T) => void;\n  error: (err: any) => void;\n  complete?: () => void;\n}\n\nexport interface CompletionObserver<T> {\n  closed?: boolean;\n  next?: (value: T) => void;\n  error?: (err: any) => void;\n  complete: () => void;\n}\n\nexport type PartialObserver<T> = NextObserver<T> | ErrorObserver<T> | CompletionObserver<T>;\n\n/**\n * An object interface that defines a set of callback functions a user can use to get\n * notified of any set of {@link Observable}\n * {@link guide/glossary-and-semantics#notification notification} events.\n *\n * For more info, please refer to {@link guide/observer this guide}.\n */\nexport interface Observer<T> {\n  /**\n   * A callback function that gets called by the producer during the subscription when\n   * the producer \"has\" the `value`. It won't be called if `error` or `complete` callback\n   * functions have been called, nor after the consumer has unsubscribed.\n   *\n   * For more info, please refer to {@link guide/glossary-and-semantics#next this guide}.\n   */\n  next: (value: T) => void;\n  /**\n   * A callback function that gets called by the producer if and when it encountered a\n   * problem of any kind. The errored value will be provided through the `err` parameter.\n   * This callback can't be called more than one time, it can't be called if the\n   * `complete` callback function have been called previously, nor it can't be called if\n   * the consumer has unsubscribed.\n   *\n   * For more info, please refer to {@link guide/glossary-and-semantics#error this guide}.\n   */\n  error: (err: any) => void;\n  /**\n   * A callback function that gets called by the producer if and when it has no more\n   * values to provide (by calling `next` callback function). This means that no error\n   * has happened. This callback can't be called more than one time, it can't be called\n   * if the `error` callback function have been called previously, nor it can't be called\n   * if the consumer has unsubscribed.\n   *\n   * For more info, please refer to {@link guide/glossary-and-semantics#complete this guide}.\n   */\n  complete: () => void;\n}\n\nexport interface SubjectLike<T> extends Observer<T>, Subscribable<T> {}\n\n/* SCHEDULER INTERFACES */\n\nexport interface SchedulerLike extends TimestampProvider {\n  schedule<T>(work: (this: SchedulerAction<T>, state: T) => void, delay: number, state: T): Subscription;\n  schedule<T>(work: (this: SchedulerAction<T>, state?: T) => void, delay: number, state?: T): Subscription;\n  schedule<T>(work: (this: SchedulerAction<T>, state?: T) => void, delay?: number, state?: T): Subscription;\n}\n\nexport interface SchedulerAction<T> extends Subscription {\n  schedule(state?: T, delay?: number): Subscription;\n}\n\n/**\n * This is a type that provides a method to allow RxJS to create a numeric timestamp\n */\nexport interface TimestampProvider {\n  /**\n   * Returns a timestamp as a number.\n   *\n   * This is used by types like `ReplaySubject` or operators like `timestamp` to calculate\n   * the amount of time passed between events.\n   */\n  now(): number;\n}\n\n/**\n * Extracts the type from an `ObservableInput<any>`. If you have\n * `O extends ObservableInput<any>` and you pass in `Observable<number>`, or\n * `Promise<number>`, etc, it will type as `number`.\n */\nexport type ObservedValueOf<O> = O extends ObservableInput<infer T> ? T : never;\n\n/**\n * Extracts a union of element types from an `ObservableInput<any>[]`.\n * If you have `O extends ObservableInput<any>[]` and you pass in\n * `Observable<string>[]` or `Promise<string>[]` you would get\n * back a type of `string`.\n * If you pass in `[Observable<string>, Observable<number>]` you would\n * get back a type of `string | number`.\n */\nexport type ObservedValueUnionFromArray<X> = X extends Array<ObservableInput<infer T>> ? T : never;\n\n/**\n * Extracts a tuple of element types from an `ObservableInput<any>[]`.\n * If you have `O extends ObservableInput<any>[]` and you pass in\n * `[Observable<string>, Observable<number>]` you would get back a type\n * of `[string, number]`.\n */\nexport type ObservedValueTupleFromArray<X> = { [K in keyof X]: ObservedValueOf<X[K]> };\n\n/**\n * Used to infer types from arguments to functions like {@link forkJoin}.\n * So that you can have `forkJoin([Observable<A>, PromiseLike<B>]): Observable<[A, B]>`\n * et al.\n */\nexport type ObservableInputTuple<T> = {\n  [K in keyof T]: ObservableInput<T[K]>;\n};\n\n/**\n * Constructs a new tuple with the specified type at the head.\n * If you declare `Cons<A, [B, C]>` you will get back `[A, B, C]`.\n */\nexport type Cons<X, Y extends readonly any[]> = ((arg: X, ...rest: Y) => any) extends (...args: infer U) => any ? U : never;\n\n/**\n * Extracts the head of a tuple.\n * If you declare `Head<[A, B, C]>` you will get back `A`.\n */\nexport type Head<X extends readonly any[]> = ((...args: X) => any) extends (arg: infer U, ...rest: any[]) => any ? U : never;\n\n/**\n * Extracts the tail of a tuple.\n * If you declare `Tail<[A, B, C]>` you will get back `[B, C]`.\n */\nexport type Tail<X extends readonly any[]> = ((...args: X) => any) extends (arg: any, ...rest: infer U) => any ? U : never;\n\n/**\n * Extracts the generic value from an Array type.\n * If you have `T extends Array<any>`, and pass a `string[]` to it,\n * `ValueFromArray<T>` will return the actual type of `string`.\n */\nexport type ValueFromArray<A extends readonly unknown[]> = A extends Array<infer T> ? T : never;\n\n/**\n * Gets the value type from an {@link ObservableNotification}, if possible.\n */\nexport type ValueFromNotification<T> = T extends { kind: 'N' | 'E' | 'C' }\n  ? T extends NextNotification<any>\n    ? T extends { value: infer V }\n      ? V\n      : undefined\n    : never\n  : never;\n\n/**\n * A simple type to represent a gamut of \"falsy\" values... with a notable exception:\n * `NaN` is \"falsy\" however, it is not and cannot be typed via TypeScript. See\n * comments here: https://github.com/microsoft/TypeScript/issues/28682#issuecomment-707142417\n */\nexport type Falsy = null | undefined | false | 0 | -0 | 0n | '';\n\nexport type TruthyTypesOf<T> = T extends Falsy ? never : T;\n\n/**\n * The base signature RxJS will look for to identify and use\n * a [ReadableStream](https://streams.spec.whatwg.org/#rs-class)\n * as an {@link ObservableInput} source.\n */\nexport type ReadableStreamLike<T> = Pick<ReadableStream<T>, 'getReader'>;\n\n/**\n * An observable with a `connect` method that is used to create a subscription\n * to an underlying source, connecting it with all consumers via a multicast.\n */\nexport interface Connectable<T> extends Observable<T> {\n  /**\n   * (Idempotent) Calling this method will connect the underlying source observable to all subscribed consumers\n   * through an underlying {@link Subject}.\n   * @returns A subscription, that when unsubscribed, will \"disconnect\" the source from the connector subject,\n   * severing notifications to all consumers.\n   */\n  connect(): Subscription;\n}\n"
  },
  {
    "path": "packages/observable/tsconfig.json",
    "content": "{\n  \"compilerOptions\": {\n    \"declaration\": true,\n    \"declarationMap\": true,\n    \"esModuleInterop\": true,\n    \"forceConsistentCasingInFileNames\": true,\n    \"inlineSources\": true,\n    \"jsx\": \"react\",\n    \"module\": \"nodenext\",\n    \"moduleResolution\": \"nodenext\",\n    \"noUncheckedIndexedAccess\": true,\n    \"resolveJsonModule\": true,\n    \"skipLibCheck\": true,\n    \"sourceMap\": true,\n    \"strict\": true,\n    \"target\": \"es2022\"\n  }\n}\n"
  },
  {
    "path": "packages/rxjs/.dependency-cruiser.json",
    "content": "{\n  \"forbidden\": [\n    {\n      \"name\": \"not-to-spec\",\n      \"comment\": \"Don't allow dependencies from outside the spec folder to spec\",\n      \"severity\": \"error\",\n      \"from\": {\n        \"pathNot\": \"^spec\"\n      },\n      \"to\": {\n        \"path\": \"^spec\"\n      }\n    },\n    {\n      \"name\": \"not-to-spec\",\n      \"comment\": \"Don't allow dependencies to (typescript/ javascript/ coffeescript) spec files\",\n      \"severity\": \"error\",\n      \"from\": {},\n      \"to\": {\n        \"path\": \"\\\\.spec\\\\.[js|ts|ls|coffee|litcoffee|coffee\\\\.md]$\"\n      }\n    },\n    {\n      \"name\": \"no-deprecated-core\",\n      \"comment\": \"Warn about dependencies on deprecated core modules.\",\n      \"severity\": \"warn\",\n      \"from\": {},\n      \"to\": {\n        \"dependencyTypes\": [\"core\"],\n        \"path\": \"^(punycode|domain)$\"\n      }\n    },\n    {\n      \"name\": \"no-deprecated-npm\",\n      \"comment\": \"These npm modules are deprecated - find an alternative.\",\n      \"severity\": \"warn\",\n      \"from\": {},\n      \"to\": {\n        \"dependencyTypes\": [\"deprecated\"]\n      }\n    },\n    {\n      \"name\": \"not-to-dev-dep\",\n      \"severity\": \"error\",\n      \"comment\": \"Don't allow dependencies from src/app/lib to a development only package\",\n      \"from\": {\n        \"path\": \"^(src|app|lib)\"\n      },\n      \"to\": {\n        \"dependencyTypes\": [\"npm-dev\"]\n      }\n    },\n    {\n      \"name\": \"no-non-package-json\",\n      \"severity\": \"error\",\n      \"comment\": \"Don't allow dependencies to packages not in package.json (except from within node_modules)\",\n      \"from\": {\n        \"pathNot\": \"^node_modules\"\n      },\n      \"to\": {\n        \"dependencyTypes\": [\"undetermined\", \"npm-no-pkg\", \"npm-unknown\"],\n        \"pathNot\": \"^electron\"\n      }\n    },\n    {\n      \"name\": \"peer-deps-used\",\n      \"comment\": \"Error about the use of a peer dependency (peer dependencies are deprecated).\",\n      \"severity\": \"error\",\n      \"from\": {},\n      \"to\": {\n        \"dependencyTypes\": [\"npm-peer\"]\n      }\n    },\n    {\n      \"name\": \"no-duplicate-dep-types\",\n      \"comment\": \"Warn if a dependency occurs in your package.json more than once (technically: has more than one dependency type)\",\n      \"severity\": \"warn\",\n      \"from\": {},\n      \"to\": {\n        \"moreThanOneDependencyType\": true\n      }\n    },\n    {\n      \"name\": \"no-circular\",\n      \"severity\": \"error\",\n      \"comment\": \"Error in case we have circular dependencies\",\n      \"from\": {\n        \"path\": \"^dist/esm\"\n      },\n      \"to\": {\n        \"circular\": true\n      }\n    }\n  ]\n}\n"
  },
  {
    "path": "packages/rxjs/.dockerignore",
    "content": "node_modules\nnpm-debug.log\nDockerfile*\ndocker-compose*\n.dockerignore\n.git\n.gitignore"
  },
  {
    "path": "packages/rxjs/.eslintrc.json",
    "content": "{\n  \"extends\": [\"../../.eslintrc.json\"],\n  \"ignorePatterns\": [\"!**/*\"],\n  \"overrides\": [\n    {\n      \"files\": [\"*.ts\", \"*.tsx\", \"*.js\", \"*.jsx\"],\n      \"rules\": {\n        \"@nx/enforce-module-boundaries\": \"off\"\n      }\n    },\n    {\n      \"files\": [\"*.ts\", \"*.tsx\"],\n      \"parserOptions\": {\n        \"project\": [\"./packages/rxjs/tsconfig.json\"]\n      },\n      \"rules\": {}\n    },\n    {\n      \"files\": [\"*.js\", \"*.jsx\"],\n      \"rules\": {}\n    },\n    {\n      \"files\": [\"./package.json\"],\n      \"parser\": \"jsonc-eslint-parser\",\n      \"rules\": {\n        \"@nx/dependency-checks\": [\"error\"]\n      }\n    },\n    {\n      \"files\": \"spec/**/*.js\",\n      \"rules\": {\n        \"@typescript-eslint/no-var-requires\": \"off\"\n      }\n    }\n  ]\n}\n"
  },
  {
    "path": "packages/rxjs/.gitattributes",
    "content": "# no eol conversions!\n"
  },
  {
    "path": "packages/rxjs/CHANGELOG.md",
    "content": "## 8.0.0-alpha.14\n\n### 🩹 Fixes\n\n- **rxjs:** removed unnecessary peer deps\n\n### ❤️ Thank You\n\n- Ben Lesh\n\n## 8.0.0-alpha.13\n\n### 🚀 Features\n\n- support web standard modules\n\n- ⚠️ remove `Symbol.observable` export\n\n- ⚠️ **Subject.create:** Removed the deprecated `Subject.create` method.\n\n- ⚠️ **WebSocketSubject:** no longer extends `Subject`.\n\n- **webSocket:** now allows input and output typing to differ\n\n### 🩹 Fixes\n\n- **config:** onStoppedNotification and onUnhandledError will now always async dispatch\n\n- **TestScheduler:** explicit unsubscribe works properly with toEqual\n\n- **fromEvent:** `fromEvent` now handles symbols as event names\n\n- **fromEvent:** passing a generic parameter is no longer deprecated\n\n#### ⚠️ Breaking Changes\n\n- `observable` (the `Symbol.observable` symbol instance) is no longer exported. Use a polyfill like `symbol-observable`, or use `Symbol.observable ?? '@@observable'` as a workaround.\"\n- **Subject.create:** Removed the deprecated `Subject.create` method. If you need to create an object that is \"half Observable, half Observer\", you'll need to either bolt `next`, `error`, and `complete` handlers onto an `Observable` and property type the return... or you'll need to create your own class that is backed by an `Observable`. In any case, if the `Observer` and the `Observable` are so unrelated that you have to bolt them together, you're probably better off with those two objects separately. This is why `Subject.create` has been deprecated for so long.\n- **WebSocketSubject:** `WebSocketSubject` is no longer `instanceof Subject`. Check for `instanceof WebSocketSubject` instead.\n\n### ❤️ Thank You\n\n- Ben Lesh\n- Dmitry Demensky\n- tmair\n\n# [8.0.0-alpha.12](https://github.com/reactivex/rxjs/compare/8.0.0-alpha.11...8.0.0-alpha.12) (2023-08-19)\n\n### Bug Fixes\n\n- **TestScheduler:** no longer throws errors finding `logSubscribedFrame` in some CJS environments. ([#7325](https://github.com/reactivex/rxjs/issues/7325)) ([e01d3c1](https://github.com/reactivex/rxjs/commit/e01d3c10ec475018c029296b1e660448fae44478))\n\n# [8.0.0-alpha.11](https://github.com/reactivex/rxjs/compare/8.0.0-alpha.10...8.0.0-alpha.11) (2023-08-18)\n\n### Bug Fixes\n\n- **Subscriber:** next method no longer has optional value argument ([#7290](https://github.com/reactivex/rxjs/issues/7290)) ([1c5673f](https://github.com/reactivex/rxjs/commit/1c5673fb49b54bfa4cd780b93c97182643c8217b)), closes [#2852](https://github.com/reactivex/rxjs/issues/2852)\n\n### Features\n\n- **cjs:** output ES2022 ([#7319](https://github.com/reactivex/rxjs/issues/7319)) ([bc2e9c2](https://github.com/reactivex/rxjs/commit/bc2e9c2b8043c7d75b50aa5c0daa9243cf3674ac))\n- **Subscription:** Subscription now implements `Symbol.dispose` if it's available ([#7305](https://github.com/reactivex/rxjs/issues/7305)) ([9bb0341](https://github.com/reactivex/rxjs/commit/9bb03419be3048e573c69932b44d4672864e6ba0))\n\n# [8.0.0-alpha.10](https://github.com/reactivex/rxjs/compare/8.0.0-alpha.7...8.0.0-alpha.10) (2023-05-25)\n\n### Bug Fixes\n\n- **asapScheduler:** No longer stops after scheduling twice during flush ([#7198](https://github.com/reactivex/rxjs/issues/7198)) ([414a692](https://github.com/reactivex/rxjs/commit/414a692db7744d9ec2e3d8ac14536fd48d65dc14)), closes [ReactiveX#7196](https://github.com/ReactiveX/issues/7196)\n- **buffer:** subscribe to the closing notifier before the source ([#7185](https://github.com/reactivex/rxjs/issues/7185)) ([f37be62](https://github.com/reactivex/rxjs/commit/f37be627b6742c9ae666e40f9035b51596971fc0))\n- **elementAt:** Reentrant errors no longer supercede results ([6146604](https://github.com/reactivex/rxjs/commit/6146604c790657137d5d07290ed5f9b870cc965c)), closes [#5487](https://github.com/reactivex/rxjs/issues/5487)\n- **first/take:** behave properly with reentrant errors and completions ([65bff45](https://github.com/reactivex/rxjs/commit/65bff4554abf75eaa5a8b3a74648f9313edcc0ef)), closes [#5487](https://github.com/reactivex/rxjs/issues/5487)\n- **forkJoin:** the first empty source will now cause an EmptyError ([#7266](https://github.com/reactivex/rxjs/issues/7266)) ([4ca507a](https://github.com/reactivex/rxjs/commit/4ca507abb91643445b35c791a5080b5f00ad0e55)), closes [#5561](https://github.com/reactivex/rxjs/issues/5561)\n- **groupBy:** will no longer leak inner subscriptions ([#7252](https://github.com/reactivex/rxjs/issues/7252)) ([9ed27bf](https://github.com/reactivex/rxjs/commit/9ed27bf8f51a8f7a1f6713fab8b800f452599170)), closes [#6805](https://github.com/reactivex/rxjs/issues/6805)\n- **subjects:** All subjects will now correctly be `closed` after `complete()` and `error()`. Removed `ObjectUnsubscribedError`. Unsubscribed subjects will no longer throw. ([c71d2fc](https://github.com/reactivex/rxjs/commit/c71d2fc1b7822b89986665e1825cc58ee3d5e1f6)), closes [#7200](https://github.com/reactivex/rxjs/issues/7200) [#7209](https://github.com/reactivex/rxjs/issues/7209)\n- **takeWhile:** reentrant errors and completions behave properly ([f83d7e3](https://github.com/reactivex/rxjs/commit/f83d7e3c1c941ccd1c2bc6322f0ba1c3fa3adb88)), closes [#5487](https://github.com/reactivex/rxjs/issues/5487)\n- **throttle:** properly handle default ThrottleConfig values ([#7176](https://github.com/reactivex/rxjs/issues/7176)) ([b7a4e94](https://github.com/reactivex/rxjs/commit/b7a4e9493d3242a2b07195c134efa2215a0cbb9f))\n- **windowWhen:** don't signal on complete ([67992c4](https://github.com/reactivex/rxjs/commit/67992c49c861c05e94812d578d9549116a4dc35d)), closes [#6876](https://github.com/reactivex/rxjs/issues/6876)\n\n### Features\n\n- **ajax:** Drop IE support ([#7184](https://github.com/reactivex/rxjs/issues/7184)) ([4e14361](https://github.com/reactivex/rxjs/commit/4e14361b287411d4d1a3216aab685edc8b5f0abb))\n- **combineLatest:** remove deprecated combineLatest scheduler signature ([82bff35](https://github.com/reactivex/rxjs/commit/82bff350c1b7c1d6c02629288bb5a2d698238afa))\n- **combineLatest:** remove deprecated spread signature ([#7168](https://github.com/reactivex/rxjs/issues/7168)) ([f03c8bf](https://github.com/reactivex/rxjs/commit/f03c8bf9869052ee96e72334306f3a14d3bc9f33))\n- **combineLatest:** removed deprecated `combineLatest` operator ([d6bf2cb](https://github.com/reactivex/rxjs/commit/d6bf2cbb5646687f419ed6cc8b61ed463a5bffc3))\n- **concat:** removed deprecated `concat` operator ([#7162](https://github.com/reactivex/rxjs/issues/7162)) ([3807dae](https://github.com/reactivex/rxjs/commit/3807dae39044b5b3f6caa2694aef408bb5a9b5e1))\n- **concatMap:** removed deprecated concatMap(project, resultSelector) call pattern ([674bf01](https://github.com/reactivex/rxjs/commit/674bf017d836e1c5537f505eb7bd7a07811d4d84))\n- **concatMapTo:** removed deprecated concatMapTo(observable, resultSelector) call pattern ([d552e22](https://github.com/reactivex/rxjs/commit/d552e22b721787e454283258f05b286a0a1e5f65))\n- **endWith:** removed deprecated `endWith(value, scheduler)` call pattern ([#7163](https://github.com/reactivex/rxjs/issues/7163)) ([1ad9425](https://github.com/reactivex/rxjs/commit/1ad9425b21d900c40d307f0f34e25f20c8dd79f3))\n- **exhaustMap:** removed deprecated exhaustMap(project, resultSelector) call pattern ([04269d4](https://github.com/reactivex/rxjs/commit/04269d4a5909180e6938ce7b19697441c3f2152c))\n- **find:** removed deprecated find(predicate, thisArg) call pattern ([25215c7](https://github.com/reactivex/rxjs/commit/25215c7a8d1213922a9ee831d44afae45cd975b7))\n- **findIndex:** removed deprecated findIndex(predicate, thisArg) call pattern ([cd54089](https://github.com/reactivex/rxjs/commit/cd540898314bf9f01d3921520150e39545f95e0d))\n- **from:** Remove deprecated scheduler signature. ([f64eb63](https://github.com/reactivex/rxjs/commit/f64eb6321af65518377c3ac7184d7fc1c8bb64fc))\n- **map:** removed deprecated `map(project, thisArg)` call pattern ([#7158](https://github.com/reactivex/rxjs/issues/7158)) ([d7eab2b](https://github.com/reactivex/rxjs/commit/d7eab2baf928f22d9806ed17b4da5e0e7eb8c690))\n- **mergeMap:** removed deprecated mergeMap(project, resultSelector) call pattern ([8f9a5e3](https://github.com/reactivex/rxjs/commit/8f9a5e3d7389c3dc60b7d09666792387b4460479))\n- **mergeMapTo:** removed deprecated mergeMapTo(observable, resultSelector) call pattern ([b5a91c9](https://github.com/reactivex/rxjs/commit/b5a91c9e4ad5ce85cfd91bcb42f11f916c297a08))\n- **observable:** removed deprecated `pairs` function ([071b448](https://github.com/reactivex/rxjs/commit/071b448e590316f65256e3db55619eae76fbb0d3))\n- **Observable:** now implements `Symbol.asyncIterator` ([#7189](https://github.com/reactivex/rxjs/issues/7189)) ([256ab5c](https://github.com/reactivex/rxjs/commit/256ab5c25d6166da600529b732fed3ca21b59ba0))\n- **Observable:** RxJS doesn't even lift. ([#7202](https://github.com/reactivex/rxjs/issues/7202)) ([e0bdccf](https://github.com/reactivex/rxjs/commit/e0bdccf1ee3578ada0a47155109d95405a2e5765)), closes [#7201](https://github.com/reactivex/rxjs/issues/7201)\n- **of:** removed deprecated `of(...values, scheduler)` call pattern ([#7220](https://github.com/reactivex/rxjs/issues/7220)) ([458cbe9](https://github.com/reactivex/rxjs/commit/458cbe957a892e2e14b92553b49c4f7e4e41fb7e))\n- **operate:** Adds new subscriber chaining mechanism for operator creation ([804e9c7](https://github.com/reactivex/rxjs/commit/804e9c7925abc8d124ed336b9a2d06fa9f6bb598))\n- **operator:** removed deprecated `combineAll` operator ([981c9c8](https://github.com/reactivex/rxjs/commit/981c9c8538705e225b4ec8e81e6665424c421d6c))\n- **operator:** removed deprecated `exhaust` operator ([6965b8a](https://github.com/reactivex/rxjs/commit/6965b8a6da84734df4f6c32e26d73c4259802cdc))\n- **operator:** removed deprecated `flatMap` operator ([099a4f1](https://github.com/reactivex/rxjs/commit/099a4f1ac0a748ca7d01da90b8c37a986c846bc8))\n- **operator:** removed deprecated `merge` operator ([f97c73d](https://github.com/reactivex/rxjs/commit/f97c73d412586afc29482efadbdcd4ff98de4654))\n- **operator:** removed deprecated `multicast` operator ([709be5a](https://github.com/reactivex/rxjs/commit/709be5a28f1cc8b435688d23b6ca6f65cb3efea7))\n- **operator:** removed deprecated `onErrorResumeNext` operator ([de7becf](https://github.com/reactivex/rxjs/commit/de7becfe1dd62f881fc724d841ac8bff06e6062a))\n- **operator:** removed deprecated `pluck` operator ([fd1936d](https://github.com/reactivex/rxjs/commit/fd1936de0d25bbcdc3a73dcf3fc4a8d454b64e73))\n- **operator:** removed deprecated `publish` operator ([2cd2b88](https://github.com/reactivex/rxjs/commit/2cd2b88aa75d4cab314172720db02ba7d4c43cce))\n- **operator:** removed deprecated `publishBehavior` operator ([a65f878](https://github.com/reactivex/rxjs/commit/a65f8782a8453a09681f8a5f11b3ed543095af54))\n- **operator:** removed deprecated `publishLast` operator ([3ea5f99](https://github.com/reactivex/rxjs/commit/3ea5f991f4dcb070e53b00d8f001360db48f67bf))\n- **operator:** removed deprecated `publishReplay` operator ([5dd12e4](https://github.com/reactivex/rxjs/commit/5dd12e4985c083cd32919f7070cdaa213466353c))\n- **operator:** removed deprecated `race` operator ([8fd5ced](https://github.com/reactivex/rxjs/commit/8fd5ced782b24703760d46fdc47d72fc88dbce02))\n- **operator:** removed deprecated `refCount` operator ([e477847](https://github.com/reactivex/rxjs/commit/e477847b916fd8bf014bfc64371816ed3eb26b02))\n- **operator:** removed deprecated `zip` operator ([7404cbf](https://github.com/reactivex/rxjs/commit/7404cbfd1f69b491001b2a42ca5e18ac19bac34a))\n- **rx:** A new method of piping has been added ([#7229](https://github.com/reactivex/rxjs/issues/7229)) ([c2cf0c4](https://github.com/reactivex/rxjs/commit/c2cf0c4a9dfe5904d65e998b4831909c082f78f7)), closes [#7203](https://github.com/reactivex/rxjs/issues/7203)\n- **scheduler:** removed deprecated `animationFrame` constant ([138688b](https://github.com/reactivex/rxjs/commit/138688b710adc1e2aecb46fc4135da28b10d4575))\n- **scheduler:** removed deprecated `asap` constant ([edac583](https://github.com/reactivex/rxjs/commit/edac583ad3585632b28747f97ffa15bcd7e496a1))\n- **scheduler:** removed deprecated `queueScheduler` constant ([b7b9edf](https://github.com/reactivex/rxjs/commit/b7b9edf35871888de69fd7bf0b1c9527687defa3))\n- **startWith:** remove deprecated scheduler signature. ([#7166](https://github.com/reactivex/rxjs/issues/7166)) ([bbdce3b](https://github.com/reactivex/rxjs/commit/bbdce3b77321fcdceb61e393bd153ea0ec5d164e))\n- **Subject:** `isStopped`, `observers`, `hasError`, and `thrownError` no longer in public API. ([d734be4](https://github.com/reactivex/rxjs/commit/d734be479efa2b063be8930f3ffcd5558252a1d0))\n- **Subscriber:** constructing `new Subscriber` is deprecated ([2e29a73](https://github.com/reactivex/rxjs/commit/2e29a737730f8da7fc4a4419ed44cdc512d9284c))\n- Dropping support for Node 14. ([b171f35](https://github.com/reactivex/rxjs/commit/b171f354927dd57ac3e74cf2d3774bcfed4f142e))\n- No longer publishing UMD or ES5 builds ([fce318a](https://github.com/reactivex/rxjs/commit/fce318a6455a179a197d9d126d9fc09b535788ef))\n- Reduction in size of core piece `Subscriber` and `Subscription`. ([f7f7e8c](https://github.com/reactivex/rxjs/commit/f7f7e8c04e4fd288f311e9f69b54c6da67dedeea))\n- **scheduler:** removed deprecated `asyncScheduler` constant ([3c0553b](https://github.com/reactivex/rxjs/commit/3c0553b32a9b6b04a34ae6908080d120a067d168))\n- **switchMap:** removed deprecated switchMap(project, resultSelector) call pattern ([9a907d6](https://github.com/reactivex/rxjs/commit/9a907d62cdf7a1155b1029afd9e51a34f2472375))\n- **switchMapTo:** removed deprecated switchMapTo(observable, resultSelector) call pattern ([f14f633](https://github.com/reactivex/rxjs/commit/f14f633b6b3540ed0d3b0a5dec7596387cd69efb))\n- **throwError:** removed deprecated throwError(error) call pattern ([f140eee](https://github.com/reactivex/rxjs/commit/f140eee70d3a8a1e696d1efe83f93772f7ff9825))\n- **throwError:** removed deprecated throwError(errorFactory, scheduler) call pattern ([f031611](https://github.com/reactivex/rxjs/commit/f031611cb868a451752d7e64b7ec971db5fd8158))\n- **types:** removed deprecated `ObservableLike` interface ([e8134e4](https://github.com/reactivex/rxjs/commit/e8134e4e07e0aca7e94bc3ead8279e7756ad968b))\n- **types:** removed deprecated `ObservedValuesFromArray` interface ([e80a182](https://github.com/reactivex/rxjs/commit/e80a18299e25530c2cc44c2001039baec83ae069))\n- RxJS updated to TypeScript 4.9 ([76c38f7](https://github.com/reactivex/rxjs/commit/76c38f75cdc166948fd92d94740d187bf787bc03))\n\n### Performance Improvements\n\n- **endWith:** simplify the implementation of the `endWith` operator ([#7165](https://github.com/reactivex/rxjs/issues/7165)) ([5de4796](https://github.com/reactivex/rxjs/commit/5de47962ac5823fa17dcd4340707239912c47c4d))\n- **Subject:** create one less subscription on subscribe ([79d5ae4](https://github.com/reactivex/rxjs/commit/79d5ae464fc234422883b5204112cc2fef401ec7))\n- **Subject:** subscription, unsubscription, and nexting improved ~4x ([#7240](https://github.com/reactivex/rxjs/issues/7240)) ([dbbae80](https://github.com/reactivex/rxjs/commit/dbbae809fec30796517d0c76d367e36705618f85))\n\n### BREAKING CHANGES\n\n- **startWith:** `startWith` no longer accepts a scheduler. If you would like to schedule emissions in this manner, instead of `source$.pipe(startWith(1, 2, 3, scheduler)) use `concat(scheduled([1, 2, 3], scheduler), source$)`.\n- **forkJoin:** `forkJoin` will no longer just complete if a source completes without a value. Instead you will get an error of `EmptyError`. If you want to complete in this case, add `catchError(() => EMPTY)` to the forkJoin... however, if you just want to default the sources of your `forkJoin` to some other value if they're empty, apply the `defaultIfEmpty` operator. for example, `forkJoin(sources.map(defaultIfEmpty(null)))`.\n- **rx:** `Observable#pipe` now allows any pipeable unary function as an argument, just so long as the types properly compose, this means in some cases it will now return `unknown` instead of `Observable<unknown>` the workaround is just to cast the result for those cases. (or you can break your operator piping into smaller pipe sets)\n- **groupBy:** `groupBy` no longer allows grouped observable subscriptions to stay connected after parent subscription unsubscribed. If you need this behavior, don't unsubscribe from the parent.\n- **of:** `of(...values, scheduler)` call pattern is no longer available. Alternatively, use `scheduled(values, scheduler)`. [Read more](https://rxjs.dev/deprecations/scheduler-argument).\n- **combineLatest:** `combineLatest` no longer accepts a spread of ObservableInputs. Use an array instead. If you need `combineLatest(a$, b$, c$)`, use `combineLatest([a$, b$, c$])` instead.\n- **Subject:** `isStopped`, `observers`, `thrownError` and `hasError` are no longer part of the public API. The only known use case for any of these was detecting that a Subject was observed, like so: `if (subject.observers.length > 0)`. That shouldn't be done. Instead use `if (subject.observed)`.\n- **subjects:** `ObjectUnsubscribedError` is no longer exported. The constructor was long deprecated. If you need a similar error, you can construct and throw your own. RxJS no longer throws this error.\n- **subjects:** `Subject#closed` is no longer writeable. That was never an intended API. If you need to silently close a `Subject`, call `Subject#unsubscribe()`.\n- **subjects:** Windows from `windowToggle` will no longer through if leaked and subscribed outside of the main subscription. There's no real use case for this behavior. If you find you needed this behavior, please file and issue.\n- **Observable:** `Observable#lift`, `Observable#source`, and `Observable#operator` is no longer a part of the API. These were never meant to be public and have been deprecated for more than 3 years.\n- **ajax:** `ajax` no longer supports IE\n- **buffer:** Weird patterns where an observable is used to notify buffers of itself will result in a first emission of `[]`. If you need to buffer an array with itself, just use `map(x => [x])`. If that doesn't work, feel free to file a use case as an issue. `skip(1)` would be the other workaround.\n- **elementAt:** If a the source synchronously errors after it recieves a completion from `elementAt`, the error will no longer be emitted. This is a bug fix, but may be a breaking change for those relying on this behavior. If you need to mimic the behavior, you'll need to throw the error before `elementAt` finds the element at the index.\n- **first/take:** If a the source synchronously errors after `take` or `first` notice a completion, the error will no longer be emitted. This is a bug fix, but may be a breaking change for those relying on this behavior. If you need to mimic the behavior, you'll need to throw the error before `take` or `first` notice the completion.\n- **takeWhile:** If a the source synchronously errors after it recieves a completion notification, the error will no longer be emitted. This is a bug fix, but may be a breaking change for those relying on this behavior. If you need to mimic the behavior, you'll need to throw the error before the takeWhile notifier is notified.\n- **observable:** The `pairs` function is no longer available. Use `from(Object.entries(obj))` instead `pairs(obj)`.\n- **operator:** The `pluck('foo', 'bar')` operator is no longer available. Use `map(x => x?.foo?.bar)`.\n- **operator:** The `race` operator is no longer available. Use `raceWith`.\n- **operator:** The `refCount` operator is no longer available. [Multicasting](https://rxjs.dev/deprecations/multicasting#refcount).\n- **operator:** The `ConnectableObservable` observable is no longer available. [Multicasting](https://rxjs.dev/deprecations/multicasting#connectableobservable).\n- **operator:** The `multicast` operator is no longer available. Use `share({ connector: () => new Subject() })` or `connectable(source$, {connector: () => new Subject() })` [Multicasting](https://rxjs.dev/deprecations/multicasting#multicast).\n- **operator:** The `publish` operator is no longer available. Use `share({ resetOnError: false, resetOnComplete: false, resetOnRefCountZero: false })` or ` connectable(source$, { connector: () => new Subject(), resetOnDisconnect: false })`. [Multicasting](https://rxjs.dev/deprecations/multicasting#publish).\n- **operator:** The `publishBehavior` operator is no longer available. Use `share({ connector: () => new BehaviorSubject(0), resetOnError: false, resetOnComplete: false, resetOnRefCountZero: false })` or `connectable(source$, { connector: () => new BehaviorSubject(0), resetOnDisconnect: false })`. [Multicasting](https://rxjs.dev/deprecations/multicasting#publishbehavior).\n- **operator:** The `publishReplay` operator is no longer available. Use `share({ connector: () => new ReplaySubject(1), resetOnError: false, resetOnComplete: false, resetOnRefCountZero: false })` or `connectable(source$, { connector: () => new ReplaySubject(1), resetOnDisconnect: false })` [Multicasting](https://rxjs.dev/deprecations/multicasting#publishreplay).\n- **operator:** The `publishLast` operator is no longer available. Use `share({ connector: () => new AsyncSubject(), resetOnError: false, resetOnComplete: false, resetOnRefCountZero: false })` or `connectable(source$, { connector: () => new AsyncSubject(), resetOnDisconnect: false })`. [Multicasting](https://rxjs.dev/deprecations/multicasting#publishlast).\n- **operator:** The `zip` operator is no longer available. Use `zipWith`.\n- **operator:** The `merge` operator is no longer available. Use `mergeWith`.\n- Node 14 is no longer supported in version 8. End of life for Node 14 is April 30, 2023. There's no reason for RxJS version 8 to support it, as we won't even be out of beta at that point.\n- Deprecated `subscriber.isStopped` has been made internal. Use `subscriber.closed` or create a custom observer that tracks `isStopped` state.\n- Deprecated `subscriber.destination` has been made internal. If you need to access the subscriber's destination for some reason, you will have to trap the value ahead of time. If this is something you really need, please file and issue and bring it to our attention. There shouldn't be any use cases for this.\n- **from:** `from` no longer supports passing a scheduler as the second argument. Use `scheduled` instead.\n- **combineLatest:** The deprecated signature of combineLatest that accepted a scheduler as the last argument has been removed. If you wanted `combineLatest([a$, b$], scheduler)`, you'll now need to use `combineLatest([scheduled(a$, scheduler), scheduled(b$, scheduler)])`.\n- **operator:** The `onErrorResumeNext` operator is no longer available. Use `onErrorResumeNextWith`.\n- **scheduler:** The `async` constant is no longer available. Use `asyncScheduler`.\n- **scheduler:** The `queue` constant is no longer available. Use `queueScheduler`.\n- **scheduler:** The `asap` constant is no longer available. Use `asapScheduler`.\n- **operator:** The `exhaust` operator is no longer available. Use `exhaustAll`.\n- **operator:** The `flatMap` operator is no longer available. Use `mergeMap`.\n- **operator:** The `combineAll` operator is no longer available. Use `combineLatestAll`.\n- **types:** The `ObservedValuesFromArray` interface is no longer available. Use `ObservedValueUnionFromArray`.\n- **types:** The `ObservableLike` interface is no longer available. Use `InteropObservable`.\n- **scheduler:** The `animationFrame` constant is no longer available. Use `animationFrameScheduler`.\n- **map:** `map(project, thisArg)` call pattern is no longer available. Use Function#bind method: `map(project.bind(thisArg))`\n- **endWith:** `endWith(value, scheduler)` call pattern is no longer available. [Read more](https://rxjs.dev/deprecations/scheduler-argument).\n- **concat:** The `concat` operator is no longer available. Use `concatWith`.\n- **combineLatest:** The `combineLatest` operator is no longer available. Use `combineLatestWith`.\n- **throwError:** `throwError(errorFactory, scheduler)` call pattern is no longer available. [Read more](https://rxjs.dev/deprecations/scheduler-argument).\n- **throwError:** `throwError(error)` call pattern is no longer available. Use `throwError(() => error)`\n- **findIndex:** `findIndex(predicate, thisArg)` call pattern is no longer available. Use `findIndex(predicate.bind(thisArg))`\n- **find:** `find(predicate, thisArg)` call pattern is no longer available. Use `find(predicate.bind(thisArg))`\n- **switchMap:** `switchMap(project, resultSelector)` call pattern is no longer available. [Read more](https://rxjs.dev/deprecations/resultSelector).\n- **switchMapTo:** `switchMapTo(observable, resultSelector)` call pattern is no longer available. [Read more](https://rxjs.dev/deprecations/resultSelector).\n- **mergeMap:** `mergeMap(project, resultSelector)` call pattern is no longer available. [Read more](https://rxjs.dev/deprecations/resultSelector).\n- **exhaustMap:** `exhaustMap(project, resultSelector)` call pattern is no longer available. [Read more](https://rxjs.dev/deprecations/resultSelector).\n- **mergeMapTo:** `mergeMapTo(observable, resultSelector)` call pattern is no longer available. [Read more](https://rxjs.dev/deprecations/resultSelector).\n- **concatMap:** `concatMap(project, resultSelector)` call pattern is no longer available. [Read more](https://rxjs.dev/deprecations/resultSelector).\n- **concatMapTo:** `concatMapTo(observable, resultSelector)` call pattern is no longer available. [Read more](https://rxjs.dev/deprecations/resultSelector).\n- RxJS is now being built with TypeScript 4.9 and we assume that TS 4.9 or higher will be used with our types. At the time of this writing the risk is around the existence of the `ReadableStream` type in TypeScript. If that's not supported in your version of TypeScript, you might be able to work around this issue by defining a global ReadableStream type.\n\n# [8.0.0-alpha.7](https://github.com/reactivex/rxjs/compare/7.8.0...8.0.0-alpha.7) (2022-12-15)\n\nMerged in changes from 7.8.0\n\n# [8.0.0-alpha.6](https://github.com/reactivex/rxjs/compare/7.7.0...8.0.0-alpha.6) (2022-12-15)\n\nMerged in changes from 7.7.0\n\n# [8.0.0-alpha.5](https://github.com/reactivex/rxjs/compare/7.5.7...8.0.0-alpha.5) (2022-09-25)\n\nMerged updates from 7.x branch\n\n# [8.0.0-alpha.4](https://github.com/reactivex/rxjs/compare/7.5.6...8.0.0-alpha.4) (2022-07-11)\n\n### Bug Fixes\n\n- add missing deprecated JSDoc tag to pluck overload signatures ([#6896](https://github.com/reactivex/rxjs/issues/6896)) ([08a549b](https://github.com/reactivex/rxjs/commit/08a549b735602322eb8895768bc45bd218fa5827))\n\n### Features\n\n- **Subscriber:** ctor no longer deprecated. Creates safe subscribers. ([ac2b001](https://github.com/reactivex/rxjs/commit/ac2b001b31bb2b9f4f2ea1dbafddd6b92cb421aa))\n- **Subscriber.create:** Removed. ([826d807](https://github.com/reactivex/rxjs/commit/826d8075fb94b3127ea6313883fded2fdc0636ef))\n\n### BREAKING CHANGES\n\n- **Subscriber.create:** Subscriber.create has been removed. Please use `new Subscriber` instead.\n\n# [8.0.0-alpha.1](https://github.com/reactivex/rxjs/compare/7.5.3...8.0.0-alpha.1) (2022-02-08)\n\nMerged updates from 7.x branch\n\n# [8.0.0-alpha.0](https://github.com/reactivex/rxjs/compare/7.5.2...8.0.0-alpha.0) (2022-01-13)\n\n### Bug Fixes\n\n- takeWhile Boolean constructor types ([#6633](https://github.com/reactivex/rxjs/issues/6633)) ([edbaf4f](https://github.com/reactivex/rxjs/commit/edbaf4f2c6203b7a53c6070924ebd4e9103caa77))\n- **forEach:** properly unsubs after error in next handler ([#6677](https://github.com/reactivex/rxjs/issues/6677)) ([4c675b8](https://github.com/reactivex/rxjs/commit/4c675b83d6e6112efc51e0fffd8172c2e3c6d0aa)), closes [#6676](https://github.com/reactivex/rxjs/issues/6676)\n- **WebSocketSubject:** handle slow WebSocket close ([#6708](https://github.com/reactivex/rxjs/issues/6708)) ([bf3831b](https://github.com/reactivex/rxjs/commit/bf3831b72a8ff2a04c9ed4c8e069932c47b9d208)), closes [#4650](https://github.com/reactivex/rxjs/issues/4650) [#3935](https://github.com/reactivex/rxjs/issues/3935)\n- RxJS now supports tslib 2.x, rather than just 2.1.x ([#6692](https://github.com/reactivex/rxjs/issues/6692)) ([d5d98bc](https://github.com/reactivex/rxjs/commit/d5d98bc7a5bb2b81971cfa944250d330945c51e6)), closes [#6689](https://github.com/reactivex/rxjs/issues/6689)\n- schedulers will no longer error while rescheduling and unsubscribing during flushes ([7f9c8d3](https://github.com/reactivex/rxjs/commit/7f9c8d3773ae042cd0938482242edb31a8f2adc7)), closes [#6672](https://github.com/reactivex/rxjs/issues/6672)\n\n### Features\n\n- **empty:** removed deprecated `empty` function. ([9bab0d0](https://github.com/reactivex/rxjs/commit/9bab0d0073794b6c864437fea026a96092f6e3fe))\n- **forEach:** Removed PromiseCtor argument ([#6736](https://github.com/reactivex/rxjs/issues/6736)) ([b7ba41c](https://github.com/reactivex/rxjs/commit/b7ba41c2b6d55db9190fc680ab8b6f12dbf7a146))\n- **never:** remove `never` function ([25cdca6](https://github.com/reactivex/rxjs/commit/25cdca6fddcc9ae52696828475502f47bbbee5b8))\n- **Notification:** Removed Notification class. ([ca4d42a](https://github.com/reactivex/rxjs/commit/ca4d42a6a68c5262d634170378f14fd792fb8430))\n- **Observable.create:** removed ([#6602](https://github.com/reactivex/rxjs/issues/6602)) ([fb94ee8](https://github.com/reactivex/rxjs/commit/fb94ee87cf9986418b4d55b019d34655e5533fa9))\n- **subscribe:** Removed deprecated fn, fn, fn call pattern. ([#6757](https://github.com/reactivex/rxjs/issues/6757)) ([ef59c7e](https://github.com/reactivex/rxjs/commit/ef59c7ed3668f4501bf3a7635affd0dd5cc5e500))\n- **tap:** Removed deprecated `tap(fn, fn, fn)` call pattern. ([#6759](https://github.com/reactivex/rxjs/issues/6759)) ([2c0b3e5](https://github.com/reactivex/rxjs/commit/2c0b3e590e427e355b7c9e4cfb7d2506f5c7c15d))\n- `toPromise` removed. ([#6598](https://github.com/reactivex/rxjs/issues/6598)) ([8233648](https://github.com/reactivex/rxjs/commit/82336482154ca446bdc956490c9661ed5fbe4636))\n- `useDeprecatedNextContext` no longer available ([#6596](https://github.com/reactivex/rxjs/issues/6596)) ([df25015](https://github.com/reactivex/rxjs/commit/df25015cf3756068d959aa0981b4a8b1c1ca9d8f))\n- Remove \"super gross mode\" once and for all! `useDeprecatedSynchronousErrorHandling` is removed ([#6595](https://github.com/reactivex/rxjs/issues/6595)) ([5225692](https://github.com/reactivex/rxjs/commit/5225692351bb089305d7790e625e49263d753eed))\n- Remove SubscribableOrPromise type. ([#6735](https://github.com/reactivex/rxjs/issues/6735)) ([d79fd00](https://github.com/reactivex/rxjs/commit/d79fd000a5babaefaea56c33c593cab3eeb538a1))\n- **Subscription:** idempotent add and remove of teardowns ([#6401](https://github.com/reactivex/rxjs/issues/6401)) ([d197e40](https://github.com/reactivex/rxjs/commit/d197e40032ba2ea8defcfba86a209083c8933d8c)), closes [#6400](https://github.com/reactivex/rxjs/issues/6400)\n- removed `config.Promise` injection point. ([#6597](https://github.com/reactivex/rxjs/issues/6597)) ([6552b85](https://github.com/reactivex/rxjs/commit/6552b85afb66a76ae61b54efce66ab225347bd30))\n\n### BREAKING CHANGES\n\n- **tap:** `tap(fn, fn, fn)` call pattern is no longer available. Use named arguments (observers) instead: `tap({ complete: fn, error: fn, next: fn })`.\n\n- chore: update dtslint for tap\n\n- chore: update api guardian files\n- **subscribe:** `subscribe(fn, fn, fn)` is no longer a valid call for `subscribe`. Instead, use an observer: `subscribe({ next: fn, error: fn, complete: fn })`.\n\n- chore: remove unnecessary deprecation tests\n- **forEach:** PromiseCtor argument removed. If your runtime lacks a Promise implementation, you'll need to polyfill it.\n- **Notification:** `Notification` is no longer exported. To create a notification object you may use an object literal. To convert a notification object to an observable, you can use `materialize`: `of({ kind: 'N' as const, value: 'test' }).pipe(materialize())`.\n\n- chore: update side-effects snapshots\n- **never:** `never()` has been removed finally. Just use `NEVER`.\n- **empty:** `empty` no longer exists, use `EMPTY` or if you need scheduling, `scheduled`.\n- `SubscribableOrPromise` is no longer an exported type, you will likely want to use `ObservableInput` instead.\n- **Observable.create:** `Observable.create` has been removed. Use `new Observable` instead.\n- Removed `useDeprecatedSynchronousErrorHandling`. No workarounds for this.\n\n- chore: update api_guardian files\n\n- chore: remove unnecessary comment\n\n- chore: update api_guardian files\n- `toPromise` has been removed from `Observable`. As a workaround, use `firstValueFrom` and `lastValueFrom` functions, which can be imported from `rxjs`. For example `source$.toPromise()` would be `lastValueFrom(source$)`. In the case that you know your source only has one value, we recommend using `firstValueFrom(source$)`.\n- **Subscription:** Adding the same function instance to a subscription as a teardown multiple times will now result in that function being executed only once on teardown. This brings us inline with the behavior of EventTarget, and also makes removing teardowns faster. The workaround is to make sure you are adding a new function instance to the Subscription each time if you need the same effect.\n- `useDeprecatedNextContext` is no longer available. No workaround.\n- `config.Promise` no longer exists. As a workaround, you will need to set a global Promise if one does not already exist in your environment.\n\n- chore: remove unused import\n\n# [8.0.0-alpha.4](https://github.com/reactivex/rxjs/compare/7.5.6...8.0.0-alpha.4) (2022-07-11)\n\n### Bug Fixes\n\n- add missing deprecated JSDoc tag to pluck overload signatures ([#6896](https://github.com/reactivex/rxjs/issues/6896)) ([08a549b](https://github.com/reactivex/rxjs/commit/08a549b735602322eb8895768bc45bd218fa5827))\n\n### Features\n\n- **Subscriber:** ctor no longer deprecated. Creates safe subscribers. ([ac2b001](https://github.com/reactivex/rxjs/commit/ac2b001b31bb2b9f4f2ea1dbafddd6b92cb421aa))\n- **Subscriber.create:** Removed. ([826d807](https://github.com/reactivex/rxjs/commit/826d8075fb94b3127ea6313883fded2fdc0636ef))\n\n### BREAKING CHANGES\n\n- **Subscriber.create:** Subscriber.create has been removed. Please use `new Subscriber` instead.\n\n# [8.0.0-alpha.1](https://github.com/reactivex/rxjs/compare/7.5.3...8.0.0-alpha.1) (2022-02-08)\n\n# [8.0.0-alpha.0](https://github.com/reactivex/rxjs/compare/7.5.2...8.0.0-alpha.0) (2022-01-13)\n\n### Bug Fixes\n\n- takeWhile Boolean constructor types ([#6633](https://github.com/reactivex/rxjs/issues/6633)) ([edbaf4f](https://github.com/reactivex/rxjs/commit/edbaf4f2c6203b7a53c6070924ebd4e9103caa77))\n- **forEach:** properly unsubs after error in next handler ([#6677](https://github.com/reactivex/rxjs/issues/6677)) ([4c675b8](https://github.com/reactivex/rxjs/commit/4c675b83d6e6112efc51e0fffd8172c2e3c6d0aa)), closes [#6676](https://github.com/reactivex/rxjs/issues/6676)\n- **WebSocketSubject:** handle slow WebSocket close ([#6708](https://github.com/reactivex/rxjs/issues/6708)) ([bf3831b](https://github.com/reactivex/rxjs/commit/bf3831b72a8ff2a04c9ed4c8e069932c47b9d208)), closes [#4650](https://github.com/reactivex/rxjs/issues/4650) [#3935](https://github.com/reactivex/rxjs/issues/3935)\n- RxJS now supports tslib 2.x, rather than just 2.1.x ([#6692](https://github.com/reactivex/rxjs/issues/6692)) ([d5d98bc](https://github.com/reactivex/rxjs/commit/d5d98bc7a5bb2b81971cfa944250d330945c51e6)), closes [#6689](https://github.com/reactivex/rxjs/issues/6689)\n- schedulers will no longer error while rescheduling and unsubscribing during flushes ([7f9c8d3](https://github.com/reactivex/rxjs/commit/7f9c8d3773ae042cd0938482242edb31a8f2adc7)), closes [#6672](https://github.com/reactivex/rxjs/issues/6672)\n\n### Features\n\n- **empty:** removed deprecated `empty` function. ([9bab0d0](https://github.com/reactivex/rxjs/commit/9bab0d0073794b6c864437fea026a96092f6e3fe))\n- **forEach:** Removed PromiseCtor argument ([#6736](https://github.com/reactivex/rxjs/issues/6736)) ([b7ba41c](https://github.com/reactivex/rxjs/commit/b7ba41c2b6d55db9190fc680ab8b6f12dbf7a146))\n- **never:** remove `never` function ([25cdca6](https://github.com/reactivex/rxjs/commit/25cdca6fddcc9ae52696828475502f47bbbee5b8))\n- **Notification:** Removed Notification class. ([ca4d42a](https://github.com/reactivex/rxjs/commit/ca4d42a6a68c5262d634170378f14fd792fb8430))\n- **Observable.create:** removed ([#6602](https://github.com/reactivex/rxjs/issues/6602)) ([fb94ee8](https://github.com/reactivex/rxjs/commit/fb94ee87cf9986418b4d55b019d34655e5533fa9))\n- **subscribe:** Removed deprecated fn, fn, fn call pattern. ([#6757](https://github.com/reactivex/rxjs/issues/6757)) ([ef59c7e](https://github.com/reactivex/rxjs/commit/ef59c7ed3668f4501bf3a7635affd0dd5cc5e500))\n- **tap:** Removed deprecated `tap(fn, fn, fn)` call pattern. ([#6759](https://github.com/reactivex/rxjs/issues/6759)) ([2c0b3e5](https://github.com/reactivex/rxjs/commit/2c0b3e590e427e355b7c9e4cfb7d2506f5c7c15d))\n- `toPromise` removed. ([#6598](https://github.com/reactivex/rxjs/issues/6598)) ([8233648](https://github.com/reactivex/rxjs/commit/82336482154ca446bdc956490c9661ed5fbe4636))\n- `useDeprecatedNextContext` no longer available ([#6596](https://github.com/reactivex/rxjs/issues/6596)) ([df25015](https://github.com/reactivex/rxjs/commit/df25015cf3756068d959aa0981b4a8b1c1ca9d8f))\n- Remove \"super gross mode\" once and for all! `useDeprecatedSynchronousErrorHandling` is removed ([#6595](https://github.com/reactivex/rxjs/issues/6595)) ([5225692](https://github.com/reactivex/rxjs/commit/5225692351bb089305d7790e625e49263d753eed))\n- Remove SubscribableOrPromise type. ([#6735](https://github.com/reactivex/rxjs/issues/6735)) ([d79fd00](https://github.com/reactivex/rxjs/commit/d79fd000a5babaefaea56c33c593cab3eeb538a1))\n- **Subscription:** idempotent add and remove of teardowns ([#6401](https://github.com/reactivex/rxjs/issues/6401)) ([d197e40](https://github.com/reactivex/rxjs/commit/d197e40032ba2ea8defcfba86a209083c8933d8c)), closes [#6400](https://github.com/reactivex/rxjs/issues/6400)\n- removed `config.Promise` injection point. ([#6597](https://github.com/reactivex/rxjs/issues/6597)) ([6552b85](https://github.com/reactivex/rxjs/commit/6552b85afb66a76ae61b54efce66ab225347bd30))\n\n### BREAKING CHANGES\n\n- **tap:** `tap(fn, fn, fn)` call pattern is no longer available. Use named arguments (observers) instead: `tap({ complete: fn, error: fn, next: fn })`.\n\n- chore: update dtslint for tap\n\n- chore: update api guardian files\n- **subscribe:** `subscribe(fn, fn, fn)` is no longer a valid call for `subscribe`. Instead, use an observer: `subscribe({ next: fn, error: fn, complete: fn })`.\n\n- chore: remove unnecessary deprecation tests\n- **forEach:** PromiseCtor argument removed. If your runtime lacks a Promise implementation, you'll need to polyfill it.\n- **Notification:** `Notification` is no longer exported. To create a notification object you may use an object literal. To convert a notification object to an observable, you can use `materialize`: `of({ kind: 'N' as const, value: 'test' }).pipe(materialize())`.\n\n- chore: update side-effects snapshots\n- **never:** `never()` has been removed finally. Just use `NEVER`.\n- **empty:** `empty` no longer exists, use `EMPTY` or if you need scheduling, `scheduled`.\n- `SubscribableOrPromise` is no longer an exported type, you will likely want to use `ObservableInput` instead.\n- **Observable.create:** `Observable.create` has been removed. Use `new Observable` instead.\n- Removed `useDeprecatedSynchronousErrorHandling`. No workarounds for this.\n\n- chore: update api_guardian files\n\n- chore: remove unnecessary comment\n\n- chore: update api_guardian files\n- `toPromise` has been removed from `Observable`. As a workaround, use `firstValueFrom` and `lastValueFrom` functions, which can be imported from `rxjs`. For example `source$.toPromise()` would be `lastValueFrom(source$)`. In the case that you know your source only has one value, we recommend using `firstValueFrom(source$)`.\n- **Subscription:** Adding the same function instance to a subscription as a teardown multiple times will now result in that function being executed only once on teardown. This brings us inline with the behavior of EventTarget, and also makes removing teardowns faster. The workaround is to make sure you are adding a new function instance to the Subscription each time if you need the same effect.\n- `useDeprecatedNextContext` is no longer available. No workaround.\n- `config.Promise` no longer exists. As a workaround, you will need to set a global Promise if one does not already exist in your environment.\n\n- chore: remove unused import\n\n# [7.8.0](https://github.com/reactivex/rxjs/compare/7.7.0...7.8.0) (2022-12-15)\n\n### Features\n\n- **buffer:** `closingNotifier` now supports any `ObservableInput` ([#7073](https://github.com/reactivex/rxjs/issues/7073)) ([61b877a](https://github.com/reactivex/rxjs/commit/61b877a50c2557196a45e12622305c5a84fc3f0a))\n- **delayWhen:** `delayWhen`'s `delayDurationSelector` now supports any `ObservableInput` ([#7049](https://github.com/reactivex/rxjs/issues/7049)) ([dfd95db](https://github.com/reactivex/rxjs/commit/dfd95db952a6772d35d11bdd1974f2c4b4d68b25))\n- **sequenceEqual:** `compareTo` now supports any `ObservableInput` ([#7102](https://github.com/reactivex/rxjs/issues/7102)) ([d501961](https://github.com/reactivex/rxjs/commit/d50196187710c7a0cad50703b2071fc3f2cabd3c))\n- **share:** `ShareConfig` factory properties now supports any `ObservableInput` ([#7093](https://github.com/reactivex/rxjs/issues/7093)) ([cc3995a](https://github.com/reactivex/rxjs/commit/cc3995a6f6baf9456ec11f749fe89bf61b9e2d62))\n- **skipUntil:** `notifier` now supports any `ObservableInput` ([#7091](https://github.com/reactivex/rxjs/issues/7091)) ([60d6c40](https://github.com/reactivex/rxjs/commit/60d6c40fb484903286feca2bbfa9fcb2cde720e2))\n- **window:** `windowBoundaries` now supports any `ObservableInput` ([#7088](https://github.com/reactivex/rxjs/issues/7088)) ([8c4347c](https://github.com/reactivex/rxjs/commit/8c4347c48f2432d7399c911d329fa74e0d6c6e8d))\n\n# [7.7.0](https://github.com/reactivex/rxjs/compare/7.6.0...7.7.0) (2022-12-15)\n\n### Features\n\n- **distinct:** `flush` argument now supports any `ObservableInput` ([#7081](https://github.com/reactivex/rxjs/issues/7081)) ([74c9ebd](https://github.com/reactivex/rxjs/commit/74c9ebd818113f9f25f1fb2b9fee4a0eac121ae0))\n- **repeatWhen:** `notifier` supports `ObservableInput` ([#7103](https://github.com/reactivex/rxjs/issues/7103)) ([8f1b976](https://github.com/reactivex/rxjs/commit/8f1b976125c55a5e884317c2b463fd019662e6af))\n- **retryWhen:** `notifier` now supports any `ObservableInput` ([#7105](https://github.com/reactivex/rxjs/issues/7105)) ([794f806](https://github.com/reactivex/rxjs/commit/794f8064cf8fe754e9dfebeee0ffef0ac1562252))\n- **sample:** `notifier` now supports any `ObservableInput` ([#7104](https://github.com/reactivex/rxjs/issues/7104)) ([b18c2eb](https://github.com/reactivex/rxjs/commit/b18c2eb2bc8dc1a717c927f998028316eec83937))\n\n# [7.6.0](https://github.com/reactivex/rxjs/compare/7.5.7...7.6.0) (2022-12-03)\n\n### Bug Fixes\n\n- **schedulers:** no longer cause TypeScript build failures when Node types aren't included ([c1a07b7](https://github.com/reactivex/rxjs/commit/c1a07b71ac050ab36b371ff7f18dc9a924fffc9f))\n- **types:** Improved subscribe and tap type overloads ([#6718](https://github.com/reactivex/rxjs/issues/6718)) ([af1a9f4](https://github.com/reactivex/rxjs/commit/af1a9f446a860883abaa36ace21345dc923e7e53)), closes [#6717](https://github.com/reactivex/rxjs/issues/6717)\n\n### Features\n\n- **onErrorResumeNextWith:** renamed `onErrorResumeNext` and exported from the top level. (`onErrorResumeNext` operator is stil available, but deprecated) ([#6755](https://github.com/reactivex/rxjs/issues/6755)) ([51e3b2c](https://github.com/reactivex/rxjs/commit/51e3b2c8ec28b5d30bca4c63ad69ce6942c2cdcc))\n\n## [7.5.7](https://github.com/reactivex/rxjs/compare/7.5.6...7.5.7) (2022-09-25)\n\n### Bug Fixes\n\n- **schedulers:** improve performance of animationFrameScheduler and asapScheduler ([#7059](https://github.com/reactivex/rxjs/issues/7059)) ([c93aa60](https://github.com/reactivex/rxjs/commit/c93aa60e9f073297d959fa1fff9323e48872d47e)), closes [#7017](https://github.com/reactivex/rxjs/issues/7017), related to [#7018](https://github.com/reactivex/rxjs/issues/7018) and [#6674](https://github.com/reactivex/rxjs/issues/6674)\n\n### Performance Improvements\n\n- **animationFrames:** uses fewer Subscription instances ([#7060](https://github.com/reactivex/rxjs/issues/7060)) ([2d57b38](https://github.com/reactivex/rxjs/commit/2d57b38ec9f7ada838ee130ab75cd795b156c182)), closes [#7018](https://github.com/reactivex/rxjs/issues/7018)\n\n## [7.5.6](https://github.com/reactivex/rxjs/compare/7.5.5...7.5.6) (2022-07-11)\n\n### Bug Fixes\n\n- **share:** No longer results in a bad-state observable in an edge case where a synchronous source was shared and refCounted, and the result is subscribed to twice in a row synchronously. ([#7005](https://github.com/reactivex/rxjs/issues/7005)) ([5d4c1d9](https://github.com/reactivex/rxjs/commit/5d4c1d9a37b1347217223adb0d9e166fd85f67a9))\n- **share & connect:** `share` and `connect` no longer bundle scheduling code by default ([#6873](https://github.com/reactivex/rxjs/issues/6873)) ([9948dc2](https://github.com/reactivex/rxjs/commit/9948dc2f5577eaa4013de234f3552508918518c7)), closes [#6872](https://github.com/reactivex/rxjs/issues/6872)\n- **exhaustAll:** Result will now complete properly when flattening all synchronous observables. ([#6911](https://github.com/reactivex/rxjs/issues/6911)) ([3c1c6b8](https://github.com/reactivex/rxjs/commit/3c1c6b8303028eebc7af31cfc5e5bad42a5b2da4)), closes [#6910](https://github.com/reactivex/rxjs/issues/6910)\n- **TypeScript:** Now compatible with TypeScript 4.6 type checks ([#6895](https://github.com/reactivex/rxjs/issues/6895)) ([fce9aa1](https://github.com/reactivex/rxjs/commit/fce9aa12931796892673581761bba1f7ceafabff))\n\n## [7.5.5](https://github.com/reactivex/rxjs/compare/7.5.4...7.5.5) (2022-03-08)\n\n### Bug Fixes\n\n- **package:** add types to exports ([#6802](https://github.com/reactivex/rxjs/issues/6802)) ([3750f75](https://github.com/reactivex/rxjs/commit/3750f75104bb82d870c53c0605c942e41245d79c))\n- **package:** add `require` export condition ([#6821](https://github.com/reactivex/rxjs/issues/6821)) ([c8955e4](https://github.com/reactivex/rxjs/commit/c8955e4c6a972135030fdfddc18a7a48337ae9c7))\n- **timeout:** no longer will timeout when receiving the first value synchronously ([#6865](https://github.com/reactivex/rxjs/issues/6865)) ([2330c96](https://github.com/reactivex/rxjs/commit/2330c9660b20f2e0cda0c4eeb36bb582b4a85186)), closes [#6862](https://github.com/reactivex/rxjs/issues/6862)\n\n### Performance Improvements\n\n- Don't clone observers unless you have to ([#6842](https://github.com/reactivex/rxjs/issues/6842)) ([3289d20](https://github.com/reactivex/rxjs/commit/3289d20ddc3a84d2aede8e3ab9962a8ef5d43c83))\n\n## [7.5.4](https://github.com/reactivex/rxjs/compare/7.5.3...7.5.4) (2022-02-09)\n\n### Performance Improvements\n\n- removed code that would `bind` functions passed with observers to `subscribe`. ([#6815](https://github.com/reactivex/rxjs/issues/6815)) ([fb375a0](https://github.com/reactivex/rxjs/commit/fb375a0c5befd6852cd63d3c310448e42fa9580e)), closes [#6783](https://github.com/reactivex/rxjs/issues/6783)\n\n## [7.5.3](https://github.com/reactivex/rxjs/compare/7.5.2...7.5.3) (2022-02-08)\n\n### Bug Fixes\n\n- **subscribe:** allow interop with Monio and other libraries that patch function bind ([0ab91eb](https://github.com/reactivex/rxjs/commit/0ab91eb4c1da914efbf03a2732629914cd3398dc)), closes [#6783](https://github.com/reactivex/rxjs/issues/6783)\n\n## [7.5.2](https://github.com/reactivex/rxjs/compare/7.5.1...7.5.2) (2022-01-11)\n\n### Bug Fixes\n\n- operators that ignore input values now use `unknown` rather than `any`, which should resolve issues with eslint no-unsafe-argument ([#6738](https://github.com/reactivex/rxjs/issues/6738)) ([67cb317](https://github.com/reactivex/rxjs/commit/67cb317a7a6b9fdbd3d2e8fdbc2ac9ac7e57179c)), closes [#6536](https://github.com/reactivex/rxjs/issues/6536)\n- **ajax:** crossDomain flag deprecated and properly reported to consumers ([#6710](https://github.com/reactivex/rxjs/issues/6710)) ([7fd0575](https://github.com/reactivex/rxjs/commit/7fd05756c595dddb288b732b00a90fcfb2a9080a)), closes [#6663](https://github.com/reactivex/rxjs/issues/6663)\n\n## [7.5.1](https://github.com/reactivex/rxjs/compare/7.5.0...7.5.1) (2021-12-28)\n\n### Bug Fixes\n\n- export supporting interfaces from top-level `rxjs` site. ([#6733](https://github.com/reactivex/rxjs/issues/6733)) ([299a1e1](https://github.com/reactivex/rxjs/commit/299a1e16f725edfc2e333c430e3a7dfc75dd94e7))\n\n# [7.5.0](https://github.com/reactivex/rxjs/compare/7.4.0...7.5.0) (2021-12-27)\n\n### Bug Fixes\n\n- **takeWhile:** Now returns proper types when passed a `Boolean` constructor. ([#6633](https://github.com/reactivex/rxjs/issues/6633)) ([081ca2b](https://github.com/reactivex/rxjs/commit/081ca2ba7290aa3084c1477a6d4bcc573bf478f6))\n- **forEach:** properly unsubs after error in next handler ([#6677](https://github.com/reactivex/rxjs/issues/6677)) ([b9ab67d](https://github.com/reactivex/rxjs/commit/b9ab67d21ca9d227fcd1123bf80ab87ca9296af9)), closes [#6676](https://github.com/reactivex/rxjs/issues/6676)\n- **WebSocketSubject:** handle slow WebSocket close ([#6708](https://github.com/reactivex/rxjs/issues/6708)) ([8cb201c](https://github.com/reactivex/rxjs/commit/8cb201cd42dd751b4185b94fe2d36c6bfda02fe2)), closes [#4650](https://github.com/reactivex/rxjs/issues/4650) [#3935](https://github.com/reactivex/rxjs/issues/3935)\n- RxJS now supports tslib 2.x, rather than just 2.1.x ([#6692](https://github.com/reactivex/rxjs/issues/6692)) ([0b2495f](https://github.com/reactivex/rxjs/commit/0b2495f72e76627fdd19dd7a670dd74847d6449c)), closes [#6689](https://github.com/reactivex/rxjs/issues/6689)\n- schedulers will no longer error while rescheduling and unsubscribing during flushes ([e35f589](https://github.com/reactivex/rxjs/commit/e35f589e2ca10ab2d2d69f7e9fe60727edc4c53d)), closes [#6672](https://github.com/reactivex/rxjs/issues/6672)\n\n### Features\n\n- **repeat:** now has configurable delay ([#6640](https://github.com/reactivex/rxjs/issues/6640)) ([6b7a534](https://github.com/reactivex/rxjs/commit/6b7a534f579f95f97f47eff74bdea9991ee85712))\n\n# [7.4.0](https://github.com/reactivex/rxjs/compare/7.3.1...7.4.0) (2021-10-06)\n\n### Features\n\n- Add es2015 entries to the exports declaration to support Angular ([#6614](https://github.com/reactivex/rxjs/issues/6614)) ([268777b](https://github.com/reactivex/rxjs/commit/268777bc3a4fd0cf76882683b51809771741ddc3)), closes [/github.com/ReactiveX/rxjs/pull/6613#discussion_r716958551](https://github.com//github.com/ReactiveX/rxjs/pull/6613/issues/discussion_r716958551)\n\n## [7.3.1](https://github.com/reactivex/rxjs/compare/7.3.0...7.3.1) (2021-10-01)\n\n### Bug Fixes\n\n- **Schedulers:** Throwing a falsy error in a scheduled function no longer results in strange error objects. ([#6594](https://github.com/reactivex/rxjs/issues/6594)) ([c70fcc0](https://github.com/reactivex/rxjs/commit/c70fcc02b4b737709aba559bf36b030a47902ee4))\n- scheduling with Rx-provided schedulers will no longer leak action references ([#6562](https://github.com/reactivex/rxjs/issues/6562)) ([ff5a748](https://github.com/reactivex/rxjs/commit/ff5a748b31ee73a6517e2f4220c920c73fbdd1fc)), closes [#6561](https://github.com/reactivex/rxjs/issues/6561)\n- **forkJoin:** now finalizes sources before emitting ([#6546](https://github.com/reactivex/rxjs/issues/6546)) ([c52ff2e](https://github.com/reactivex/rxjs/commit/c52ff2e3aae19cd0877adb63182c03b79427de96)), closes [#4914](https://github.com/reactivex/rxjs/issues/4914)\n- **observeOn:** release action references on teardown ([321d205](https://github.com/reactivex/rxjs/commit/321d2052696a7c366786c1ef3be7ad2a98a55f62))\n- **types:** update schedule signature overload ([c61e57c](https://github.com/reactivex/rxjs/commit/c61e57c9c64a1525d034aea641f1b846737e1eee))\n\n# [7.3.0](https://github.com/reactivex/rxjs/compare/7.2.0...7.3.0) (2021-07-28)\n\n### Bug Fixes\n\n- Expose `Connectable`, the return type of `connectable` ([#6531](https://github.com/reactivex/rxjs/issues/6531)) ([69f5bfa](https://github.com/reactivex/rxjs/commit/69f5bfae0eb2880a3d5cfb34db3a182182b325de)), closes [#6529](https://github.com/reactivex/rxjs/issues/6529)\n- **AsyncSubject:** properly emits values during reentrant subscriptions ([#6522](https://github.com/reactivex/rxjs/issues/6522)) ([dd8bdf3](https://github.com/reactivex/rxjs/commit/dd8bdf3b18b596155b66029ef16ebabf989360c5)), closes [#6520](https://github.com/reactivex/rxjs/issues/6520)\n\n### Features\n\n- **retry:** Now supports configurable delay as a named argument ([#6421](https://github.com/reactivex/rxjs/issues/6421)) ([5f69795](https://github.com/reactivex/rxjs/commit/5f69795f4be035499cf223bf9a3d7352c4975291))\n- **tap:** Now supports subscribe, unsubscribe, and finalize handlers ([#6527](https://github.com/reactivex/rxjs/issues/6527)) ([eb26cbc](https://github.com/reactivex/rxjs/commit/eb26cbc4488c9953cdde565b598b1dbdeeeee9ea))\n\n# [7.2.0](https://github.com/reactivex/rxjs/compare/7.1.0...7.2.0) (2021-07-05)\n\n### Bug Fixes\n\n- **debounceTime:** unschedule dangling task on unsubscribe before complete ([#6464](https://github.com/reactivex/rxjs/issues/6464)) ([7ab0a4c](https://github.com/reactivex/rxjs/commit/7ab0a4c649b1b54e763a726c4ffdc183b0b45b23))\n- **fromEvent:** Types now properly infer when resultSelector is provided ([#6447](https://github.com/reactivex/rxjs/issues/6447)) ([39b9d81](https://github.com/reactivex/rxjs/commit/39b9d818ef6ea033dc8e53800e3a220d56c76b4a))\n\n### Features\n\n- Operators are all exported at the top level, from \"rxjs\". From here on out, we encourage top-level imports with RxJS. Importing from `rxjs/operators` will be deprecated soon. ([#6488](https://github.com/reactivex/rxjs/issues/6488)) ([512adc2](https://github.com/reactivex/rxjs/commit/512adc25f350660113275d8277d16b7f3eec1d49)), closes [#6242](https://github.com/reactivex/rxjs/issues/6242)\n\n# [7.1.0](https://github.com/reactivex/rxjs/compare/7.0.1...7.1.0) (2021-05-21)\n\n### Bug Fixes\n\n- returned operator functions from multicast operators `share`, `publish`, `publishReplay` are now referentially transparent. Meaning if you take the result of calling `publishReplay(3)` and pass it to more than one observable's `pipe` method, it will behave the same in each case, rather than having a cumulative effect, which was a regression introduced sometime in version 6. If you required this broken behavior, there is a workaround posted [here](https://github.com/ReactiveX/rxjs/pull/6410#issuecomment-846087374) ([#6410](https://github.com/reactivex/rxjs/issues/6410)) ([e2f2e51](https://github.com/reactivex/rxjs/commit/e2f2e516514bdeb76229e69c639f10f21bccafad)), closes [/github.com/ReactiveX/rxjs/pull/6410#issuecomment-846087374](https://github.com//github.com/ReactiveX/rxjs/pull/6410/issues/issuecomment-846087374) [#5411](https://github.com/reactivex/rxjs/issues/5411)\n\n### Features\n\n- All subjects now have an `observed` property. This will allow users to check whether a subject has current subscribers without us allowing access to the `observers` array, which is going to be made private in future versions. ([#6405](https://github.com/reactivex/rxjs/issues/6405)) ([f47425d](https://github.com/reactivex/rxjs/commit/f47425d349475231c0f3542bb6ecef16a63e933a))\n- **groupBy:** Support named arguments, support ObservableInputs for duration selector ([#5679](https://github.com/reactivex/rxjs/issues/5679)) ([7a99397](https://github.com/reactivex/rxjs/commit/7a9939773802c4f7948c6d868a8f75facdea9f37))\n- **share:** use another observable to control resets ([#6169](https://github.com/reactivex/rxjs/issues/6169)) ([12c3716](https://github.com/reactivex/rxjs/commit/12c3716cecbf01f353c980488bf18845177b37b6))\n\n## [7.0.1](https://github.com/reactivex/rxjs/compare/7.0.0...7.0.1) (2021-05-12)\n\n### Bug Fixes\n\n- **bindCallback:** resulting function now recreated underlying Subject and is reusable once again. ([#6369](https://github.com/reactivex/rxjs/issues/6369)) ([abf2bc1](https://github.com/reactivex/rxjs/commit/abf2bc13e38406717127159c8c373b910223b562))\n- **retry:** properly handles retry counts smaller than `1`. ([#6359](https://github.com/reactivex/rxjs/issues/6359)) ([e797bd7](https://github.com/reactivex/rxjs/commit/e797bd70b1368e189df00d697504304a3a5ef1a8))\n- **share:** properly closes synchronous \"firehose\" sources. ([#6370](https://github.com/reactivex/rxjs/issues/6370)) ([2271a91](https://github.com/reactivex/rxjs/commit/2271a9180131a0becdbf789c1429ef741ace4b2f))\n- Observable teardowns now properly called if `useDeprecatedSynchronousErrorHandling` is `true`. ([#6365](https://github.com/reactivex/rxjs/issues/6365)) ([e19e104](https://github.com/reactivex/rxjs/commit/e19e104d011233d83bc10c37f1ee0b3ac6e15612)), closes [#6364](https://github.com/reactivex/rxjs/issues/6364)\n- **Subscription:** properly release parent subscriptions when unsubscribed. ([#6352](https://github.com/reactivex/rxjs/issues/6352)) ([88331d2](https://github.com/reactivex/rxjs/commit/88331d2ecdcf0f81a0712b315ed810d4da7d4b97)), closes [#6351](https://github.com/reactivex/rxjs/issues/6351) [#6351](https://github.com/reactivex/rxjs/issues/6351)\n- **node**: do not reference DOM-related imports to assist in node usage. ([#6305](https://github.com/reactivex/rxjs/issues/6305)) ([b24818e](https://github.com/reactivex/rxjs/commit/b24818e96775045c7485932bf33349471e8f1363)), closes [#6297](https://github.com/reactivex/rxjs/issues/6297)\n\n# [7.0.0](https://github.com/reactivex/rxjs/compare/7.0.0-rc.3...7.0.0) (2021-04-29)\n\n### Bug Fixes\n\n- VS code will now properly auto-import operators, et al ([#6276](https://github.com/reactivex/rxjs/issues/6276)) ([f43c728](https://github.com/reactivex/rxjs/commit/f43c72815f9ebe5ee3a8ed11513be0f541c9517d)), closes [#6067](https://github.com/reactivex/rxjs/issues/6067)\n- **AjaxResponse:** add stricter `type` (`AjaxResponseType`) ([#6279](https://github.com/reactivex/rxjs/issues/6279)) ([839e192](https://github.com/reactivex/rxjs/commit/839e192b7d826d833d7ce941be97c3735bd19c0a))\n\n# [7.0.0-rc.3](https://github.com/reactivex/rxjs/compare/7.0.0-rc.2...7.0.0-rc.3) (2021-04-28)\n\n### Bug Fixes\n\n- finalize behaves well with useDeprecatedSynchronousErrorHandling ([#6251](https://github.com/reactivex/rxjs/issues/6251)) ([e4bed2a](https://github.com/reactivex/rxjs/commit/e4bed2a2bad994f05a39246707d4f203412cebbd)), closes [#6250](https://github.com/reactivex/rxjs/issues/6250)\n- resolve run-time errors when using deprecated sync error handling ([#6272](https://github.com/reactivex/rxjs/issues/6272)) ([35daaf7](https://github.com/reactivex/rxjs/commit/35daaf77d3a9a909a7ec22c362c97ac42a597f79)), closes [#6271](https://github.com/reactivex/rxjs/issues/6271)\n- resolve issue that made users unable to assert `instanceof AjaxError`. ([#6275](https://github.com/reactivex/rxjs/issues/6275)) ([a7c2d29](https://github.com/reactivex/rxjs/commit/a7c2d297ad6b2f405ac312b38f6360e9a645d890))\n\n### Features\n\n- add config object to connectable ([#6267](https://github.com/reactivex/rxjs/issues/6267)) ([4d98b40](https://github.com/reactivex/rxjs/commit/4d98b40f969d5f55381f9a178ef3c18e6850cf47))\n\n### BREAKING CHANGES\n\n- Our very new creation function, `connectable`, now takes a configuration object instead of just the `Subject` instance. This was necessary to make sure it covered all use cases for what we were trying to replace in the deprecated multicasting operators. Apologies for the late-in-the-game change, but we know it's not widely used yet (it's new in v7), and we want to get it right.\n\n# [7.0.0-rc.2](https://github.com/reactivex/rxjs/compare/7.0.0-rc.1...7.0.0-rc.2) (2021-04-20)\n\n### Bug Fixes\n\n- **webSocket:** return the correct type for `WebSocketSubject` `multiplex` method([#6232](https://github.com/reactivex/rxjs/issues/6232)) ([33383b8](https://github.com/reactivex/rxjs/commit/33383b884d895fa77866362b8b00fd2e2c3597e6))\n\n### Reverts\n\n- Revert \"chore: Add typesVersions to package.json (#6229)\" (#6241) ([304f3a7](https://github.com/reactivex/rxjs/commit/304f3a73e67871f9b37f39675e503174d3dcc23a)), closes [#6229](https://github.com/reactivex/rxjs/issues/6229) [#6241](https://github.com/reactivex/rxjs/issues/6241)\n\n# [7.0.0-rc.1](https://github.com/reactivex/rxjs/compare/7.0.0-rc.0...7.0.0-rc.1) (2021-04-19)\n\n### Bug Fixes\n\n- **TypeScript:** Add typesVersions definition to package.json in order to help VS Code find automatic imports. ([#6067](https://github.com/reactivex/rxjs/issues/6067)) ([659a623](https://github.com/reactivex/rxjs/commit/659a623c94bd6b210e9beb6bb6061be540b05538))\n\n# [7.0.0-rc.0](https://github.com/reactivex/rxjs/compare/7.0.0-beta.15...7.0.0-rc.0) (2021-04-19)\n\n### Bug Fixes\n\n- **symbol:** revert unique symbol in [#5874](https://github.com/reactivex/rxjs/issues/5874) ([#6224](https://github.com/reactivex/rxjs/issues/6224)) ([3c49429](https://github.com/reactivex/rxjs/commit/3c49429fadc31ebaddd143d4412907edc50e32be)), closes [#5919](https://github.com/reactivex/rxjs/issues/5919) [#6178](https://github.com/reactivex/rxjs/issues/6178) [#6175](https://github.com/reactivex/rxjs/issues/6175)\n- forkJoin/combineLatest return Observable<unknown> if passed any ([#6227](https://github.com/reactivex/rxjs/issues/6227)) ([ce0a2fa](https://github.com/reactivex/rxjs/commit/ce0a2fa975e7c08de2bbf893010f2c25c090b1ca)), closes [#6226](https://github.com/reactivex/rxjs/issues/6226)\n- **fromEvent:** match targets properly; fix result selector type ([#6208](https://github.com/reactivex/rxjs/issues/6208)) ([8412c73](https://github.com/reactivex/rxjs/commit/8412c739bb47cc45ec3f38327115301b4fcc0118))\n- **merge:** single array is not an array of sources ([#6211](https://github.com/reactivex/rxjs/issues/6211)) ([4e900dc](https://github.com/reactivex/rxjs/commit/4e900dc745b5fbd7659b104c49fb0fce4ae84707))\n- **pipe:** Ensure that `unknown` is inferred for 9+ arguments. ([#6212](https://github.com/reactivex/rxjs/issues/6212)) ([6fa819b](https://github.com/reactivex/rxjs/commit/6fa819beb91ba99dadd6262d6c13f7ddfd9470c5))\n\n### Features\n\n- add (optional) defaultValue configuration to firstValueFrom and lastValueFrom ([#6204](https://github.com/reactivex/rxjs/issues/6204)) ([df51b04](https://github.com/reactivex/rxjs/commit/df51b04d7ec68a72b3a4b0d69c3bb29264c72611))\n\n# [7.0.0-beta.15](https://github.com/reactivex/rxjs/compare/7.0.0-beta.14...7.0.0-beta.15) (2021-03-31)\n\n### Bug Fixes\n\n- **esm:** duplicate directory in export path ([#6194](https://github.com/reactivex/rxjs/issues/6194)) ([aa41462](https://github.com/reactivex/rxjs/commit/aa4146288ec6542754f41ffd260fa4d6936a4d22))\n\n# [7.0.0-beta.14](https://github.com/reactivex/rxjs/compare/7.0.0-beta.13...7.0.0-beta.14) (2021-03-30)\n\n### Bug Fixes\n\n- **share:** No longer throws errors for reentrant observables ([#6151](https://github.com/reactivex/rxjs/issues/6151)) ([fc728cd](https://github.com/reactivex/rxjs/commit/fc728cdf2f395620cca347602e66f3d173c057b5)), closes [#6144](https://github.com/reactivex/rxjs/issues/6144)\n\n### Features\n\n- **ajax:** Now allows configuration of query string parameters, via a `params` option in the request configuration ([#6174](https://github.com/reactivex/rxjs/issues/6174)) ([980f4d4](https://github.com/reactivex/rxjs/commit/980f4d4bb6a3bc1513a4335ed124f4d11b93d251))\n- **esm:** Added exports within package.json to enable scoped package loading. ([#6192](https://github.com/reactivex/rxjs/issues/6192)) ([33a9f06](https://github.com/reactivex/rxjs/commit/33a9f06f2c59c8aef3bb583bdb7d61d08ab597a0)), closes [sveltejs/kit#612](https://github.com/sveltejs/kit/issues/612) [nodejs/node#27408](https://github.com/nodejs/node/issues/27408)\n- **ReadableStreams:** RxJS now supports conversions for ReadableStreams e.g. `from(readableStream)`. ([#6163](https://github.com/reactivex/rxjs/issues/6163)) ([19d6502](https://github.com/reactivex/rxjs/commit/19d650223cf0e1964e893baca19f264154422a7d))\n\n# [7.0.0-beta.13](https://github.com/reactivex/rxjs/compare/7.0.0-beta.12...7.0.0-beta.13) (2021-03-15)\n\n### Bug Fixes\n\n- **fromEvent:** throw if passed invalid target ([#6136](https://github.com/reactivex/rxjs/issues/6136)) ([317ba0c](https://github.com/reactivex/rxjs/commit/317ba0c9254e447385414e2c57e1d81760f88aa6)), closes [#5823](https://github.com/reactivex/rxjs/issues/5823)\n- remove misused type parameter from static pipe ([#6119](https://github.com/reactivex/rxjs/issues/6119)) ([8dc7d17](https://github.com/reactivex/rxjs/commit/8dc7d1793b4067d9eedc42b28d49ace8296672f5)), closes [#5557](https://github.com/reactivex/rxjs/issues/5557)\n- **Subscriber:** don't leak destination ([#6116](https://github.com/reactivex/rxjs/issues/6116)) ([5bba36c](https://github.com/reactivex/rxjs/commit/5bba36c6dde5b1b4b7e434104e716b233e5f402c))\n- **combineLatest:** POJO signature should match only ObservableInput values ([#6103](https://github.com/reactivex/rxjs/issues/6103)) ([d633494](https://github.com/reactivex/rxjs/commit/d633494dcdcabecda2c64ee84b8b6ceeaa2cb3d8))\n- **forkJoin:** POJO signature should match only ObservableInput values ([#6095](https://github.com/reactivex/rxjs/issues/6095)) ([566427e](https://github.com/reactivex/rxjs/commit/566427e88e597589f21b8cfb057dd13d5c61e0f2))\n- predicates that return `any` will now behave property with findIndex ([#6097](https://github.com/reactivex/rxjs/issues/6097)) ([c6f73d6](https://github.com/reactivex/rxjs/commit/c6f73d687e6b2142da4cab2a66047cc6dd123bf9))\n- remove misused type parameter from isObservable ([#6083](https://github.com/reactivex/rxjs/issues/6083)) ([f16b634](https://github.com/reactivex/rxjs/commit/f16b6341eef85009fc16de13623dc860d8d87778))\n- unhandled errors in observers correctly scheduled ([#6118](https://github.com/reactivex/rxjs/issues/6118)) ([c02ceb7](https://github.com/reactivex/rxjs/commit/c02ceb75e3de12fedbe270d5d323f508171f9cfd))\n- **defaultIfEmpty:** Allow `undefined` as an argument, require an argument ([4983760](https://github.com/reactivex/rxjs/commit/4983760b9179da27ddfcbf419ac5975cff9447c9)), closes [#6064](https://github.com/reactivex/rxjs/issues/6064)\n- **elementAt:** Allow `defaultValue` of `undefined`. ([5bc1b3e](https://github.com/reactivex/rxjs/commit/5bc1b3e22deceb5ea5f1882c0f92f061c1c4792d))\n- **first:** Allow `defaultValue` of `undefined`. ([62a6bbe](https://github.com/reactivex/rxjs/commit/62a6bbe1c3c51468c57e4e8f754c1c09da2db51b))\n- **last:** Allow `defaultValue` of `undefined`. ([ef3e721](https://github.com/reactivex/rxjs/commit/ef3e721f440132cf199f662b6a987349a0a70418))\n\n### Features\n\n- rename and alias `combineLatest` as `combineLatestAll` for consistency ([#6079](https://github.com/reactivex/rxjs/issues/6079)) ([42cee80](https://github.com/reactivex/rxjs/commit/42cee8045594779e8802b370c7244e6bbeeccaa3)), closes [#4590](https://github.com/reactivex/rxjs/issues/4590)\n\n### BREAKING CHANGES\n\n- **defaultIfEmpty:** `defaultIfEmpty` requires a value be passed. Will no longer convert `undefined` to `null` for no good reason.\n\n# [7.0.0-beta.12](https://github.com/reactivex/rxjs/compare/7.0.0-beta.11...7.0.0-beta.12) (2021-02-27)\n\n5bc8e3361 Fix/6052 ajax responseType should default to \"json\" (#6056)\n\n### Bug Fixes\n\n- **ajax**: `responseType` is now properly defaulted to `\"json\"` again. ([#6056](https://github.com/reactivex/rxjs/issues/6056)) ([5bc8e3361](https://github.com/reactivex/rxjs/commit/5bc8e3361))\n- Corner case resolved where an error thrown in a completion handler might delay teardown if it happened to be after a completing operator like `take`. ([#6062](https://github.com/reactivex/rxjs/issues/6062)) ([a2b9563](https://github.com/reactivex/rxjs/commit/a2b95631be882d2cf0fd87f43804d1ed699591d7))\n- **AsyncGenerator support**: consumed async generators are now properly finalized. ([#6062](https://github.com/reactivex/rxjs/issues/6062)) ([a2b9563](https://github.com/reactivex/rxjs/commit/a2b95631be882d2cf0fd87f43804d1ed699591d7)), closes [#5998](https://github.com/reactivex/rxjs/issues/5998)\n- **throttle:** no longer emits more than necessary in sync/sync trailing case ([#6059](https://github.com/reactivex/rxjs/issues/6059)) ([9da638a](https://github.com/reactivex/rxjs/commit/9da638a70d5abb862439ab4ee6a55368228811b0)), closes [#6058](https://github.com/reactivex/rxjs/issues/6058)\n\n# [7.0.0-beta.11](https://github.com/reactivex/rxjs/compare/7.0.0-beta.10...7.0.0-beta.11) (2021-02-24)\n\n### Bug Fixes\n\n- **ajax:** now errors on forced abort ([#6041](https://github.com/reactivex/rxjs/issues/6041)) ([d950921](https://github.com/reactivex/rxjs/commit/d95092143c1860eef054d27f2a1e50cb98b0ef58)), closes [#4251](https://github.com/reactivex/rxjs/issues/4251)\n- **buffer:** closingNotifier completion does not complete resulting observable ([358ae84](https://github.com/reactivex/rxjs/commit/358ae84cb9d59170216e7e0845c192eb3e1dcb51))\n- **buffer:** Remaining buffer will correctly be emitted on source close. ([0c667d5](https://github.com/reactivex/rxjs/commit/0c667d596d4a14002ffe9d4db319ed7cd7442ada)), closes [#3990](https://github.com/reactivex/rxjs/issues/3990) [#6035](https://github.com/reactivex/rxjs/issues/6035)\n- **debounceTime:** improves performance on quick succession of emits ([#6049](https://github.com/reactivex/rxjs/issues/6049)) ([9b70861](https://github.com/reactivex/rxjs/commit/9b708613cb7687647dc43c5e15b821e17ccc23ef))\n- **distinctUntilChanged:** Ensure reentrant code is compared properly ([#6014](https://github.com/reactivex/rxjs/issues/6014)) ([0ebcf17](https://github.com/reactivex/rxjs/commit/0ebcf1751a5359072b137ff197789570be4d7ead))\n- **share:** Ensure proper memory clean up ([1aa400a](https://github.com/reactivex/rxjs/commit/1aa400a5214325bc843a74602022a7912da20166))\n- **window:** final window stays open until source complete ([e8b05ef](https://github.com/reactivex/rxjs/commit/e8b05ef090d33af5b883e8020b8b7a3c4c8fa30e))\n- **concat/merge:** operators will finalize inners before moving to the next ([#6010](https://github.com/reactivex/rxjs/issues/6010)) ([5249a23](https://github.com/reactivex/rxjs/commit/5249a23b38bdda4639e9d669afd62a624172f89c)), closes [#3338](https://github.com/reactivex/rxjs/issues/3338)\n- predicates that return `any` will now behave property in TS ([#5987](https://github.com/reactivex/rxjs/issues/5987)) ([f5ae97d](https://github.com/reactivex/rxjs/commit/f5ae97d49a35b9f99ac59f79dd244a6d8d6c8a7b)), closes [#5986](https://github.com/reactivex/rxjs/issues/5986)\n- `publish` variants returning `ConnectableObservable` not properly utilizing lift ([#6003](https://github.com/reactivex/rxjs/issues/6003)) ([9acb950](https://github.com/reactivex/rxjs/commit/9acb950aec9efda95eb7492bfc47a33b71ef2e55))\n- Resolve issues with deprecated synchronous error handling and chained operators ([#5980](https://github.com/reactivex/rxjs/issues/5980)) ([0ad2802](https://github.com/reactivex/rxjs/commit/0ad2802a5aa9cd19875dc05c1cfb33f0b2f2c153)), closes [#5979](https://github.com/reactivex/rxjs/issues/5979)\n- `useDeprecatedSynchronousErrorThrowing` honored for flattened sync sources ([#5984](https://github.com/reactivex/rxjs/issues/5984)) ([abd95ce](https://github.com/reactivex/rxjs/commit/abd95ce1aa81a64de81c074a72570a8f0949cd0d)), closes [#5983](https://github.com/reactivex/rxjs/issues/5983)\n\n### Features\n\n- **ajax:** Add option for streaming progress ([#6001](https://github.com/reactivex/rxjs/issues/6001)) ([873e52d](https://github.com/reactivex/rxjs/commit/873e52d0d67b0f8470e6290c6fbc35c571464aaf))\n- **exhaustAll:** renamed `exhaust` to `exhaustAll` ([#5639](https://github.com/reactivex/rxjs/issues/5639)) ([701c7d4](https://github.com/reactivex/rxjs/commit/701c7d48cf1c3e60941692010254d6a27fc70980))\n\n### BREAKING CHANGES\n\n- **window:** The `windowBoundaries` observable no longer completes the result. It was only ever meant to notify of the window boundary. To get the same behavior as the old behavior, you would need to add an `endWith` and a `skipLast(1)` like so: `source$.pipe(window(notifier$.pipe(endWith(true))), skipLast(1))`.\n- **buffer:** Final buffered values will now always be emitted. To get the same behavior as the previous release, you can use `endWith` and `skipLast(1)`, like so: `source$.pipe(buffer(notifier$.pipe(endWith(true))), skipLast(1))`\n- **buffer:** `closingNotifier` completion no longer completes the result of `buffer`. If that is truly a desired behavior, then you should use `takeUntil`. Something like: `source$.pipe(buffer(notifier$), takeUntil(notifier$.pipe(ignoreElements(), endWith(true))))`, where `notifier$` is multicast, although there are many ways to compose this behavior.\n\n# [7.0.0-beta.10](https://github.com/reactivex/rxjs/compare/7.0.0-beta.9...7.0.0-beta.10) (2021-01-18)\n\n### Bug Fixes\n\n- **combineLatest:** Ensure `EMPTY` is returned if no observables are passed. ([#5963](https://github.com/reactivex/rxjs/issues/5963)) ([157c7e8](https://github.com/reactivex/rxjs/commit/157c7e8068befdfb26a9ba6ca770d38a66966ab5)), closes [#5962](https://github.com/reactivex/rxjs/issues/5962)\n- **fromEvent:** fixed HasEventTargetAddRemove to support EventTarget types ([#5945](https://github.com/reactivex/rxjs/issues/5945)) ([5f022d7](https://github.com/reactivex/rxjs/commit/5f022d784570684632e6fd5ae247fc259ee34c4b))\n\n### Features\n\n- **connect:** Adds new `connect` operator. ([9d53af0](https://github.com/reactivex/rxjs/commit/9d53af04103dbbb3bae40a4c511e2eebf117be09))\n- **connectable:** Adds `connectable` creation method ([f968a79](https://github.com/reactivex/rxjs/commit/f968a791c1b48f3100e925d700e8a0ecd69cc7e5))\n- **share:** Make `share` completely configurable. Also adds `SubjectLike`. ([2d600c7](https://github.com/reactivex/rxjs/commit/2d600c75c1065d862a2089dc1cd26007996b1c9d))\n- **TestScheduler:** add `expectObservable(a$).toEqual(b$)`. ([3372c72](https://github.com/reactivex/rxjs/commit/3372c72ed77a96e29a613a620e85f93bcf447920))\n\n### Performance Improvements\n\n- ensure same hidden class for OperatorSubscriber ([#5878](https://github.com/reactivex/rxjs/issues/5878)) ([246b449](https://github.com/reactivex/rxjs/commit/246b44902acde3a80e659f362969e6e2f8b19ef2))\n\n### BREAKING CHANGES\n\n- **share:** The TypeScript type `Subscribable` now only supports what is a valid return for `[Symbol.observable]()`.\n- **share:** The TypeScript type `Observer` no longer incorrectly has an optional `closed` property.\n\n# [7.0.0-beta.9](https://github.com/reactivex/rxjs/compare/7.0.0-beta.8...7.0.0-beta.9) (2020-12-07)\n\n### Bug Fixes\n\n- **audit:** don't signal on complete ([54cb428](https://github.com/reactivex/rxjs/commit/54cb42823ceec4db469f6155de67993b67ec85be))\n- **bufferToggle:** don't signal on complete ([65686ff](https://github.com/reactivex/rxjs/commit/65686ffd23f2d5a5145f2b7c33ea739e9bb808cd))\n- **bufferWhen:** don't signal on complete ([a2ba364](https://github.com/reactivex/rxjs/commit/a2ba364ede3c69c7703795a744f57122b49eac40))\n- **debounce:** don't signal on complete ([c919c68](https://github.com/reactivex/rxjs/commit/c919c684ad63724f0b55ccc4561f847773d945c8))\n- **delayWhen:** no longer emits if duration selector is empty ([#5769](https://github.com/reactivex/rxjs/issues/5769)) ([0872341](https://github.com/reactivex/rxjs/commit/087234146760ab2c67a04f9f0b5494a93affadb7)), closes [#3665](https://github.com/reactivex/rxjs/issues/3665)\n- **forkJoin:** ensure readonly array argument `forkJoin([a$, b$, c$] as const)` result is correct ([6baec53](https://github.com/reactivex/rxjs/commit/6baec536015253ac96827f2136ede17a324c634e))\n- **iif:** No longer allow accidental undefined arguments ([#5829](https://github.com/reactivex/rxjs/issues/5829)) ([23b98b4](https://github.com/reactivex/rxjs/commit/23b98b4e61c3284c81c07a8d810e8c3ec99ddfec))\n- **sample:** don't signal on complete ([95e0b70](https://github.com/reactivex/rxjs/commit/95e0b703caaf288657c7d722b9823458280be88b))\n- **Symbol.observable:** properly defined as a `unique symbol`. ([#5874](https://github.com/reactivex/rxjs/issues/5874)) ([374138e](https://github.com/reactivex/rxjs/commit/374138e09eb7ceb6f8da556c6c11dea1ba8cdbee)), closes [#5861](https://github.com/reactivex/rxjs/issues/5861) [#4415](https://github.com/reactivex/rxjs/issues/4415)\n- **throttle:** don't signal on complete ([4af0227](https://github.com/reactivex/rxjs/commit/4af022753d6dd4e94bcfcf0cc6082bb2312a3f02))\n- **windowToggle:** don't signal on complete ([9cb56c4](https://github.com/reactivex/rxjs/commit/9cb56c45de289ef5b062f33971996bdb8414cf99)), closes [#5838](https://github.com/reactivex/rxjs/issues/5838)\n- use empty object type in combineLatest/forkJoin sigs ([#5832](https://github.com/reactivex/rxjs/issues/5832)) ([22aaaa2](https://github.com/reactivex/rxjs/commit/22aaaa2f03dc721f850d9836243773c5310e85e8))\n- **withLatestFrom:** allow synchronous source ([#5828](https://github.com/reactivex/rxjs/issues/5828)) ([adbe65e](https://github.com/reactivex/rxjs/commit/adbe65e659bbf17f6ab20a9b30fcca0e4d76af9a))\n\n### Features\n\n- stopped notification handler ([#5750](https://github.com/reactivex/rxjs/issues/5750)) ([cfa267b](https://github.com/reactivex/rxjs/commit/cfa267bc0916ede09c8b14aedcdb69a791055fb6))\n- support emoji in marble diagrams ([#5907](https://github.com/reactivex/rxjs/issues/5907)) ([1b4608c](https://github.com/reactivex/rxjs/commit/1b4608cea3a9db96d7a629ad5de0e100145c180e))\n- **filter:** improve type inference for filter(Boolean) ([#5831](https://github.com/reactivex/rxjs/issues/5831)) ([d2658fa](https://github.com/reactivex/rxjs/commit/d2658fa32d7a86ac1e0796c452df258fc5470f67))\n\n### BREAKING CHANGES\n\n- **windowToggle:** the observable returned by the windowToggle operator's\n  closing selector must emit a next notification to close the window.\n  Complete notifications no longer close the window.\n- **bufferToggle:** the observable returned by the bufferToggle operator's\n  closing selector must emit a next notification to close the buffer.\n  Complete notifications no longer close the buffer.\n- **bufferWhen:** the observable returned by the bufferWhen operator's\n  closing selector must emit a next notification to close the buffer.\n  Complete notifications no longer close the buffer.\n- **debounce:** the observable returned by the debounce operator's\n  duration selector must emit a next notification to end the duration.\n  Complete notifications no longer end the duration.\n- **throttle:** the observable returned by the throttle operator's\n  duration selector must emit a next notification to end the duration.\n  Complete notifications no longer end the duration.\n- **sample:** the sample operator's notifier observable must emit a next notification to effect a sample. Complete notifications no longer effect a sample.\n- **audit:** the observable returned by the audit operator's duration selector must emit a next notification to end the duration. Complete notifications no longer end the duration.\n- **Symbol.observable:** `rxjs@7` is only compatible with `@types/node@14.14.3` or higher and `symbol-observable@3.0.0` and higher. Older versions of `@types/node` incorrectly defined `Symbol.observable` and will be in conflict with `rxjs` and `symbol-observable@3.0.0`.\n- **delayWhen:** `delayWhen` will no longer emit if the duration selector simply completes without a value. Notifiers must notify with a value, not a completion.\n- **iif:** `iif` will no longer allow result arguments that are `undefined`. This was a bad call pattern that was likely an error in most cases. If for some reason you are relying on this behavior, simply substitute `EMPTY` in place of the `undefined` argument. This ensures that the behavior was intentional and desired, rather than the result of an accidental `undefined` argument.\n\n# [7.0.0-beta.8](https://github.com/reactivex/rxjs/compare/7.0.0-beta.7...7.0.0-beta.8) (2020-10-15)\n\n### Bug Fixes\n\n- **audit, auditTime:** audit and auditTime emit last value after source completes ([#5799](https://github.com/reactivex/rxjs/issues/5799)) ([643bc85](https://github.com/reactivex/rxjs/commit/643bc85ab17a15a5d96f8bef8f08c3987d16eb40)), closes [#5730](https://github.com/reactivex/rxjs/issues/5730)\n- No longer allow invalid \"Subscribable\" type as valid observable source in `from` and others. ([258dddd](https://github.com/reactivex/rxjs/commit/258dddd8a392456e7d0b5ed9a7e294044f7c2518)), closes [#4532](https://github.com/reactivex/rxjs/issues/4532)\n- **bindNodeCallback:** ensure underlying function is not called twice during subscription ([#5780](https://github.com/reactivex/rxjs/issues/5780)) ([74aa4b2](https://github.com/reactivex/rxjs/commit/74aa4b2ea6685f475329a8b8ecbcebed9adae547))\n- **delay:** Now properly handles Date and negative numbers ([#5719](https://github.com/reactivex/rxjs/issues/5719)) ([868c02b](https://github.com/reactivex/rxjs/commit/868c02b47bb6f4ec4cd1d68b5b474731c470f27e)), closes [#5232](https://github.com/reactivex/rxjs/issues/5232)\n- **delayWhen:** only deprecates when subscriptionDelay presents ([#5797](https://github.com/reactivex/rxjs/issues/5797)) ([43d1731](https://github.com/reactivex/rxjs/commit/43d17311a521234375146029aa5c4709cb221344))\n- **every:** index properly increments in predicate ([5686f83](https://github.com/reactivex/rxjs/commit/5686f838fdc3da710d3f1eed1a6381791e3cc644))\n- **firstValueFrom:** now unsubscribes from source after first value is received ([#5813](https://github.com/reactivex/rxjs/issues/5813)) ([a321516](https://github.com/reactivex/rxjs/commit/a321516908aa036fb658395a372668a986af2504)), closes [#5811](https://github.com/reactivex/rxjs/issues/5811)\n- **from:** objects that are thennable that happen to have a subscribe method will no longer error. ([789d6e3](https://github.com/reactivex/rxjs/commit/789d6e3d851d57ab3b4488381f702120fd079737))\n- **fromEvent:** now properly types JQuery event targets ([b5aa15a](https://github.com/reactivex/rxjs/commit/b5aa15a7f58377310438aa5957e1516749d36219))\n- **mergeScan:** no longer emits state again upon completion. ([#5805](https://github.com/reactivex/rxjs/issues/5805)) ([68c2894](https://github.com/reactivex/rxjs/commit/68c28943b4d2c51068fecbc359a68ca6982307bf)), closes [#5372](https://github.com/reactivex/rxjs/issues/5372)\n- **throttle:** now supports synchronous duration selectors ([55e953e](https://github.com/reactivex/rxjs/commit/55e953e1f7b915e6c9072bf14a2febd5b8431393)), closes [#5658](https://github.com/reactivex/rxjs/issues/5658)\n- **throttle:** trailing values will now emit after source completes ([d5fd69c](https://github.com/reactivex/rxjs/commit/d5fd69c123d2232335563eea95c69c07576d079d))\n- **timeout:** allows synchronous observable as a source ([84c5c0b](https://github.com/reactivex/rxjs/commit/84c5c0b9d9e0d1791ac2f066c26e462e822d73e1)), closes [#5746](https://github.com/reactivex/rxjs/issues/5746)\n- **zip:** zip now accepts an array of arguments like its counterparts ([3123b67](https://github.com/reactivex/rxjs/commit/3123b670cca9b77919845333952ef70275ed6e90))\n\n### Code Refactoring\n\n- **count:** Base off of `reduce`. ([98a6d09](https://github.com/reactivex/rxjs/commit/98a6d0991df2a28366ab8f34098109a67257c235))\n- **pairs:** Based off of `from` and `Object.entries` ([#5775](https://github.com/reactivex/rxjs/issues/5775)) ([d39f830](https://github.com/reactivex/rxjs/commit/d39f8309c33917cb7070c7432fcd382395e4211e))\n\n### Features\n\n- **ajax:** now supports passing custom XSRF cookies in a custom header ([#5702](https://github.com/reactivex/rxjs/issues/5702)) ([1a2c2e4](https://github.com/reactivex/rxjs/commit/1a2c2e49482a460778ea92c7f6a92e58cc3e87bb)), closes [#4003](https://github.com/reactivex/rxjs/issues/4003)\n- **switchScan:** add switchScan() operator ([#4442](https://github.com/reactivex/rxjs/issues/4442)) ([73fa910](https://github.com/reactivex/rxjs/commit/73fa910cb62eccbccc4b4249f9b2606095704328)), closes [#2931](https://github.com/reactivex/rxjs/issues/2931)\n\n### BREAKING CHANGES\n\n- **mergeScan:** `mergeScan` will no longer emit its inner state again upon completion.\n- **pairs:** `pairs` will no longer function in IE without a polyfill for `Object.entries`. `pairs` itself is also deprecated in favor of users just using `from(Object.entries(obj))`.\n- **zip:** Zipping a single array will now have a different result. This is an extreme corner-case, because it is very unlikely that anyone would want to zip an array with nothing at all. The workaround would be to wrap the array in another array `zip([[1,2,3]])`. But again, that's pretty weird.\n- **count:** No longer passes `source` observable as a third argument to the predicate. That feature was rarely used, and of limited value. The workaround is to simply close over the source inside of the function if you need to access it in there.\n\n# [7.0.0-beta.7](https://github.com/reactivex/rxjs/compare/7.0.0-beta.5...7.0.0-beta.7) (2020-09-23)\n\n### Bug Fixes\n\n- **multicast:** and other publish variants will handle errors thrown in a selector appropriately ([bde8eda](https://github.com/reactivex/rxjs/commit/bde8eda09310463b05c5ec7d8a1dd1bafe9dba6f))\n\n### Code Refactoring\n\n- **tap:** reduce the size of the implementation ([1222d5a](https://github.com/reactivex/rxjs/commit/1222d5a68faa9d3f3c9ad8f8d5db1440971502bd))\n- **Subscriber:** Massively untangle Subscriber and SafeSubscriber ([07902ca](https://github.com/reactivex/rxjs/commit/07902ca99ee828521ce238826f10b55e25fbf554))\n\n### BREAKING CHANGES\n\n- **Subscriber:** `new Subscriber` no longer takes 0-3 arguments. To create a `Subscriber` with 0-3 arguments, use `Subscriber.create`. However, please note that there is little to no reason that you should be creating `Subscriber` references directly, and `Subscriber.create` and `new Subscriber` are both deprecated.\n\n# [7.0.0-beta.6](https://github.com/reactivex/rxjs/compare/7.0.0-beta.5...7.0.0-beta.6) (2020-09-23)\n\n### Bug Fixes\n\n- **AsyncSubject:** fixed reentrancy issue in complete ([9e00f11](https://github.com/reactivex/rxjs/commit/9e00f11e992d223edf1013d0a44c7cad41b72470)), closes [/github.com/ReactiveX/rxjs/pull/5729/files/30d429cf1b791db15c04a61f6a683e189b53fb3e#r492314703](https://github.com//github.com/ReactiveX/rxjs/pull/5729/files/30d429cf1b791db15c04a61f6a683e189b53fb3e/issues/r492314703)\n- **delay:** proper handling of absolute time (`Date`) passed as an argument ([8ae89b1](https://github.com/reactivex/rxjs/commit/8ae89b19a095541eb3dfe6e6d9f26367486c435e))\n- **fromEvent:** properly teardown for ArrayLike targets ([066de74](https://github.com/reactivex/rxjs/commit/066de7408810864891b9fd16e05c6c8b4ca88087))\n- **ReplaySubject:** no longer buffers additional values after it's already stopped ([#5696](https://github.com/reactivex/rxjs/issues/5696)) ([a08232b](https://github.com/reactivex/rxjs/commit/a08232be6dcab74e94cfbb17cc5138050bcd6ddb))\n- **scan:** proper indexes when seed is not supplied ([f93fb9c](https://github.com/reactivex/rxjs/commit/f93fb9c1fb7434c97e1d156370756159c5f2b077)), closes [#4348](https://github.com/reactivex/rxjs/issues/4348) [#3879](https://github.com/reactivex/rxjs/issues/3879)\n- **windowTime:** Passing no creation interval will now properly open new window when old one closes ([cbd0ac0](https://github.com/reactivex/rxjs/commit/cbd0ac0478730ec10172b57210e7d269d1ce62a2))\n\n### Code Refactoring\n\n- **Massive Size Reduction:** reduced the size of all operator implementations as well as other utilities and types ([#5729](https://github.com/reactivex/rxjs/issues/5729)) ([4d3fc23](https://github.com/reactivex/rxjs/commit/fc41e13a1b9a05fc242c1369b4f597c931bd28b5))\n\n### Features\n\n- **onUnhandledError:** configuration point added for unhandled errors ([#5681](https://github.com/reactivex/rxjs/issues/5681)) ([3485dd5](https://github.com/reactivex/rxjs/commit/3485dd5149b731e1103d2d070e3892735cbacef1))\n- **skipLast:** counts zero or less will mirror the source ([02e113b](https://github.com/reactivex/rxjs/commit/02e113b3345a9efe8f7c29f8b9c1c0d088aaf726))\n\n### BREAKING CHANGES\n\n- **skipLast:** `skipLast` will no longer error when passed a negative number, rather it will simply return the source, as though `0` was passed.\n- **map:** `thisArg` will now default to `undefined`. The previous default of `MapSubscriber` never made any sense. This will only affect code that calls map with a `function` and references `this` like so: `source.pipe(map(function () { console.log(this); }))`. There wasn't anything useful about doing this, so the breakage is expected to be very minimal. If anything we're no longer leaking an implementation detail.\n- **onUnhandledError:** Errors that occur during setup of an observable subscription after the subscription has emitted an error or completed will now throw in their own call stack. Before it would call `console.warn`. This is potentially breaking in edge cases for node applications, which may be configured to terminate for unhandled exceptions. In the unlikely event this affects you, you can configure the behavior to `console.warn` in the new configuration setting like so: `import { config } from 'rxjs'; config.onUnhandledError = (err) => console.warn(err);`\n\n# [7.0.0-beta.5](https://github.com/reactivex/rxjs/compare/7.0.0-beta.4...7.0.0-beta.5) (2020-09-03)\n\n### Bug Fixes\n\n- **ajax:** Allow XHR to perform body serialization and set content-type where possible ([d8657ed](https://github.com/reactivex/rxjs/commit/d8657ede8d9620ac2a7d61557e1f1d0e89b0b52a)), closes [#2837](https://github.com/reactivex/rxjs/issues/2837)\n- **ajax:** Do not mutate headers passed as arguments ([0d66ba4](https://github.com/reactivex/rxjs/commit/0d66ba458f07fba51cfc73440d01ef453c24cda7)), closes [#2801](https://github.com/reactivex/rxjs/issues/2801)\n- **bindCallback:** now emits errors that happen after callback ([2bddd31](https://github.com/reactivex/rxjs/commit/2bddd317fad962ad375de4a04dd528b02479ec5b))\n- **bindNodeCallback:** now emits errors that happen after callback ([edc28cf](https://github.com/reactivex/rxjs/commit/edc28cfd13ba3d7fadc24ea3c20ec8ca5a19064d))\n- **buffer:** Ensure notifier is subscribed after source ([#5654](https://github.com/reactivex/rxjs/issues/5654)) ([c088b0e](https://github.com/reactivex/rxjs/commit/c088b0eca904ab835b23df629d472003d6a82561)), closes [#2195](https://github.com/reactivex/rxjs/issues/2195) [#1754](https://github.com/reactivex/rxjs/issues/1754)\n- **catchError:** ensure proper handling of async return for synchronous source error handling ([#5627](https://github.com/reactivex/rxjs/issues/5627)) ([1b29d4b](https://github.com/reactivex/rxjs/commit/1b29d4b6d42e3d6b649f9f2c4bb718f343233d83)), closes [#5115](https://github.com/reactivex/rxjs/issues/5115)\n- **catchError:** inner synchronous observables will properly terminate ([#5655](https://github.com/reactivex/rxjs/issues/5655)) ([d3fd2fb](https://github.com/reactivex/rxjs/commit/d3fd2fb2bd619b79d0c4afebc3c10299afbca262))\n- **errors:** Custom RxJS errors now all have a call stack ([#5686](https://github.com/reactivex/rxjs/issues/5686)) ([9bb046c](https://github.com/reactivex/rxjs/commit/9bb046c744cc1f9438a805849b655946e5793936)), closes [#4250](https://github.com/reactivex/rxjs/issues/4250)\n- **onErrorResumeNext:** observables always finalized before moving to next source ([#5650](https://github.com/reactivex/rxjs/issues/5650)) ([ff68ad2](https://github.com/reactivex/rxjs/commit/ff68ad2caa3d275a23416984fab5570d3fed9458))\n- **package.json:** change homepage setting to official docs site. ([#5669](https://github.com/reactivex/rxjs/issues/5669)) ([e57c402](https://github.com/reactivex/rxjs/commit/e57c402b29288f61fe886b00e51817730bcb320b))\n- **repeat:** Ensure teardown happens between repeated synchronous obs… ([#5620](https://github.com/reactivex/rxjs/issues/5620)) ([0ca8a65](https://github.com/reactivex/rxjs/commit/0ca8a65b73aea93172366ca67207b53e3e3e77a8))\n- **repeatWhen:** Ensure teardown happens between repeat subscriptions ([#5625](https://github.com/reactivex/rxjs/issues/5625)) ([98356f4](https://github.com/reactivex/rxjs/commit/98356f4ebefdba1f5a14edbd96de1592694a01a8))\n- **retry:** Ensure teardown happens before resubscription with synchronous observables ([6f90597](https://github.com/reactivex/rxjs/commit/6f90597e51e038dabd8397b9f066ab4e3d344a5b)), closes [#5620](https://github.com/reactivex/rxjs/issues/5620)\n- **retryWhen:** Ensure subscription tears down between retries ([#5623](https://github.com/reactivex/rxjs/issues/5623)) ([6752af7](https://github.com/reactivex/rxjs/commit/6752af7c1839baf3cd7ed9d024499de61a2477e9))\n- **throttleTime:** ensure the spacing between throttles is always at least the throttled amount ([#5687](https://github.com/reactivex/rxjs/issues/5687)) ([ea84fc4](https://github.com/reactivex/rxjs/commit/ea84fc4dce84e32598701f79d9449be00a05352c)), closes [#3712](https://github.com/reactivex/rxjs/issues/3712) [#4864](https://github.com/reactivex/rxjs/issues/4864) [#2727](https://github.com/reactivex/rxjs/issues/2727) [#4727](https://github.com/reactivex/rxjs/issues/4727) [#4429](https://github.com/reactivex/rxjs/issues/4429)\n- **zip:** zip operators and functions are now able to zip all iterable sources ([#5688](https://github.com/reactivex/rxjs/issues/5688)) ([02c3a1b](https://github.com/reactivex/rxjs/commit/02c3a1b70c0e96b784a3c5c214c0f89c5ebdd696)), closes [#4304](https://github.com/reactivex/rxjs/issues/4304)\n- `switchMap` and `exhaustMap` behave correctly with re-entrant code. ([c289688](https://github.com/reactivex/rxjs/commit/c289688f5e1f33ec21306b4d2f5539dd19f963f2))\n- **webSocket:** close websocket connection attempt on unsubscribe ([e1a671c](https://github.com/reactivex/rxjs/commit/e1a671cbd7f5a6ce547ed9ee6ce98c22264500f4)), closes [#4446](https://github.com/reactivex/rxjs/issues/4446)\n\n### Code Refactoring\n\n- **ajax:** Use simple Observable ([17b9add](https://github.com/reactivex/rxjs/commit/17b9add03a90aec6e708a87c0fc387745f0b9df6))\n- **Subscriber:** remove \\_unsubscribeAndRecycle ([d879c3f](https://github.com/reactivex/rxjs/commit/d879c3f3ae4b1de5660d1613bb8b300e7194d581))\n- **VirtualTimeScheduler:** remove sortActions from public API ([#5657](https://github.com/reactivex/rxjs/issues/5657)) ([a468f88](https://github.com/reactivex/rxjs/commit/a468f881c8c02195b089889486d1a94fab2771e0))\n\n### Features\n\n- **combineLatest:** add N-args signature for observable inputs ([#5488](https://github.com/reactivex/rxjs/issues/5488)) ([fcc47e7](https://github.com/reactivex/rxjs/commit/fcc47e75a4c811199c5071144172f4d06ffc7c70))\n- **Subscription:** `add` no longer returns unnecessary Subscription reference ([#5656](https://github.com/reactivex/rxjs/issues/5656)) ([4de604e](https://github.com/reactivex/rxjs/commit/4de604ea66261f597af11918aec53cd94590b30f))\n- **Subscription:** `remove` will now remove any teardown by reference ([#5659](https://github.com/reactivex/rxjs/issues/5659)) ([1531152](https://github.com/reactivex/rxjs/commit/15311529fa1b880ed469b6c253cd0be7ff2f98a1))\n- **throwError:** now accepts a factory to create the error ([#5647](https://github.com/reactivex/rxjs/issues/5647)) ([dad270a](https://github.com/reactivex/rxjs/commit/dad270afcf496de74b4392024191715d7dbef4f5)), closes [#5617](https://github.com/reactivex/rxjs/issues/5617)\n- **useDeprecatedNextContext:** Puts deprecated next context behavior behind a flag ([dfdef5d](https://github.com/reactivex/rxjs/commit/dfdef5dcaf52363be59359786aef8bc733197b43))\n- support schedulers within run ([#5619](https://github.com/reactivex/rxjs/issues/5619)) ([c63de0d](https://github.com/reactivex/rxjs/commit/c63de0d380a923987aab587720473fad1d205d71))\n\n### Performance Improvements\n\n- **SafeSubscriber:** avoid using `Object.create` ([40a9e77](https://github.com/reactivex/rxjs/commit/40a9e77fe3d75df9161ad0093f54750b70f57245))\n\n### BREAKING CHANGES\n\n- **ajax:**\n  - `ajax` body serialization will now use default XHR behavior in all cases. If the body is a `Blob`, `ArrayBuffer`, any array buffer view (like a byte sequence, e.g. `Uint8Array`, etc), `FormData`, `URLSearchParams`, `string`, or `ReadableStream`, default handling is use. If the `body` is otherwise `typeof` `\"object\"`, then it will be converted to JSON via `JSON.stringify`, and the `Content-Type` header will be set to `application/json;charset=utf-8`. All other types will emit an error.\n  - The `Content-Type` header passed to `ajax` configuration no longer has any effect on the serialization behavior of the AJAX request.\n  - For TypeScript users, `AjaxRequest` is no longer the type that should be explicitly used to create an `ajax`. It is now `AjaxConfig`, although the two types are compatible, only `AjaxConfig` has `progressSubscriber` and `createXHR`.\n\n* **zip:** `zip` operators will no longer iterate provided iterables \"as needed\", instead the iterables will be treated as push-streams just like they would be everywhere else in RxJS. This means that passing an endless iterable will result in the thread locking up, as it will endlessly try to read from that iterable. This puts us in-line with all other Rx implementations. To work around this, it is probably best to use `map` or some combination of `map` and `zip`. For example, `zip(source$, iterator)` could be `source$.pipe(map(value => [value, iterator.next().value]))`.\n\n* **Subscription:** `add` no longer returns an unnecessary Subscription reference. This was done to prevent confusion caused by a legacy behavior. You can now add and remove functions and Subscriptions as teardowns to and from a `Subscription` using `add` and `remove` directly. Before this, `remove` only accepted subscriptions.\n\n* **RxJS Error types** Tests that are written with naive expectations against errors may fail now that errors have a proper `stack` property. In some testing frameworks, a deep equality check on two error instances will check the values in `stack`, which could be different.\n\n* **Undocumented Behaviors/APIs Removed**:\n\n  - `unsubscribe` no longer available via the `this` context of observer functions. To reenable, set `config.useDeprecatedNextContext = true` on the rxjs `config` found at `import { config } from 'rxjs';`. Note that enabling this will result in a performance penalty for all consumer subscriptions.\n  - Leaked implementation detail `_unsubscribeAndRecycle` of `Subscriber` has been removed. Just use new `Subscription` objects\n  - Removed an undocumented behavior where passing a negative count argument to `retry` would result in an observable that repeats forever.\n  - An undocumented behavior where passing a negative count argument to `repeat` would result in an observable that repeats forever.\n  - The static `sortActions` method on `VirtualTimeScheduler` is no longer publicly exposed by our TS types.\n\n* **throwError:** In an extreme corner case for usage, `throwError` is no longer able to emit a function as an error directly. If you need to push a function as an error, you will have to use the factory function to return the function like so: `throwError(() => functionToEmit)`, in other words `throwError(() => () => console.log('called later'))`.\n\n# [7.0.0-beta.4](https://github.com/reactivex/rxjs/compare/7.0.0-beta.1...7.0.0-beta.4) (2020-08-02)\n\n### Bug Fixes\n\n- **ajax:** Partial observers passed to `progressSubscriber` will no longer error ([25d279f](https://github.com/reactivex/rxjs/commit/25d279f0b45d07f39bfb87b19bc7e2279df8b542))\n- **ajax:** Unparsable responses will no longer prevent full AjaxError from being thrown ([605ee55](https://github.com/reactivex/rxjs/commit/605ee550e5efc266b5dc5d3a9756c7c3b3968a61))\n- **animationFrames:** emit the timestamp from the rAF's callback ([#5438](https://github.com/reactivex/rxjs/issues/5438)) ([c980ae6](https://github.com/reactivex/rxjs/commit/c980ae65ee1b585e8ed66a366eb534ac3e50c205))\n- Ensure unsubscriptions/teardowns on internal subscribers are idempotent ([#5465](https://github.com/reactivex/rxjs/issues/5465)) ([3e39749](https://github.com/reactivex/rxjs/commit/3e39749a58ca663c17f5f0354b0f27532fb6d319)), closes [#5464](https://github.com/reactivex/rxjs/issues/5464)\n- **timeout:** defer error creation until timeout occurs ([#5497](https://github.com/reactivex/rxjs/issues/5497)) ([3be9840](https://github.com/reactivex/rxjs/commit/3be98404fafd5a8de758deb4e0d103a7b60aa31e)), closes [#5491](https://github.com/reactivex/rxjs/issues/5491)\n\n### Code Refactoring\n\n- **ajax:** Drop support for IE10 and lower ([0eaadd6](https://github.com/reactivex/rxjs/commit/0eaadd60c716050f5e3701d513a028a9cd49085a))\n- **Observable:** Update property and method types ([#5572](https://github.com/reactivex/rxjs/issues/5572)) ([144b626](https://github.com/reactivex/rxjs/commit/144b626c3905640b4adeb2b97e722912eff1b264))\n\n### Features\n\n- **combineLatest:** support for observable dictionaries ([#5022](https://github.com/reactivex/rxjs/issues/5022)) ([#5363](https://github.com/reactivex/rxjs/issues/5363)) ([f5278aa](https://github.com/reactivex/rxjs/commit/f5278aa89ea164caf5cf10e77d7bd00eff26fc0f))\n- **TestScheduler:** add an animate \"run mode\" helper ([#5607](https://github.com/reactivex/rxjs/issues/5607)) ([edd6731](https://github.com/reactivex/rxjs/commit/edd67313814bfc32e8a5129d8049e4d4678cd35d))\n- **timeout:** One timeout to rule them all ([def1d34](https://github.com/reactivex/rxjs/commit/def1d346b43008bc413a3ac985e1611bbbf62003))\n\n### BREAKING CHANGES\n\n- **ajax:** In an extreme corner-case... If an error occurs, the responseType is `\"json\"`, we're in IE, and the `responseType` is not valid JSON, the `ajax` observable will no longer emit a syntax error, rather it will emit a full `AjaxError` with more details.\n- **ajax:** Ajax implementation drops support for IE10 and lower. This puts us in-line with other implementations and helps clean up code in this area\n- **Observable:** `lift` no longer exposed. It was _NEVER_ documented that end users of the library should be creating operators using `lift`. Lift has a [variety of issues](https://github.com/ReactiveX/rxjs/issues/5431) and was always an internal implementation detail of rxjs that might have been used by a few power users in the early days when it had the most value. The value of `lift`, originally, was that subclassed `Observable`s would compose through all operators that implemented lift. The reality is that feature is not widely known, used, or supported, and it was never documented as it was very experimental when it was first added. Until the end of v7, `lift` will remain on Observable. Standard JavaScript users will notice no difference. However, TypeScript users might see complaints about `lift` not being a member of observable. To workaround this issue there are two things you can do: 1. Rewrite your operators as [outlined in the documentation](https://rxjs.dev/guide/operators), such that they return `new Observable`. or 2. cast your observable as `any` and access `lift` that way. Method 1 is recommended if you do not want things to break when we move to version 8.\n\n# [7.0.0-beta.3](https://github.com/reactivex/rxjs/compare/7.0.0-beta.1...7.0.0-beta.3) (2020-07-30)\n\n### Bug Fixes\n\n- **perf:** Ensure unsubscriptions/teardowns on internal subscribers are idempotent ([#5465](https://github.com/reactivex/rxjs/issues/5465)) ([3e39749](https://github.com/reactivex/rxjs/commit/3e39749a58ca663c17f5f0354b0f27532fb6d319)), closes [#5464](https://github.com/reactivex/rxjs/issues/5464)\n- **timeout:** defer error creation until timeout occurs ([#5497](https://github.com/reactivex/rxjs/issues/5497)) ([3be9840](https://github.com/reactivex/rxjs/commit/3be98404fafd5a8de758deb4e0d103a7b60aa31e)), closes [#5491](https://github.com/reactivex/rxjs/issues/5491)\n\n### Code Refactoring\n\n- **perf:** Reduce memory pressure by no longer retaining outer values across the majority of operators. ([#5610](https://github.com/reactivex/rxjs/pull/5610)) ([bff1827](https://github.com/ReactiveX/rxjs/commit/bff18272dca23938a5f5b57cec6eb8d8be5bfddf))\n- **Observable:** Update property and method types ([#5572](https://github.com/reactivex/rxjs/issues/5572)) ([144b626](https://github.com/reactivex/rxjs/commit/144b626c3905640b4adeb2b97e722912eff1b264))\n\n### Features\n\n- **combineLatest:** support for observable dictionaries ([#5022](https://github.com/reactivex/rxjs/issues/5022)) ([#5363](https://github.com/reactivex/rxjs/issues/5363)) ([f5278aa](https://github.com/reactivex/rxjs/commit/f5278aa89ea164caf5cf10e77d7bd00eff26fc0f))\n\n### BREAKING CHANGES\n\n- **Observable:** `lift` no longer exposed. It was _never_ documented that end users of the library should be creating operators using `lift`. Lift has a [variety of issues](https://github.com/ReactiveX/rxjs/issues/5431) and was always an internal implementation detail of rxjs that might have been used by a few power users in the early days when it had the most value. The value of `lift`, originally, was that subclassed `Observable`s would compose through all operators that implemented lift. The reality is that feature is not widely known, used, or supported, and it was never documented as it was very experimental when it was first added. Until the end of v7, `lift` will remain on Observable. Standard JavaScript users will notice no difference. However, TypeScript users might see complaints about `lift` not being a member of observable. To workaround this issue there are two things you can do: 1. Rewrite your operators as [outlined in the documentation](https://rxjs.dev/guide/operators), such that they return `new Observable`. or 2. cast your observable as `any` and access `lift` that way. It is recommended that operators be implemented in terms of functions that return `(source: Observable<T>) => new Observable<R>(...)`, per the documentation/guide.\n\n# [7.0.0-beta.2](https://github.com/reactivex/rxjs/compare/7.0.0-beta.1...7.0.0-beta.2) (2020-07-03)\n\n### Bug Fixes\n\n- **dependencies:** Move accidental dependency on `typedoc` to dev-dependencies. ([#5566](https://github.com/reactivex/rxjs/issues/5566)) ([45702bf](https://github.com/ReactiveX/rxjs/commit/45702bf6cd1b4a150f47b2a1d273f1ee31ca2482))\n\n# [7.0.0-beta.1](https://github.com/reactivex/rxjs/compare/7.0.0-beta.0...7.0.0-beta.1) (2020-07-02)\n\n### Bug Fixes\n\n- **pluck:** operator breaks with null/undefined inputs. ([#5524](https://github.com/reactivex/rxjs/issues/5524)) ([c5f6550](https://github.com/reactivex/rxjs/commit/c5f65508505cf1f90560e6be76425e09c455bec3))\n- **shareReplay:** no longer misses synchronous values from source ([92452cc](https://github.com/reactivex/rxjs/commit/92452cc20021141aa0f047c7e5af569a413143e5))\n- **interop:** chain interop/safe subscriber unsubscriptions correctly ([#5472](https://github.com/reactivex/rxjs/issues/5472)) ([98ad0eb](https://github.com/reactivex/rxjs/commit/98ad0eba6bc079851b44951f3963e8aae0abf861)), closes [#5469](https://github.com/reactivex/rxjs/issues/5469) [#5311](https://github.com/reactivex/rxjs/issues/5311) [#2675](https://github.com/reactivex/rxjs/issues/2675)\n- **finalize:** chain subscriptions for interop with finalize ([#5239](https://github.com/reactivex/rxjs/issues/5239)) ([04ba662](https://github.com/reactivex/rxjs/commit/04ba6621fe9e09238e1796217d04107e52dd36d5)), closes [#5237](https://github.com/reactivex/rxjs/issues/5237) [#5237](https://github.com/reactivex/rxjs/issues/5237)\n- **animationFrameScheduler:** don't execute rescheduled animation frame and asap actions in flush ([#5399](https://github.com/reactivex/rxjs/issues/5399)) ([33c9c8c](https://github.com/reactivex/rxjs/commit/33c9c8cf7e247d4ad4d7318bfd02e8e5bedb0f40)), closes [#4972](https://github.com/reactivex/rxjs/issues/4972) [#5397](https://github.com/reactivex/rxjs/issues/5397)\n- **iterables:** errors thrown from iterables now properly propagated ([#5444](https://github.com/reactivex/rxjs/issues/5444)) ([75d4c2f](https://github.com/reactivex/rxjs/commit/75d4c2f33d2e2121b2a316849044ad17ab28dbaf))\n- **finalize:** callback will be called after the source observable is torn down. ([0d7b7c1](https://github.com/reactivex/rxjs/commit/0d7b7c14e34eed43fb2ad1386281800fa3ae8aec)), closes [#5357](https://github.com/reactivex/rxjs/issues/5357)\n- **Notification:** typing improvements ([#5478](https://github.com/reactivex/rxjs/issues/5478)) ([96868ac](https://github.com/reactivex/rxjs/commit/96868ac754c0147a9aa61182185f27224eb7f11a))\n- **TestScheduler:** support empty subscription marbles ([#5502](https://github.com/reactivex/rxjs/issues/5502)) ([e65696e](https://github.com/reactivex/rxjs/commit/e65696e2f7f7338659a873f6653026b33b9011a9)), closes [#5499](https://github.com/reactivex/rxjs/issues/5499)\n- **expand:** now works properly with asynchronous schedulers ([294b27e](https://github.com/reactivex/rxjs/commit/294b27eb6a96e8edee3af35e6aaaef50628376e4))\n- **subscribeOn:** allow Infinity as valid delay ([#5500](https://github.com/reactivex/rxjs/issues/5500)) ([cd7d649](https://github.com/reactivex/rxjs/commit/cd7d64901e82fd7fb5e8407f1f30828906fac420))\n- **Subject:** resolve issue where Subject constructor errantly allowed an argument ([#5476](https://github.com/reactivex/rxjs/issues/5476)) ([e1d35dc](https://github.com/reactivex/rxjs/commit/e1d35dc258edea0237ef49a31f7b34c058755969))\n- **Subject:** no default generic ([e678e81](https://github.com/reactivex/rxjs/commit/e678e81ba80f5bcc27b0e956295ce2fc8dfe4576))\n- **defer:** No longer allows `() => undefined` to observableFactory (#5449) ([1ae937a](https://github.com/reactivex/rxjs/commit/1ae937a8e594aef96b93313bb3c68ea910e6f528)), closes [#5449](https://github.com/reactivex/rxjs/issues/5449)\n- **single:** Corrected behavior for `single(() => false)` on empty observables. (#5325) ([27931bc](https://github.com/reactivex/rxjs/commit/27931bcfd2aa864e277d3e72128c57e807b28bb0)), closes [#5325](https://github.com/reactivex/rxjs/issues/5325)\n- **take/takeLast**: Properly assert number types at runtime (#5326) ([5efc474](https://github.com/reactivex/rxjs/commit/5efc474161c9196dbdf4803a9cc444a547067549)), closes [#5326](https://github.com/reactivex/rxjs/issues/5326)\n\n### Features\n\n- **Observable:** Remove async iteration ([#5492](https://github.com/reactivex/rxjs/issues/5492)) ([8f43e71](https://github.com/reactivex/rxjs/commit/8f43e71f5692119e57a7acc5817c146d0b288e8c))\n- **groupBy:** Add typeguards support for groupBy ([#5441](https://github.com/reactivex/rxjs/issues/5441)) ([da382da](https://github.com/reactivex/rxjs/commit/da382da4cdcc6e7ab1ffc6a499f4f7f5ea7de130))\n- **raceWith:** add raceWith, the renamed `race` operator ([#5303](https://github.com/reactivex/rxjs/issues/5303)) ([ca7f370](https://github.com/reactivex/rxjs/commit/ca7f370d8379f22526cfb17d40deff53e1358742))\n- **fetch:** add selector ([#5306](https://github.com/reactivex/rxjs/issues/5306)) ([99b5af1](https://github.com/reactivex/rxjs/commit/99b5af1af5d169d55d454ff8e27d88105cee4b6f)), closes [#4744](https://github.com/reactivex/rxjs/issues/4744)\n- **TimestampProvider:** Reduced scheduler footprint for default usage of shareReplay, timeInterval, and timestamp ([#4973](https://github.com/reactivex/rxjs/issues/4973)) ([b2e67e3](https://github.com/reactivex/rxjs/commit/b2e67e3139f0be1fb000ba42bb42c5ba60cc803a))\n\n### BREAKING CHANGES\n\n- `Notification.createNext(undefined)` will no longer return the exact same reference every time.\n- Type signatures tightened up around `Notification` and `dematerialize`, may uncover issues with invalid types passed to those operators.\n- Experimental support for `for await` as been removed. Use https://github.com/benlesh/rxjs-for-await instead.\n- `defer` no longer allows factories to return `void` or `undefined`. All factories passed to defer must return a proper `ObservableInput`, such as `Observable`, `Promise`, et al. To get the same behavior as you may have relied on previously, `return EMPTY` or `return of()` from the factory.\n- `single` operator will now throw for scenarios where values coming in are either not present, or do not match the provided predicate. Error types have thrown have also been updated, please check documentation for changes.\n- `take` and will now throw runtime error for arguments that are negative or NaN, this includes non-TS calls like `take()`.\n\n- `takeLast` now has runtime assertions that throw `TypeError`s for invalid arguments. Calling takeLast without arguments or with an argument that is `NaN` will throw a `TypeError`\n- `ReplaySubject` no longer schedules emissions when a scheduler is provided. If you need that behavior,\n  please compose in `observeOn` using `pipe`, for example: `new ReplaySubject(2, 3000).pipe(observeOn(asap))`\n\n- `timestamp` operator accepts a `TimestampProvider`, which is any object with a `now` method\n  that returns a number. This means pulling in less code for the use of the `timestamp` operator. This may cause\n  issues with `TestScheduler` run mode. (Issue here: https://github.com/ReactiveX/rxjs/issues/5553)\n\n# [7.0.0-beta.0](https://github.com/reactivex/rxjs/compare/7.0.0-alpha.1...7.0.0-beta.0) (2020-04-03)\n\n### Bug Fixes\n\n- **mergeMapTo:** remove redundant/unused generic ([#5299](https://github.com/reactivex/rxjs/issues/5299)) ([d67b7da](https://github.com/reactivex/rxjs/commit/d67b7dafbacb3aac8f4dd7f215fe2d2c602f0d36))\n- **ajax:** AjaxTimeoutErrorImpl extends AjaxError ([#5226](https://github.com/reactivex/rxjs/issues/5226)) ([a8da8dc](https://github.com/reactivex/rxjs/commit/a8da8dcc899342d3bb6d2d913247d9e734095287))\n- **delay:** emit complete notification as soon as possible ([63b8797](https://github.com/reactivex/rxjs/commit/63b8797fbeed09eb675ea64b0b83607cef1367a9)), closes [#4249](https://github.com/reactivex/rxjs/issues/4249)\n- **endWith:** will properly type N arguments ([#5246](https://github.com/reactivex/rxjs/issues/5246)) ([81ee1f7](https://github.com/reactivex/rxjs/commit/81ee1f72408854f4017615fe7949edf5dd50533b))\n- **fetch:** don't leak event listeners added to passed-in signals ([#5305](https://github.com/reactivex/rxjs/issues/5305)) ([d4d6c47](https://github.com/reactivex/rxjs/commit/d4d6c47d8abccc8cbe17e46192fc1eaa42d2d023))\n- **TestScheduler:** Subclassing TestScheduler needs RunHelpers ([#5138](https://github.com/reactivex/rxjs/issues/5138)) ([927d5d9](https://github.com/reactivex/rxjs/commit/927d5d90ab5f12a79cd50f7290b4f8df1e83ecfc))\n- **pipe:** Special handling for 0-arg case. ([#4936](https://github.com/reactivex/rxjs/issues/4936)) ([290fa51](https://github.com/reactivex/rxjs/commit/290fa51c44881f25f2fe4cf9885028396c7fd74c))\n- **pluck:** fix pluck's catch-all signature for better type safety ([#5192](https://github.com/reactivex/rxjs/issues/5192)) ([e0c5b7c](https://github.com/reactivex/rxjs/commit/e0c5b7c790bb9d99fa8bee26c805b5e70c1e456b))\n- **pluck:** param type now accepts number and symbol ([9697b69](https://github.com/reactivex/rxjs/commit/9697b695c23c3dcb614e6a70be63a94ffcd86ed9))\n- **startWith:** accepts N arguments and returns correct type ([#5247](https://github.com/reactivex/rxjs/issues/5247)) ([150ed8b](https://github.com/reactivex/rxjs/commit/150ed8b75909b0e0bb9dc8928287ebdc47e19c51))\n- **combineLatestWith:** and zipWith infer types from n-arguments ([#5257](https://github.com/reactivex/rxjs/issues/5257)) ([3e282a5](https://github.com/reactivex/rxjs/commit/3e282a58b1baf7aa03b17142f858bca09a542adf))\n- **race:** support N args in static race and ensure observable returned ([#5286](https://github.com/reactivex/rxjs/issues/5286)) ([6d901cb](https://github.com/reactivex/rxjs/commit/6d901cbb0c0f2aa3fc5a02ef895cc9e9a7a09243))\n- **toPromise:** correct toPromise return type ([#5072](https://github.com/reactivex/rxjs/issues/5072)) ([b1c3573](https://github.com/reactivex/rxjs/commit/b1c35738204b5b1a5d325a16e70cdbf25b523976))\n- **fromFetch:** don't reassign closed-over parameter in fromFetch ([#5234](https://github.com/reactivex/rxjs/issues/5234)) ([37d2d99](https://github.com/reactivex/rxjs/commit/37d2d99762264ef5faabc0ce4f56d7aab51806dc)), closes [#5233](https://github.com/reactivex/rxjs/issues/5233) [#5233](https://github.com/reactivex/rxjs/issues/5233)\n\n### Features\n\n- add `lastValueFrom` and `firstValueFrom` methods ([#5295](https://github.com/reactivex/rxjs/issues/5295)) ([e69b765](https://github.com/reactivex/rxjs/commit/e69b76584d6872b3c55aa1bdf39c8984e9d9b00e))\n- RxJS now supports first-class interop with AsyncIterables ([4fa9d01](https://github.com/reactivex/rxjs/commit/4fa9d016a83049d014d77b89c56301e42db16b4d))\n- **combineLatestWith:** adds `combineLatestWith` - renamed legacy `combineLatest` operator ([#5251](https://github.com/reactivex/rxjs/issues/5251)) ([6d7b146](https://github.com/reactivex/rxjs/commit/6d7b1469110b405405549c9b6c311d2621738353))\n- **retry:** add config to reset error count on successful emission ([#5280](https://github.com/reactivex/rxjs/issues/5280)) ([ab6e9fc](https://github.com/reactivex/rxjs/commit/ab6e9fc32c19c1f14f8f59459db75312e75b9351))\n- **zipWith:** add `zipWith` which is just a rename of legacy `zip` operator ([#5249](https://github.com/reactivex/rxjs/issues/5249)) ([86b6a27](https://github.com/reactivex/rxjs/commit/86b6a272fd48c4712adba78963e05bb759ecf4f9))\n\n### BREAKING CHANGES\n\n- **startWith:** `startWith` will return incorrect types when called with more than 7 arguments and a scheduler. Passing scheduler to startWith is deprecated\n- **toPromise:** toPromise return type now returns `T | undefined` in TypeScript, which is correct, but may break builds.\n\n# [7.0.0-alpha.1](https://github.com/reactivex/rxjs/compare/7.0.0-alpha.0...7.0.0-alpha.1) (2019-12-27)\n\n### Bug Fixes\n\n- chain subscriptions from observables that belong to other instances of RxJS (e.g. in node_modules) ([#5059](https://github.com/reactivex/rxjs/issues/5059)) ([d7f7078](https://github.com/reactivex/rxjs/commit/d7f7078))\n- clear subscription on `shareReplay` completion ([#5044](https://github.com/reactivex/rxjs/issues/5044)) ([35e600f](https://github.com/reactivex/rxjs/commit/35e600f)), closes [#5034](https://github.com/reactivex/rxjs/issues/5034)\n- **closure:** Annotate next() for ReplaySubject ([#5088](https://github.com/reactivex/rxjs/issues/5088)) ([8687fbd](https://github.com/reactivex/rxjs/commit/8687fbd))\n- **closure:** static prop frameTimeFactor being collapsed when compiled with closure. ([39872c9](https://github.com/reactivex/rxjs/commit/39872c9))\n- **docs:** remove repetitive op3() in example ([#5043](https://github.com/reactivex/rxjs/issues/5043)) ([e17df33](https://github.com/reactivex/rxjs/commit/e17df33))\n- **filter:** Fix overload order for filter to support inferring the generic type ([#5024](https://github.com/reactivex/rxjs/issues/5024)) ([8255365](https://github.com/reactivex/rxjs/commit/8255365))\n- **fromFetch:** passing already aborted signal to init aborts fetch ([0e4849a](https://github.com/reactivex/rxjs/commit/0e4849a))\n\n### Features\n\n- **concatWith:** adds concatWith ([#4988](https://github.com/reactivex/rxjs/issues/4988)) ([dc89736](https://github.com/reactivex/rxjs/commit/dc89736))\n\n# [7.0.0-alpha.0](https://github.com/reactivex/rxjs/compare/6.5.2...7.0.0-alpha.0) (2019-09-18)\n\n### Bug Fixes\n\n- missing package.json in rxjs/fetch ([#5001](https://github.com/reactivex/rxjs/issues/5001)) ([f4bee07](https://github.com/reactivex/rxjs/commit/f4bee07))\n- **filter:** Resolve TS build failures for certain situations where Boolean is the predicate ([77c7dfd](https://github.com/reactivex/rxjs/commit/77c7dfd))\n- **pluck:** key union type strictness ([#4585](https://github.com/reactivex/rxjs/issues/4585)) ([bd5ec2d](https://github.com/reactivex/rxjs/commit/bd5ec2d))\n- **race:** ignore latter sources after first complete or error ([#4809](https://github.com/reactivex/rxjs/issues/4809)) ([f31c3df](https://github.com/reactivex/rxjs/commit/f31c3df)), closes [#4808](https://github.com/reactivex/rxjs/issues/4808)\n- **scan/reduce:** Typings correct for mixed seed/value types ([#4858](https://github.com/reactivex/rxjs/issues/4858)) ([b89ebe5](https://github.com/reactivex/rxjs/commit/b89ebe5))\n- **scheduled:** import from relative paths ([#4832](https://github.com/reactivex/rxjs/issues/4832)) ([1d37a87](https://github.com/reactivex/rxjs/commit/1d37a87))\n- **TS:** Error impls now properly type `this` ([#4978](https://github.com/reactivex/rxjs/issues/4978)) ([7606dc7](https://github.com/reactivex/rxjs/commit/7606dc7))\n- **TS:** fix type inference for defaultIfEmpty. ([#4833](https://github.com/reactivex/rxjs/issues/4833)) ([9b5ce2f](https://github.com/reactivex/rxjs/commit/9b5ce2f))\n- **types:** add Boolean signature to filter ([#4961](https://github.com/reactivex/rxjs/issues/4961)) ([259853e](https://github.com/reactivex/rxjs/commit/259853e)), closes [#4959](https://github.com/reactivex/rxjs/issues/4959) [/github.com/ReactiveX/rxjs/issues/4959#issuecomment-520629091](https://github.com//github.com/ReactiveX/rxjs/issues/4959/issues/issuecomment-520629091)\n\n### Features\n\n- **animationFrames:** Adds an observable of animationFrames ([#5021](https://github.com/reactivex/rxjs/issues/5021)) ([6a4cd68](https://github.com/reactivex/rxjs/commit/6a4cd68))\n- **concat:** can infer N types ([6c0cbc4](https://github.com/reactivex/rxjs/commit/6c0cbc4))\n- **of:** Update of typings ([e8adbb5](https://github.com/reactivex/rxjs/commit/e8adbb5))\n- **rxjs-compat:** removed for v7 ([#4839](https://github.com/reactivex/rxjs/issues/4839)) ([79b1b95](https://github.com/reactivex/rxjs/commit/79b1b95))\n- **TestScheduler:** expose `frameTimeFactor` property ([#4977](https://github.com/reactivex/rxjs/issues/4977)) ([8c32ed0](https://github.com/reactivex/rxjs/commit/8c32ed0))\n- **TS:** Update to TypeScript 3.5.3 ([741a136](https://github.com/reactivex/rxjs/commit/741a136))\n\n### BREAKING CHANGES\n\n- **concat:** Generic signature changed. Recommend not explicitly passing generics, just let inference do its job. If you must, cast with `as`.\n- **of:** Generic signature changed, do not specify generics, allow them to be inferred or use `as`\n- **of:** Use with more than 9 arguments, where the last argument is a `SchedulerLike` may result in the wrong type which includes the `SchedulerLike`, even though the run time implementation does not support that. Developers should be using `scheduled` instead\n- **TS:** RxJS requires TS 3.5\n- **rxjs-compat:** `rxjs/Rx` is no longer a valid import site.\n- **rxjs-compat:** `rxjs-compat` is not published for v7 (yet)\n- **race:** `race()` will no longer subscribe to subsequent observables if a provided source synchronously errors or completes. This means side effects that might have occurred during subscription in those rare cases will no longer occur.\n\n## [6.5.3](https://github.com/reactivex/rxjs/compare/6.5.2...6.5.3) (2019-09-03)\n\n### Bug Fixes\n\n- **general:** Refactor modules so they don't show side effects in some tools ([#4769](https://github.com/reactivex/rxjs/issues/4769)) ([9829c5e0](https://github.com/reactivex/rxjs/commit/9829c5e0))\n- **defer:** restrict allowed factory types ([#4835](https://github.com/reactivex/rxjs/issues/4835)) ([40a22096](https://github.com/reactivex/rxjs/commit/40a22096))\n\n## [6.5.2](https://github.com/reactivex/rxjs/compare/6.5.0...6.5.2) (2019-05-10)\n\n### Bug Fixes\n\n- **endWith:** wrap args - they are not observables - in of before concatenating ([#4735](https://github.com/reactivex/rxjs/issues/4735)) ([986be2f](https://github.com/reactivex/rxjs/commit/986be2f))\n- **forkJoin:** test for object literal ([#4741](https://github.com/reactivex/rxjs/issues/4741)) ([c11e1b3](https://github.com/reactivex/rxjs/commit/c11e1b3)), closes [#4737](https://github.com/reactivex/rxjs/issues/4737) [#4737](https://github.com/reactivex/rxjs/issues/4737)\n- **Notification:** replace const enum ([#4556](https://github.com/reactivex/rxjs/issues/4556)) ([e460eec](https://github.com/reactivex/rxjs/commit/e460eec)), closes [#4538](https://github.com/reactivex/rxjs/issues/4538)\n- **of:** remove deprecation comment to prevent false positive warning ([#4724](https://github.com/reactivex/rxjs/issues/4724)) ([da69c16](https://github.com/reactivex/rxjs/commit/da69c16))\n- **pairwise:** make it recursion-proof ([#4743](https://github.com/reactivex/rxjs/issues/4743)) ([21ab261](https://github.com/reactivex/rxjs/commit/21ab261))\n- **scan:** fixed declarations to properly support different return types ([#4598](https://github.com/reactivex/rxjs/issues/4598)) ([126d2b6](https://github.com/reactivex/rxjs/commit/126d2b6))\n- **Subscription:** Return Empty when teardown === null ([#4575](https://github.com/reactivex/rxjs/issues/4575)) ([ffc4e68](https://github.com/reactivex/rxjs/commit/ffc4e68))\n- **throttleTime:** emit single value with trailing enabled ([#4564](https://github.com/reactivex/rxjs/issues/4564)) ([fd690a6](https://github.com/reactivex/rxjs/commit/fd690a6)), closes [#2859](https://github.com/reactivex/rxjs/issues/2859) [#4491](https://github.com/reactivex/rxjs/issues/4491)\n- **umd:** export fetch namespace ([#4738](https://github.com/reactivex/rxjs/issues/4738)) ([7926122](https://github.com/reactivex/rxjs/commit/7926122))\n- **fromFetch:** don't abort if fetch resolves ([#4742](https://github.com/reactivex/rxjs/issues/4742) ([ed8d771](https://github.com/reactivex/rxjs/commit/ed8d771))\n\n## [6.5.1](https://github.com/reactivex/rxjs/compare/6.5.0...6.5.1) (2019-04-23)\n\n### Bug Fixes\n\n- **Notification:** replace const enum ([#4556](https://github.com/reactivex/rxjs/issues/4556)) ([e460eec](https://github.com/reactivex/rxjs/commit/e460eec)), closes [#4538](https://github.com/reactivex/rxjs/issues/4538)\n- **throttleTime:** emit single value with trailing enabled ([#4564](https://github.com/reactivex/rxjs/issues/4564)) ([fd690a6](https://github.com/reactivex/rxjs/commit/fd690a6)), closes [#2859](https://github.com/reactivex/rxjs/issues/2859) [#4491](https://github.com/reactivex/rxjs/issues/4491)\n\n# [6.5.0](https://github.com/reactivex/rxjs/compare/6.4.0...6.5.0) (2019-04-23)\n\n### Bug Fixes\n\n- **docs-app:** remove stopWordFilter from lunr pipeline ([#4536](https://github.com/reactivex/rxjs/issues/4536)) ([9eaebd4](https://github.com/reactivex/rxjs/commit/9eaebd4))\n- **dtslint:** disable tests that break in TS@next ([#4705](https://github.com/reactivex/rxjs/issues/4705)) ([ecc73d2](https://github.com/reactivex/rxjs/commit/ecc73d2))\n- **index:** export NotificationKind ([#4514](https://github.com/reactivex/rxjs/issues/4514)) ([7125355](https://github.com/reactivex/rxjs/commit/7125355)), closes [#4513](https://github.com/reactivex/rxjs/issues/4513)\n- **race:** better typings ([#4643](https://github.com/reactivex/rxjs/issues/4643)) ([fb9bc48](https://github.com/reactivex/rxjs/commit/fb9bc48)), closes [#4390](https://github.com/reactivex/rxjs/issues/4390) [#4642](https://github.com/reactivex/rxjs/issues/4642)\n- **throwIfEmpty:** ensure result is retry-able ([c4f44b9](https://github.com/reactivex/rxjs/commit/c4f44b9))\n- **types:** Fixed signature for onErrorResumeNext ([#4603](https://github.com/reactivex/rxjs/issues/4603)) ([4dd0be0](https://github.com/reactivex/rxjs/commit/4dd0be0))\n\n### Features\n\n- **combineLatest:** deprecated rest argument and scheduler signatures ([#4641](https://github.com/reactivex/rxjs/issues/4641)) ([6661c79](https://github.com/reactivex/rxjs/commit/6661c79)), closes [#4640](https://github.com/reactivex/rxjs/issues/4640)\n- **fromFetch:** We now export a `fromFetch` static observable creation method from `rxjs/fetch`. Mirrors native `fetch` only it's lazy and cancellable via `Observable` interface. ([#4702](https://github.com/reactivex/rxjs/issues/4702)) ([5a1ef86](https://github.com/reactivex/rxjs/commit/5a1ef86))\n- **forkJoin:** accepts a dictionary of sources ([#4640](https://github.com/reactivex/rxjs/issues/4640)) ([b5a2ac9](https://github.com/reactivex/rxjs/commit/b5a2ac9))\n- **partition:** new `partition` observable creation function. Old `partition` operator is deprecated ([#4419](https://github.com/reactivex/rxjs/issues/4419)) ([#4685](https://github.com/reactivex/rxjs/issues/4685)) ([d5d6980](https://github.com/reactivex/rxjs/commit/d5d6980))\n- **scheduled:** Add `scheduled` creation function to use to create scheduled observable of values. Deprecate scheduled versions of `from`, `range`, et al. ([#4595](https://github.com/reactivex/rxjs/issues/4595)) ([f57e1fc](https://github.com/reactivex/rxjs/commit/f57e1fc))\n\n### Performance Improvements\n\n- **Subscription:** improve parent management ([#4526](https://github.com/reactivex/rxjs/issues/4526)) ([06f1a25](https://github.com/reactivex/rxjs/commit/06f1a25))\n\n# [6.4.0](https://github.com/reactivex/rxjs/compare/6.3.3...6.4.0) (2019-01-30)\n\n### Bug Fixes\n\n- **ajax:** Fix case-insensitive headers in HTTP request ([#4453](https://github.com/reactivex/rxjs/issues/4453)) ([673bf47](https://github.com/reactivex/rxjs/commit/673bf47))\n- **bundle:** closure to not rewrite polyfills for minification ([#4487](https://github.com/reactivex/rxjs/issues/4487)) ([a1fedb9](https://github.com/reactivex/rxjs/commit/a1fedb9))\n- **bundle:** don't export `operators` twice ([#4310](https://github.com/reactivex/rxjs/issues/4310)) ([2399f6e](https://github.com/reactivex/rxjs/commit/2399f6e))\n- **combineLatest:** improve typings for combineLatest ([#4470](https://github.com/reactivex/rxjs/issues/4470)) ([40c3d9f](https://github.com/reactivex/rxjs/commit/40c3d9f))\n- **compat:** remove internal from import locations ([#4498](https://github.com/reactivex/rxjs/issues/4498)) ([a6c0017](https://github.com/reactivex/rxjs/commit/a6c0017)), closes [#4070](https://github.com/reactivex/rxjs/issues/4070)\n- **endWith:** ability to endWith different types ([#4183](https://github.com/reactivex/rxjs/issues/4183)) ([#4185](https://github.com/reactivex/rxjs/issues/4185)) ([83533d1](https://github.com/reactivex/rxjs/commit/83533d1))\n- **fromEventPattern:** improve typings for fromEventPattern ([#4496](https://github.com/reactivex/rxjs/issues/4496)) ([037f53d](https://github.com/reactivex/rxjs/commit/037f53d))\n- **Observable:** Fix Observable.subscribe to add operator TeardownLogic to returned Subscription. ([#4434](https://github.com/reactivex/rxjs/issues/4434)) ([f28955f](https://github.com/reactivex/rxjs/commit/f28955f))\n- **subscribe:** Deprecate null starting parameter signatures for subscribe ([#4202](https://github.com/reactivex/rxjs/issues/4202)) ([c85ddf6](https://github.com/reactivex/rxjs/commit/c85ddf6))\n- **combineLatest:** support passing union types ([ffda319](https://github.com/reactivex/rxjs/commit/ffda319))\n- **from:** support passing union types ([eb1d596](https://github.com/reactivex/rxjs/commit/eb1d596))\n- **withLatestFrom:** support passing union types ([1e19a24](https://github.com/reactivex/rxjs/commit/1e19a24))\n- **zip:** support passing union types ([0d87f52](https://github.com/reactivex/rxjs/commit/0d87f52))\n- **multicast:** support returning union types from projection ([e9e9041](https://github.com/reactivex/rxjs/commit/e9e9041))\n- **exhaustMap:** support returning union types from projection ([ff1f5dc](https://github.com/reactivex/rxjs/commit/ff1f5dc))\n- **merge:** support union type inference for merge operators ([c2ac39c](https://github.com/reactivex/rxjs/commit/c2ac39c))\n- **catchError:** support union type returns ([8350622](https://github.com/reactivex/rxjs/commit/8350622))\n- **switchMap:** support union type returns ([32d35fd](https://github.com/reactivex/rxjs/commit/32d35fd))\n- **defer:** support union types passed ([5aea50e](https://github.com/reactivex/rxjs/commit/5aea50e))\n- **race:** Update typings to support proper return types ([#4465](https://github.com/reactivex/rxjs/issues/4465)) ([0042846](https://github.com/reactivex/rxjs/commit/0042846))\n- **VirtualTimeScheduler:** rework flush so it won't lose actions ([#4433](https://github.com/reactivex/rxjs/issues/4433)) ([d068bc9](https://github.com/reactivex/rxjs/commit/d068bc9))\n- **WebSocketSubject:** fix subject failing to close socket ([#4446](https://github.com/reactivex/rxjs/issues/4446)) ([dcfa52b](https://github.com/reactivex/rxjs/commit/dcfa52b))\n\n### Features\n\n- **shareReplay:** Add configuration object for named arguments, and add argument to support unsubscribing from source observable by `refCount` when all resulting subscriptions have unsubscribed. The default behavior is to leave the source subscription running.\n- **mergeScan:** Add index to the accumulator function ([#4458](https://github.com/reactivex/rxjs/issues/4458)) ([f5e143d](https://github.com/reactivex/rxjs/commit/f5e143d)), closes [#4441](https://github.com/reactivex/rxjs/issues/4441)\n- **range:** accept one argument ([#4360](https://github.com/reactivex/rxjs/issues/4360)) ([a388578](https://github.com/reactivex/rxjs/commit/a388578))\n- **takeWhile:** add an `inclusive` option to the operator which causes to emit final value ([#4115](https://github.com/reactivex/rxjs/issues/4115)) ([6e7f407](https://github.com/reactivex/rxjs/commit/6e7f407))\n\n### Performance Improvements\n\n- **internal:** optimize Subscription#add() for the common case ([#4489](https://github.com/reactivex/rxjs/issues/4489)) ([bdd201c](https://github.com/reactivex/rxjs/commit/bdd201c))\n- **internal:** use strict equality for isObject() ([#4493](https://github.com/reactivex/rxjs/issues/4493)) ([fc84a00](https://github.com/reactivex/rxjs/commit/fc84a00))\n- **Subscription:** use `instanceof` to avoid megamorphic LoadIC ([#4499](https://github.com/reactivex/rxjs/issues/4499)) ([065b4e3](https://github.com/reactivex/rxjs/commit/065b4e3))\n\n<a name=\"6.3.3\"></a>\n\n## [6.3.3](https://github.com/reactivex/rxjs/compare/6.3.2...6.3.3) (2018-09-25)\n\n### Bug Fixes\n\n- **pipe:** align static pipe to Observable pipe rest parameters overl… ([#4112](https://github.com/reactivex/rxjs/issues/4112)) ([8c607e9](https://github.com/reactivex/rxjs/commit/8c607e9)), closes [#4109](https://github.com/reactivex/rxjs/issues/4109) [#4109](https://github.com/reactivex/rxjs/issues/4109)\n- **RxJS:** each instance of RxJS now has a unique Subscriber symbol ([0972c56](https://github.com/reactivex/rxjs/commit/0972c56))\n- **subscribe:** report errors that occur in subscribe after the initial error ([#4089](https://github.com/reactivex/rxjs/issues/4089)) ([9b4b2bc](https://github.com/reactivex/rxjs/commit/9b4b2bc)), closes [#3803](https://github.com/reactivex/rxjs/issues/3803)\n- **Subscriber:** Can no longer subscribe to itself in a circular manner ([#4106](https://github.com/reactivex/rxjs/issues/4106)) ([e623ec6](https://github.com/reactivex/rxjs/commit/e623ec6)), closes [#4095](https://github.com/reactivex/rxjs/issues/4095)\n- **Subscriber:** use only local Subscriber instances ([50ee0a7](https://github.com/reactivex/rxjs/commit/50ee0a7))\n- **TypeScript:** ensure RxJS builds with TS@next as well ([f03e790](https://github.com/reactivex/rxjs/commit/f03e790))\n\n<a name=\"6.3.2\"></a>\n\n## [6.3.2](https://github.com/reactivex/rxjs/compare/6.3.1...6.3.2) (2018-09-04)\n\n### Bug Fixes\n\n- **node:** will no longer error mixing RxJS 6.3 and 6.2 ([#4078](https://github.com/reactivex/rxjs/issues/4078)) ([69d9ccf](https://github.com/reactivex/rxjs/commit/69d9ccf)), closes [#4077](https://github.com/reactivex/rxjs/issues/4077)\n\n<a name=\"6.3.1\"></a>\n\n## [6.3.1](https://github.com/reactivex/rxjs/compare/6.3.0...6.3.1) (2018-08-31)\n\n### Bug Fixes\n\n- **mergeMap:** fix nested mergeMaps ([#4072](https://github.com/reactivex/rxjs/issues/4072)) ([0ab701b](https://github.com/reactivex/rxjs/commit/0ab701b)), closes [#4071](https://github.com/reactivex/rxjs/issues/4071)\n\n<a name=\"6.3.0\"></a>\n\n# [6.3.0](https://github.com/reactivex/rxjs/compare/6.2.2...6.3.0) (2018-08-30)\n\n### Bug Fixes\n\n- **find:** unsubscribe from source when found ([#3968](https://github.com/reactivex/rxjs/issues/3968)) ([fd01f7b](https://github.com/reactivex/rxjs/commit/fd01f7b))\n- convert [@internal](https://github.com/internal) comment to JSDoc ([#3932](https://github.com/reactivex/rxjs/issues/3932)) ([f8a9d6e](https://github.com/reactivex/rxjs/commit/f8a9d6e))\n- **AjaxObservable:** notify with error if fails to parse json response ([#3139](https://github.com/reactivex/rxjs/issues/3139)) ([d8231e2](https://github.com/reactivex/rxjs/commit/d8231e2)), closes [#3138](https://github.com/reactivex/rxjs/issues/3138)\n- **catchError:** stop listening to a synchronous inner-observable when unsubscribed ([456ef33](https://github.com/reactivex/rxjs/commit/456ef33))\n- **distinctUntilKeyChanged:** improved key typing with keyof T ([#3988](https://github.com/reactivex/rxjs/issues/3988)) ([4ec4ff1](https://github.com/reactivex/rxjs/commit/4ec4ff1))\n- **exhaustMap:** stop listening to a synchronous inner-observable when unsubscribed ([ee1a339](https://github.com/reactivex/rxjs/commit/ee1a339))\n- **find:** add undefined to return type ([#3970](https://github.com/reactivex/rxjs/issues/3970)) ([5a6c90f](https://github.com/reactivex/rxjs/commit/5a6c90f)), closes [#3969](https://github.com/reactivex/rxjs/issues/3969)\n- **IE10:** Remove dependency on Object.setPrototypeOf ([#3967](https://github.com/reactivex/rxjs/issues/3967)) ([5c52a73](https://github.com/reactivex/rxjs/commit/5c52a73)), closes [#3966](https://github.com/reactivex/rxjs/issues/3966)\n- **mergeAll:** add source subscription to composite before actually subscribing ([#2479](https://github.com/reactivex/rxjs/issues/2479)) ([40852ff](https://github.com/reactivex/rxjs/commit/40852ff)), closes [#2476](https://github.com/reactivex/rxjs/issues/2476)\n- **mergeScan:** stop listening to a synchronous inner-observable when unsubscribed ([c4002f3](https://github.com/reactivex/rxjs/commit/c4002f3))\n- **Observable:** forEach will no longer next values after an error ([b4bad1f](https://github.com/reactivex/rxjs/commit/b4bad1f))\n- **Observable:** use more granular Observable exports in compat mode ([#3974](https://github.com/reactivex/rxjs/issues/3974)) ([3f75564](https://github.com/reactivex/rxjs/commit/3f75564))\n- **onErrorResumeNext:** stop listening to a synchronous inner-observable when unsubscribed ([1d14277](https://github.com/reactivex/rxjs/commit/1d14277))\n- **pipe:** replace rest parameters overload ([#3945](https://github.com/reactivex/rxjs/issues/3945)) ([872b0ec](https://github.com/reactivex/rxjs/commit/872b0ec)), closes [#3841](https://github.com/reactivex/rxjs/issues/3841)\n- **skipUntil:** stop listening to a synchronous notifier after its first nexted value ([1c257db](https://github.com/reactivex/rxjs/commit/1c257db))\n- **startWith:** allow empty type signature and passing a different type ([b7866a0](https://github.com/reactivex/rxjs/commit/b7866a0))\n- **subscribable:** make subscribe() signature match Observable ([#4050](https://github.com/reactivex/rxjs/issues/4050)) ([865d8d7](https://github.com/reactivex/rxjs/commit/865d8d7)), closes [#3891](https://github.com/reactivex/rxjs/issues/3891)\n- **subscriber:** unsubscribe parents on error/complete ([ad8131b](https://github.com/reactivex/rxjs/commit/ad8131b))\n- **switchMap:** stop listening to a synchronous inner-observable when unsubscribed ([260d52a](https://github.com/reactivex/rxjs/commit/260d52a))\n- **takeUntil:** takeUntil should subscribe to the source if notifier sync completes without emitting ([#4039](https://github.com/reactivex/rxjs/issues/4039)) ([21fd0b4](https://github.com/reactivex/rxjs/commit/21fd0b4)), closes [#3504](https://github.com/reactivex/rxjs/issues/3504)\n- **testscheduler:** type arguments to Observable creation functions ([#3928](https://github.com/reactivex/rxjs/issues/3928)) ([0e30ef1](https://github.com/reactivex/rxjs/commit/0e30ef1))\n\n### Features\n\n- **delayWhen:** add index to the selector function ([#2473](https://github.com/reactivex/rxjs/issues/2473)) ([0979d31](https://github.com/reactivex/rxjs/commit/0979d31))\n- **forEach:** deprecating passing promise constructor ([5178ab9](https://github.com/reactivex/rxjs/commit/5178ab9))\n- **TestScheduler:** Add subscription schedule to expectObservable ([#3997](https://github.com/reactivex/rxjs/issues/3997)) ([0d20255](https://github.com/reactivex/rxjs/commit/0d20255))\n\n<a name=\"6.2.2\"></a>\n\n## [6.2.2](https://github.com/reactivex/rxjs/compare/6.2.1...6.2.2) (2018-07-13)\n\n### Bug Fixes\n\n- **first:** improved type guards for TypeScript ([3e12f7a](https://github.com/reactivex/rxjs/commit/3e12f7a))\n- **last:** improved type guards for TypeScript ([3e12f7a](https://github.com/reactivex/rxjs/commit/3e12f7a))\n\n<a name=\"6.2.1\"></a>\n\n## [6.2.1](https://github.com/reactivex/rxjs/compare/6.2.0...6.2.1) (2018-06-12)\n\n### Bug Fixes\n\n- **ci:** do not trigger postbuild script on PR ([f82c085](https://github.com/reactivex/rxjs/commit/f82c085))\n- **delayWhen:** Emit source value if duration selector completes synchronously ([#3664](https://github.com/reactivex/rxjs/issues/3664)) ([2c43af7](https://github.com/reactivex/rxjs/commit/2c43af7)), closes [#3663](https://github.com/reactivex/rxjs/issues/3663)\n- **docs:** fix broken github links ([#3802](https://github.com/reactivex/rxjs/issues/3802)) ([9f9bf9b](https://github.com/reactivex/rxjs/commit/9f9bf9b))\n- **docs:** fix code examples ([#3784](https://github.com/reactivex/rxjs/issues/3784)) ([a95441b](https://github.com/reactivex/rxjs/commit/a95441b))\n- **from:** Objects implementing Symbol.observable take precedence over other types ([80ceea0](https://github.com/reactivex/rxjs/commit/80ceea0))\n- **fromEvent:** Support React Native and node-compatible event sources. ([#3821](https://github.com/reactivex/rxjs/issues/3821)) ([1969f18](https://github.com/reactivex/rxjs/commit/1969f18))\n- **Observable.prototype.pipe:** TS typings now more correct for >8 parameters ([#3789](https://github.com/reactivex/rxjs/issues/3789)) ([ad010ea](https://github.com/reactivex/rxjs/commit/ad010ea))\n- **subscribe:** ignore syncError when deprecated ([#3749](https://github.com/reactivex/rxjs/issues/3749)) ([f94560c](https://github.com/reactivex/rxjs/commit/f94560c))\n- **Symbol.observable:** make observable declaration readonly ([#3697](https://github.com/reactivex/rxjs/issues/3697)) ([#3773](https://github.com/reactivex/rxjs/issues/3773)) ([e1c203f](https://github.com/reactivex/rxjs/commit/e1c203f))\n- **TypeScript:** resolved typings issue for TS 3.0 ([bf2cdeb](https://github.com/reactivex/rxjs/commit/bf2cdeb))\n- **typings:** allow bufferCreationInterval null for bufferTime ([#3734](https://github.com/reactivex/rxjs/issues/3734)) ([0bda9cd](https://github.com/reactivex/rxjs/commit/0bda9cd)), closes [#3728](https://github.com/reactivex/rxjs/issues/3728)\n\n### Performance Improvements\n\n- remove comments from js-files ([#3760](https://github.com/reactivex/rxjs/issues/3760)) ([bb2c334](https://github.com/reactivex/rxjs/commit/bb2c334))\n\n<a name=\"6.2.0\"></a>\n\n# [6.2.0](https://github.com/ReactiveX/RxJS/compare/6.1.0...6.2.0) (2018-05-22)\n\n### Bug Fixes\n\n- **ajax:** Handle timeouts as errors ([#3653](https://github.com/ReactiveX/RxJS/issues/3653)) ([e4128ea](https://github.com/ReactiveX/RxJS/commit/e4128ea))\n- **ajax:** RxJS v6 TimeoutError is missing name property ([576d943](https://github.com/ReactiveX/RxJS/commit/576d943))\n- **isObservable:** Fix throwing error when testing isObservable(null) ([#3688](https://github.com/ReactiveX/RxJS/issues/3688)) ([c9acc61](https://github.com/ReactiveX/RxJS/commit/c9acc61))\n- **range:** Range should be same for every subscriber ([#3707](https://github.com/ReactiveX/RxJS/issues/3707)) ([9642133](https://github.com/ReactiveX/RxJS/commit/9642133))\n- **skipUntil:** fix skipUntil when innerSubscription is null ([#3686](https://github.com/ReactiveX/RxJS/issues/3686)) ([4226432](https://github.com/ReactiveX/RxJS/commit/4226432))\n- **TestScheduler:** restore run changes upon error ([27cb9b6](https://github.com/ReactiveX/RxJS/commit/27cb9b6))\n- **TimeoutError:** Add name to TimeoutError ([44042d0](https://github.com/ReactiveX/RxJS/commit/44042d0))\n- **WebSocketSubject:** Check to see if WebSocket exists in global scope ([#3694](https://github.com/ReactiveX/RxJS/issues/3694)) ([2db0788](https://github.com/ReactiveX/RxJS/commit/2db0788))\n\n### Features\n\n- **endWith:** add new operator endWith ([#3679](https://github.com/ReactiveX/RxJS/issues/3679)) ([537fe7d](https://github.com/ReactiveX/RxJS/commit/537fe7d))\n\n<a name=\"6.1.0\"></a>\n\n# [6.1.0](https://github.com/ReactiveX/RxJS/compare/6.0.0...6.1.0) (2018-05-03)\n\n### Bug Fixes\n\n- **audit:** will not crash if duration is synchronous ([#3608](https://github.com/ReactiveX/RxJS/issues/3608)) ([76b7e27](https://github.com/ReactiveX/RxJS/commit/76b7e27)), closes [#2743](https://github.com/ReactiveX/RxJS/issues/2743)\n- **delay:** fix memory leak ([#3605](https://github.com/ReactiveX/RxJS/issues/3605)) ([96f05b0](https://github.com/ReactiveX/RxJS/commit/96f05b0))\n\n### Features\n\n- **isObservable:** a new method for checking to see if an object is an RxJS Observable ([edb33e5](https://github.com/ReactiveX/RxJS/commit/edb33e5))\n\n<a name=\"6.0.0\"></a>\n\n# [6.0.0](https://github.com/ReactiveX/RxJS/compare/6.0.0-uncanny-rc.7...v6.0.0) (2018-04-24)\n\n### Bug Fixes\n\n- **websocket:** no longer throws errors in operators applied to it ([#3577](https://github.com/ReactiveX/RxJS/issues/3577)) ([cb38ddf](https://github.com/ReactiveX/RxJS/commit/cb38ddf))\n\n### Code Refactoring\n\n- **webSocket:** rename back to webSocket ala 5.0 ([#3590](https://github.com/ReactiveX/RxJS/issues/3590)) ([d5658fe](https://github.com/ReactiveX/RxJS/commit/d5658fe))\n\n### Features\n\n- **testing:** Add testScheduler.run() helper ([2d5b3b2](https://github.com/ReactiveX/RxJS/commit/2d5b3b2))\n- **testing:** testScheduler.run() supports time progression syntax ([9322b7d](https://github.com/ReactiveX/RxJS/commit/9322b7d))\n\n### BREAKING CHANGES\n\n- **webSocket:** UNBREAKING websocket to be named `webSocket` again, just like it was in 5.0. Now you should import from `rxjs/webSocket`\n\n<a name=\"6.0.0-uncanny-rc.7\"></a>\n\n# [6.0.0-uncanny-rc.7](https://github.com/ReactiveX/RxJS/compare/6.0.0-ucandoit-rc.6...v6.0.0-uncanny-rc.7) (2018-04-13)\n\n### Bug Fixes\n\n- **interop:** functions with `[Symbol.observable]` on them will now be accepted in operators like `mergeMap`, `from`, etc ([#3562](https://github.com/ReactiveX/RxJS/issues/3562)) ([c9570df](https://github.com/ReactiveX/RxJS/commit/c9570df))\n- **migrations:** change the version the migration applies to ([#3564](https://github.com/ReactiveX/RxJS/issues/3564)) ([9217a03](https://github.com/ReactiveX/RxJS/commit/9217a03))\n- **rxjs:** no longer requires `dom` lib ([#3566](https://github.com/ReactiveX/RxJS/issues/3566)) ([8b33ee2](https://github.com/ReactiveX/RxJS/commit/8b33ee2))\n- **throttleTime:** emit throttled values when complete if trailing=true ([#3559](https://github.com/ReactiveX/RxJS/issues/3559)) ([3e846f2](https://github.com/ReactiveX/RxJS/commit/3e846f2)), closes [#3351](https://github.com/ReactiveX/RxJS/issues/3351)\n- **websocket:** export WebSocketSubject, WebSocketSubjectConfig from rxjs/websocket ([#3557](https://github.com/ReactiveX/RxJS/issues/3557)) ([c365405](https://github.com/ReactiveX/RxJS/commit/c365405))\n\n<a name=\"6.0.0-ucandoit-rc.6\"></a>\n\n# [6.0.0-ucandoit-rc.6](https://github.com/ReactiveX/RxJS/compare/6.0.0-uber-rc.5...v6.0.0-ucandoit-rc.6) (2018-04-13)\n\n### Bug Fixes\n\n- **migrations:** make sure collection.json is present ([63e10a8](https://github.com/ReactiveX/RxJS/commit/63e10a8))\n\n<a name=\"6.0.0-uber-rc.5\"></a>\n\n# [6.0.0-uber-rc.5](https://github.com/ReactiveX/RxJS/compare/6.0.0-turbo-rc.4...6.0.0-uber-rc.5) (2018-04-13)\n\n### Bug Fixes\n\n- **migrations:** deploy compiled JS rather than just the TS files. ([9aed72f](https://github.com/ReactiveX/RxJS/commit/9aed72f))\n\n<a name=\"6.0.0-turbo-rc.4\"></a>\n\n# [6.0.0-turbo-rc.4](https://github.com/ReactiveX/RxJS/compare/6.0.0-terrific-rc.3...6.0.0-turbo-rc.4) (2018-04-12)\n\n### Bug Fixes\n\n- **groupBy:** reexporting the GroupedObservable type ([#3556](https://github.com/ReactiveX/RxJS/issues/3556)) ([12d4933](https://github.com/ReactiveX/RxJS/commit/12d4933)), closes [#3551](https://github.com/ReactiveX/RxJS/issues/3551)\n- **migrations:** build now properly copies migration into package ([#3555](https://github.com/ReactiveX/RxJS/issues/3555)) ([329a145](https://github.com/ReactiveX/RxJS/commit/329a145))\n\n<a name=\"6.0.0-terrific-rc.3\"></a>\n\n# [6.0.0-terrific-rc.3](https://github.com/ReactiveX/RxJS/compare/6.0.0-tenacious-rc.2...v6.0.0-terrific-rc.3) (2018-04-11)\n\n### Features\n\n- **schematics:** add migration schematics for schematics users ([20a2f07](https://github.com/ReactiveX/RxJS/commit/20a2f07))\n\n<a name=\"6.0.0-tenacious-rc.2\"></a>\n\n# [6.0.0-tenacious-rc.2](https://github.com/ReactiveX/RxJS/compare/6.0.0-tactical-rc.1...v6.0.0-tenacious-rc.2) (2018-04-11)\n\n### Bug Fixes\n\n- **compat:** fix first & last operators so undefined arguments won't create empty values ([#3542](https://github.com/ReactiveX/RxJS/issues/3542)) ([a327db2](https://github.com/ReactiveX/RxJS/commit/a327db2))\n- **node/TS:** eliminate incompatible types to protected properties ([#3544](https://github.com/ReactiveX/RxJS/issues/3544)) ([21dd3bd](https://github.com/ReactiveX/RxJS/commit/21dd3bd))\n\n### BREAKING CHANGES\n\n- **NodeJS** Dropping support for non-LTS versions of Node.\n\n<a name=\"6.0.0-tactical-rc.1\"></a>\n\n# [6.0.0-tactical-rc.1](https://github.com/ReactiveX/RxJS/compare/6.0.0-rc.0...6.0.0-tactical-rc.1) (2018-04-07)\n\nWhy \"tactical\"? Because I _TOTALLY MEANT_ to ruin the release names by publishing an amazingly funny April Fool's joke about smooshMap. So this was \"tactical\". Super tactical. So very tactical.\n\n### Bug Fixes\n\n- **closure-compiler:** adds nocollapse to static members ([#3519](https://github.com/ReactiveX/RxJS/issues/3519)) ([8758a5d](https://github.com/ReactiveX/RxJS/commit/8758a5d))\n- **closure-compiler:** remove internal flag from \\_isScalar ([#3520](https://github.com/ReactiveX/RxJS/issues/3520)) ([b3a657d](https://github.com/ReactiveX/RxJS/commit/b3a657d))\n- **closure-compiler:** remove top level throws ([#3518](https://github.com/ReactiveX/RxJS/issues/3518)) ([b069473](https://github.com/ReactiveX/RxJS/commit/b069473))\n- **closure-compiler:** removes bad \\[@params](https://github.com/params) comments that caused issues ([#3521](https://github.com/ReactiveX/RxJS/issues/3521)) ([09c874c](https://github.com/ReactiveX/RxJS/commit/09c874c))\n- **compat:** deprecate Observable.if/throw ([#3527](https://github.com/ReactiveX/RxJS/issues/3527)) ([3116275](https://github.com/ReactiveX/RxJS/commit/3116275))\n- **compat:** export TeardownLogic ([#3532](https://github.com/ReactiveX/RxJS/issues/3532)) ([0c76e64](https://github.com/ReactiveX/RxJS/commit/0c76e64)), closes [#3531](https://github.com/ReactiveX/RxJS/issues/3531)\n- **compat:** remove observable/scalar deep import as it wasn't previously available ([4566001](https://github.com/ReactiveX/RxJS/commit/4566001))\n- **Scheduler:** export but deprecate ([#3522](https://github.com/ReactiveX/RxJS/issues/3522)) ([a3e1fb8](https://github.com/ReactiveX/RxJS/commit/a3e1fb8))\n- **skipUntil:** properly manages notifier subscription ([889f84a](https://github.com/ReactiveX/RxJS/commit/889f84a)), closes [#1886](https://github.com/ReactiveX/RxJS/issues/1886)\n- fix type mismatch in NodeStyleEventEmitter ([#3530](https://github.com/ReactiveX/RxJS/issues/3530)) ([3f51ddd](https://github.com/ReactiveX/RxJS/commit/3f51ddd))\n- **sourcemaps:** fix mappings for source maps so they will work ([#3523](https://github.com/ReactiveX/RxJS/issues/3523)) ([32e7f75](https://github.com/ReactiveX/RxJS/commit/32e7f75)), closes [#3479](https://github.com/ReactiveX/RxJS/issues/3479)\n\n### Features\n\n- **compat:** add Observable extension classes with static create() ([ecd7f68](https://github.com/ReactiveX/RxJS/commit/ecd7f68))\n- **compat:** add rxjs/interfaces exports ([ba5c266](https://github.com/ReactiveX/RxJS/commit/ba5c266))\n\n<a name=\"6.0.0-rc.0\"></a>\n\n# [6.0.0-rc.0](https://github.com/ReactiveX/RxJS/compare/6.0.0-beta.4...6.0.0-rc.0) (2018-03-31)\n\n### Bug Fixes\n\n- **ajax:** properly encode body with form data that includes URLs ([#3502](https://github.com/ReactiveX/RxJS/issues/3502)) ([4455d21](https://github.com/ReactiveX/RxJS/commit/4455d21)), closes [#2399](https://github.com/ReactiveX/RxJS/issues/2399)\n- **bindNodeCallback:** better type inference ([932bb7a](https://github.com/ReactiveX/RxJS/commit/932bb7a))\n- **elementAt:** now allows falsy defaultValues ([13706e7](https://github.com/ReactiveX/RxJS/commit/13706e7))\n- **lint_perf:** fix lint issues with newer perf tests ([1013754](https://github.com/ReactiveX/RxJS/commit/1013754))\n- **throttle:** now properly trailing throttles for individual values ([#3505](https://github.com/ReactiveX/RxJS/issues/3505)) ([3db18d1](https://github.com/ReactiveX/RxJS/commit/3db18d1)), closes [#2864](https://github.com/ReactiveX/RxJS/issues/2864)\n\n### Features\n\n- **takeUntil:** no longer subscribes to source if notifier synchronously emits ([#3504](https://github.com/ReactiveX/RxJS/issues/3504)) ([7b8a3e3](https://github.com/ReactiveX/RxJS/commit/7b8a3e3)), closes [#2189](https://github.com/ReactiveX/RxJS/issues/2189)\n\n### Performance Improvements\n\n- **pluck,bufferTime,asObservable:** add performance tests for pluck(), bufferTime() and asObservable() operators ([#2491](https://github.com/ReactiveX/RxJS/issues/2491)) ([24506b3](https://github.com/ReactiveX/RxJS/commit/24506b3))\n- **ReplaySubject:** slightly improved performance ([#2677](https://github.com/ReactiveX/RxJS/issues/2677)) ([9fea36d](https://github.com/ReactiveX/RxJS/commit/9fea36d))\n\n### BREAKING CHANGES\n\n- **throttle:** This changes the behavior of throttle, in particular\n  throttling with both leading and trailing behaviors set to true, to more\n  closely match the throttling behavior of lodash and other libraries.\n  Throttling now starts immediately after any emission from the\n  observable, and values will not be double emitted for both leading and\n  trailing values\n\n<a name=\"6.0.0-beta.4\"></a>\n\n# [6.0.0-beta.4](https://github.com/ReactiveX/RxJS/compare/6.0.0-beta.3...v6.0.0-beta.4) (2018-03-29)\n\n### Bug Fixes\n\n- **bindCallback:** add better type overloads ([#3480](https://github.com/ReactiveX/RxJS/issues/3480)) ([037cf34](https://github.com/ReactiveX/RxJS/commit/037cf34))\n- **compat:** add IScheduler to compat/Scheduler ([0a67df6](https://github.com/ReactiveX/RxJS/commit/0a67df6))\n\n### Features\n\n- **compat:** add all utilities to internal-compatibility ([a9ecfe7](https://github.com/ReactiveX/RxJS/commit/a9ecfe7))\n- **websocket:** Add serializer/deserializer config settings ([#3489](https://github.com/ReactiveX/RxJS/issues/3489)) ([8d44124](https://github.com/ReactiveX/RxJS/commit/8d44124))\n\n### BREAKING CHANGES\n\n- **websocket:** WebSocketSubject will now JSON serialize all messages sent over it by default, to return to the old behavior, pass a config setting of `serializer: x => x` like so: `websocket({ url, serializer: x => x })`\n\n<a name=\"6.0.0-beta.3\"></a>\n\n# [6.0.0-beta.3](https://github.com/ReactiveX/RxJS/compare/6.0.0-beta.1...6.0.0-beta.3) (2018-03-27)\n\n### Bug Fixes\n\n- **build:** update build-optimizer and point to correct sources ([6717a01](https://github.com/ReactiveX/RxJS/commit/6717a01))\n- **node:** Subscriber no longer trampled if from another copy of rxjs ([371b658](https://github.com/ReactiveX/RxJS/commit/371b658))\n- **Observable:** empty ctor returns valid Observable ([#3464](https://github.com/ReactiveX/RxJS/issues/3464)) ([58b8ebc](https://github.com/ReactiveX/RxJS/commit/58b8ebc))\n- **subscribeOn:** add subscribeOn back to the distribution ([d6556f2](https://github.com/ReactiveX/RxJS/commit/d6556f2))\n\n<a name=\"6.0.0-beta.2\"></a>\n\n# [6.0.0-beta.2](https://github.com/ReactiveX/RxJS/compare/6.0.0-beta.1...6.0.0-beta.2) (2018-03-24)\n\n### Bug Fixes\n\n- **build:** update build-optimizer and point to correct sources ([6717a01](https://github.com/ReactiveX/RxJS/commit/6717a01))\n- **Observable:** empty ctor returns valid Observable ([#3464](https://github.com/ReactiveX/RxJS/issues/3464)) ([58b8ebc](https://github.com/ReactiveX/RxJS/commit/58b8ebc))\n- **subscribeOn:** add subscribeOn back to the distribution ([d6556f2](https://github.com/ReactiveX/RxJS/commit/d6556f2))\n\n<a name=\"6.0.0-beta.1\"></a>\n\n# [6.0.0-beta.1](https://github.com/ReactiveX/RxJS/compare/6.0.0-beta.0...v6.0.0-beta.1) (2018-03-21)\n\n### Bug Fixes\n\n- remove duplicate Subscribable<T> interface declaration ([#3450](https://github.com/ReactiveX/RxJS/issues/3450)) ([ac78d89](https://github.com/ReactiveX/RxJS/commit/ac78d89))\n- **compat:** add package.json for internal-compatibility package ([#3455](https://github.com/ReactiveX/RxJS/issues/3455)) ([3b306ed](https://github.com/ReactiveX/RxJS/commit/3b306ed))\n- **config.useDeprecatedSynchronousErrorThrowing:** reentrant error throwing no longer trapped ([#3449](https://github.com/ReactiveX/RxJS/issues/3449)) ([0892a2d](https://github.com/ReactiveX/RxJS/commit/0892a2d)), closes [#3161](https://github.com/ReactiveX/RxJS/issues/3161)\n\n### Features\n\n- **compat:** add interfaces export ([d8f8122](https://github.com/ReactiveX/RxJS/commit/d8f8122))\n- **compat:** add rxjs/observable/dom/\\* APIs to compatibility package ([d9a618f](https://github.com/ReactiveX/RxJS/commit/d9a618f))\n\n<a name=\"6.0.0-beta.0\"></a>\n\n# [6.0.0-beta.0](https://github.com/ReactiveX/RxJS/compare/6.0.0-alpha.3...6.0.0-beta.0) (2018-03-16)\n\n### Bug Fixes\n\n- **AjaxObservable:** 1xx,2xx,3xx requests shouldn't error, only 4xx,5xx ([#3438](https://github.com/ReactiveX/RxJS/issues/3438)) ([2128932](https://github.com/ReactiveX/RxJS/commit/2128932))\n- **compat:** adjustments to get rxjs-compat to build correctly ([dea6964](https://github.com/ReactiveX/RxJS/commit/dea6964))\n- **config:** expose configuration via rxjs exports ([#3441](https://github.com/ReactiveX/RxJS/issues/3441)) ([4287424](https://github.com/ReactiveX/RxJS/commit/4287424))\n- **config:** make sure that Promise config is undefined initially ([#3440](https://github.com/ReactiveX/RxJS/issues/3440)) ([469afe8](https://github.com/ReactiveX/RxJS/commit/469afe8))\n- **ESM:** Add [operators|ajax|websocket|testing]/package.json for ESM support, fixes [#3227](https://github.com/ReactiveX/RxJS/issues/3227) ([#3356](https://github.com/ReactiveX/RxJS/issues/3356)) ([725dcb4](https://github.com/ReactiveX/RxJS/commit/725dcb4))\n- **forkJoin:** fix forkJoin typings for forkJoin(Observable<any>[]) ([#3436](https://github.com/ReactiveX/RxJS/issues/3436)) ([17c7f8f](https://github.com/ReactiveX/RxJS/commit/17c7f8f))\n- **fromEvent:** Defines toString to fix Closure compilations ([#3417](https://github.com/ReactiveX/RxJS/issues/3417)) ([1558b43](https://github.com/ReactiveX/RxJS/commit/1558b43))\n- **fromEvent:** pass options in unsubscribe ([f1872b0](https://github.com/ReactiveX/RxJS/commit/f1872b0)), closes [#3349](https://github.com/ReactiveX/RxJS/issues/3349)\n- **publishReplay:** type inference improved ([#3437](https://github.com/ReactiveX/RxJS/issues/3437)) ([dd7c9f1](https://github.com/ReactiveX/RxJS/commit/dd7c9f1)), closes [#3260](https://github.com/ReactiveX/RxJS/issues/3260)\n- **rxjs:** add exports for symbols/interfaces that were missing ([#3380](https://github.com/ReactiveX/RxJS/issues/3380)) ([1622ee0](https://github.com/ReactiveX/RxJS/commit/1622ee0))\n- **rxjs:** make sure esm imports from index.js by default, not Rx.js ([#3316](https://github.com/ReactiveX/RxJS/issues/3316)) ([c2b00f4](https://github.com/ReactiveX/RxJS/commit/c2b00f4)), closes [#3315](https://github.com/ReactiveX/RxJS/issues/3315)\n- **rxjs:** once again exports custom error types ([#3371](https://github.com/ReactiveX/RxJS/issues/3371)) ([4465a9f](https://github.com/ReactiveX/RxJS/commit/4465a9f))\n- **rxjs:** remove types.ts importing from itself. ([#3383](https://github.com/ReactiveX/RxJS/issues/3383)) ([8fd50ad](https://github.com/ReactiveX/RxJS/commit/8fd50ad))\n- **spec:** get tests running using compatibility package ([916e968](https://github.com/ReactiveX/RxJS/commit/916e968))\n- correct internal module paths to be systemjs compatible ([#3412](https://github.com/ReactiveX/RxJS/issues/3412)) ([35abc9d](https://github.com/ReactiveX/RxJS/commit/35abc9d))\n- **Symbol.iterator:** correctly handle case where Symbol constructor itself is not defined ([#3394](https://github.com/ReactiveX/RxJS/issues/3394)) ([6725be1](https://github.com/ReactiveX/RxJS/commit/6725be1))\n- **typings:** fixed some cases where multicast and publish would not return a ConnectableObservable ([#3320](https://github.com/ReactiveX/RxJS/issues/3320)) ([ddffecc](https://github.com/ReactiveX/RxJS/commit/ddffecc))\n- reexport Symbol.observable typings patch ([4c4d7b0](https://github.com/ReactiveX/RxJS/commit/4c4d7b0))\n- remove the root operators.ts because it overshadows operators/package.json ([184b6d4](https://github.com/ReactiveX/RxJS/commit/184b6d4))\n\n### Code Refactoring\n\n- **Observable.if:** remove ts hacks from Observable ([f46f261](https://github.com/ReactiveX/RxJS/commit/f46f261))\n- **Rx.ts:** move Rx.ts to internal ([#3400](https://github.com/ReactiveX/RxJS/issues/3400)) ([7ad2119](https://github.com/ReactiveX/RxJS/commit/7ad2119))\n\n### Features\n\n- **ajax:** default to opting into CORS ([#3442](https://github.com/ReactiveX/RxJS/issues/3442)) ([aa3bf57](https://github.com/ReactiveX/RxJS/commit/aa3bf57)), closes [#3273](https://github.com/ReactiveX/RxJS/issues/3273)\n- **bindCallback:** remove result selector ([2535641](https://github.com/ReactiveX/RxJS/commit/2535641))\n- **bindNodeCallback:** remove resultSelector ([26e6e5c](https://github.com/ReactiveX/RxJS/commit/26e6e5c))\n- **compat:** add compatability package definition ([40aca82](https://github.com/ReactiveX/RxJS/commit/40aca82))\n- **compat:** add concat operator to compatibility layer ([6e84e78](https://github.com/ReactiveX/RxJS/commit/6e84e78))\n- **compat:** add legacy reexport compat layer for 'rxjs/Observable' and other top-level symbols ([70e562b](https://github.com/ReactiveX/RxJS/commit/70e562b))\n- **compat:** add Rx.ts to rxjs-compat ([df25de1](https://github.com/ReactiveX/RxJS/commit/df25de1))\n- **compat:** compatibility mode for combineLatest ([fd86df5](https://github.com/ReactiveX/RxJS/commit/fd86df5))\n- **compat:** compatibility mode for merge operator ([ffce980](https://github.com/ReactiveX/RxJS/commit/ffce980))\n- **compat:** compatibility mode for zip operator ([9f131d0](https://github.com/ReactiveX/RxJS/commit/9f131d0))\n- **compat:** make Rx.ts for compatability layer work as the default for rxjs-compat ([d43a4c2](https://github.com/ReactiveX/RxJS/commit/d43a4c2))\n- **compat:** set up correct imports & get build working for rxjs-comapt ([1a0dc97](https://github.com/ReactiveX/RxJS/commit/1a0dc97))\n- **deprecated-error-handling-warning:** add console warning when code sets the flag to bad mode ([49be56a](https://github.com/ReactiveX/RxJS/commit/49be56a))\n- **error-handling:** add deprecated sync error handling behind a flag ([583cd1d](https://github.com/ReactiveX/RxJS/commit/583cd1d))\n- **exhaustMap:** simplify interface ([42589d0](https://github.com/ReactiveX/RxJS/commit/42589d0))\n- **first:** simplify interface ([a011338](https://github.com/ReactiveX/RxJS/commit/a011338))\n- **forkJoin:** simplify interface ([4d2338b](https://github.com/ReactiveX/RxJS/commit/4d2338b))\n- **fromEvent:** remove resultSelector ([197f449](https://github.com/ReactiveX/RxJS/commit/197f449))\n- **fromEvent:** will now emit an array when event emits multiple arguments ([51b37fd](https://github.com/ReactiveX/RxJS/commit/51b37fd))\n- **fromEventPattern:** removed resultSelector ([6b34f9f](https://github.com/ReactiveX/RxJS/commit/6b34f9f))\n- **last:** simplify interface ([3240419](https://github.com/ReactiveX/RxJS/commit/3240419))\n- **mergeMap|concatMap|concatMapTo:** simplified the signatures ([d293245](https://github.com/ReactiveX/RxJS/commit/d293245))\n- **mergeMapTo:** simplify interface ([582c7be](https://github.com/ReactiveX/RxJS/commit/582c7be))\n- **never:** no longer export `never` function ([#3386](https://github.com/ReactiveX/RxJS/issues/3386)) ([53debc8](https://github.com/ReactiveX/RxJS/commit/53debc8))\n- **switchMap|switchMapTo:** simplify interface ([959fb6a](https://github.com/ReactiveX/RxJS/commit/959fb6a))\n- **Symbol.iterator:** no longer polyfilled ([#3389](https://github.com/ReactiveX/RxJS/issues/3389)) ([6319f3c](https://github.com/ReactiveX/RxJS/commit/6319f3c))\n- **Symbol.observable:** is no longer polyfilled ([#3387](https://github.com/ReactiveX/RxJS/issues/3387)) ([4a5aaaf](https://github.com/ReactiveX/RxJS/commit/4a5aaaf))\n- **throwIfEmpty:** adds throwIfEmpty operator ([#3368](https://github.com/ReactiveX/RxJS/issues/3368)) ([9b21458](https://github.com/ReactiveX/RxJS/commit/9b21458))\n- **typings:** updated typings for combineAll, mergeAll, concatAll, switch, exhaust, zipAll ([#3321](https://github.com/ReactiveX/RxJS/issues/3321)) ([f7e4c02](https://github.com/ReactiveX/RxJS/commit/f7e4c02))\n- **umd:** UMD now mirrors export schema for ESM and CJS ([#3426](https://github.com/ReactiveX/RxJS/issues/3426)) ([556c904](https://github.com/ReactiveX/RxJS/commit/556c904))\n\n### BREAKING CHANGES\n\n- **ajax:** will no longer execute a CORS request by default, you must opt-in with the `crossDomain` flag in the config.\n- **mergeMap|concatMap|concatMapTo:** mergeMap, concatMap and concatMapTo no longer support a result selector, if you need to use a result selector, use the following pattern: `source.mergeMap(x => of(x + x).pipe(map(y => y + x))` (the pattern would be the same for `concatMap`).\n- **never:** no longer exported. Use the `NEVER` constant instead.\n- **bindCallback:** removes result selector, use `map` instead: `bindCallback(fn1, fn2)()` becomes `bindCallback(fn1)().pipe(map(fn2))`\n- **Rx.ts:** importing from `rxjs/Rx` is no longer available. Upcoming backwards compat solution will allow that\n- **Symbol.iterator:** We are no longer polyfilling `Symbol.iterator`. That would be done by a proper polyfilling library\n- **Observable.if:** TypeScript users using `Observable.if` will have to cast `Observable` as any to get to `if`. It is a better idea to just use `iif` directly via `import { iif } from 'rxjs';`\n- **bindNodeCallback:** resultSelector removed, use `map` instead: `bindNodeCallback(fn1, fn2)()` becomes `bindNodeCallback(fn1)().pipe(map(fn2))`\n- **Symbol.observable:** RxJS will no longer be polyfilling Symbol.observable. That should be done by an actual polyfill library. This is to prevent duplication of code, and also to prevent having modules with side-effects in rxjs.\n- **fromEvent:** result selector removed, use `map` instead: `fromEvent(target, 'click', fn)` becomes `fromEvent(target, 'click').pipe(map(fn))`\n- **last:** no longer accepts `resultSelector` argument. To get this same functionality, use `map`.\n- **first:** no longer supports `resultSelector` argument. The same functionality can be achieved by simply mapping either before or after `first` depending on your use case.\n- **exhaustMap:** `resultSelector` no longer supported, to get this functionality use: `source.pipe(exhaustMap(x => of(x + x).pipe(map(y => x + y))))`\n- **switchMap|switchMapTo:** `switchMap` and `switchMapTo` no longer take `resultSelector` arguments, to get the same functionality use `switchMap` and `map` in combination: `source.pipe(switchMap(x => of(x + x).pipe(y => x + y)))`.\n- **mergeMapTo:** `mergeMapTo` no longer accepts a resultSelector, to get this functionality, you'll want to use `mergeMap` and `map` together: `source.pipe(mergeMap(() => inner).pipe(map(y => x + y)))`\n- **fromEventPattern:** no longer supports a result selector, use `map` instead: `fromEventPattern(fn1, fn2, fn3)` becomes `fromEventPattern(fn1, fn2).pipe(map(fn3))`\n\n<a name=\"6.0.0-alpha.4\"></a>\n\n# [6.0.0-alpha.4](https://github.com/ReactiveX/RxJS/compare/6.0.0-alpha.3...v6.0.0-alpha.4) (2018-03-13)\n\n### Bug Fixes\n\n- **ESM:** Add [operators|ajax|websocket|testing]/package.json for ESM support, fixes [#3227](https://github.com/ReactiveX/RxJS/issues/3227) ([#3356](https://github.com/ReactiveX/RxJS/issues/3356)) ([725dcb4](https://github.com/ReactiveX/RxJS/commit/725dcb4))\n- **fromEvent:** Defines toString to fix Closure compilations ([#3417](https://github.com/ReactiveX/RxJS/issues/3417)) ([1558b43](https://github.com/ReactiveX/RxJS/commit/1558b43))\n- **fromEvent:** pass options in unsubscribe ([f1872b0](https://github.com/ReactiveX/RxJS/commit/f1872b0)), closes [#3349](https://github.com/ReactiveX/RxJS/issues/3349)\n- **rxjs:** add exports for symbols/interfaces that were missing ([#3380](https://github.com/ReactiveX/RxJS/issues/3380)) ([1622ee0](https://github.com/ReactiveX/RxJS/commit/1622ee0))\n- **rxjs:** make sure esm imports from index.js by default, not Rx.js ([#3316](https://github.com/ReactiveX/RxJS/issues/3316)) ([c2b00f4](https://github.com/ReactiveX/RxJS/commit/c2b00f4)), closes [#3315](https://github.com/ReactiveX/RxJS/issues/3315)\n- **rxjs:** once again exports custom error types ([#3371](https://github.com/ReactiveX/RxJS/issues/3371)) ([4465a9f](https://github.com/ReactiveX/RxJS/commit/4465a9f))\n- **rxjs:** remove types.ts importing from itself. ([#3383](https://github.com/ReactiveX/RxJS/issues/3383)) ([8fd50ad](https://github.com/ReactiveX/RxJS/commit/8fd50ad))\n- correct internal module paths to be systemjs compatible ([#3412](https://github.com/ReactiveX/RxJS/issues/3412)) ([35abc9d](https://github.com/ReactiveX/RxJS/commit/35abc9d))\n- **Symbol.iterator:** correctly handle case where Symbol constructor itself is not defined ([#3394](https://github.com/ReactiveX/RxJS/issues/3394)) ([6725be1](https://github.com/ReactiveX/RxJS/commit/6725be1))\n- **typings:** fixed some cases where multicast and publish would not return a ConnectableObservable ([#3320](https://github.com/ReactiveX/RxJS/issues/3320)) ([ddffecc](https://github.com/ReactiveX/RxJS/commit/ddffecc))\n- reexport Symbol.observable typings patch ([4c4d7b0](https://github.com/ReactiveX/RxJS/commit/4c4d7b0))\n- remove the root operators.ts because it overshadows operators/package.json ([184b6d4](https://github.com/ReactiveX/RxJS/commit/184b6d4))\n\n### Code Refactoring\n\n- **Observable.if:** remove ts hacks from Observable ([f46f261](https://github.com/ReactiveX/RxJS/commit/f46f261))\n- **Rx.ts:** move Rx.ts to internal ([#3400](https://github.com/ReactiveX/RxJS/issues/3400)) ([7ad2119](https://github.com/ReactiveX/RxJS/commit/7ad2119))\n\n### Features\n\n- **bindCallback:** remove result selector ([2535641](https://github.com/ReactiveX/RxJS/commit/2535641))\n- **bindNodeCallback:** remove resultSelector ([26e6e5c](https://github.com/ReactiveX/RxJS/commit/26e6e5c))\n- **exhaustMap:** simplify interface ([42589d0](https://github.com/ReactiveX/RxJS/commit/42589d0))\n- **first:** simplify interface ([a011338](https://github.com/ReactiveX/RxJS/commit/a011338))\n- **forkJoin:** simplify interface ([4d2338b](https://github.com/ReactiveX/RxJS/commit/4d2338b))\n- **fromEvent:** remove resultSelector ([197f449](https://github.com/ReactiveX/RxJS/commit/197f449))\n- **fromEvent:** will now emit an array when event emits multiple arguments ([51b37fd](https://github.com/ReactiveX/RxJS/commit/51b37fd))\n- **fromEventPattern:** removed resultSelector ([6b34f9f](https://github.com/ReactiveX/RxJS/commit/6b34f9f))\n- **last:** simplify interface ([3240419](https://github.com/ReactiveX/RxJS/commit/3240419))\n- **mergeMap|concatMap|concatMapTo:** simplified the signatures ([d293245](https://github.com/ReactiveX/RxJS/commit/d293245))\n- **mergeMapTo:** simplify interface ([582c7be](https://github.com/ReactiveX/RxJS/commit/582c7be))\n- **never:** no longer export `never` function ([#3386](https://github.com/ReactiveX/RxJS/issues/3386)) ([53debc8](https://github.com/ReactiveX/RxJS/commit/53debc8))\n- **switchMap|switchMapTo:** simplify interface ([959fb6a](https://github.com/ReactiveX/RxJS/commit/959fb6a))\n- **Symbol.iterator:** no longer polyfilled ([#3389](https://github.com/ReactiveX/RxJS/issues/3389)) ([6319f3c](https://github.com/ReactiveX/RxJS/commit/6319f3c))\n- **Symbol.observable:** is no longer polyfilled ([#3387](https://github.com/ReactiveX/RxJS/issues/3387)) ([4a5aaaf](https://github.com/ReactiveX/RxJS/commit/4a5aaaf))\n- **throwIfEmpty:** adds throwIfEmpty operator ([#3368](https://github.com/ReactiveX/RxJS/issues/3368)) ([9b21458](https://github.com/ReactiveX/RxJS/commit/9b21458))\n- **typings:** updated typings for combineAll, mergeAll, concatAll, switch, exhaust, zipAll ([#3321](https://github.com/ReactiveX/RxJS/issues/3321)) ([f7e4c02](https://github.com/ReactiveX/RxJS/commit/f7e4c02))\n- **umd:** UMD now mirrors export schema for ESM and CJS ([#3426](https://github.com/ReactiveX/RxJS/issues/3426)) ([556c904](https://github.com/ReactiveX/RxJS/commit/556c904))\n\n### BREAKING CHANGES\n\n- **Symbol.observable:** RxJS will no longer be polyfilling Symbol.observable. That should be done by an actual polyfill library. This is to prevent duplication of code, and also to prevent having modules with side-effects in rxjs.\n- **mergeMap|concatMap|concatMapTo:** mergeMap, concatMap and concatMapTo no longer support a result selector, if you need to use a result selector, use the following pattern: `source.mergeMap(x => of(x + x).pipe(map(y => y + x))` (the pattern would be the same for `concatMap`).\n- **bindCallback:** removes result selector, use `map` instead: `bindCallback(fn1, fn2)()` becomes `bindCallback(fn1)().pipe(map(fn2))`\n- **Rx.ts:** importing from `rxjs/Rx` is no longer available. Upcoming backwards compat solution will allow that\n- **Symbol.iterator:** We are no longer polyfilling `Symbol.iterator`. That would be done by a proper polyfilling library\n- **Observable.if:** TypeScript users using `Observable.if` will have to cast `Observable` as any to get to `if`. It is a better idea to just use `iif` directly via `import { iif } from 'rxjs';`\n- **bindNodeCallback:** resultSelector removed, use `map` instead: `bindNodeCallback(fn1, fn2)()` becomes `bindNodeCallback(fn1)().pipe(map(fn2))`\n- **never:** no longer exported. Use the `NEVER` constant instead.\n- **fromEvent:** result selector removed, use `map` instead: `fromEvent(target, 'click', fn)` becomes `fromEvent(target, 'click').pipe(map(fn))`\n- **last:** no longer accepts `resultSelector` argument. To get this same functionality, use `map`.\n- **first:** no longer supports `resultSelector` argument. The same functionality can be achieved by simply mapping either before or after `first` depending on your use case.\n- **exhaustMap:** `resultSelector` no longer supported, to get this functionality use: `source.pipe(exhaustMap(x => of(x + x).pipe(map(y => x + y))))`\n- **switchMap|switchMapTo:** `switchMap` and `switchMapTo` no longer take `resultSelector` arguments, to get the same functionality use `switchMap` and `map` in combination: `source.pipe(switchMap(x => of(x + x).pipe(y => x + y)))`.\n- **mergeMapTo:** `mergeMapTo` no longer accepts a resultSelector, to get this functionality, you'll want to use `mergeMap` and `map` together: `source.pipe(mergeMap(() => inner).pipe(map(y => x + y)))`\n- **fromEventPattern:** no longer supports a result selector, use `map` instead: `fromEventPattern(fn1, fn2, fn3)` becomes `fromEventPattern(fn1, fn2).pipe(map(fn3))`\n\n<a name=\"6.0.0-alpha.3\"></a>\n\n# [6.0.0-alpha.3](https://github.com/ReactiveX/RxJS/compare/6.0.0-alpha.2...v6.0.0-alpha.3) (2018-02-06)\n\n### Bug Fixes\n\n- **animationFrame.spec:** spec description fix ([#3140](https://github.com/ReactiveX/RxJS/issues/3140)) ([ab6c325](https://github.com/ReactiveX/RxJS/commit/ab6c325))\n- **debounce:** support scalar selectors ([#3236](https://github.com/ReactiveX/RxJS/issues/3236)) ([1548393](https://github.com/ReactiveX/RxJS/commit/1548393)), closes [#3232](https://github.com/ReactiveX/RxJS/issues/3232)\n- **forkJoin:** catch and forward selector errors ([#3261](https://github.com/ReactiveX/RxJS/issues/3261)) ([e57bbb7](https://github.com/ReactiveX/RxJS/commit/e57bbb7)), closes [#3216](https://github.com/ReactiveX/RxJS/issues/3216)\n- **Observable:** expose pipe rest parameter overload ([#3292](https://github.com/ReactiveX/RxJS/issues/3292)) ([7ff5bc3](https://github.com/ReactiveX/RxJS/commit/7ff5bc3))\n- **onErrorResumeNext:** no longer holds onto subscriptions too long ([abbbdad](https://github.com/ReactiveX/RxJS/commit/abbbdad)), closes [#3178](https://github.com/ReactiveX/RxJS/issues/3178)\n- **scheduler:** prevent unwanted clearInterval ([#3226](https://github.com/ReactiveX/RxJS/issues/3226)) ([d7cfb42](https://github.com/ReactiveX/RxJS/commit/d7cfb42)), closes [#3042](https://github.com/ReactiveX/RxJS/issues/3042)\n- **timer:** multiple subscriptions to timer(Date) behaves correctly ([aafa7ff](https://github.com/ReactiveX/RxJS/commit/aafa7ff)), closes [#3252](https://github.com/ReactiveX/RxJS/issues/3252)\n- **typings:** correct compilation warnings from missing types in tests ([3aad6bc](https://github.com/ReactiveX/RxJS/commit/3aad6bc))\n- **typings:** relax debounce selector type ([c419ab4](https://github.com/ReactiveX/RxJS/commit/c419ab4)), closes [#3164](https://github.com/ReactiveX/RxJS/issues/3164)\n- **typings:** relax throttle selector type ([#3205](https://github.com/ReactiveX/RxJS/issues/3205)) ([e83fda7](https://github.com/ReactiveX/RxJS/commit/e83fda7)), closes [#3204](https://github.com/ReactiveX/RxJS/issues/3204)\n- **typings:** the return type of factory of defer should be ObservableInput<T> ([#3211](https://github.com/ReactiveX/RxJS/issues/3211)) ([dc41a5e](https://github.com/ReactiveX/RxJS/commit/dc41a5e))\n\n### Features\n\n- **empty:** empty() returns the same instance ([5c7c749](https://github.com/ReactiveX/RxJS/commit/5c7c749))\n- **EMPTY:** observable constant EMPTY now exported ([08fb074](https://github.com/ReactiveX/RxJS/commit/08fb074))\n- **never:** always return the same instance ([#3249](https://github.com/ReactiveX/RxJS/issues/3249)) ([d57fa52](https://github.com/ReactiveX/RxJS/commit/d57fa52))\n- **rxjs:** move rxjs/create into rxjs ([#3299](https://github.com/ReactiveX/RxJS/issues/3299)) ([6711fe2](https://github.com/ReactiveX/RxJS/commit/6711fe2))\n- **throwError:** functional version of throwError ([639236e](https://github.com/ReactiveX/RxJS/commit/639236e))\n\n### BREAKING CHANGES\n\n- **rxjs:** `rxjs/create` items are now exported from `rxjs`\n- **throwError:** Observable.throw no longer available in TypeScript without a cast\n- **empty:** `empty()` without a scheduler will return the same\n  instance every time.\n- **empty:** In TypeScript, `empty()` no longer accepts a generic\n  argument, as it returns `Observable<never>`\n- **never:** `never()` always returns the same instance\n- **never:** TypeScript typing for `never()` is now `Observable<never>` and the function no longer requires a generic type.\n\n<a name=\"6.0.0-alpha.2\"></a>\n\n# [6.0.0-alpha.2](https://github.com/ReactiveX/RxJS/compare/6.0.0-alpha.1...6.0.0-alpha.2) (2018-01-14)\n\n### Bug Fixes\n\n- **build:** properly outputs subdirectories like `rxjs/operators` ([34fe560](https://github.com/ReactiveX/RxJS/commit/34fe560))\n\n<a name=\"6.0.0-alpha.1\"></a>\n\n# [6.0.0-alpha.1](https://github.com/ReactiveX/RxJS/compare/5.5.3...v6.0.0-alpha.1) (2018-01-12)\n\n### Bug Fixes\n\n- Revert \"fix(scheduler): prevent unwanted clearInterval ([#3044](https://github.com/ReactiveX/RxJS/issues/3044))\" ([ad5c7c6](https://github.com/ReactiveX/RxJS/commit/ad5c7c6))\n- Revert \"fix(scheduler): prevent unwanted clearInterval ([#3044](https://github.com/ReactiveX/RxJS/issues/3044))\" ([64f9285](https://github.com/ReactiveX/RxJS/commit/64f9285))\n- **debounceTime:** synchronous reentrancy of debounceTime no longer swallows the second value ([#3218](https://github.com/ReactiveX/RxJS/issues/3218)) ([598e9ce](https://github.com/ReactiveX/RxJS/commit/598e9ce)), closes [#2748](https://github.com/ReactiveX/RxJS/issues/2748)\n- **dependency:** move symbol-observable into devdependency ([4400628](https://github.com/ReactiveX/RxJS/commit/4400628))\n- **IteratorObservable:** get new iterator for each subscription ([#2497](https://github.com/ReactiveX/RxJS/issues/2497)) ([1bd0a58](https://github.com/ReactiveX/RxJS/commit/1bd0a58)), closes [#2496](https://github.com/ReactiveX/RxJS/issues/2496)\n- **Observable.toArray:** Fix toArray with multiple subscriptions. ([#3134](https://github.com/ReactiveX/RxJS/issues/3134)) ([3390926](https://github.com/ReactiveX/RxJS/commit/3390926))\n- **SystemJS:** avoid node module resolution of pipeable operators ([#3025](https://github.com/ReactiveX/RxJS/issues/3025)) ([0f3cf71](https://github.com/ReactiveX/RxJS/commit/0f3cf71)), closes [#2971](https://github.com/ReactiveX/RxJS/issues/2971) [#2996](https://github.com/ReactiveX/RxJS/issues/2996) [#3011](https://github.com/ReactiveX/RxJS/issues/3011)\n- **tap:** make next optional ([#3073](https://github.com/ReactiveX/RxJS/issues/3073)) ([e659f0c](https://github.com/ReactiveX/RxJS/commit/e659f0c)), closes [#2534](https://github.com/ReactiveX/RxJS/issues/2534)\n- **TSC:** Fixing TSC errors. Fixes [#3020](https://github.com/ReactiveX/RxJS/issues/3020) ([01d1575](https://github.com/ReactiveX/RxJS/commit/01d1575))\n- **typings:** the return type of project of mergeScan should be ObservableInput<R> ([23fe17d](https://github.com/ReactiveX/RxJS/commit/23fe17d))\n\n### Chores\n\n- **TypeScript:** Bump up typescript to latest ([#3009](https://github.com/ReactiveX/RxJS/issues/3009)) ([2f395da](https://github.com/ReactiveX/RxJS/commit/2f395da))\n\n### Code Refactoring\n\n- **asap:** Remove setImmediate polyfill ([5eb6af7](https://github.com/ReactiveX/RxJS/commit/5eb6af7))\n- **distinct:** Remove Set polyfill ([68ee499](https://github.com/ReactiveX/RxJS/commit/68ee499))\n- **groupBy:** Remove Map polyfill ([74b5b1a](https://github.com/ReactiveX/RxJS/commit/74b5b1a))\n\n### Features\n\n- **Observable:** unhandled errors are now reported to HostReportErrors ([#3062](https://github.com/ReactiveX/RxJS/issues/3062)) ([cd9626a](https://github.com/ReactiveX/RxJS/commit/cd9626a))\n- **reorganize:** move ./interfaces.ts to internal/types.ts ([cfbfaac](https://github.com/ReactiveX/RxJS/commit/cfbfaac))\n- **reorganize:** internal utils hidden ([70058cd](https://github.com/ReactiveX/RxJS/commit/70058cd))\n- **reorganize:** add `rxjs/create` exports ([c9963bd](https://github.com/ReactiveX/RxJS/commit/c9963bd))\n- **reorganize:** ajax observable creator now exported from `rxjs/ajax` ([e971c93](https://github.com/ReactiveX/RxJS/commit/e971c93))\n- **reorganize:** all patch operators moved to `internal` directory ([7342401](https://github.com/ReactiveX/RxJS/commit/7342401))\n- **reorganize:** export `noop` and `identity` from `rxjs` ([810c4d0](https://github.com/ReactiveX/RxJS/commit/810c4d0))\n- **reorganize:** export `Notification` from `rxjs` ([8809b48](https://github.com/ReactiveX/RxJS/commit/8809b48))\n- **reorganize:** export schedulers from `rxjs` ([abd3b61](https://github.com/ReactiveX/RxJS/commit/abd3b61))\n- **reorganize:** export Subject, ReplaySubject, BehaviorSubject from rxjs ([bd683ca](https://github.com/ReactiveX/RxJS/commit/bd683ca))\n- **reorganize:** export the `pipe` utility function from `rxjs` ([4574310](https://github.com/ReactiveX/RxJS/commit/4574310))\n- **reorganize:** hid testing implementation details ([b981666](https://github.com/ReactiveX/RxJS/commit/b981666))\n- **reorganize:** move observable implementations under internal directory ([2d5c3f8](https://github.com/ReactiveX/RxJS/commit/2d5c3f8))\n- **reorganize:** move operator impls under internal directory ([207976f](https://github.com/ReactiveX/RxJS/commit/207976f))\n- **reorganize:** move top-level impls under internal directory ([c3bb705](https://github.com/ReactiveX/RxJS/commit/c3bb705))\n- **reorganize:** moved symbols to be internal ([80783ab](https://github.com/ReactiveX/RxJS/commit/80783ab))\n- **reorganize:** operators all exported from `rxjs/operators` ([b1f8bfe](https://github.com/ReactiveX/RxJS/commit/b1f8bfe))\n- **reorganize:** websocket subject creator now exported from `rxjs/websocket` ([5ac62c0](https://github.com/ReactiveX/RxJS/commit/5ac62c0))\n\n### BREAKING CHANGES\n\n- **webSocket:** `webSocket` creator function now exported from `rxjs/websocket` as `websocket`.\n- **IteratorObservable:** IteratorObservable no longer share iterator between\n  subscription\n- **utils:** Many internal use utilities like `isArray` are now hidden under `rxjs/internal`, they are implementation details and should not be used.\n- **testing observables:** `HotObservable` and `ColdObservable`, and other testing support types are no longer exported directly.\n- **creation functions:** All create functions such as `of`, `from`, `combineLatest` and `fromEvent` should now be imported from `rxjs/create`.\n- **types and interfaces:** Can no longer explicitly import types from `rxjs/interfaces`, import them from `rxjs` instead\n- **symbols:** Symbols are no longer exported directly from modules such as `rxjs/symbol/observable` please use `Symbol.observable` and `Symbol.iterator` (polyfills may be required)\n- **deep imports:** Can no longer deep import top-level types such as `rxjs/Observable`, `rxjs/Subject`, `rxjs/ReplaySubject`, et al. All imports should be done directly from `rxjs`, for example: `import \\{ Observable, Subject \\} from 'rxjs';`\n- **schedulers:** Scheduler instances have changed names to be suffixed with `Scheduler`, (e.g. `asap` -> `asapScheduler`)\n- **operators:** Pipeable operators must now be imported from `rxjs`\n  like so: `import { map, filter, switchMap } from 'rxjs/operators';`. No deep imports.\n- **ajax:** Ajax observable should be imported from `rxjs/ajax`.\n- **Observable:** You should no longer deep import custom Observable\n  implementations such as `ArrayObservable` or `ForkJoinObservable`.\n- **\\_throw:** `_throw` is now exported as `throwError`\n- **if:** `if` is now exported as `iif`\n- **operators:** Deep imports to `rxjs/operator/*` will no longer work. Again, pipe operators are still where they were.\n- **error handling:** Unhandled errors are no longer caught and rethrown, rather they are caught and scheduled to be thrown, which causes them to be reported to window.onerror or process.on('error'), depending on the environment. Consequently, teardown after a synchronous, unhandled, error will no longer occur, as the teardown would not exist, and producer interference cannot occur\n- **distinct:** Using `distinct` requires a `Set` implementation and must be polyfilled in older runtimes\n- **asap:** Old runtimes must polyfill Promise in order to use ASAP scheduling.\n- **groupBy:** Older runtimes will require Map to be polyfilled to use\n  `groupBy`\n- **TypeScript:** IE10 and lower will need to polyfill `Object.setPrototypeOf`\n- **operators removed:** Operator versions of static observable creators such as\n  `merge`, `concat`, `zip`, `onErrorResumeNext`, and `race` have been\n  removed. Please use the static versions of those operations. e.g.\n  `a.pipe(concat(b, c))` becomes `concat(a, b, c)`.\n\n<a name=\"5.5.6\"></a>\n\n## [5.5.6](https://github.com/ReactiveX/RxJS/compare/5.5.5...v5.5.6) (2017-12-21)\n\n### Bug Fixes\n\n- **Observable:** rethrow errors when syncErrorThrowable and inherit it from destination. Fixes [#2813](https://github.com/ReactiveX/RxJS/issues/2813) ([541b49d](https://github.com/ReactiveX/RxJS/commit/541b49d))\n\n<a name=\"5.5.5\"></a>\n\n## [5.5.5](https://github.com/ReactiveX/RxJS/compare/5.5.4...v5.5.5) (2017-12-06)\n\n### Support Added\n\n- **Bazel:** Add files to support users that want Bazel builds with RxJS ([12dac3b](https://github.com/ReactiveX/rxjs/commit/12dac3b))\n\n<a name=\"5.5.4\"></a>\n\n## [5.5.4](https://github.com/ReactiveX/RxJS/compare/5.5.3...v5.5.4) (2017-12-05)\n\n### Bug Fixes\n\n- **scheduler:** resolve regression on angular router with zones ([#3158](https://github.com/ReactiveX/RxJS/issues/3158)) ([520b06a](https://github.com/ReactiveX/RxJS/commit/520b06a))\n- **publish:** re-publish after having built with proper version of TypeScript. ([f0ff5bc](https://github.com/ReactiveX/RxJS/commit/f0ff5bc), closes[#3155](https://github.com/ReactiveX/rxjs/issues/3155))\n\n<a name=\"5.5.3\"></a>\n\n## [5.5.3](https://github.com/ReactiveX/RxJS/compare/5.5.2...v5.5.3) (2017-12-01)\n\n### Bug Fixes\n\n- **concatStatic:** missing exports for mergeStatic and concatStatic ([#2999](https://github.com/ReactiveX/RxJS/issues/2999)) ([cae5f9b](https://github.com/ReactiveX/RxJS/commit/cae5f9b))\n- **scheduler:** prevent unwanted clearInterval ([#3044](https://github.com/ReactiveX/RxJS/issues/3044)) ([7d722d4](https://github.com/ReactiveX/RxJS/commit/7d722d4)), closes [#3042](https://github.com/ReactiveX/RxJS/issues/3042)\n- **SystemJS:** avoid node module resolution of pipeable operators ([#3025](https://github.com/ReactiveX/RxJS/issues/3025)) ([d77e3d7](https://github.com/ReactiveX/RxJS/commit/d77e3d7)), closes [#2971](https://github.com/ReactiveX/RxJS/issues/2971) [#2996](https://github.com/ReactiveX/RxJS/issues/2996) [#3011](https://github.com/ReactiveX/RxJS/issues/3011)\n- **typings:** fix subscribe overloads ([#3053](https://github.com/ReactiveX/RxJS/issues/3053)) ([1a9fd42](https://github.com/ReactiveX/RxJS/commit/1a9fd42)), closes [#3052](https://github.com/ReactiveX/RxJS/issues/3052)\n\n<a name=\"5.5.2\"></a>\n\n## [5.5.2](https://github.com/ReactiveX/RxJS/compare/5.5.1...v5.5.2) (2017-10-25)\n\n### Bug Fixes\n\n- **package:** fixed import failures in Webpack ([#2987](https://github.com/ReactiveX/RxJS/issues/2987)) ([e16202d](https://github.com/ReactiveX/RxJS/commit/e16202d))\n- **typings:** improved type inference for arguments to publishReplay ([#2992](https://github.com/ReactiveX/RxJS/issues/2992)) ([0753ff7](https://github.com/ReactiveX/RxJS/commit/0753ff7)), closes [#2991](https://github.com/ReactiveX/RxJS/issues/2991)\n- **typings:** ensure TS types for `zip` and `combineLatest` are properly inferred. ([b8e6cf8](https://github.com/ReactiveX/RxJS/commit/b8e6cf8))\n- **typings:** publish variants will properly return ConnectableObservable([#2983](https://github.com/ReactiveX/RxJS/issues/2983)) ([d563bfa](https://github.com/ReactiveX/RxJS/commit/d563bfa))\n\n<a name=\"5.5.1\"></a>\n\n## [5.5.1](https://github.com/ReactiveX/RxJS/compare/5.5.0...v5.5.1) (2017-10-24)\n\n### Bug Fixes\n\n- **build:** Remove `module` and `es2015` keys to avoid resolution conflicts ([5073139](https:/github.com/ReactiveX/RxJS/commit/5073139))\n- **ajaxobservable:** fix operator import path ([d9b62ed](https://github.com/ReactiveX/RxJS/commit/d9b62ed))\n\n<a name=\"5.5.0\"></a>\n\n# [5.5.0](https://github.com/ReactiveX/RxJS/compare/5.5.0-beta.7...v5.5.0) (2017-10-18)\n\n### Bug Fixes\n\n- **build:** CJS sourceMaps now inlined into sourcesContent ([39b4af5](https://github.com/ReactiveX/RxJS/commit/39b4af5)), closes [#2934](https://github.com/ReactiveX/RxJS/issues/2934)\n\n### Features\n\n- **publishReplay:** add selector function to publishReplay ([#2885](https://github.com/ReactiveX/RxJS/issues/2885)) ([e0efd13](https://github.com/ReactiveX/RxJS/commit/e0efd13))\n\n<a name=\"5.5.0-beta.7\"></a>\n\n# [5.5.0-beta.7](https://github.com/ReactiveX/RxJS/compare/5.5.0-beta.5...5.5.0-beta.7) (2017-10-13)\n\n(Due to a publish snafu, there is no 5.5.0-beta.6) (womp womp 👎)\n\n### Bug Fixes\n\n- **build:** sourceMaps updated to support CJS properly again ([75f7f11](https://github.com/ReactiveX/RxJS/commit/75f7f11)), closes [#2934](https://github.com/ReactiveX/RxJS/issues/2934)\n- **flatMap:** reexport flatMap as alias of mergeMap ([#2920](https://github.com/ReactiveX/RxJS/issues/2920)) ([9922c02](https://github.com/ReactiveX/RxJS/commit/9922c02))\n- **publish:** correct the name and republish to sync packages ([464b115](https://github.com/ReactiveX/RxJS/commit/464b115))\n- **shareReplay:** no longer exporting function unnecessarily ([#2928](https://github.com/ReactiveX/RxJS/issues/2928)) ([e159578](https://github.com/ReactiveX/RxJS/commit/e159578))\n- **shareReplay:** properly uses `lift` ([#2924](https://github.com/ReactiveX/RxJS/issues/2924)) ([3d9cf87](https://github.com/ReactiveX/RxJS/commit/3d9cf87)), closes [#2921](https://github.com/ReactiveX/RxJS/issues/2921)\n- **toPromise:** include toPromise in build output ([#2923](https://github.com/ReactiveX/RxJS/issues/2923)) ([f55bfa5](https://github.com/ReactiveX/RxJS/commit/f55bfa5)), closes [#2922](https://github.com/ReactiveX/RxJS/issues/2922)\n\n<a name=\"5.5.0-beta.5\"></a>\n\n# [5.5.0-beta.5](https://github.com/ReactiveX/RxJS/compare/5.5.0-beta.4...v5.5.0-beta.5) (2017-10-06)\n\n### Bug Fixes\n\n- **toPromise:** remove lettable version of toPromise ([031edca](https://github.com/ReactiveX/RxJS/commit/031edca)), closes [#2868](https://github.com/ReactiveX/RxJS/issues/2868)\n\n### Features\n\n- **toPromise:** now exists as a permanent method on Observable ([2e49a5c](https://github.com/ReactiveX/RxJS/commit/2e49a5c))\n\n<a name=\"5.5.0-beta.4\"></a>\n\n# [5.5.0-beta.4](https://github.com/ReactiveX/RxJS/compare/5.5.0-beta.3...v5.5.0-beta.4) (2017-10-06)\n\n### Bug Fixes\n\n- **publish:** fix selector typings ([#2891](https://github.com/ReactiveX/RxJS/issues/2891)) ([9ee234d](https://github.com/ReactiveX/RxJS/commit/9ee234d)), closes [#2889](https://github.com/ReactiveX/RxJS/issues/2889)\n- **shareReplay:** properly retains history on subscribe ([#2910](https://github.com/ReactiveX/RxJS/issues/2910)) ([accbcd0](https://github.com/ReactiveX/RxJS/commit/accbcd0)), closes [#2908](https://github.com/ReactiveX/RxJS/issues/2908)\n- **subscribeOn:** remove subscribeOn from reexport to support treesha… ([#2899](https://github.com/ReactiveX/RxJS/issues/2899)) ([fb51a02](https://github.com/ReactiveX/RxJS/commit/fb51a02))\n\n<a name=\"5.5.0-beta.3\"></a>\n\n# [5.5.0-beta.3](https://github.com/ReactiveX/RxJS/compare/5.5.0-beta.2...v5.5.0-beta.3) (2017-10-03)\n\n### Bug Fixes\n\n- **build:** revert to 5.4.x build output for CJS & add configurable support for ESM ([#2878](https://github.com/ReactiveX/RxJS/issues/2878)) ([167456a](https://github.com/ReactiveX/RxJS/commit/167456a))\n- **concatAll:** use higher-order lettable version of concatAll ([60c96ab](https://github.com/ReactiveX/RxJS/commit/60c96ab))\n- **mergeAll:** use higher-order lettable version of mergeAll ([f0b703b](https://github.com/ReactiveX/RxJS/commit/f0b703b))\n\n<a name=\"5.5.0-beta.2\"></a>\n\n# [5.5.0-beta.2](https://github.com/ReactiveX/RxJS/compare/5.5.0-beta.1...v5.5.0-beta.2) (2017-09-27)\n\n### Bug Fixes\n\n- **build:** make CJS references to import X from '../operators' work correctly with SystemJS ([#2874](https://github.com/ReactiveX/RxJS/issues/2874)) ([3dd4cc4](https://github.com/ReactiveX/RxJS/commit/3dd4cc4))\n\n<a name=\"5.5.0-beta.1\"></a>\n\n# [5.5.0-beta.1](https://github.com/ReactiveX/RxJS/compare/5.5.0-beta.0...v5.5.0-beta.1) (2017-09-27)\n\n### Bug Fixes\n\n- **package:** published from a Linux machine to prevent a strange issue where\n  the Observable directory was not showing up when installed on some Linux\n  environments.\n- **build:** fix source maps by adding back sources and fixing path ([#2872](https://github.com/ReactiveX/RxJS/issues/2872)) ([daaf424](https://github.com/ReactiveX/RxJS/commit/daaf424))\n- **package:** remove src directory and fix typings location ([#2866](https://github.com/ReactiveX/RxJS/issues/2866)) ([c57eea7](https://github.com/ReactiveX/RxJS/commit/c57eea7))\n\n### Features\n\n- **global:** export lettables as Rx.operators ([#2862](https://github.com/ReactiveX/RxJS/issues/2862)) ([ba2f586](https://github.com/ReactiveX/RxJS/commit/ba2f586)), closes [#2861](https://github.com/ReactiveX/RxJS/issues/2861)\n\n<a name=\"5.5.0-beta.0\"></a>\n\n# [5.5.0-beta.0](https://github.com/ReactiveX/RxJS/compare/5.4.3...5.5.0-beta.0) (2017-09-22)\n\n**Important! Checkout the explanation of the new [lettable operators features here](doc/lettable-operators.md)**\n\n### Bug Fixes\n\n- **package:** correct errors generated during rollup for UMD generation ([#2839](https://github.com/ReactiveX/RxJS/issues/2839)) ([124cc93](https://github.com/ReactiveX/RxJS/commit/124cc93))\n- **partition:** update TypeScript signature to match docs and filter operator ([#2819](https://github.com/ReactiveX/RxJS/issues/2819)) ([755df9b](https://github.com/ReactiveX/RxJS/commit/755df9b))\n- **subscribeToResult:** throw error in subscriber with inner observable ([d7bffa9](https://github.com/ReactiveX/RxJS/commit/d7bffa9)), closes [#2618](https://github.com/ReactiveX/RxJS/issues/2618)\n\n### Features\n\n- **ajax:** Include the response on instances of AjaxError ([3f6553c](https://github.com/ReactiveX/RxJS/commit/3f6553c))\n- **audit:** add higher-order lettable version of audit ([e2daefe](https://github.com/ReactiveX/RxJS/commit/e2daefe))\n- **auditTime:** add higher-order lettable version of auditTime ([9e963aa](https://github.com/ReactiveX/RxJS/commit/9e963aa))\n- **buffer:** add higher-order lettable version of buffer ([d8ca9de](https://github.com/ReactiveX/RxJS/commit/d8ca9de))\n- **bufferCount:** add higher-order lettable version of bufferCount ([0ae2ed5](https://github.com/ReactiveX/RxJS/commit/0ae2ed5))\n- **bufferTime:** add higher-order lettable version of bufferTime operator ([0377ca6](https://github.com/ReactiveX/RxJS/commit/0377ca6))\n- **bufferToggle:** add higher-order lettable version of bufferToggle ([ea1c3ee](https://github.com/ReactiveX/RxJS/commit/ea1c3ee))\n- **bufferWhen:** add higher-order lettable version of bufferWhen ([ec3eceb](https://github.com/ReactiveX/RxJS/commit/ec3eceb))\n- **catchError:** add higher-order lettable version of `catch` ([408a2af](https://github.com/ReactiveX/RxJS/commit/408a2af))\n- **combineAll:** add higher-order lettable version of combineAll ([97704b3](https://github.com/ReactiveX/RxJS/commit/97704b3))\n- **combineLatest:** add higher-order lettable version of combineLatest ([b7154f2](https://github.com/ReactiveX/RxJS/commit/b7154f2))\n- **concatMap:** add higher-order lettable version of concatMap ([c4125ff](https://github.com/ReactiveX/RxJS/commit/c4125ff))\n- **concatMapTo:** add higher-order lettable version of concatMapTo ([0a6672e](https://github.com/ReactiveX/RxJS/commit/0a6672e))\n- **count:** add higher-order lettable version of count ([caf713e](https://github.com/ReactiveX/RxJS/commit/caf713e))\n- **debounce:** add higher-order lettable version of debounce ([cb8ce46](https://github.com/ReactiveX/RxJS/commit/cb8ce46))\n- **debounceTime:** add higher-order lettable version of debounceTime ([df0d439](https://github.com/ReactiveX/RxJS/commit/df0d439))\n- **delay:** add higher-order lettable version of delay ([7efb803](https://github.com/ReactiveX/RxJS/commit/7efb803))\n- **delayWhen:** add higher-order lettable version of delayWhen ([cb91c3f](https://github.com/ReactiveX/RxJS/commit/cb91c3f))\n- **dematerialize:** add higher-order lettable version of dematerialize ([b5948f9](https://github.com/ReactiveX/RxJS/commit/b5948f9))\n- **distinct:** add higher-order lettable version of distinct ([0429a69](https://github.com/ReactiveX/RxJS/commit/0429a69))\n- **distinctUntilChanged:** add higher-order lettable version of distinctUntilChanged ([b2725e7](https://github.com/ReactiveX/RxJS/commit/b2725e7))\n- **distinctUntilKeyChanged:** add higher-order lettable version of distinctUntilKeyChanged ([9db141c](https://github.com/ReactiveX/RxJS/commit/9db141c))\n- **elementAt:** add higher-order lettable version of elementAt ([b8e956b](https://github.com/ReactiveX/RxJS/commit/b8e956b))\n- **every:** add higher-order lettable version of every ([13f3503](https://github.com/ReactiveX/RxJS/commit/13f3503))\n- **exhaust:** add higher-order lettable version of exhaust ([b145dca](https://github.com/ReactiveX/RxJS/commit/b145dca))\n- **exhaustMap:** add higher-order lettable exhaustMap ([b134e0c](https://github.com/ReactiveX/RxJS/commit/b134e0c))\n- **expand:** add higher-order lettable expand ([6ec8a19](https://github.com/ReactiveX/RxJS/commit/6ec8a19))\n- **filter:** add higher-order lettable version of filter ([2848556](https://github.com/ReactiveX/RxJS/commit/2848556))\n- **finalize:** add higher-order lettable version of finally, called finalize ([cfeae9f](https://github.com/ReactiveX/RxJS/commit/cfeae9f))\n- **find:** add higher-order lettable version of find ([ff6d5af](https://github.com/ReactiveX/RxJS/commit/ff6d5af))\n- **findIndex:** add higher-order lettable findIndex ([40e680e](https://github.com/ReactiveX/RxJS/commit/40e680e))\n- **first:** add higher-order lettable first ([33eac1e](https://github.com/ReactiveX/RxJS/commit/33eac1e))\n- **groupBy:** add higher-order lettable groupBy ([5281229](https://github.com/ReactiveX/RxJS/commit/5281229))\n- **ignoreElements:** add higher-order lettable version of ignoreElements ([68286d4](https://github.com/ReactiveX/RxJS/commit/68286d4))\n- **isEmpty:** add higher-order lettable version of isEmpty ([aad1833](https://github.com/ReactiveX/RxJS/commit/aad1833))\n- **last:** add higher-order lettable version of last ([bf33b97](https://github.com/ReactiveX/RxJS/commit/bf33b97))\n- **lettables:** add higher-order lettable versions of concat, concatAll, mergeAll ([d7e8be7](https://github.com/ReactiveX/RxJS/commit/d7e8be7))\n- **map:** add higher-order lettable map operator ([ce40b2d](https://github.com/ReactiveX/RxJS/commit/ce40b2d))\n- **mapTo:** add higher-order lettable version of mapTo ([e97530f](https://github.com/ReactiveX/RxJS/commit/e97530f))\n- **materialize:** add higher-order lettable materialize operator ([ce42477](https://github.com/ReactiveX/RxJS/commit/ce42477))\n- **merge:** add higher-order lettable version of merge ([#2809](https://github.com/ReactiveX/RxJS/issues/2809)) ([3136403](https://github.com/ReactiveX/RxJS/commit/3136403))\n- **mergeMap:** add higher-order lettable version of mergeMap ([417efde](https://github.com/ReactiveX/RxJS/commit/417efde))\n- **mergeMapTo:** add higher-order lettable version of mergeMapTo ([653b47a](https://github.com/ReactiveX/RxJS/commit/653b47a))\n- **mergeScan:** add higher-order lettable version of mergeScan ([fde7205](https://github.com/ReactiveX/RxJS/commit/fde7205))\n- **multicast:** add higher-order lettable variant of multicast ([fb6014d](https://github.com/ReactiveX/RxJS/commit/fb6014d))\n- **observeOn:** add higher-order lettable version of observeOn ([feb0f5a](https://github.com/ReactiveX/RxJS/commit/feb0f5a))\n- **onErrorResumeNext:** add higher-order lettable version of onErrorResumeNext ([badec6a](https://github.com/ReactiveX/RxJS/commit/badec6a))\n- **operators:** higher-order lettables of reduce, min, max and defaultIfEmpty added ([9974fc2](https://github.com/ReactiveX/RxJS/commit/9974fc2))\n- **package:** rxjs distribution now supports main, module and es2015 keys in package.json ([988e1af](https://github.com/ReactiveX/RxJS/commit/988e1af))\n- **pairwise:** add higher-order lettable version of pairwise ([bb21a44](https://github.com/ReactiveX/RxJS/commit/bb21a44))\n- **partition:** add higher-order lettable version of partition ([595e588](https://github.com/ReactiveX/RxJS/commit/595e588))\n- **pipe:** add pipe method ot Observable ([9f6312d](https://github.com/ReactiveX/RxJS/commit/9f6312d))\n- **pipe:** add pipe utility function([42f9daf](https://github.com/ReactiveX/RxJS/commit/42f9daf))\n- **pluck:** add higher-order lettable version of pluck ([8ab0914](https://github.com/ReactiveX/RxJS/commit/8ab0914))\n- **publish:** add higher-order lettable variant of publish ([4ccf794](https://github.com/ReactiveX/RxJS/commit/4ccf794))\n- **publishBehavior:** add higher-order lettable version of publishBehavior ([e911aef](https://github.com/ReactiveX/RxJS/commit/e911aef))\n- **publishLast:** add higher-order lettable version of publishLast ([684728c](https://github.com/ReactiveX/RxJS/commit/684728c))\n- **publishReplay:** add higher-order lettable version of publishReplay ([2958917](https://github.com/ReactiveX/RxJS/commit/2958917))\n- **race:** add higher-order lettable version of race ([e646851](https://github.com/ReactiveX/RxJS/commit/e646851))\n- **refCount:** add higher-order lettable version of refCount ([21fba63](https://github.com/ReactiveX/RxJS/commit/21fba63))\n- **repeat:** add higher-order lettable version of repeat ([8473fe5](https://github.com/ReactiveX/RxJS/commit/8473fe5))\n- **repeatWhen:** add higher-order lettable version of repeatWhen ([1d1cecd](https://github.com/ReactiveX/RxJS/commit/1d1cecd))\n- **retry:** add higher-order lettable version of retry ([28e9b13](https://github.com/ReactiveX/RxJS/commit/28e9b13))\n- **retryWhen:** add higher-order lettable version of retryWhen ([1290e3c](https://github.com/ReactiveX/RxJS/commit/1290e3c))\n- **sample:** add higher-order lettable version of sample ([8c73e6e](https://github.com/ReactiveX/RxJS/commit/8c73e6e))\n- **sampleTime:** add higher-order lettable version of sampleTime ([ba6a9ce](https://github.com/ReactiveX/RxJS/commit/ba6a9ce))\n- **scan:** add higher-order lettable version of scan ([2cc5d75](https://github.com/ReactiveX/RxJS/commit/2cc5d75))\n- **sequenceEqual:** add higher-order lettable version of sequenceEqual ([7cd3165](https://github.com/ReactiveX/RxJS/commit/7cd3165))\n- **share:** add higher-order lettable version of share ([f10c42e](https://github.com/ReactiveX/RxJS/commit/f10c42e))\n- **shareReplay:** add higher-order lettable version of shareReplay ([e8be197](https://github.com/ReactiveX/RxJS/commit/e8be197))\n- **single:** add higher-order lettable version of single ([3bc050a](https://github.com/ReactiveX/RxJS/commit/3bc050a))\n- **skip:** add higher-order lettable version of skip ([baed383](https://github.com/ReactiveX/RxJS/commit/baed383))\n- **skipLast:** add higher-order lettable version of skipLast ([6e1ff3c](https://github.com/ReactiveX/RxJS/commit/6e1ff3c))\n- **skipUntil:** add higher-order lettable version of skipUntil ([6cc2cd6](https://github.com/ReactiveX/RxJS/commit/6cc2cd6))\n- **skipWhile:** add higher-order lettable version of skipWhile ([76d8ffa](https://github.com/ReactiveX/RxJS/commit/76d8ffa))\n- **subscribeOn:** add higher-order lettable version of subscribeOn ([866af37](https://github.com/ReactiveX/RxJS/commit/866af37))\n- **switchAll:** add higher-order lettable version of switch ([2f12572](https://github.com/ReactiveX/RxJS/commit/2f12572))\n- **switchMap:** add higher-order lettable version of switchMap ([b6e5b56](https://github.com/ReactiveX/RxJS/commit/b6e5b56))\n- **switchMapTo:** add higher-order lettable version of switchMapTo ([2640184](https://github.com/ReactiveX/RxJS/commit/2640184))\n- **take:** add higher-order lettable version of take ([089a5a6](https://github.com/ReactiveX/RxJS/commit/089a5a6))\n- **takeLast:** add higher-order lettable version of takeLast ([cd7e7dd](https://github.com/ReactiveX/RxJS/commit/cd7e7dd))\n- **takeUntil:** add higher-order lettable version of takeUntil ([bb2ddaa](https://github.com/ReactiveX/RxJS/commit/bb2ddaa))\n- **takeWhile:** add higher-order lettable version of takeWhile ([f86c862](https://github.com/ReactiveX/RxJS/commit/f86c862))\n- **tap:** add higher-order lettable version of do ([f85c60e](https://github.com/ReactiveX/RxJS/commit/f85c60e))\n- **throttle:** add higher-order lettable version of throttle ([e4dd1fd](https://github.com/ReactiveX/RxJS/commit/e4dd1fd))\n- **throttleTime:** add higher-order lettable version of throttleTime ([34a592d](https://github.com/ReactiveX/RxJS/commit/34a592d))\n- **timeInterval:** add higher-order lettable version of timeInterval ([fcad034](https://github.com/ReactiveX/RxJS/commit/fcad034))\n- **timeout:** add higher-order lettable version of timeout ([2546750](https://github.com/ReactiveX/RxJS/commit/2546750))\n- **timeoutWith:** add higher-order lettable version of timeoutWith ([bd7f5ed](https://github.com/ReactiveX/RxJS/commit/bd7f5ed))\n- **timestamp:** add higher-order lettable version of timestamp ([a780bf2](https://github.com/ReactiveX/RxJS/commit/a780bf2))\n- **toArray:** add higher-order lettable version of toArray ([82480cf](https://github.com/ReactiveX/RxJS/commit/82480cf))\n- **toArray:** add higher-order lettable version of toArray ([a03a50c](https://github.com/ReactiveX/RxJS/commit/a03a50c))\n- **toPromise:** add higher-order lettable version of toPromise ([1627da2](https://github.com/ReactiveX/RxJS/commit/1627da2))\n- **window:** add higher-order lettable version of window ([9f6373e](https://github.com/ReactiveX/RxJS/commit/9f6373e))\n- **windowCount:** add higher-order lettable version of windowCount ([2a9e54c](https://github.com/ReactiveX/RxJS/commit/2a9e54c))\n- **windowTime:** add higher-order lettable version of windowTime ([29ffa1b](https://github.com/ReactiveX/RxJS/commit/29ffa1b))\n- **windowToggle:** add higher-order lettable version of windowToggle ([81ec389](https://github.com/ReactiveX/RxJS/commit/81ec389))\n- **windowWhen:** add higher-order lettable version of windowWhen ([0b73208](https://github.com/ReactiveX/RxJS/commit/0b73208))\n- **withLatestFrom:** add higher-order lettable version of withLatestFrom ([509c97c](https://github.com/ReactiveX/RxJS/commit/509c97c))\n- **zip:** add higher-order lettable version of zip ([8a9b9b2](https://github.com/ReactiveX/RxJS/commit/8a9b9b2))\n- **zipAll:** add higher-order lettable version of zipAll ([f6bd51f](https://github.com/ReactiveX/RxJS/commit/f6bd51f))\n\n<a name=\"5.4.3\"></a>\n\n## [5.4.3](https://github.com/ReactiveX/RxJS/compare/5.4.2...v5.4.3) (2017-08-10)\n\n### Bug Fixes\n\n- **compilation:** compiles under typescript 2.4.2 ([#2780](https://github.com/ReactiveX/RxJS/issues/2780)) ([d2a32f9](https://github.com/ReactiveX/RxJS/commit/d2a32f9))\n- **exports:** add exports for missing static operators: generate, ([08c4196](https://github.com/ReactiveX/RxJS/commit/08c4196))\n\n<a name=\"5.4.2\"></a>\n\n## [5.4.2](https://github.com/ReactiveX/RxJS/compare/5.4.1...v5.4.2) (2017-07-05)\n\n### Bug Fixes\n\n- **Notification:** Don't reference `this` from static methods. ([9f8e375](https://github.com/ReactiveX/RxJS/commit/9f8e375))\n- **Subject:** lift signature is now appropriate for stricter TypeScript 2.4 checks ([#2722](https://github.com/ReactiveX/RxJS/issues/2722)) ([9804de7](https://github.com/ReactiveX/RxJS/commit/9804de7))\n\n<a name=\"5.4.1\"></a>\n\n## [5.4.1](https://github.com/ReactiveX/RxJS/compare/5.4.0...v5.4.1) (2017-06-14)\n\n### Bug Fixes\n\n- **ajax:** Only set timeout & responseType if request is asynchronous ([#2486](https://github.com/ReactiveX/RxJS/issues/2486)) ([380fbcf](https://github.com/ReactiveX/RxJS/commit/380fbcf))\n- **audit:** will now properly mirror source if durations are Observable.empty() ([#2595](https://github.com/ReactiveX/RxJS/issues/2595)) ([6ded82e](https://github.com/ReactiveX/RxJS/commit/6ded82e))\n- **elementAt:** will now properly unsubscribe when it completes or errors ([#2501](https://github.com/ReactiveX/RxJS/issues/2501)) ([a400cab](https://github.com/ReactiveX/RxJS/commit/a400cab))\n- **ErrorObservable:** will now propagate errors properly when used in a `catch` after `fromPromise`. ([#2552](https://github.com/ReactiveX/RxJS/issues/2552)) ([cf88a20](https://github.com/ReactiveX/RxJS/commit/cf88a20))\n- **groupBy:** group duration notifiers will now properly unsubscribe and clean up ([#2662](https://github.com/ReactiveX/RxJS/issues/2662)) ([ab92083](https://github.com/ReactiveX/RxJS/commit/ab92083)), closes [#2660](https://github.com/ReactiveX/RxJS/issues/2660) [#2661](https://github.com/ReactiveX/RxJS/issues/2661)\n- **Observable:** errors thrown in observer/handlers without an operator applied will no longer be swallowed ([#2626](https://github.com/ReactiveX/RxJS/issues/2626)) ([c250afc](https://github.com/ReactiveX/RxJS/commit/c250afc)), closes [#2565](https://github.com/ReactiveX/RxJS/issues/2565)\n- **reduce:** type definitions overloads for TypeScript are now in proper order ([#2523](https://github.com/ReactiveX/RxJS/issues/2523)) ([ccc0647](https://github.com/ReactiveX/RxJS/commit/ccc0647))\n- **Schedulers:** Fix issue where canceling an asap or animationFrame action early could throw ([#2638](https://github.com/ReactiveX/RxJS/issues/2638)) ([fc39043](https://github.com/ReactiveX/RxJS/commit/fc39043))\n\n<a name=\"5.4.0\"></a>\n\n# [5.4.0](https://github.com/ReactiveX/RxJS/) (2017-05-09)\n\n### Features\n\n- **shareReplay:** adds `shareReplay` variant of `publishReplay` ([#2443](https://github.com/ReactiveX/RxJS/issues/2443)) ([5a2266a](https://github.com/ReactiveX/RxJS/commit/5a2266a))\n- **skipLast:** add skipLast operator ([#2316](https://github.com/ReactiveX/RxJS/issues/2316)) ([4ffbbe5](https://github.com/ReactiveX/RxJS/commit/4ffbbe5)), closes [#1404](https://github.com/ReactiveX/RxJS/issues/1404)\n- **TypeScript:** fromPromise accepts PromiseLike object ([#2505](https://github.com/ReactiveX/RxJS/issues/2505)) ([ade1fd5](https://github.com/ReactiveX/RxJS/commit/ade1fd5))\n\n<a name=\"5.3.3\"></a>\n\n## [5.3.3](https://github.com/ReactiveX/RxJS/compare/5.3.1...5.3.3) (2017-05-09)\n\n### Bug Fixes\n\n- **delayWhen:** correctly handle synchronous duration observable ([#2589](https://github.com/ReactiveX/RxJS/issues/2589)) ([695f280](https://github.com/ReactiveX/RxJS/commit/695f280)), closes [#2587](https://github.com/ReactiveX/RxJS/issues/2587)\n- **race:** allow TypeScript support for array of observables other than rest param ([#2548](https://github.com/ReactiveX/RxJS/issues/2548)) ([ace553c](https://github.com/ReactiveX/RxJS/commit/ace553c))\n- **Subscriber:** do not call complete with undefined value param ([#2559](https://github.com/ReactiveX/RxJS/issues/2559)) ([3d63de2](https://github.com/ReactiveX/RxJS/commit/3d63de2))\n\n**(NOTE: 5.3.2 was a broken release and was removed)**\n\n<a name=\"5.3.1\"></a>\n\n## [5.3.1](https://github.com/ReactiveX/RxJS/compare/5.3.0...v5.3.1) (2017-05-02)\n\n### Bug Fixes\n\n- **AsyncAction:** rescheduling an action with the same delay before it has executed will now schedule appropriately. ([#2580](https://github.com/ReactiveX/RxJS/issues/2580)) ([281760e](https://github.com/ReactiveX/RxJS/commit/281760e))\n- **closure:** make root.ts work with closure ([#2546](https://github.com/ReactiveX/RxJS/issues/2546)) ([0ecf55d](https://github.com/ReactiveX/RxJS/commit/0ecf55d))\n- **tests:** add missing babel-polyfill to package.json ([b277ce9](https://github.com/ReactiveX/RxJS/commit/b277ce9)), closes [#2261](https://github.com/ReactiveX/RxJS/issues/2261)\n- **withLatestFrom:** change from hot to cold observable in marble test ([0c65446](https://github.com/ReactiveX/RxJS/commit/0c65446)), closes [#2526](https://github.com/ReactiveX/RxJS/issues/2526)\n\n<a name=\"5.3.0\"></a>\n\n# [5.3.0](https://github.com/ReactiveX/RxJS/compare/5.2.0...v5.3.0) (2017-04-03)\n\n### Bug Fixes\n\n- **catch:** return type is now the union of input types ([#2478](https://github.com/ReactiveX/RxJS/issues/2478)) ([840def0](https://github.com/ReactiveX/RxJS/commit/840def0))\n- **forEach:** fix a temporal dead zone issue in forEach. ([#2474](https://github.com/ReactiveX/RxJS/issues/2474)) ([e9e9801](https://github.com/ReactiveX/RxJS/commit/e9e9801))\n- **multicast:** Ensure ConnectableObservables returned by multicast are state-isolated. ([aaa9e6b](https://github.com/ReactiveX/RxJS/commit/aaa9e6b))\n- **reduce:** proper TypeScript signature overload ordering ([#2382](https://github.com/ReactiveX/RxJS/issues/2382)) ([f6a4951](https://github.com/ReactiveX/RxJS/commit/f6a4951)), closes [#2338](https://github.com/ReactiveX/RxJS/issues/2338)\n- **SafeSubscriber:** SafeSubscriber shouldn't mutate incoming Observers. ([a1778e0](https://github.com/ReactiveX/RxJS/commit/a1778e0))\n- **timeout:** Cancels scheduled timeout, if no longer needed ([3e9d529](https://github.com/ReactiveX/RxJS/commit/3e9d529)), closes [#2134](https://github.com/ReactiveX/RxJS/issues/2134) [#2244](https://github.com/ReactiveX/RxJS/issues/2244) [#2355](https://github.com/ReactiveX/RxJS/issues/2355) [#2347](https://github.com/ReactiveX/RxJS/issues/2347) [#2353](https://github.com/ReactiveX/RxJS/issues/2353) [#2254](https://github.com/ReactiveX/RxJS/issues/2254) [#2372](https://github.com/ReactiveX/RxJS/issues/2372) [#1301](https://github.com/ReactiveX/RxJS/issues/1301)\n- **zipAll:** complete when the source is empty ([712fece](https://github.com/ReactiveX/RxJS/commit/712fece))\n\n### Features\n\n- **delayWhen:** add index to the selector function ([5d6291e](https://github.com/ReactiveX/RxJS/commit/5d6291e))\n- **symbol exports:** symbols now also exported without `$$` prefix to work with Babel UMD exporting ([#2435](https://github.com/ReactiveX/RxJS/issues/2435)) ([747bef6](https://github.com/ReactiveX/RxJS/commit/747bef6)), closes [#2415](https://github.com/ReactiveX/RxJS/issues/2415)\n\n### Performance Improvements\n\n- **bufferCount:** optimize bufferCount operator ([#2359](https://github.com/ReactiveX/RxJS/issues/2359)) ([28d0883](https://github.com/ReactiveX/RxJS/commit/28d0883))\n\n### April Fools\n\n- **smooth:** `smooth()` was never really a thing. Sorry, folks. :D\n\n<a name=\"5.2.0\"></a>\n\n# [5.2.0](https://github.com/ReactiveX/RxJS/compare/5.1.1...v5.2.0) (2017-02-21)\n\n### Bug Fixes\n\n- **ajax:** will set `withCredentials` after `open` on XHR for IE10 ([#2332](https://github.com/ReactiveX/RxJS/issues/2332)) ([0ab1d3b](https://github.com/ReactiveX/RxJS/commit/0ab1d3b))\n- **bindCallback:** emit undefined when callback is without arguments ([915a2a8](https://github.com/ReactiveX/RxJS/commit/915a2a8))\n- **bindNodeCallback:** emit undefined when callback has no success arguments ([8b81fc6](https://github.com/ReactiveX/RxJS/commit/8b81fc6)), closes [#2254](https://github.com/ReactiveX/RxJS/issues/2254)\n- **bindNodeCallback:** errors thrown in callback will be scheduled if a scheduler is provided ([#2344](https://github.com/ReactiveX/RxJS/issues/2344)) ([82ec4f1](https://github.com/ReactiveX/RxJS/commit/82ec4f1))\n- **concat:** will now return Observable when given a single object implementing Symbol.observable ([#2387](https://github.com/ReactiveX/RxJS/issues/2387)) ([f5d035a](https://github.com/ReactiveX/RxJS/commit/f5d035a))\n- **ErrorObservable:** remove type constraint to error value ([2f951cd](https://github.com/ReactiveX/RxJS/commit/2f951cd)), closes [#2395](https://github.com/ReactiveX/RxJS/issues/2395)\n- **forkJoin:** add type signature for single observable with selector ([7983b91](https://github.com/ReactiveX/RxJS/commit/7983b91)), closes [#2347](https://github.com/ReactiveX/RxJS/issues/2347)\n- **merge:** return Observable when called with single lowerCaseO ([85752eb](https://github.com/ReactiveX/RxJS/commit/85752eb))\n- **mergeAll:** introduce variant support <T, R> for mergeMap ([656f2b3](https://github.com/ReactiveX/RxJS/commit/656f2b3)), closes [#2372](https://github.com/ReactiveX/RxJS/issues/2372)\n- **single:** predicate function receives indices starting at 0 ([#2396](https://github.com/ReactiveX/RxJS/issues/2396)) ([c81882f](https://github.com/ReactiveX/RxJS/commit/c81882f))\n- **subscribeToResult:** accept array-like as result ([14685ba](https://github.com/ReactiveX/RxJS/commit/14685ba))\n\n### Features\n\n- **webSocket:** Add binaryType to config object ([86acbd1](https://github.com/ReactiveX/RxJS/commit/86acbd1)), closes [#2353](https://github.com/ReactiveX/RxJS/issues/2353)\n- **windowTime:** maxWindowSize parameter in windowTime operator ([381be3f](https://github.com/ReactiveX/RxJS/commit/381be3f)), closes [#1301](https://github.com/ReactiveX/RxJS/issues/1301)\n\n<a name=\"5.1.1\"></a>\n\n## [5.1.1](https://github.com/ReactiveX/RxJS/compare/5.1.0...v5.1.1) (2017-02-13)\n\n### Bug Fixes\n\n- **bindCallback:** input function context can now be properly set via output function ([#2319](https://github.com/ReactiveX/RxJS/issues/2319)) ([cb91c76](https://github.com/ReactiveX/RxJS/commit/cb91c76))\n- **bindNodeCallback:** input function context can now be properly set via output function ([#2320](https://github.com/ReactiveX/RxJS/issues/2320)) ([3ec315d](https://github.com/ReactiveX/RxJS/commit/3ec315d))\n- **Subscription:** fold ChildSubscription logic into Subscriber to prevent operators from leaking ChildSubscriptions. ([#2360](https://github.com/ReactiveX/RxJS/issues/2360)) ([22e4c17](https://github.com/ReactiveX/RxJS/commit/22e4c17)), closes [#2244](https://github.com/ReactiveX/RxJS/issues/2244) [#2355](https://github.com/ReactiveX/RxJS/issues/2355)\n\n<a name=\"5.1.0\"></a>\n\n# [5.1.0](https://github.com/ReactiveX/RxJS/compare/5.0.3...v5.1.0) (2017-02-01)\n\n### Bug Fixes\n\n- **catch:** update the catch operator to dispose inner subscriptions if the catch subscription is di ([#2271](https://github.com/ReactiveX/RxJS/issues/2271)) ([8a1e089](https://github.com/ReactiveX/RxJS/commit/8a1e089))\n- **combineLatest:** Don't mutate array of observables passed to ([#2276](https://github.com/ReactiveX/RxJS/issues/2276)) ([9b73c46](https://github.com/ReactiveX/RxJS/commit/9b73c46))\n- **ISubscription:** update type definition of ISubscription::closed ([#2249](https://github.com/ReactiveX/RxJS/issues/2249)) ([0c304a2](https://github.com/ReactiveX/RxJS/commit/0c304a2))\n- **Observable:** Ensure the generic type of the Observer passed to Observable's initializer function is the same. ([51a0bc1](https://github.com/ReactiveX/RxJS/commit/51a0bc1)), closes [#2166](https://github.com/ReactiveX/RxJS/issues/2166)\n- **Observable:** errors thrown during subscription are now properly sent down error channel ([#2313](https://github.com/ReactiveX/RxJS/issues/2313)) ([d4a9aac](https://github.com/ReactiveX/RxJS/commit/d4a9aac)), closes [#1833](https://github.com/ReactiveX/RxJS/issues/1833)\n- **reduce:** index will properly start at 1 if no seed is provided, to match native Array reduce behavior ([30a4ca4](https://github.com/ReactiveX/RxJS/commit/30a4ca4)), closes [#2290](https://github.com/ReactiveX/RxJS/issues/2290)\n- **repeatWhen:** resulting observable will wait for the source to complete, even if a hot notifier completes first. ([#2209](https://github.com/ReactiveX/RxJS/issues/2209)) ([c65a098](https://github.com/ReactiveX/RxJS/commit/c65a098)), closes [#2054](https://github.com/ReactiveX/RxJS/issues/2054)\n- **Subject:** ensure subject properly throws ObjectUnsubscribedError when unsubscribed then resubscribed to ([#2318](https://github.com/ReactiveX/RxJS/issues/2318)) ([41489eb](https://github.com/ReactiveX/RxJS/commit/41489eb))\n- **TestScheduler:** helper methods return proper types, `HotObservable` and `ColdObservable` instead of Observable ([#2305](https://github.com/ReactiveX/RxJS/issues/2305)) ([758aae9](https://github.com/ReactiveX/RxJS/commit/758aae9))\n- **windowTime:** ensure windows created when only a timespan is passed are closed and cleaned up properly. ([#2278](https://github.com/ReactiveX/RxJS/issues/2278)) ([d4533c4](https://github.com/ReactiveX/RxJS/commit/d4533c4))\n\n### Features\n\n- **fromEventPattern:** support optional removeHandler ([86960c2](https://github.com/ReactiveX/RxJS/commit/86960c2))\n- **fromEventPattern:** support pass signal from addHandler to removeHandler ([01d0622](https://github.com/ReactiveX/RxJS/commit/01d0622))\n\n<a name=\"5.0.3\"></a>\n\n## [5.0.3](https://github.com/ReactiveX/RxJS/compare/5.0.2...v5.0.3) (2017-01-05)\n\n### Bug Fixes\n\n- **observeOn:** seal memory leak involving old notifications ([9664a38](https://github.com/ReactiveX/RxJS/commit/9664a38)), closes [#2244](https://github.com/ReactiveX/RxJS/issues/2244)\n- **Subscription:** `add` will return Subscription that `remove`s itself when unsubscribed ([375d4a5](https://github.com/ReactiveX/RxJS/commit/375d4a5))\n- **TypeScript:** interfaces that accepted `Scheduler` now accept `IScheduler` interface ([a0d28a8](https://github.com/ReactiveX/RxJS/commit/a0d28a8))\n\n<a name=\"5.0.2\"></a>\n\n## [5.0.2](https://github.com/ReactiveX/RxJS/compare/5.0.1...v5.0.2) (2016-12-23)\n\n### Bug Fixes\n\n- **ajax:** upload progress is now set correctly ([#2200](https://github.com/ReactiveX/RxJS/issues/2200)) ([1a83041](https://github.com/ReactiveX/RxJS/commit/1a83041))\n- **groupBy:** Fix groupBy to dispose of outer subscription. ([#2201](https://github.com/ReactiveX/RxJS/issues/2201)) ([2269618](https://github.com/ReactiveX/RxJS/commit/2269618))\n\n<a name=\"5.0.1\"></a>\n\n## [5.0.1](https://github.com/ReactiveX/RxJS/compare/5.0.0...v5.0.1) (2016-12-13)\n\n### Bug Fixes\n\n- **TypeScript:** pin to TypeScript 2.0.x, fix errors with Error subclassing ([300504c](https://github.com/ReactiveX/RxJS/commit/300504c))\n\n<a name=\"5.0.0\"></a>\n\n# [5.0.0](https://github.com/ReactiveX/RxJS/compare/5.0.0-rc.5...v5.0.0) (2016-12-13)\n\n### Bug Fixes\n\n- **race:** unsubscribe raced observables with immediate scheduler ([#2158](https://github.com/ReactiveX/RxJS/issues/2158)) ([7dd533b](https://github.com/ReactiveX/RxJS/commit/7dd533b))\n- **SubscribeOnObservable:** Add the source subscription to the action disposable so the source will ([64e3815](https://github.com/ReactiveX/RxJS/commit/64e3815))\n\n<a name=\"5.0.0-rc.5\"></a>\n\n# [5.0.0-rc.5](https://github.com/ReactiveX/RxJS/compare/5.0.0-rc.4...v5.0.0-rc.5) (2016-12-07)\n\n### Bug Fixes\n\n- **AjaxObservable:** catch XHR send failures to observer ([#2159](https://github.com/ReactiveX/RxJS/issues/2159)) ([128fb9c](https://github.com/ReactiveX/RxJS/commit/128fb9c))\n- **distinctKey:** Removed accidental leftover reference of `distinctKey` ([9fd8096](https://github.com/ReactiveX/RxJS/commit/9fd8096)), closes [#2161](https://github.com/ReactiveX/RxJS/issues/2161)\n- **errors:** Better error message when you return non-observable things, ([#2152](https://github.com/ReactiveX/RxJS/issues/2152)) ([86a909c](https://github.com/ReactiveX/RxJS/commit/86a909c)), closes [#215](https://github.com/ReactiveX/RxJS/issues/215)\n- **event:** uses `Object.prototype.toString.call` on objects ([#2143](https://github.com/ReactiveX/RxJS/issues/2143)) ([e036e79](https://github.com/ReactiveX/RxJS/commit/e036e79))\n- **typings:** type guard support for `last`, `first`, `find` and `filter`. ([5f2e849](https://github.com/ReactiveX/RxJS/commit/5f2e849))\n\n### Features\n\n- **timeout:** remove `errorToSend` argument, always throw TimeoutError ([#2172](https://github.com/ReactiveX/RxJS/issues/2172)) ([98ea3d2](https://github.com/ReactiveX/RxJS/commit/98ea3d2))\n\n### BREAKING CHANGES\n\n- timeout: `timeout` no longer accepts the `errorToSend` argument\n\nrelated #2141\n\n<a name=\"5.0.0-rc.4\"></a>\n\n# [5.0.0-rc.4](https://github.com/ReactiveX/RxJS/compare/5.0.0-rc.3...v5.0.0-rc.4) (2016-11-19)\n\n### Bug Fixes\n\n- **partition:** handles `thisArg` as expected ([#2138](https://github.com/ReactiveX/RxJS/issues/2138)) ([6cf7296](https://github.com/ReactiveX/RxJS/commit/6cf7296))\n- **timeout:** throw traceable TimeoutError ([#2132](https://github.com/ReactiveX/RxJS/issues/2132)) ([9ebc46b](https://github.com/ReactiveX/RxJS/commit/9ebc46b))\n\n<a name=\"5.0.0-rc.3\"></a>\n\n# [5.0.0-rc.3](https://github.com/ReactiveX/RxJS/compare/5.0.0-rc.2...v5.0.0-rc.3) (2016-11-15)\n\n### Bug Fixes\n\n- **typings:** You no longer have to install the type definition for chai ([#2112](https://github.com/ReactiveX/rxjs/issues/2112))\n\n### Features\n\n- **filter:** support type guards without casting ([68b7922](https://github.com/ReactiveX/RxJS/commit/68b7922))\n- **find:** support type guards without casting ([9058bf6](https://github.com/ReactiveX/RxJS/commit/9058bf6))\n- **first:** support type guards without casting ([3aa1988](https://github.com/ReactiveX/RxJS/commit/3aa1988))\n- **last:** support type guards without casting ([07ecd5e](https://github.com/ReactiveX/RxJS/commit/07ecd5e))\n\n<a name=\"5.0.0-rc.2\"></a>\n\n# [5.0.0-rc.2](https://github.com/ReactiveX/RxJS/compare/5.0.0-rc.1...v5.0.0-rc.2) (2016-11-05)\n\n### Bug Fixes\n\n- **AjaxObservable:** remove needless type param R from AjaxObservable.getJSON() ([#2069](https://github.com/ReactiveX/RxJS/issues/2069)) ([0c3d4a4](https://github.com/ReactiveX/RxJS/commit/0c3d4a4))\n- **bufferCount:** will behave as expected when `startBufferEvery` is less than `bufferSize` ([#2076](https://github.com/ReactiveX/RxJS/issues/2076)) ([d13dbb4](https://github.com/ReactiveX/RxJS/commit/d13dbb4)), closes [#2062](https://github.com/ReactiveX/RxJS/issues/2062)\n- **build_docs:** fix doc building ([#1974](https://github.com/ReactiveX/RxJS/issues/1974)) ([1bbbe8b](https://github.com/ReactiveX/RxJS/commit/1bbbe8b))\n- **ErrorObservable:** Add generic error type for ErrorObservable. ([#2071](https://github.com/ReactiveX/RxJS/issues/2071)) ([9df86ba](https://github.com/ReactiveX/RxJS/commit/9df86ba))\n- **first:** will now only emit one value in recursive cases ([#2100](https://github.com/ReactiveX/RxJS/issues/2100)) ([a047e7a](https://github.com/ReactiveX/RxJS/commit/a047e7a)), closes [#2098](https://github.com/ReactiveX/RxJS/issues/2098)\n- **fromEvent:** Throw if event target is invalid ([#2107](https://github.com/ReactiveX/RxJS/issues/2107)) ([147ce3e](https://github.com/ReactiveX/RxJS/commit/147ce3e))\n- **IteratorObservable:** clarify the return type of IteratorObservable.create() ([#2070](https://github.com/ReactiveX/RxJS/issues/2070)) ([4f0f865](https://github.com/ReactiveX/RxJS/commit/4f0f865))\n- **IteratorObservable:** Observables `from` generators will now finalize when subscription ends ([22d286a](https://github.com/ReactiveX/RxJS/commit/22d286a)), closes [#1938](https://github.com/ReactiveX/RxJS/issues/1938)\n- **multicast:** fix a bug that caused multicast to omit messages after termination ([#2021](https://github.com/ReactiveX/RxJS/issues/2021)) ([44fbc14](https://github.com/ReactiveX/RxJS/commit/44fbc14))\n- **Notification:** `materialize` output will now match Rx4 ([#2106](https://github.com/ReactiveX/RxJS/issues/2106)) ([c83bab9](https://github.com/ReactiveX/RxJS/commit/c83bab9)), closes [#2105](https://github.com/ReactiveX/RxJS/issues/2105)\n- **Object.assign:** stop polyfilling Object assign ([#2080](https://github.com/ReactiveX/RxJS/issues/2080)) ([b5f8ab3](https://github.com/ReactiveX/RxJS/commit/b5f8ab3))\n- **Observable/Ajax:** mount properties to origin readystatechange fn ([#2025](https://github.com/ReactiveX/RxJS/issues/2025)) ([76a9abb](https://github.com/ReactiveX/RxJS/commit/76a9abb))\n- **operator/do:** fix typings ([9a40297](https://github.com/ReactiveX/RxJS/commit/9a40297))\n- **reduce/scan:** both scan/reduce operators now accepts `undefined` itself as a valid seed ([#2050](https://github.com/ReactiveX/RxJS/issues/2050)) ([fee7585](https://github.com/ReactiveX/RxJS/commit/fee7585)), closes [#2047](https://github.com/ReactiveX/RxJS/issues/2047)\n- **ReplaySubject:** observer now subscribed prior to running subscription function ([#2046](https://github.com/ReactiveX/RxJS/issues/2046)) ([fea08e9](https://github.com/ReactiveX/RxJS/commit/fea08e9)), closes [#2044](https://github.com/ReactiveX/RxJS/issues/2044)\n- **sample:** source is now subscribed to before the notifier ([ffe99e8](https://github.com/ReactiveX/RxJS/commit/ffe99e8)), closes [#2075](https://github.com/ReactiveX/RxJS/issues/2075)\n- **Symbol.iterator:** will not polyfill Symbol iterator unless Symbol exists ([#2082](https://github.com/ReactiveX/RxJS/issues/2082)) ([1138c99](https://github.com/ReactiveX/RxJS/commit/1138c99))\n- **typings:** fixed Subject<T>.lift to have the same shape as Observable<T>.lift ([b07f597](https://github.com/ReactiveX/RxJS/commit/b07f597))\n- **WebSocketSubject.prototype.multiplex:** no longer nulls out socket after first unsubscribe ([#2039](https://github.com/ReactiveX/RxJS/issues/2039)) ([a5e9cfe](https://github.com/ReactiveX/RxJS/commit/a5e9cfe)), closes [#2037](https://github.com/ReactiveX/RxJS/issues/2037)\n\n### Features\n\n- **distinct:** remove `distinctKey`, `distinct` signature change and perf improvements ([#2049](https://github.com/ReactiveX/RxJS/issues/2049)) ([89612b2](https://github.com/ReactiveX/RxJS/commit/89612b2)), closes [#2009](https://github.com/ReactiveX/RxJS/issues/2009)\n- **groupBy:** Adds subjectSelector argument to groupBy ([#2023](https://github.com/ReactiveX/RxJS/issues/2023)) ([f94ceb9](https://github.com/ReactiveX/RxJS/commit/f94ceb9))\n- **typescript:** remove dependency to 3rd party es2015 definition ([#2027](https://github.com/ReactiveX/RxJS/issues/2027)) ([4c31974](https://github.com/ReactiveX/RxJS/commit/4c31974)), closes [#2016](https://github.com/ReactiveX/RxJS/issues/2016)\n\n### BREAKING CHANGES\n\n- Notification: `Notification.prototype.exception` is now `Notification.prototype.error` to match Rx4 semantics\n- Symbol.iterator: RxJS will no longer polyfill `Symbol.iterator` if `Symbol` does not exist. This may break code that inadvertently relies on this behavior\n- Object.assign: RxJS will no longer polyfill `Object.assign`. It does\n  not require `Object.assign` to function, however, your code may be\n  inadvertently relying on this polyfill.\n- AjaxObservable: Observable.ajax.getJSON() now only supports a single type parameter,\n  `getJSON<T>(url: string, headers?: Object): Observable<T>`.\n  The extra type parameter it accepted previously was superfluous.\n- distinct: `distinctKey` has been removed. Use `distinct`\n- distinct: `distinct` operator has changed, first argument is an\n  optional `keySelector`. The custom `compare` function is no longer\n  supported.\n\n<a name=\"5.0.0-rc.1\"></a>\n\n# [5.0.0-rc.1](https://github.com/ReactiveX/RxJS/compare/5.0.0-beta.12...v5.0.0-rc.1) (2016-10-11)\n\n### Bug Fixes\n\n- **AjaxObservable:** Fix for [#1921](https://github.com/ReactiveX/RxJS/issues/1921) exposed AjaxObservable unsubscription error calling xhr.abort(). ([4d23f87](https://github.com/ReactiveX/RxJS/commit/4d23f87))\n- **AnonymousSubject:** is now exposed on Rx namespace ([0a6f049](https://github.com/ReactiveX/RxJS/commit/0a6f049)), closes [#2002](https://github.com/ReactiveX/RxJS/issues/2002)\n- **bufferTime:** no errors with take after bufferTime with maxBufferSize ([ecec640](https://github.com/ReactiveX/RxJS/commit/ecec640)), closes [#1944](https://github.com/ReactiveX/RxJS/issues/1944)\n- **docs:** Fix esdoc for Observable.merge spread argument ([b794e9b](https://github.com/ReactiveX/RxJS/commit/b794e9b))\n- **Observer:** fix Observable#subscribe() signature to suggest correct usable ([459d2a2](https://github.com/ReactiveX/RxJS/commit/459d2a2))\n- **operator:** Fix take to complete when the source is re-entrant. ([86615cb](https://github.com/ReactiveX/RxJS/commit/86615cb))\n- **root:** find global context (window/self/global) in a more safe way ([a098132](https://github.com/ReactiveX/RxJS/commit/a098132)), closes [#1930](https://github.com/ReactiveX/RxJS/issues/1930)\n- **schedulers:** Queue, Asap, and AnimationFrame Schedulers should be Async if delay > 0 ([d5c682c](https://github.com/ReactiveX/RxJS/commit/d5c682c))\n- **util/toSubscriber:** Supplies the Subscriber constructor with emptyObserver as destination if no ([8e7e4e3](https://github.com/ReactiveX/RxJS/commit/8e7e4e3))\n- **WebSocketSubject:** ensure all internal state properly reset when socket is nulled out ([62d242e](https://github.com/ReactiveX/RxJS/commit/62d242e)), closes [#1863](https://github.com/ReactiveX/RxJS/issues/1863)\n\n### Features\n\n- **cache:** remove `cache` operator ([1b23ace](https://github.com/ReactiveX/RxJS/commit/1b23ace))\n- **ES2015:** stop publishing `rxjs-es`, ES2015 output no longer included in `@reactivex/rxjs` package under `/dist/es6` ([6be9968](https://github.com/ReactiveX/RxJS/commit/6be9968)), closes [#1671](https://github.com/ReactiveX/RxJS/issues/1671)\n- **filter:** Observable<T>.filter() can take type guard as the predicate function ([d62fbf0](https://github.com/ReactiveX/RxJS/commit/d62fbf0))\n- **find:** Observable<T>.find() can take type guard as the predicate function ([b952718](https://github.com/ReactiveX/RxJS/commit/b952718))\n- **first:** Observable<T>.first() can take type guard as the predicate function ([f99ca49](https://github.com/ReactiveX/RxJS/commit/f99ca49))\n- **last:** Observable<T>.last() can take type guard as the predicate function ([76a8a57](https://github.com/ReactiveX/RxJS/commit/76a8a57))\n- **operators:** Use lift in the operators that don't currently use lift. ([68af9ef](https://github.com/ReactiveX/RxJS/commit/68af9ef))\n- **TypeScript:** update TypeScript to v2.0 ([3478b0b](https://github.com/ReactiveX/RxJS/commit/3478b0b))\n\n### BREAKING CHANGES\n\n- **cache:** The .cache() operator has been removed, pending further discussion ([1b23ace](https://github.com/ReactiveX/RxJS/commit/1b23ace))\n- ES2015: `rxjs-es` is no longer being published\n- ES2015: `@reactivex/rxjs` no longer has `/dist/es6` output\n\nrelated #2016\nrelated #1992\n\n- package.json: TypeScript definitions are now for TS 2.0 and higher\n\nEven if we use getter for class, they are marked with `readonly` properties\nin d.ts.\n\n- operators: Removes MulticastObservable subclass in favor of a MulticastOperator.\n\n<a name=\"5.0.0-beta.12\"></a>\n\n# [5.0.0-beta.12](https://github.com/ReactiveX/RxJS/compare/5.0.0-beta.11...v5.0.0-beta.12) (2016-09-09)\n\n### Bug Fixes\n\n- **ajaxObservable:** remove implicit dependency to map operator patch ([1744ae9](https://github.com/ReactiveX/RxJS/commit/1744ae9)), closes [#1874](https://github.com/ReactiveX/RxJS/issues/1874)\n- **AjaxObservable:** return null value from JSON.Parse (#1904) ([6ba374e](https://github.com/ReactiveX/RxJS/commit/6ba374e))\n- **catch:** removed unneeded overload for catch ([dd0e586](https://github.com/ReactiveX/RxJS/commit/dd0e586))\n- **max:** do not return comparer values ([f454e93](https://github.com/ReactiveX/RxJS/commit/f454e93)), closes [#1892](https://github.com/ReactiveX/RxJS/issues/1892)\n- **min:** do not return comparer values ([222fd17](https://github.com/ReactiveX/RxJS/commit/222fd17)), closes [#1892](https://github.com/ReactiveX/RxJS/issues/1892)\n- **operators:** export reserved name operators on prototype ([34c39dd](https://github.com/ReactiveX/RxJS/commit/34c39dd)), closes [#1924](https://github.com/ReactiveX/RxJS/issues/1924)\n- **VirtualTimeScheduler:** remove default maxFrame limit ([1de86f1](https://github.com/ReactiveX/RxJS/commit/1de86f1)), closes [#1889](https://github.com/ReactiveX/RxJS/issues/1889)\n- **WebSocketSubject:** pass constructor errors onto observable ([49c7d67](https://github.com/ReactiveX/RxJS/commit/49c7d67))\n\n### Features\n\n- **operator:** Add repeatWhen operator ([c288d88](https://github.com/ReactiveX/RxJS/commit/c288d88))\n- **sequenceEqual:** adds sequenceEqual operator ([3c30293](https://github.com/ReactiveX/RxJS/commit/3c30293)), closes [#1882](https://github.com/ReactiveX/RxJS/issues/1882)\n\n<a name=\"5.0.0-beta.11\"></a>\n\n# [5.0.0-beta.11](https://github.com/ReactiveX/RxJS/compare/5.0.0-beta.10...v5.0.0-beta.11) (2016-08-09)\n\n### Bug Fixes\n\n- **ajaxObservable:** only set default Content-Type header when no body is sent (#1830) ([5a895e8](https://github.com/ReactiveX/RxJS/commit/5a895e8))\n- **AjaxObservable:** drop resultSelector support in ajax method ([7a77437](https://github.com/ReactiveX/RxJS/commit/7a77437)), closes [#1783](https://github.com/ReactiveX/RxJS/issues/1783)\n- **AsyncSubject:** do not allow change value after complete ([801f282](https://github.com/ReactiveX/RxJS/commit/801f282)), closes [#1800](https://github.com/ReactiveX/RxJS/issues/1800)\n- **BoundNodeCallbackObservable:** cast to `any` to access to private field in `source` ([54f342f](https://github.com/ReactiveX/RxJS/commit/54f342f))\n- **catch:** accept selector returns ObservableInput ([e55c62d](https://github.com/ReactiveX/RxJS/commit/e55c62d)), closes [#1857](https://github.com/ReactiveX/RxJS/issues/1857)\n- **combineLatest:** emit unique array instances with the default projection ([2e30fd1](https://github.com/ReactiveX/RxJS/commit/2e30fd1))\n- **Observable.from:** standardise arguments (remove map/context) ([aa30af2](https://github.com/ReactiveX/RxJS/commit/aa30af2))\n- **schedulers:** fix asap and animationFrame schedulers to execute across async boundaries. (#182 ([548ec2a](https://github.com/ReactiveX/RxJS/commit/548ec2a)), closes [(#1820](https://github.com/(/issues/1820) [#1814](https://github.com/ReactiveX/RxJS/issues/1814)\n- **subscribeToResult:** update subscription to iterables ([5d6339a](https://github.com/ReactiveX/RxJS/commit/5d6339a))\n- **WebSocketSubject:** prevent early close (#1831) ([848a527](https://github.com/ReactiveX/RxJS/commit/848a527)), closes [(#1831](https://github.com/(/issues/1831)\n\n### Features\n\n- **fromEvent:** Pass through event listener options (#1845) ([8f0dc01](https://github.com/ReactiveX/RxJS/commit/8f0dc01))\n- **PairsObservable:** add PairsObservable creation method ([26bafff](https://github.com/ReactiveX/RxJS/commit/26bafff)), closes [#1804](https://github.com/ReactiveX/RxJS/issues/1804)\n\n### BREAKING CHANGES\n\n- Observable.from: - Observable.from no longer supports the optional map function and associated context argument.\n  This change has been reflected in the related constructors and their properties have been standardised.\n- AjaxObservable: ajax.\\*() method no longer support resultSelector, encourage to use `map` instead\n\n<a name=\"5.0.0-beta.10\"></a>\n\n# [5.0.0-beta.10](https://github.com/ReactiveX/RxJS/compare/5.0.0-beta.9...v5.0.0-beta.10) (2016-07-06)\n\n### Bug Fixes\n\n- **AjaxObservable:** ignore content-type for formdata (#1746) ([43d05e7](https://github.com/ReactiveX/RxJS/commit/43d05e7))\n- **AjaxObservable:** support withCredentials for CORS request ([8084572](https://github.com/ReactiveX/RxJS/commit/8084572)), closes [#1732](https://github.com/ReactiveX/RxJS/issues/1732) [#1711](https://github.com/ReactiveX/RxJS/issues/1711)\n- **babel:** fix an issue where babel could not compile `Scheduler.async` (#1807) ([12c5c74](https://github.com/ReactiveX/RxJS/commit/12c5c74)), closes [(#1807](https://github.com/(/issues/1807) [#1806](https://github.com/ReactiveX/RxJS/issues/1806)\n- **bufferTime:** handle closing context when synchronously unsubscribed ([4ce4433](https://github.com/ReactiveX/RxJS/commit/4ce4433)), closes [#1763](https://github.com/ReactiveX/RxJS/issues/1763)\n- **multicast:** Fixes multicast with selector to create a new source connection per subscriber. ([c3ac852](https://github.com/ReactiveX/RxJS/commit/c3ac852)), closes [(#1774](https://github.com/(/issues/1774)\n- **Subject:** allow optional next value in type definition ([3e0c6d9](https://github.com/ReactiveX/RxJS/commit/3e0c6d9)), closes [#1728](https://github.com/ReactiveX/RxJS/issues/1728)\n- **WebSocketSubject:** respect WebSocketCtor, support source/destination arguments in constructor. (#179 ([cd8cdd0](https://github.com/ReactiveX/RxJS/commit/cd8cdd0)), closes [#1745](https://github.com/ReactiveX/RxJS/issues/1745) [#1784](https://github.com/ReactiveX/RxJS/issues/1784)\n\n<a name=\"5.0.0-beta.9\"></a>\n\n# [5.0.0-beta.9](https://github.com/ReactiveX/RxJS/compare/5.0.0-beta.8...v5.0.0-beta.9) (2016-06-14)\n\n### Bug Fixes\n\n- **cache:** get correct caching behavior (#1765) ([cb0b806](https://github.com/ReactiveX/RxJS/commit/cb0b806)), closes [#1628](https://github.com/ReactiveX/RxJS/issues/1628)\n- **ConnectableObservable:** fix ConnectableObservable connection handling issue ([41ce80c](https://github.com/ReactiveX/RxJS/commit/41ce80c))\n- **typings:** make HotObservable.\\_subscribe protected ([1c3d6ea](https://github.com/ReactiveX/RxJS/commit/1c3d6ea))\n- **WebSocketSubject:** WebSocketSubject will now chain operators properly (#1752) ([bf54db4](https://github.com/ReactiveX/RxJS/commit/bf54db4)), closes [#1745](https://github.com/ReactiveX/RxJS/issues/1745)\n- **window:** don't track internal window subjects as subscriptions. ([f3357b9](https://github.com/ReactiveX/RxJS/commit/f3357b9))\n\n### Performance Improvements\n\n- **fromEventPattern:** ~3x improvement in speed ([3dc1c00](https://github.com/ReactiveX/RxJS/commit/3dc1c00))\n\n<a name=\"5.0.0-beta.8\"></a>\n\n# [5.0.0-beta.8](https://github.com/ReactiveX/RxJS/compare/5.0.0-beta.7...v5.0.0-beta.8) (2016-05-22)\n\n### Bug Fixes\n\n- **AnonymousSubject:** allow anonymous observers as destination ([0e2c28b](https://github.com/ReactiveX/RxJS/commit/0e2c28b))\n- **combineLatest:** rxjs/observable/combineLatest is now properly exported ([21fab73](https://github.com/ReactiveX/RxJS/commit/21fab73)), closes [#1722](https://github.com/ReactiveX/RxJS/issues/1722)\n- **ConnectableObservable:** fix race conditions in ConnectableObservable and refCount. ([d1412bc](https://github.com/ReactiveX/RxJS/commit/d1412bc))\n- **Rx:** remove kitchenSink and DOM, let Rx export all ([f5090b4](https://github.com/ReactiveX/RxJS/commit/f5090b4)), closes [#1650](https://github.com/ReactiveX/RxJS/issues/1650)\n- **ScalarObservable:** set \\_isScalar to false when initialized with a scheduler ([5037b3a](https://github.com/ReactiveX/RxJS/commit/5037b3a))\n- **Subject:** correct Subject behaviors to be more like Rx4 ([ba9ef2b](https://github.com/ReactiveX/RxJS/commit/ba9ef2b))\n- **subscriptions:** fixes bug that tracked subscriber subscriptions twice. ([29ff794](https://github.com/ReactiveX/RxJS/commit/29ff794))\n\n### Features\n\n- **bufferTime:** add `maxBufferSize` optional argument ([cf45540](https://github.com/ReactiveX/RxJS/commit/cf45540)), closes [#1295](https://github.com/ReactiveX/RxJS/issues/1295)\n- **multicast:** subjectfactory allows selectors ([32fa3a4](https://github.com/ReactiveX/RxJS/commit/32fa3a4))\n- **onErrorResumeNext:** add onErrorResumeNext operator ([51e022b](https://github.com/ReactiveX/RxJS/commit/51e022b)), closes [#1665](https://github.com/ReactiveX/RxJS/issues/1665)\n- **publish:** support optional selectors ([0e5991d](https://github.com/ReactiveX/RxJS/commit/0e5991d)), closes [#1629](https://github.com/ReactiveX/RxJS/issues/1629)\n\n### Performance Improvements\n\n- **combineLatest:** avoid splice and indexOf ([33599cd](https://github.com/ReactiveX/RxJS/commit/33599cd))\n\n### BREAKING CHANGES\n\n- Subject: Subjects no longer duck-type as Subscriptions\n- Subject: Subjects will no longer throw when re-subscribed to if they are not unsubscribed\n- Subject: Subjects no longer automatically unsubscribe when completed or errored\n  BREAKING CHANGE: Minor scheduling changes to groupBy to ensure proper emission ordering\n- Rx: `Rx.kitchenSink` and `Rx.DOM` are removed, `Rx`\n  export everything.\n\n<a name=\"5.0.0-beta.7\"></a>\n\n# [5.0.0-beta.7](https://github.com/ReactiveX/RxJS/compare/5.0.0-beta.6...v5.0.0-beta.7) (2016-04-27)\n\n### Bug Fixes\n\n- **race:** handle observables completes immediately ([abac3d1](https://github.com/ReactiveX/RxJS/commit/abac3d1)), closes [#1615](https://github.com/ReactiveX/RxJS/issues/1615)\n- **scan:** accumulator passes current index ([a3ec896](https://github.com/ReactiveX/RxJS/commit/a3ec896)), closes [#1614](https://github.com/ReactiveX/RxJS/issues/1614)\n\n### Features\n\n- **Observable.generate:** add generate static creation method ([c03434c](https://github.com/ReactiveX/RxJS/commit/c03434c))\n\n<a name=\"5.0.0-beta.6\"></a>\n\n# [5.0.0-beta.6](https://github.com/ReactiveX/RxJS/compare/5.0.0-beta.5...v5.0.0-beta.6) (2016-04-12)\n\n### Bug Fixes\n\n- **AjaxObservable:** support json responseType on IE ([bba13d8](https://github.com/ReactiveX/RxJS/commit/bba13d8)), closes [#1381](https://github.com/ReactiveX/RxJS/issues/1381)\n- **bufferToggle:** accepts closing selector returns promise ([b1c575c](https://github.com/ReactiveX/RxJS/commit/b1c575c))\n- **bufferToggle:** accepts promise as openings ([3d22c7a](https://github.com/ReactiveX/RxJS/commit/3d22c7a))\n- **bufferToggle:** handle closingSelector completes immediately ([02239fb](https://github.com/ReactiveX/RxJS/commit/02239fb))\n- **typings:** explicitly export typings for arguments to functions that destructure configuration objects ([ef305af](https://github.com/ReactiveX/RxJS/commit/ef305af))\n\n### Features\n\n- **UnsubscriptionError:** add messages from inner errors to output message ([dd01279](https://github.com/ReactiveX/RxJS/commit/dd01279)), closes [#1590](https://github.com/ReactiveX/RxJS/issues/1590)\n\n### Performance Improvements\n\n- **DeferSubscriber:** split up 'tryDefer()' into a method to call a factory function. ([566f46b](https://github.com/ReactiveX/RxJS/commit/566f46b))\n\n<a name=\"5.0.0-beta.5\"></a>\n\n# [5.0.0-beta.5](https://github.com/ReactiveX/RxJS/compare/5.0.0-beta.4...v5.0.0-beta.5) (2016-04-05)\n\n### Bug Fixes\n\n- **take:** make 'take' unsubscribe when it reaches the total ([9858aa3](https://github.com/ReactiveX/RxJS/commit/9858aa3))\n\n### BREAKING CHANGES\n\n- Operator: `Operator.prototype.call` has been refactored to include both the destination Subscriber, and the source Observable\n  the Operator is now responsible for describing it's own subscription process. ([26423f4](https://github.com/ReactiveX/rxjs/pull/1570/commits/26423f4))\n\n<a name=\"5.0.0-beta.4\"></a>\n\n# [5.0.0-beta.4](https://github.com/ReactiveX/RxJS/compare/5.0.0-beta.3...v5.0.0-beta.4) (2016-03-29)\n\n### Bug Fixes\n\n- **AjaxObservable:** enhance compatibility ([0ac7e1e](https://github.com/ReactiveX/RxJS/commit/0ac7e1e))\n- **Observable.if:** accept promise as source ([147166e](https://github.com/ReactiveX/RxJS/commit/147166e))\n- **mergeMap:** allow concurrent to be set as the second argument for mergeMap and mergeMapTo ([c003468](https://github.com/ReactiveX/RxJS/commit/c003468))\n- **observable:** ensure the subscriber chain is complete before calling this.\\_subscribe ([1631224](https://github.com/ReactiveX/RxJS/commit/1631224))\n- **Symbol:** fixed issue where \\$\\$observable is not defined ([e66b2d8](https://github.com/ReactiveX/RxJS/commit/e66b2d8))\n- **Observable.using:** accepts factory returns promise ([f8d7d1b](https://github.com/ReactiveX/RxJS/commit/f8d7d1b))\n- **windowToggle:** handle closingSelector completes immediately ([c755587](https://github.com/ReactiveX/RxJS/commit/c755587)), closes [#1487](https://github.com/ReactiveX/RxJS/issues/1487)\n\n### Features\n\n- **ajax:** add FormData support in AjaxObservable and add percent encoding for parameters ([1f6119c](https://github.com/ReactiveX/RxJS/commit/1f6119c))\n- **Subscription:** `add()` now returns a Subscription reference ([a3f4552](https://github.com/ReactiveX/RxJS/commit/a3f4552))\n- **timestamp:** add timestamp operator ([80b1646](https://github.com/ReactiveX/RxJS/commit/80b1646)), closes [#1515](https://github.com/ReactiveX/RxJS/issues/1515)\n\n### Performance Improvements\n\n- **forkJoin:** improve forkJoin perf slightly by removing unnecessary context tracking ([280b985](https://github.com/ReactiveX/RxJS/commit/280b985))\n\n### BREAKING CHANGES\n\n- Observable: `Observable.fromArray` was removed since it's deprecated on RxJS 4. You should use `Observable.from` instead.\n\n<a name=\"5.0.0-beta.3\"></a>\n\n# [5.0.0-beta.3](https://github.com/ReactiveX/RxJS/compare/5.0.0-beta.2...v5.0.0-beta.3) (2016-03-21)\n\n### Bug Fixes\n\n- **AjaxObservable:** update type definition for AjaxObservable ([3f5c269](https://github.com/ReactiveX/RxJS/commit/3f5c269)), closes [#1382](https://github.com/ReactiveX/RxJS/issues/1382)\n- **deferObservable:** accepts factory returns promise ([0cb44e1](https://github.com/ReactiveX/RxJS/commit/0cb44e1))\n- **do:** fix do operator to invoke observer message handlers in the right context. ([67a2f25](https://github.com/ReactiveX/RxJS/commit/67a2f25))\n- **exhaustMap:** remove innersubscription when it completes ([7ca0859](https://github.com/ReactiveX/RxJS/commit/7ca0859))\n- **forEach:** ensure that teardown logic is called when nextHandler throws ([c50f528](https://github.com/ReactiveX/RxJS/commit/c50f528)), closes [#1411](https://github.com/ReactiveX/RxJS/issues/1411)\n- **forkJoin:** accepts observables emitting null or undefined ([6279d6b](https://github.com/ReactiveX/RxJS/commit/6279d6b)), closes [#1362](https://github.com/ReactiveX/RxJS/issues/1362)\n- **forkJoin:** dispose the inner subscriptions when the outer subscription is disposed ([c7bf30c](https://github.com/ReactiveX/RxJS/commit/c7bf30c))\n- **FutureAction:** add support for periodic scheduling with setInterval instead of setTimeout ([c4f5408](https://github.com/ReactiveX/RxJS/commit/c4f5408))\n- **Observable:** introduce Subscribable interface that will be used instead of Observable in input ([2256e7b](https://github.com/ReactiveX/RxJS/commit/2256e7b))\n- **Observable.prototype.forEach:** removed thisArg to match es-observable spec ([d5f1bcd](https://github.com/ReactiveX/RxJS/commit/d5f1bcd))\n- **package.json:** install typings only after packages are installed ([a48d796](https://github.com/ReactiveX/RxJS/commit/a48d796))\n- **Schedulers:** ensure schedulers can be reused after error in execution ([202b79a](https://github.com/ReactiveX/RxJS/commit/202b79a))\n- **takeLast:** fix takeLast behavior to emit correct order ([73eb658](https://github.com/ReactiveX/RxJS/commit/73eb658)), closes [#1407](https://github.com/ReactiveX/RxJS/issues/1407)\n- **typings:** set map function parameter for Observable.from as optional ([efa4dc3](https://github.com/ReactiveX/RxJS/commit/efa4dc3))\n\n### Features\n\n- **AsyncScheduler:** add AsyncScheduler implementation ([4486c1f](https://github.com/ReactiveX/RxJS/commit/4486c1f))\n- **if:** add static Observable.if creation operator. ([f7ff7ec](https://github.com/ReactiveX/RxJS/commit/f7ff7ec))\n- **let:** adds the let operator to Rx.KitchenSink ([dca6504](https://github.com/ReactiveX/RxJS/commit/dca6504))\n- **using:** add static Observable.using creation operator. ([6c76593](https://github.com/ReactiveX/RxJS/commit/6c76593))\n\n### BREAKING CHANGES\n\n- Observable.prototype.forEach: thisArg removed to match es-observable spec\n\n<a name=\"5.0.0-beta.2\"></a>\n\n# [5.0.0-beta.2](https://github.com/ReactiveX/RxJS/compare/5.0.0-beta.1...v5.0.0-beta.2) (2016-02-10)\n\n### Bug Fixes\n\n- **ajax:** fixes error in Chrome accessing responseText when responseType isn't text. ([f3e2f73](https://github.com/ReactiveX/RxJS/commit/f3e2f73))\n- **benchpress:** fix issues with benchmarks ([16894bb](https://github.com/ReactiveX/RxJS/commit/16894bb))\n- **every:** remove eager predicate calls ([74c2c44](https://github.com/ReactiveX/RxJS/commit/74c2c44))\n- **forkJoin:** fix forkJoin to complete if sources Array is empty. ([412b13b](https://github.com/ReactiveX/RxJS/commit/412b13b))\n- **groupBy:** does not emit on unsubscribed group ([6d08705](https://github.com/ReactiveX/RxJS/commit/6d08705))\n- **groupBy:** fix groupBy to use lift(), supports composability ([815cfae](https://github.com/ReactiveX/RxJS/commit/815cfae)), closes [#1085](https://github.com/ReactiveX/RxJS/issues/1085)\n- **merge/concat:** passed scalar observables will now complete properly ([c01b92f](https://github.com/ReactiveX/RxJS/commit/c01b92f)), closes [#1150](https://github.com/ReactiveX/RxJS/issues/1150)\n- **MergeMapSubscriber:** clarify type definitions for MergeMapSubscriber's members ([4ee5f02](https://github.com/ReactiveX/RxJS/commit/4ee5f02))\n- **Observable.forEach:** errors thrown in nextHandler reject returned promise ([c5ead88](https://github.com/ReactiveX/RxJS/commit/c5ead88)), closes [#1184](https://github.com/ReactiveX/RxJS/issues/1184)\n- **Observer:** fix typing to allow observation via partial observables with PartialObservable<T ([7b6da90](https://github.com/ReactiveX/RxJS/commit/7b6da90))\n- **Subject:** align parameter order to match with RxJS4 ([44dfa07](https://github.com/ReactiveX/RxJS/commit/44dfa07)), closes [#1285](https://github.com/ReactiveX/RxJS/issues/1285)\n- **Subject:** throw ObjectUnsubscribedError when unsubscribed ([29b630b](https://github.com/ReactiveX/RxJS/commit/29b630b)), closes [#859](https://github.com/ReactiveX/RxJS/issues/859)\n- **Subscriber:** adds unsubscription when errors are thrown from user-land handlers. ([dc67d21](https://github.com/ReactiveX/RxJS/commit/dc67d21))\n- **Subscription:** fix leaks caused by unsubscribe functions that throw ([9e88c2e](https://github.com/ReactiveX/RxJS/commit/9e88c2e))\n- **subscriptions:** unsubscribe correctly when a Subscriber throws during synchronous dispatch. ([b1698fe](https://github.com/ReactiveX/RxJS/commit/b1698fe))\n- **typings:** don't expose PromiseConstructor dependency ([f59225b](https://github.com/ReactiveX/RxJS/commit/f59225b)), closes [#1270](https://github.com/ReactiveX/RxJS/issues/1270)\n- **typings:** remove R from Operator.call, update operators accordingly ([f27902d](https://github.com/ReactiveX/RxJS/commit/f27902d))\n- **typings:** remove redundant generics from call<T, R> and lift<T, R> ([603c9eb](https://github.com/ReactiveX/RxJS/commit/603c9eb))\n- **windowTime:** does not emit on unsubscribed window ([595f4ef](https://github.com/ReactiveX/RxJS/commit/595f4ef))\n\n### Features\n\n- **cache:** add cache operator ([4308a04](https://github.com/ReactiveX/RxJS/commit/4308a04))\n- **delayWhen:** add delayWhen operator ([17122f9](https://github.com/ReactiveX/RxJS/commit/17122f9))\n- **distinct:** add distinct operator ([94a034d](https://github.com/ReactiveX/RxJS/commit/94a034d))\n- **distinctKey:** add distinctKey operator ([fe4d57f](https://github.com/ReactiveX/RxJS/commit/fe4d57f))\n- **from:** allow Observable.from to handle array-like objects ([7245005](https://github.com/ReactiveX/RxJS/commit/7245005))\n- **MapPolyfill:** implement clear interface ([e3fbd05](https://github.com/ReactiveX/RxJS/commit/e3fbd05))\n- **operator:** adds inspect and inspectTime operators ([54f957b](https://github.com/ReactiveX/RxJS/commit/54f957b))\n- **OuterSubscriber:** notifyNext passes innersubscriber when next emits ([1df8928](https://github.com/ReactiveX/RxJS/commit/1df8928)), closes [#1250](https://github.com/ReactiveX/RxJS/issues/1250)\n- **Subject:** implement asObservable ([aca3dd0](https://github.com/ReactiveX/RxJS/commit/aca3dd0)), closes [#1108](https://github.com/ReactiveX/RxJS/issues/1108)\n- **takeLast:** adds takeLast operator. ([3583cd3](https://github.com/ReactiveX/RxJS/commit/3583cd3))\n\n### Performance Improvements\n\n- **catch:** remove tryCatch/errorObject for custom tryCatching, 1.3M -> 1.5M ops/sec ([35caf74](https://github.com/ReactiveX/RxJS/commit/35caf74))\n- **combineLatest:** remove tryCatch/errorObject, 156k -> 221k ops/sec ([1c7d639](https://github.com/ReactiveX/RxJS/commit/1c7d639))\n- **count:** remove tryCatch/errorObject for custom tryCatching, 1.84M -> 1.97M ops/sec ([869718d](https://github.com/ReactiveX/RxJS/commit/869718d))\n- **debounce:** remove tryCatch/errorObject for custom tryCatching ([90bf3f1](https://github.com/ReactiveX/RxJS/commit/90bf3f1))\n- **distinct:** increase perf from 60% of Rx4 to 1000% Rx4 ([d026c41](https://github.com/ReactiveX/RxJS/commit/d026c41))\n- **do:** remove tryCatch/errorObject use, 104k -> 263k ops/sec improvement ([ccba39d](https://github.com/ReactiveX/RxJS/commit/ccba39d))\n- **every:** remove tryCatch/errorObject (~1.8x improvement) ([14afeb6](https://github.com/ReactiveX/RxJS/commit/14afeb6))\n- **exhaustMap:** remove tryCatch/errorObject (~10% improvement) ([a55f459](https://github.com/ReactiveX/RxJS/commit/a55f459))\n- **filter:** remove tryCatch/errorObject for 2x perf improvement ([086c4bf](https://github.com/ReactiveX/RxJS/commit/086c4bf))\n- **find:** remove tryCatch/errorObject (~2x improvement) ([aa35b2a](https://github.com/ReactiveX/RxJS/commit/aa35b2a))\n- **first:** remove tryCatch/errorObject for custom tryCatching, 970k ops -> 1.27M ops/sec ([d8c835a](https://github.com/ReactiveX/RxJS/commit/d8c835a))\n- **groupBy:** remove tryCatch/errorObject for custom tryCatching, 38% faster. ([40c43f7](https://github.com/ReactiveX/RxJS/commit/40c43f7))\n- **last:** remove tryCatch/errorObject for custom tryCatching, 960k -> 1.38M ops/sec ([243ace3](https://github.com/ReactiveX/RxJS/commit/243ace3))\n- **map:** 2x increase from removing tryCatch/errorObject ([231f729](https://github.com/ReactiveX/RxJS/commit/231f729))\n- **mergeMap:** extra 1x factor gains from custom tryCatch member function ([c4ce2fb](https://github.com/ReactiveX/RxJS/commit/c4ce2fb))\n- **mergeMapTo:** remove tryCatch/errorObject (~2x improvement) ([42bcced](https://github.com/ReactiveX/RxJS/commit/42bcced))\n- **reduce:** remove tryCatch/errorObject, optimize calls, 2-3x perf improvement ([6186d46](https://github.com/ReactiveX/RxJS/commit/6186d46))\n- **scan:** remove tryCatch/errorObject for custom tryCatcher 1.75x improvement ([338135d](https://github.com/ReactiveX/RxJS/commit/338135d))\n- **single:** remove tryCatch/errorObject (~2.5x improvement) ([2515cfb](https://github.com/ReactiveX/RxJS/commit/2515cfb))\n- **skipWhile:** remove tryCatch/errorObject (~1.6x improvement) ([cf002db](https://github.com/ReactiveX/RxJS/commit/cf002db))\n- **Subscriber:** double performance adding tryOrUnsub to Subscriber ([4e75466](https://github.com/ReactiveX/RxJS/commit/4e75466))\n- **switchMap:** remove tryCatch/errorObject ~20% improvement ([ec0199f](https://github.com/ReactiveX/RxJS/commit/ec0199f))\n- **switchMapTo:** remove tryCatch/errorObject (~2x improvement) ([c8cf72a](https://github.com/ReactiveX/RxJS/commit/c8cf72a))\n- **takeWhile:** remove tryCatch/errorObject (~6x improvement) ([ef6c3c3](https://github.com/ReactiveX/RxJS/commit/ef6c3c3))\n- **withLatestFrom:** remove tryCatch/errorObject, 92k -> 107k (16% improvement) ([e4ccb44](https://github.com/ReactiveX/RxJS/commit/e4ccb44))\n- **zip:** extra 1x-2x factor gains from custom tryCatch member function ([a1b0e52](https://github.com/ReactiveX/RxJS/commit/a1b0e52))\n\n### BREAKING CHANGES\n\n- Subject: Subject.create arguments have been swapped to match Rx 4 signature. `Subject.create(observable, observer)` is now `Subject.create(observer, observable)`\n- Observable patching: Patch files for static observable methods such as `of` and `from` can now be found in `rxjs/add/observable/of`, `rxjs/add/observable/from`, etc.\n- Observable modules: Observable modules for subclassed Observables like `PromiseObservable`, `ArrayObservable` are now in appropriately named files like `rxjs/observable/PromiseObservable` and `rxjs/observable/ArrayObservable`\n  as opposed to `rxjs/observable/fromPromise` and `rxjs/observable/fromArray`, since they're not patching, they simply house the Observable implementations.\n\n<a name=\"5.0.0-beta.1\"></a>\n\n# [5.0.0-beta.1](https://github.com/ReactiveX/RxJS/compare/5.0.0-beta.0...v5.0.0-beta.1) (2016-01-13)\n\n### Bug Fixes\n\n- **ajax:** ensure post sending values ([7aae0a3](https://github.com/ReactiveX/RxJS/commit/7aae0a3))\n- **ajax:** ensure that headers are set properly ([1100bdd](https://github.com/ReactiveX/RxJS/commit/1100bdd))\n- **ajax:** ensure XHR props are set after open ([4a6a579](https://github.com/ReactiveX/RxJS/commit/4a6a579))\n- **ajax:** ensure XHR send is being called ([c569e3e](https://github.com/ReactiveX/RxJS/commit/c569e3e))\n- **ajax:** remove unnecessary onAbort handling ([ed8240e](https://github.com/ReactiveX/RxJS/commit/ed8240e))\n- **ajax:** response properly based off responseType ([b2a27a2](https://github.com/ReactiveX/RxJS/commit/b2a27a2))\n- **ajax:** should no longer succeed on 300 status ([4d4fa32](https://github.com/ReactiveX/RxJS/commit/4d4fa32))\n- **animationFrame:** req/cancel animationFrame has to be called within the context of root. ([30a11ee](https://github.com/ReactiveX/RxJS/commit/30a11ee))\n- **debounceTime:** align value emit behavior as same as RxJS4 ([5ee11e0](https://github.com/ReactiveX/RxJS/commit/5ee11e0)), closes [#1081](https://github.com/ReactiveX/RxJS/issues/1081)\n- **distinctUntilChanged:** implement optional keySelector ([f6a897c](https://github.com/ReactiveX/RxJS/commit/f6a897c))\n- **fromEvent:** added spread operator for emitters that pass multiple arguments ([3f8eabb](https://github.com/ReactiveX/RxJS/commit/3f8eabb))\n- **fromObservable:** expand compatibility for iterating string source ([8f7924f](https://github.com/ReactiveX/RxJS/commit/8f7924f)), closes [#1147](https://github.com/ReactiveX/RxJS/issues/1147)\n- **Immediate:** update setImmediate compatibility on IE ([39e6c0e](https://github.com/ReactiveX/RxJS/commit/39e6c0e)), closes [#1163](https://github.com/ReactiveX/RxJS/issues/1163)\n- **inspect:** remove inspect and inspectTime operators ([17341a4](https://github.com/ReactiveX/RxJS/commit/17341a4))\n- **Readme:** update link to bundle on npmcdn ([44a8ca7](https://github.com/ReactiveX/RxJS/commit/44a8ca7))\n- **ReplaySubject:** Fix case-sensitive import. ([de31f32](https://github.com/ReactiveX/RxJS/commit/de31f32))\n- **ScalarObservable:** fix issue where scalar map fired twice ([c18c42e](https://github.com/ReactiveX/RxJS/commit/c18c42e)), closes [#1142](https://github.com/ReactiveX/RxJS/issues/1142) [#1140](https://github.com/ReactiveX/RxJS/issues/1140)\n- **scheduling:** Fixes bugs in scheduled actions. ([e050f01](https://github.com/ReactiveX/RxJS/commit/e050f01))\n- **Subscriber:** errors in nextHandler no longer propagate to errorHandler ([f42eed2](https://github.com/ReactiveX/RxJS/commit/f42eed2)), closes [#1135](https://github.com/ReactiveX/RxJS/issues/1135)\n- **WebSocketSubject:** ensure error codes passed to WebSocket close method ([3b1655e](https://github.com/ReactiveX/RxJS/commit/3b1655e))\n- **WebSocketSubject:** ensure WebSocketSubject can be resubscribed ([861a0c1](https://github.com/ReactiveX/RxJS/commit/861a0c1))\n- **WebSocketSubject:** resultSelector and protocols specifications work properly ([580f69a](https://github.com/ReactiveX/RxJS/commit/580f69a))\n\n### Features\n\n- **ajax:** add resultSelector and improve perf ([6df755f](https://github.com/ReactiveX/RxJS/commit/6df755f))\n- **ajax:** adds ajax methods from rx-dom. ([2ca4236](https://github.com/ReactiveX/RxJS/commit/2ca4236))\n- **bindNodeCallback:** add Observable.bindNodeCallback ([497bb0d](https://github.com/ReactiveX/RxJS/commit/497bb0d)), closes [#736](https://github.com/ReactiveX/RxJS/issues/736)\n- **Observable:** add let to allow fluent style query building ([5a2014c](https://github.com/ReactiveX/RxJS/commit/5a2014c))\n- **Observable:** add pairwise operator ([1432e59](https://github.com/ReactiveX/RxJS/commit/1432e59))\n- **Operator:** Expose the Operator interface to library consumers ([29aa3af](https://github.com/ReactiveX/RxJS/commit/29aa3af))\n- **pluck:** add pluck operator ([8026906](https://github.com/ReactiveX/RxJS/commit/8026906)), closes [#1134](https://github.com/ReactiveX/RxJS/issues/1134)\n- **race:** add race operator ([ee3b593](https://github.com/ReactiveX/RxJS/commit/ee3b593))\n- **scheduler:** adds animationFrame scheduler. ([e637b78](https://github.com/ReactiveX/RxJS/commit/e637b78))\n- **WebSocketSubject:** add basic WebSocketSubject implementation ([58cd806](https://github.com/ReactiveX/RxJS/commit/58cd806))\n- **WebSocketSubject.multiplex:** add multiplex operator to WebSocketSubject ([904d617](https://github.com/ReactiveX/RxJS/commit/904d617))\n\n### BREAKING CHANGES\n\n- inspect: `inspect` and `inspectTime` were removed. Use `withLatestFrom` instead.\n- Subscriber/Observable: errors thrown in nextHandlers by consumer code will no longer propagate to the errorHandler.\n\n<a name=\"5.0.0-beta.0\"></a>\n\n# [5.0.0-beta.0](https://github.com/ReactiveX/RxJS/compare/5.0.0-alpha.14...v5.0.0-beta.0) (2015-12-15)\n\n### Bug Fixes\n\n- **micro-perf:** rename immediate to queue scheduler ([fe56b28](https://github.com/ReactiveX/RxJS/commit/fe56b28)), closes [#1040](https://github.com/ReactiveX/RxJS/issues/1040)\n- **micro-perf:** use the current scheduler on current-thread tests ([3dff5eb](https://github.com/ReactiveX/RxJS/commit/3dff5eb))\n- **operators:** emit declarations for patch modules ([676f82d](https://github.com/ReactiveX/RxJS/commit/676f82d))\n- **test:** make explicit unsubscription for observable ([7f67b09](https://github.com/ReactiveX/RxJS/commit/7f67b09))\n- **test:** make explicit unsubscription for observable ([65e65e2](https://github.com/ReactiveX/RxJS/commit/65e65e2))\n- **window:** fix window() to dispose window Subjects ([5168f73](https://github.com/ReactiveX/RxJS/commit/5168f73))\n- **windowCount:** fix windowCount to dispose window Subjects ([f29ee29](https://github.com/ReactiveX/RxJS/commit/f29ee29))\n- **windowTime:** fix windowTime to dispose window Subjects ([b73e260](https://github.com/ReactiveX/RxJS/commit/b73e260))\n- **windowToggle:** fix windowToggle to dispose window Subjects ([15ff3f7](https://github.com/ReactiveX/RxJS/commit/15ff3f7))\n- **windowWhen:** fix windowWhen to dispose window Subjects ([91c1941](https://github.com/ReactiveX/RxJS/commit/91c1941))\n\n### Features\n\n- **inspect:** added inspect operator ([f9944ae](https://github.com/ReactiveX/RxJS/commit/f9944ae))\n- **inspectTime:** add inspectTime operator ([6835dcd](https://github.com/ReactiveX/RxJS/commit/6835dcd))\n- **sample:** readd `sample` operator ([e93bffc](https://github.com/ReactiveX/RxJS/commit/e93bffc))\n- **sampleTime:** reimplement `sampleTime` with RxJS 4 behavior ([6b77e69](https://github.com/ReactiveX/RxJS/commit/6b77e69))\n- **TestScheduler:** add createTime() parser to return number ([cb8cf6b](https://github.com/ReactiveX/RxJS/commit/cb8cf6b))\n\n### BREAKING CHANGES\n\n- sampleTime: `sampleTime` now has the same behavior `sample(number, scheduler)` did in RxJS 4\n- sample: `sample` behavior returned to RxJS 4 behavior\n- inspectTime: `sampleTime` is now `inspectTime`\n- inspect: RxJS 5 `sample` behavior is now `inspect`\n- extended operators: All extended operators are now under the same operator directory as all others. This means that\n  `import \"rxjs/add/operator/extended/min\"` is now `import \"rxjs/add/operator/min\"`\n\n<a name=\"5.0.0-alpha.14\"></a>\n\n# [5.0.0-alpha.14](https://github.com/ReactiveX/RxJS/compare/5.0.0-alpha.13...v5.0.0-alpha.14) (2015-12-09)\n\n### Bug Fixes\n\n- **every:** handle thisArg for scalar and array observables ([eae4b00](https://github.com/ReactiveX/RxJS/commit/eae4b00))\n- **SymbolShim:** ensure for function even if Symbol already exists ([e942776](https://github.com/ReactiveX/RxJS/commit/e942776)), closes [#999](https://github.com/ReactiveX/RxJS/issues/999)\n- **SymbolShim:** Symbol polyfill is a function ([1f57157](https://github.com/ReactiveX/RxJS/commit/1f57157)), closes [#988](https://github.com/ReactiveX/RxJS/issues/988)\n- **timeoutWith:** fix to avoid unnecessary inner subscription ([6e63752](https://github.com/ReactiveX/RxJS/commit/6e63752))\n\n### Features\n\n- **count:** remove thisArg ([878a1fd](https://github.com/ReactiveX/RxJS/commit/878a1fd))\n- **distinctUntilChanged:** remove thisArg ([bfc52d6](https://github.com/ReactiveX/RxJS/commit/bfc52d6))\n- **exhaust:** rename switchFirst operators to exhaust ([9b565c9](https://github.com/ReactiveX/RxJS/commit/9b565c9)), closes [#915](https://github.com/ReactiveX/RxJS/issues/915)\n- **finally:** remove thisArg ([d4b02fc](https://github.com/ReactiveX/RxJS/commit/d4b02fc))\n- **forEach:** add thisArg ([14ffce6](https://github.com/ReactiveX/RxJS/commit/14ffce6)), closes [#878](https://github.com/ReactiveX/RxJS/issues/878)\n- **single:** remove thisArg ([43af805](https://github.com/ReactiveX/RxJS/commit/43af805))\n\n### BREAKING CHANGES\n\n- exhaust: switchFirst is now exhaust\n- exhaust: switchFirstMap is now exhaustMap\n- forEach: Observable.prototype.forEach argument order changed to accommodate thisArg. Optional PromiseCtor argument moved to third arg from second\n\n<a name=\"5.0.0-alpha.13\"></a>\n\n# [5.0.0-alpha.13](https://github.com/ReactiveX/RxJS/compare/5.0.0-alpha.12...v5.0.0-alpha.13) (2015-12-08)\n\n### Bug Fixes\n\n- **Observable:** fix circular dependency issue. ([b7672f4](https://github.com/ReactiveX/RxJS/commit/b7672f4))\n- **bufferToggle:** fix unsubscriptions of closing Observable ([439b641](https://github.com/ReactiveX/RxJS/commit/439b641))\n- **expand:** accept scheduler parameter ([79e9084](https://github.com/ReactiveX/RxJS/commit/79e9084)), closes [#841](https://github.com/ReactiveX/RxJS/issues/841)\n- **publish:** make script generate correct package names ([10563d3](https://github.com/ReactiveX/RxJS/commit/10563d3))\n- **repeat:** preserve Subscriber chain in repeat() ([d9a7328](https://github.com/ReactiveX/RxJS/commit/d9a7328))\n- **retry:** preserve Subscriber chain in retry() ([b429dac](https://github.com/ReactiveX/RxJS/commit/b429dac))\n- **retryWhen:** preserve Subscriber chain in retryWhen() ([c9cb958](https://github.com/ReactiveX/RxJS/commit/c9cb958))\n\n### Features\n\n- **AsapScheduler:** rename NextTickScheduler to AsapScheduler ([3255fb3](https://github.com/ReactiveX/RxJS/commit/3255fb3)), closes [#838](https://github.com/ReactiveX/RxJS/issues/838)\n- **BehaviorSubject:** add getValue method to access value ([33b387b](https://github.com/ReactiveX/RxJS/commit/33b387b)), closes [#758](https://github.com/ReactiveX/RxJS/issues/758)\n- **BehaviorSubject:** now throws when getValue is called after unsubscription ([1ddf116](https://github.com/ReactiveX/RxJS/commit/1ddf116))\n- **ObjectUnsubscribedError:** add ObjectUnsubscribed error class ([39836af](https://github.com/ReactiveX/RxJS/commit/39836af))\n- **Observable:** subscribe accepts objects with rxSubscriber symbol ([b7672f4](https://github.com/ReactiveX/RxJS/commit/b7672f4))\n- **QueueScheduler:** rename ImmediateScheduler to QueueScheduler ([66eb537](https://github.com/ReactiveX/RxJS/commit/66eb537))\n- **Rx.Symbol.rxSubscriber:** add rxSubscriber symbol ([d4f1670](https://github.com/ReactiveX/RxJS/commit/d4f1670))\n- **Subject:** add rxSubscriber symbol ([d2e4257](https://github.com/ReactiveX/RxJS/commit/d2e4257))\n- **Subscriber:** add rxSubscriber symbol ([7bda360](https://github.com/ReactiveX/RxJS/commit/7bda360))\n- **switchFirstMap:** rename switchMapFirst to switchFirstMap ([eddd4dc](https://github.com/ReactiveX/RxJS/commit/eddd4dc))\n\n### BREAKING CHANGES\n\n- AsapScheduler: `Rx.Scheduler.nextTick` (Rx 4's \"default\" scheduler) is now `Rx.Scheduler.asap`\n- QueueScheduler: `Rx.Scheduler.immediate` (Rx 4's \"currentThread\" scheduler) is now `Rx.Scheduler.queue`\n  related #838\n- switchFirstMap: `switchMapFirst` is now `switchFirstMap`\n\n<a name=\"5.0.0-alpha.12\"></a>\n\n# [5.0.0-alpha.12](https://github.com/ReactiveX/RxJS/compare/5.0.0-alpha.10...v5.0.0-alpha.12) (2015-12-04)\n\n### Bug Fixes\n\n- **AsyncSubject:** emit value when it's subscribed after complete ([ed0eaf6](https://github.com/ReactiveX/RxJS/commit/ed0eaf6))\n- **bindCallback:** only call function once even while scheduled ([8637d47](https://github.com/ReactiveX/RxJS/commit/8637d47)), closes [#881](https://github.com/ReactiveX/RxJS/issues/881)\n- **bufferToggle:** fix disposal of subscriptions when errors occur ([a20325c](https://github.com/ReactiveX/RxJS/commit/a20325c))\n- **catch:** fix catch to dispose old subscriptions ([280f7ed](https://github.com/ReactiveX/RxJS/commit/280f7ed)), closes [#763](https://github.com/ReactiveX/RxJS/issues/763)\n- **catch:** fix catch() to preserve Subscriber chain ([e1447ac](https://github.com/ReactiveX/RxJS/commit/e1447ac))\n- **concat:** accept scheduler parameter ([8859702](https://github.com/ReactiveX/RxJS/commit/8859702))\n- **ConnectableObservable:** fix ConnectableObservable connectability and refCounting ([aef9578](https://github.com/ReactiveX/RxJS/commit/aef9578)), closes [#678](https://github.com/ReactiveX/RxJS/issues/678)\n- **debounce:** Fix debounce to unsubscribe duration Observables ([dea7847](https://github.com/ReactiveX/RxJS/commit/dea7847))\n- **expand:** fix expand's concurrency behavior ([01f86e5](https://github.com/ReactiveX/RxJS/commit/01f86e5))\n- **expand:** terminate recursive call when destination completes ([3b8cf94](https://github.com/ReactiveX/RxJS/commit/3b8cf94))\n- **Observable:** Subjects no longer wrapped in Subscriber ([5cb0f2b](https://github.com/ReactiveX/RxJS/commit/5cb0f2b)), closes [#825](https://github.com/ReactiveX/RxJS/issues/825) [#748](https://github.com/ReactiveX/RxJS/issues/748)\n- **Observer:** anonymous observers now allow missing handlers ([a11c763](https://github.com/ReactiveX/RxJS/commit/a11c763)), closes [#723](https://github.com/ReactiveX/RxJS/issues/723)\n- **operators:** Remove shareReplay and shareBehavior ([536a6a6](https://github.com/ReactiveX/RxJS/commit/536a6a6)), closes [#710](https://github.com/ReactiveX/RxJS/issues/710)\n- **publish:** copy readme and license, remove scripts ([439a2f3](https://github.com/ReactiveX/RxJS/commit/439a2f3)), closes [#845](https://github.com/ReactiveX/RxJS/issues/845)\n- **throttleTime:** fix and rename throttleTime operator ([3b0c1f3](https://github.com/ReactiveX/RxJS/commit/3b0c1f3))\n- **TimerObservable:** accepts absolute date for dueTime ([e284fb8](https://github.com/ReactiveX/RxJS/commit/e284fb8)), closes [#648](https://github.com/ReactiveX/RxJS/issues/648)\n\n### Features\n\n- **AsyncSubject:** add AsyncSubject ([34c05fe](https://github.com/ReactiveX/RxJS/commit/34c05fe))\n- **bindCallback:** remove thisArg ([feea9a1](https://github.com/ReactiveX/RxJS/commit/feea9a1))\n- **bindCallback:** rename fromCallback to bindCallback ([305d66d](https://github.com/ReactiveX/RxJS/commit/305d66d)), closes [#876](https://github.com/ReactiveX/RxJS/issues/876)\n- **callback:** Add Observable.fromCallback ([9f751e7](https://github.com/ReactiveX/RxJS/commit/9f751e7))\n- **combineLatest:** accept array of observable as parameter ([2edd92c](https://github.com/ReactiveX/RxJS/commit/2edd92c)), closes [#594](https://github.com/ReactiveX/RxJS/issues/594)\n- **forkJoin:** accept array of observable as parameter ([d45f672](https://github.com/ReactiveX/RxJS/commit/d45f672))\n- **mergeScan:** support concurrency parameter for mergeScan ([fe0eb37](https://github.com/ReactiveX/RxJS/commit/fe0eb37)), closes [#868](https://github.com/ReactiveX/RxJS/issues/868)\n- **usage:** add auto-patching operators ([1ab3508](https://github.com/ReactiveX/RxJS/commit/1ab3508)), closes [#860](https://github.com/ReactiveX/RxJS/issues/860)\n- **skipWhile:** add skipWhile operator ([a2244e0](https://github.com/ReactiveX/RxJS/commit/a2244e0))\n- **switchFirst:** add switchFirst and switchMapFirst ([71e3dd1](https://github.com/ReactiveX/RxJS/commit/71e3dd1))\n- **publishLast:** add publishLast operator ([9bef228](https://github.com/ReactiveX/RxJS/commit/9bef228)), closes [#883](https://github.com/ReactiveX/RxJS/issues/883)\n- **takeWhile:** add takeWhile operator ([48e53ea](https://github.com/ReactiveX/RxJS/commit/48e53ea)), closes [#695](https://github.com/ReactiveX/RxJS/issues/695)\n- **takeWhile:** remove thisArg ([b5219a4](https://github.com/ReactiveX/RxJS/commit/b5219a4))\n- **throttle:** add throttle operator with durationSelector ([c3bf3e7](https://github.com/ReactiveX/RxJS/commit/c3bf3e7)), closes [#496](https://github.com/ReactiveX/RxJS/issues/496)\n\n### Performance Improvements\n\n- **ReplaySubject:** fix memory leak of growing buffer ([0a73b4d](https://github.com/ReactiveX/RxJS/commit/0a73b4d)), closes [#578](https://github.com/ReactiveX/RxJS/issues/578)\n\n<a name=\"5.0.0-alpha.11\"></a>\n\n# [5.0.0-alpha.11](https://github.com/ReactiveX/RxJS/compare/5.0.0-alpha.10...v5.0.0-alpha.11) (2015-12-01)\n\n### Bug Fixes\n\n- **catch:** fix catch to dispose old subscriptions ([280f7ed](https://github.com/ReactiveX/RxJS/commit/280f7ed)), closes [#763](https://github.com/ReactiveX/RxJS/issues/763)\n- **concat:** accept scheduler parameter ([8859702](https://github.com/ReactiveX/RxJS/commit/8859702))\n- **ConnectableObservable:** fix ConnectableObservable connectability and refCounting ([aef9578](https://github.com/ReactiveX/RxJS/commit/aef9578)), closes [#678](https://github.com/ReactiveX/RxJS/issues/678)\n- **debounce:** Fix debounce to unsubscribe duration Observables ([dea7847](https://github.com/ReactiveX/RxJS/commit/dea7847))\n- **expand:** fix expand's concurrency behavior ([01f86e5](https://github.com/ReactiveX/RxJS/commit/01f86e5))\n- **expand:** terminate recursive call when destination completes ([3b8cf94](https://github.com/ReactiveX/RxJS/commit/3b8cf94))\n- **Observer:** anonymous observers now allow missing handlers ([a11c763](https://github.com/ReactiveX/RxJS/commit/a11c763)), closes [#723](https://github.com/ReactiveX/RxJS/issues/723)\n- **operators:** Remove shareReplay and shareBehavior ([536a6a6](https://github.com/ReactiveX/RxJS/commit/536a6a6)), closes [#710](https://github.com/ReactiveX/RxJS/issues/710)\n- **test:** make explicit unsubscription for observable ([505f5b7](https://github.com/ReactiveX/RxJS/commit/505f5b7))\n- **throttleTime:** fix and rename throttleTime operator ([3b0c1f3](https://github.com/ReactiveX/RxJS/commit/3b0c1f3))\n- **TimerObservable:** accepts absolute date for dueTime ([e284fb8](https://github.com/ReactiveX/RxJS/commit/e284fb8)), closes [#648](https://github.com/ReactiveX/RxJS/issues/648)\n\n### Features\n\n- **callback:** Add Observable.fromCallback ([9f751e7](https://github.com/ReactiveX/RxJS/commit/9f751e7))\n- **combineLatest:** accept array of observable as parameter ([2edd92c](https://github.com/ReactiveX/RxJS/commit/2edd92c)), closes [#594](https://github.com/ReactiveX/RxJS/issues/594)\n- **forkJoin:** accept array of observable as parameter ([d45f672](https://github.com/ReactiveX/RxJS/commit/d45f672))\n- **operator:** add skipWhile operator ([a2244e0](https://github.com/ReactiveX/RxJS/commit/a2244e0))\n- **operator:** add switchFirst and switchMapFirst ([71e3dd1](https://github.com/ReactiveX/RxJS/commit/71e3dd1))\n- **takeWhile:** add takeWhile operator ([48e53ea](https://github.com/ReactiveX/RxJS/commit/48e53ea)), closes [#695](https://github.com/ReactiveX/RxJS/issues/695)\n- **throttle:** add throttle operator with durationSelector ([c3bf3e7](https://github.com/ReactiveX/RxJS/commit/c3bf3e7)), closes [#496](https://github.com/ReactiveX/RxJS/issues/496)\n\n### Performance Improvements\n\n- **ReplaySubject:** fix memory leak of growing buffer ([0a73b4d](https://github.com/ReactiveX/RxJS/commit/0a73b4d)), closes [#578](https://github.com/ReactiveX/RxJS/issues/578)\n\n<a name=\"5.0.0-alpha.10\"></a>\n\n# [5.0.0-alpha.10](https://github.com/ReactiveX/RxJS/compare/5.0.0-alpha.9...v5.0.0-alpha.10) (2015-11-10)\n\n### Bug Fixes\n\n- **Immediate:** set immediate should no longer throw in Chrome ([a3de7d9](https://github.com/ReactiveX/RxJS/commit/a3de7d9)), closes [#690](https://github.com/ReactiveX/RxJS/issues/690)\n\n<a name=\"5.0.0-alpha.9\"></a>\n\n# [5.0.0-alpha.9](https://github.com/ReactiveX/RxJS/compare/5.0.0-alpha.8...v5.0.0-alpha.9) (2015-11-10)\n\n### Bug Fixes\n\n- **util:** incorrect Symbol.iterator for es6-shim ([15bf32c](https://github.com/ReactiveX/RxJS/commit/15bf32c))\n\n### Features\n\n- **forkJoin:** accept promise, resultselector as parameter of forkJoin ([190f349](https://github.com/ReactiveX/RxJS/commit/190f349)), closes [#507](https://github.com/ReactiveX/RxJS/issues/507)\n\n<a name=\"5.0.0-alpha.8\"></a>\n\n# [5.0.0-alpha.8](https://github.com/ReactiveX/RxJS/compare/5.0.0-alpha.7...v5.0.0-alpha.8) (2015-11-06)\n\n### Bug Fixes\n\n- **concat:** handle a given scheduler correctly ([8745216](https://github.com/ReactiveX/RxJS/commit/8745216))\n- **package.json:** loosen the engines/npm semver range to prevent false warnings ([df791c6](https://github.com/ReactiveX/RxJS/commit/df791c6))\n- **skipUntil:** unsubscribe source when it completes ([8a4162b](https://github.com/ReactiveX/RxJS/commit/8a4162b)), closes [#577](https://github.com/ReactiveX/RxJS/issues/577)\n- **take:** deal with total <= 0 and add tests ([c5cc06f](https://github.com/ReactiveX/RxJS/commit/c5cc06f))\n- **windowWhen:** fix windowWhen with regard to unsubscriptions ([8174947](https://github.com/ReactiveX/RxJS/commit/8174947))\n\n### Features\n\n- **mergeScan:** add new mergeScan operator. ([0ebb5bd](https://github.com/ReactiveX/RxJS/commit/0ebb5bd))\n- **multicast:** support both Subject and subjectFactory arguments ([f779027](https://github.com/ReactiveX/RxJS/commit/f779027))\n\n### BREAKING CHANGES\n\n- **publish:** reverted to RxJS 4 behavior\n- **publishBehavior:** reverted to RxJS 4 behavior\n- **publishReplay:** reverted to RxJS 4 behavior\n- **shareBehavior:** removed\n- **shareReplay:** removed\n\n<a name=\"5.0.0-alpha.7\"></a>\n\n# [5.0.0-alpha.7](https://github.com/ReactiveX/RxJS/compare/5.0.0-alpha.6...v5.0.0-alpha.7) (2015-10-27)\n\n### Bug Fixes\n\n- **NextTickAction:** fix unsubscription behavior ([3d8264c](https://github.com/ReactiveX/RxJS/commit/3d8264c)), closes [#582](https://github.com/ReactiveX/RxJS/issues/582)\n- **buffer:** cleanup notifier subscription when unsubscribed ([1b30aa9](https://github.com/ReactiveX/RxJS/commit/1b30aa9))\n- **delay:** accepts absolute time delay ([b109100](https://github.com/ReactiveX/RxJS/commit/b109100))\n- **mergeMapTo:** mergeMapTo result should complete ([6f9859e](https://github.com/ReactiveX/RxJS/commit/6f9859e))\n- **operator:** update type definitions for union types ([9d90c75](https://github.com/ReactiveX/RxJS/commit/9d90c75)), closes [#581](https://github.com/ReactiveX/RxJS/issues/581)\n- **repeat:** fix inner subscription semantics for repeat ([f67a596](https://github.com/ReactiveX/RxJS/commit/f67a596)), closes [#554](https://github.com/ReactiveX/RxJS/issues/554)\n- **switchMapTo:** reimplement switchMapTo to pass tests ([d4789cd](https://github.com/ReactiveX/RxJS/commit/d4789cd))\n- **takeUntil:** unsubscribe notifier when it completes ([9415196](https://github.com/ReactiveX/RxJS/commit/9415196))\n\n### Features\n\n- **operator:** add max operator ([7fda036](https://github.com/ReactiveX/RxJS/commit/7fda036))\n- **operator:** add min operator ([79cb6cf](https://github.com/ReactiveX/RxJS/commit/79cb6cf))\n- **shareBehavior:** add shareBehavior and its tests ([97ff1ec](https://github.com/ReactiveX/RxJS/commit/97ff1ec))\n\n<a name=\"5.0.0-alpha.6\"></a>\n\n# [5.0.0-alpha.6](https://github.com/ReactiveX/RxJS/compare/5.0.0-alpha.5...v5.0.0-alpha.6) (2015-10-17)\n\n### Bug Fixes\n\n- **retryWhen:** fix internal unsubscriptions ([5aff5e8](https://github.com/ReactiveX/RxJS/commit/5aff5e8))\n- **scan:** scan now behaves like RxJS 4 scan ([27f9c09](https://github.com/ReactiveX/RxJS/commit/27f9c09))\n\n<a name=\"5.0.0-alpha.5\"></a>\n\n# [5.0.0-alpha.5](https://github.com/ReactiveX/RxJS/compare/5.0.0-alpha.4...v5.0.0-alpha.5) (2015-10-16)\n\n### Bug Fixes\n\n- **bufferToggle:** fix bugs in order to pass tests ([949fa31](https://github.com/ReactiveX/RxJS/commit/949fa31))\n- **mergeAll:** fix mergeAll micro performance tests to use mapTo instead of map. ([616e86e](https://github.com/ReactiveX/RxJS/commit/616e86e))\n- **package:** correct typings path ([a501b06](https://github.com/ReactiveX/RxJS/commit/a501b06))\n- **repeat:** add additional resubscription behavior ([4f9f33b](https://github.com/ReactiveX/RxJS/commit/4f9f33b)), closes [#516](https://github.com/ReactiveX/RxJS/issues/516)\n- **retry:** fix internal unsubscriptions for retry ([cc92f45](https://github.com/ReactiveX/RxJS/commit/cc92f45)), closes [#546](https://github.com/ReactiveX/RxJS/issues/546)\n- **windowToggle:** fix window closing and unsubscription semantics ([0cb21e6](https://github.com/ReactiveX/RxJS/commit/0cb21e6))\n\n<a name=\"5.0.0-alpha.4\"></a>\n\n# [5.0.0-alpha.4](https://github.com/ReactiveX/RxJS/compare/5.0.0-alpha.3...5.0.0-alpha.4) (2015-10-15)\n\n### Bug Fixes\n\n- **Subject:** fix missing unsubscribe call ([9dd27d6](https://github.com/ReactiveX/RxJS/commit/9dd27d6))\n- **Subscriber:** avoid implicit any ([08faaa9](https://github.com/ReactiveX/RxJS/commit/08faaa9))\n- **bufferWhen:** onComplete of closings determine buffers ([5d28a38](https://github.com/ReactiveX/RxJS/commit/5d28a38))\n- **fromEvent:** make selector argument optional in fromEvent static method ([71d90b4](https://github.com/ReactiveX/RxJS/commit/71d90b4))\n- **skipUntil:** update skipUntil behavior with error, completion ([6f0d98f](https://github.com/ReactiveX/RxJS/commit/6f0d98f)), closes [#518](https://github.com/ReactiveX/RxJS/issues/518)\n- **windowCount:** fix windowCount window opening times ([908ae56](https://github.com/ReactiveX/RxJS/commit/908ae56)), closes [#273](https://github.com/ReactiveX/RxJS/issues/273)\n\n### Features\n\n- **operator:** add debounce operator ([a1e652f](https://github.com/ReactiveX/RxJS/commit/a1e652f)), closes [#493](https://github.com/ReactiveX/RxJS/issues/493)\n- **operator:** add debounceTime operator ([dd2ba40](https://github.com/ReactiveX/RxJS/commit/dd2ba40))\n\n### Performance Improvements\n\n- **ScalarObservable:** add fast-path for mapping scalar observables ([7b0d3dc](https://github.com/ReactiveX/RxJS/commit/7b0d3dc))\n- **count:** fast-path for counting over scalars ([c35a120](https://github.com/ReactiveX/RxJS/commit/c35a120))\n- **filter:** add fast-path for filtering scalar observables ([e2e8954](https://github.com/ReactiveX/RxJS/commit/e2e8954))\n- **reduce:** add fast-path for reducing over scalar observables ([4c65136](https://github.com/ReactiveX/RxJS/commit/4c65136))\n- **scan:** fast-path for scanning scalars ([0201b92](https://github.com/ReactiveX/RxJS/commit/0201b92))\n- **skip:** fast-path for skip over scalar observable ([9b49936](https://github.com/ReactiveX/RxJS/commit/9b49936))\n- **take:** add fast-path for take over scalars ([33053b1](https://github.com/ReactiveX/RxJS/commit/33053b1))\n\n<a name=\"5.0.0-alpha.3\"></a>\n\n# [5.0.0-alpha.3](https://github.com/ReactiveX/RxJS/compare/5.0.0-alpha.2...5.0.0-alpha.3) (2015-10-13)\n\n### Bug Fixes\n\n- **Observable:** fix type signature of some static operators ([e5364de](https://github.com/ReactiveX/RxJS/commit/e5364de))\n- **Subject.create:** ensure operator property not required for Observable subscription ([2259de2](https://github.com/ReactiveX/RxJS/commit/2259de2)), closes [#483](https://github.com/ReactiveX/RxJS/issues/483)\n- **TestScheduler:** stop sorting actual results ([51db0b8](https://github.com/ReactiveX/RxJS/commit/51db0b8)), closes [#422](https://github.com/ReactiveX/RxJS/issues/422)\n- **benchpress:** update benchpress dependencies and config ([8513eaa](https://github.com/ReactiveX/RxJS/commit/8513eaa)), closes [#348](https://github.com/ReactiveX/RxJS/issues/348)\n- **buffer:** change behavior of buffer to more closely match RxJS 4 ([b66592d](https://github.com/ReactiveX/RxJS/commit/b66592d))\n- **combineLatest:** fix type signature ([a3e6deb](https://github.com/ReactiveX/RxJS/commit/a3e6deb))\n- **defer:** fix type signature ([11327b9](https://github.com/ReactiveX/RxJS/commit/11327b9))\n- **empty:** fix type signature ([893cb7e](https://github.com/ReactiveX/RxJS/commit/893cb7e))\n- **fromPromise:** fix type signature ([17415fa](https://github.com/ReactiveX/RxJS/commit/17415fa))\n- **groupBy:** durationSelector cannot keep source alive ([57e4207](https://github.com/ReactiveX/RxJS/commit/57e4207))\n- **groupBy:** fix bugs related to group resets ([23a7574](https://github.com/ReactiveX/RxJS/commit/23a7574))\n- **groupBy:** fix bugs with groupBy ([86992c6](https://github.com/ReactiveX/RxJS/commit/86992c6))\n- **interval:** fix signature type ([9c238c0](https://github.com/ReactiveX/RxJS/commit/9c238c0))\n- **operator:** startWith operator accepts scheduler, multiple values ([d1d339a](https://github.com/ReactiveX/RxJS/commit/d1d339a))\n- **operators:** reorder signature of resultSelectors ([fc1724d](https://github.com/ReactiveX/RxJS/commit/fc1724d))\n- **range:** fix type signature ([9237d0b](https://github.com/ReactiveX/RxJS/commit/9237d0b))\n- **timeout:** fix absolute timeout behavior ([8ec06cf](https://github.com/ReactiveX/RxJS/commit/8ec06cf))\n- **timeout:** update behavior of timeout, timeoutWith ([16bd691](https://github.com/ReactiveX/RxJS/commit/16bd691))\n- **timer:** fix type signature ([fffb96c](https://github.com/ReactiveX/RxJS/commit/fffb96c))\n- **window:** handle closingNotifier errors/completes ([42beff1](https://github.com/ReactiveX/RxJS/commit/42beff1))\n\n### Features\n\n- **TestScheduler:** support unsubscription marbles ([ffb0bb9](https://github.com/ReactiveX/RxJS/commit/ffb0bb9))\n- **count:** add predicate support in count() ([42d1add](https://github.com/ReactiveX/RxJS/commit/42d1add)), closes [#425](https://github.com/ReactiveX/RxJS/issues/425)\n- **dematerialize:** add dematerialize operator ([0a8b074](https://github.com/ReactiveX/RxJS/commit/0a8b074)), closes [#475](https://github.com/ReactiveX/RxJS/issues/475)\n- **do:** do will now handle an observer as an argument ([c1a4994](https://github.com/ReactiveX/RxJS/commit/c1a4994)), closes [#476](https://github.com/ReactiveX/RxJS/issues/476)\n- **first:** add resultSelector ([3c20fcc](https://github.com/ReactiveX/RxJS/commit/3c20fcc)), closes [#417](https://github.com/ReactiveX/RxJS/issues/417)\n- **last:** add resultSelector argument ([5a4896c](https://github.com/ReactiveX/RxJS/commit/5a4896c)), closes [#418](https://github.com/ReactiveX/RxJS/issues/418)\n- **operator:** add every operator ([d11f32e](https://github.com/ReactiveX/RxJS/commit/d11f32e))\n- **operator:** add timeInterval operator ([6cc0615](https://github.com/ReactiveX/RxJS/commit/6cc0615))\n- **share:** add the share operator ([c36f2be](https://github.com/ReactiveX/RxJS/commit/c36f2be)), closes [#439](https://github.com/ReactiveX/RxJS/issues/439)\n- **shareReplay:** add the shareReplay() operator ([65c84ea](https://github.com/ReactiveX/RxJS/commit/65c84ea))\n\n### Performance Improvements\n\n- **ReplaySubject:** remove unnecessary computation ([488ac2e](https://github.com/ReactiveX/RxJS/commit/488ac2e))\n\n### BREAKING CHANGES\n\n- **operators with resultSelectors** (mergeMap, concatMap, switchMap, etc):\n  The function signature of resultSelectors used to be (innerValue,\n  outerValue, innerIndex, outerIndex) but this commits changes it to\n  be (outerValue, innerValue, outerIndex, innerIndex), to match\n  signatures in RxJS 4.\n\n<a name=\"5.0.0-alpha.2\"></a>\n\n# [5.0.0-alpha.2](https://github.com/ReactiveX/RxJS/compare/5.0.0-alpha.1...5.0.0-alpha.2) (2015-09-30)\n\n### Bug Fixes\n\n- **concat:** let observable concat instead of merge ([c17e832](https://github.com/ReactiveX/RxJS/commit/c17e832))\n\n### Features\n\n- **operator:** add find, findIndex operator ([7c6cc9d](https://github.com/ReactiveX/RxJS/commit/7c6cc9d))\n- **operator:** add first operator ([274c233](https://github.com/ReactiveX/RxJS/commit/274c233))\n- **operator:** add ignoreElements operator ([fe1a952](https://github.com/ReactiveX/RxJS/commit/fe1a952))\n- **zip:** zip now supports never-ending iterables ([a5684ba](https://github.com/ReactiveX/RxJS/commit/a5684ba)), closes [#397](https://github.com/ReactiveX/RxJS/issues/397)\n\n<a name=\"5.0.0-alpha.1\"></a>\n\n# [5.0.0-alpha.1](https://github.com/ReactiveX/RxJS/compare/0.0.0-prealpha.3...5.0.0-alpha.1) (2015-09-23)\n\n### Bug Fixes\n\n- **Promises:** escape promise error trap ([c69088a](https://github.com/ReactiveX/RxJS/commit/c69088a))\n- **TestScheduler:** ensure TestScheduler subscribes to expectations before hot subjects ([b9b2ba5](https://github.com/ReactiveX/RxJS/commit/b9b2ba5))\n- **TestScheduler:** properly schedule actions added dynamically ([069ede4](https://github.com/ReactiveX/RxJS/commit/069ede4))\n- **buffer:** do not emit empty buffer when completes ([252fccb](https://github.com/ReactiveX/RxJS/commit/252fccb))\n- **bufferTime:** inner intervals will now clean up properly ([4ef41b0](https://github.com/ReactiveX/RxJS/commit/4ef41b0))\n- **expand:** Fix expand to stay open until the source Observable completes. ([20ef785](https://github.com/ReactiveX/RxJS/commit/20ef785))\n- **expand:** fix expand operator to match Rx3 ([67f9623](https://github.com/ReactiveX/RxJS/commit/67f9623))\n- **last:** emit value matches with predicate instead of result of predicate ([0f635ee](https://github.com/ReactiveX/RxJS/commit/0f635ee))\n- **merge:** fix issues with async in merge ([7a15304](https://github.com/ReactiveX/RxJS/commit/7a15304))\n- **mergeAll:** merge all will properly handle async observables ([43b63cc](https://github.com/ReactiveX/RxJS/commit/43b63cc))\n- **package:** specify supported npm version ([f72e622](https://github.com/ReactiveX/RxJS/commit/f72e622))\n- **switchAll:** switch all will properly handle async observables ([c2e2d29](https://github.com/ReactiveX/RxJS/commit/c2e2d29))\n- **switchAll/switchLatest:** inner subscriptions should now properly unsub ([38a45f8](https://github.com/ReactiveX/RxJS/commit/38a45f8)), closes [#302](https://github.com/ReactiveX/RxJS/issues/302)\n\n### Features\n\n- **combineLatest:** supports promises, iterables, lowercase-o observables and Observables ([ce76e4e](https://github.com/ReactiveX/RxJS/commit/ce76e4e))\n- **config:** add global configuration of Promise capability ([e7eb5d7](https://github.com/ReactiveX/RxJS/commit/e7eb5d7)), closes [#115](https://github.com/ReactiveX/RxJS/issues/115)\n- **expand:** now handles promises, iterables and lowercase-o observables ([c5239e9](https://github.com/ReactiveX/RxJS/commit/c5239e9))\n- **mergeAll:** now supports promises, iterables and lowercase-o observables ([4c16aa6](https://github.com/ReactiveX/RxJS/commit/4c16aa6))\n- **operator:** add elementAt operator ([cd562c4](https://github.com/ReactiveX/RxJS/commit/cd562c4))\n- **operator:** add isEmpty operator ([80f72c5](https://github.com/ReactiveX/RxJS/commit/80f72c5))\n- **operator:** add last operator ([d841b11](https://github.com/ReactiveX/RxJS/commit/d841b11)), closes [#304](https://github.com/ReactiveX/RxJS/issues/304) [#306](https://github.com/ReactiveX/RxJS/issues/306)\n- **operator:** add single operator ([49484a2](https://github.com/ReactiveX/RxJS/commit/49484a2))\n- **switch:** add promise, iterable and array support ([24fdd34](https://github.com/ReactiveX/RxJS/commit/24fdd34))\n- **withLatestFrom:** default array output, handle other types ([cb393dc](https://github.com/ReactiveX/RxJS/commit/cb393dc))\n- **zip:** supports promises, iterables and lowercase-o observables ([d332a0e](https://github.com/ReactiveX/RxJS/commit/d332a0e))\n\n<a name=\"0.0.0-prealpha.3\"></a>\n\n# [0.0.0-prealpha.3](https://github.com/ReactiveX/RxJS/compare/0.0.0-prealpha.2...0.0.0-prealpha.3) (2015-09-11)\n\n### Bug Fixes\n\n- **root:** use self as the root object when available ([0428a85](https://github.com/ReactiveX/RxJS/commit/0428a85))\n\n<a name=\"0.0.0-prealpha.2\"></a>\n\n# [0.0.0-prealpha.2](https://github.com/ReactiveX/RxJS/compare/0.0.0-prealpha.1...0.0.0-prealpha.2) (2015-09-11)\n\n### Bug Fixes\n\n- **bufferCount:** set default value for skip argument, do not emit empty buffer at the end ([2c1a9dc](https://github.com/ReactiveX/RxJS/commit/2c1a9dc))\n- **windowCount:** set default value for skip argument, do not emit empty buffer at the end ([a513dbb](https://github.com/ReactiveX/RxJS/commit/a513dbb))\n\n### Features\n\n- **Observable:** add static create method ([e0d27ba](https://github.com/ReactiveX/RxJS/commit/e0d27ba)), closes [#255](https://github.com/ReactiveX/RxJS/issues/255)\n- **TestScheduler:** add TestScheduler ([b23daf1](https://github.com/ReactiveX/RxJS/commit/b23daf1)), closes [#270](https://github.com/ReactiveX/RxJS/issues/270)\n- **VirtualTimeScheduler:** add VirtualTimeScheduler ([96f9386](https://github.com/ReactiveX/RxJS/commit/96f9386)), closes [#269](https://github.com/ReactiveX/RxJS/issues/269)\n- **operator:** add sample and sampleTime ([9e62789](https://github.com/ReactiveX/RxJS/commit/9e62789)), closes [#178](https://github.com/ReactiveX/RxJS/issues/178)\n\n<a name=\"0.0.0-prealpha.1\"></a>\n\n# [0.0.0-prealpha.1](https://github.com/ReactiveX/RxJS/compare/0441dea...0.0.0-prealpha.1) (2015-09-02)\n\n### Bug Fixes\n\n- **combineLatest:** check for limits higher than total observable count ([81e5dfb](https://github.com/ReactiveX/RxJS/commit/81e5dfb))\n- **rx:** add hack to export global until better global build exists ([1a543b0](https://github.com/ReactiveX/RxJS/commit/1a543b0))\n- **subscription-ref:** add setter for isDisposed ([6fe5427](https://github.com/ReactiveX/RxJS/commit/6fe5427))\n- **take:** complete on limit reached ([801a711](https://github.com/ReactiveX/RxJS/commit/801a711))\n\n### Features\n\n- **benchpress:** add benchpress config and flatmap spec ([0441dea](https://github.com/ReactiveX/RxJS/commit/0441dea))\n- **catch:** add catch operator, related to #141, closes #130 ([94b4c01](https://github.com/ReactiveX/RxJS/commit/94b4c01)), closes [#130](https://github.com/ReactiveX/RxJS/issues/130)\n- **from:** let from handle any \"observablesque\" ([526d4c3](https://github.com/ReactiveX/RxJS/commit/526d4c3)), closes [#156](https://github.com/ReactiveX/RxJS/issues/156) [#236](https://github.com/ReactiveX/RxJS/issues/236)\n- **index:** add index module which requires commonjs build ([379d2d1](https://github.com/ReactiveX/RxJS/commit/379d2d1)), closes [#117](https://github.com/ReactiveX/RxJS/issues/117)\n- **observable:** add Observable.all (forkJoin) ([44a4ee1](https://github.com/ReactiveX/RxJS/commit/44a4ee1))\n- **operator:** Add count operator. ([30dd894](https://github.com/ReactiveX/RxJS/commit/30dd894))\n- **operator:** Add distinctUntilChanged and distinctUntilKeyChanged ([f9ba4da](https://github.com/ReactiveX/RxJS/commit/f9ba4da))\n- **operator:** Add do operator. ([7d9b52b](https://github.com/ReactiveX/RxJS/commit/7d9b52b))\n- **operator:** Add expand operator. ([47b178b](https://github.com/ReactiveX/RxJS/commit/47b178b))\n- **operator:** Add minimal delay operator. ([7851885](https://github.com/ReactiveX/RxJS/commit/7851885))\n- **operator:** add buffer operators: buffer, bufferWhen, bufferTime, bufferCount, and bufferTog ([9f8347f](https://github.com/ReactiveX/RxJS/commit/9f8347f)), closes [#207](https://github.com/ReactiveX/RxJS/issues/207)\n- **operator:** add debounce ([f03adaf](https://github.com/ReactiveX/RxJS/commit/f03adaf)), closes [#193](https://github.com/ReactiveX/RxJS/issues/193)\n- **operator:** add defaultIfEmpty ([c80688b](https://github.com/ReactiveX/RxJS/commit/c80688b))\n- **operator:** add finally ([526e4c9](https://github.com/ReactiveX/RxJS/commit/526e4c9))\n- **operator:** add fromEventPattern creator function ([1095d4c](https://github.com/ReactiveX/RxJS/commit/1095d4c))\n- **operator:** add groupBy ([1e13aea](https://github.com/ReactiveX/RxJS/commit/1e13aea)), closes [#165](https://github.com/ReactiveX/RxJS/issues/165)\n- **operator:** add materialize. closes #132 ([6d9f6ae](https://github.com/ReactiveX/RxJS/commit/6d9f6ae)), closes [#132](https://github.com/ReactiveX/RxJS/issues/132)\n- **operator:** add publishBehavior operator and spec ([249ab8d](https://github.com/ReactiveX/RxJS/commit/249ab8d))\n- **operator:** add publishReplay operator and spec ([a0c47d6](https://github.com/ReactiveX/RxJS/commit/a0c47d6))\n- **operator:** add retry ([4451db5](https://github.com/ReactiveX/RxJS/commit/4451db5))\n- **operator:** add retryWhen operator. closes #129 ([65eb50e](https://github.com/ReactiveX/RxJS/commit/65eb50e)), closes [#129](https://github.com/ReactiveX/RxJS/issues/129)\n- **operator:** add skipUntil ([ef2620e](https://github.com/ReactiveX/RxJS/commit/ef2620e)), closes [#180](https://github.com/ReactiveX/RxJS/issues/180)\n- **operator:** add throttle ([1d735b9](https://github.com/ReactiveX/RxJS/commit/1d735b9)), closes [#191](https://github.com/ReactiveX/RxJS/issues/191)\n- **operator:** add timeout and timeoutWith ([bb440ad](https://github.com/ReactiveX/RxJS/commit/bb440ad)), closes [#244](https://github.com/ReactiveX/RxJS/issues/244)\n- **operator:** add toPromise operator. closes #159 ([361a53b](https://github.com/ReactiveX/RxJS/commit/361a53b)), closes [#159](https://github.com/ReactiveX/RxJS/issues/159)\n- **operator:** add window operators: window, windowWhen, windowTime, windowCount, windowToggle ([9f5d510](https://github.com/ReactiveX/RxJS/commit/9f5d510)), closes [#195](https://github.com/ReactiveX/RxJS/issues/195)\n- **operator:** add withLatestFrom ([322218a](https://github.com/ReactiveX/RxJS/commit/322218a)), closes [#209](https://github.com/ReactiveX/RxJS/issues/209)\n- **operator:** implement startWith(). ([1f36d99](https://github.com/ReactiveX/RxJS/commit/1f36d99))\n"
  },
  {
    "path": "packages/rxjs/Dockerfile",
    "content": "FROM node:lts\n\n# Create app directory\nWORKDIR /rxjs\n\nCOPY . .\n\nWORKDIR /rxjs/apps/rxjs.dev\n\nRUN yarn setup\n\nEXPOSE 4200\n\nCMD [\"npm\", \"start:docker\"]"
  },
  {
    "path": "packages/rxjs/README.md",
    "content": "# <img src=\"apps/rxjs.dev/src/assets/images/logos/Rx_Logo_S.png\" alt=\"RxJS Logo\" width=\"86\" height=\"86\"> RxJS: Reactive Extensions For JavaScript\n\n![CI](https://github.com/reactivex/rxjs/workflows/CI/badge.svg)\n[![npm version](https://badge.fury.io/js/rxjs.svg)](http://badge.fury.io/js/rxjs)\n[![Join the chat at https://gitter.im/Reactive-Extensions/RxJS](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/Reactive-Extensions/RxJS?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)\n\n# RxJS 8\n\n### FOR 7.X PLEASE GO TO [THE 7.x BRANCH](https://github.com/ReactiveX/rxjs/tree/7.x)\n\nReactive Extensions Library for JavaScript. This is a rewrite of [Reactive-Extensions/RxJS](https://github.com/Reactive-Extensions/RxJS) and is the latest production-ready version of RxJS. This rewrite is meant to have better performance, better modularity, better debuggable call stacks, while staying mostly backwards compatible, with some breaking changes that reduce the API surface.\n\n[Apache 2.0 License](LICENSE.txt)\n\n- [Code of Conduct](CODE_OF_CONDUCT.md)\n- [Contribution Guidelines](CONTRIBUTING.md)\n- [Maintainer Guidelines](apps/rxjs.dev/content/maintainer-guidelines.md)\n- [API Documentation](https://rxjs.dev/)\n\n## Versions In This Repository\n\n- [master](https://github.com/ReactiveX/rxjs/commits/master) - This is all of the current work, which is against v8 of RxJS right now\n- [7.x](https://github.com/ReactiveX/rxjs/tree/7.x) - This is the branch for version 7.X\n- [6.x](https://github.com/ReactiveX/rxjs/tree/6.x) - This is the branch for version 6.X\n\nMost PRs should be made to **master**.\n\n## Important\n\nBy contributing or commenting on issues in this repository, whether you've read them or not, you're agreeing to the [Contributor Code of Conduct](CODE_OF_CONDUCT.md). Much like traffic laws, ignorance doesn't grant you immunity.\n\n## Installation and Usage\n\n### ES6 via npm\n\n```shell\nnpm install rxjs\n```\n\nIt's recommended to pull in the Observable creation methods you need directly from `'rxjs'` as shown below with `range`.\nIf you're using RxJS version 7.2 or above, you can pull in any operator you need from the same spot, `'rxjs'`.\n\n```ts\nimport { range, filter, map } from 'rxjs';\n\nrange(1, 200)\n  .pipe(\n    filter((x) => x % 2 === 1),\n    map((x) => x + x)\n  )\n  .subscribe((x) => console.log(x));\n```\n\nIf you're using RxJS version below 7.2, you can pull in any operator you need from one spot, under `'rxjs/operators'`.\n\n```ts\nimport { range } from 'rxjs';\nimport { filter, map } from 'rxjs/operators';\n\nrange(1, 200)\n  .pipe(\n    filter((x) => x % 2 === 1),\n    map((x) => x + x)\n  )\n  .subscribe((x) => console.log(x));\n```\n\n## Goals\n\n- Smaller overall bundles sizes\n- Provide better performance than preceding versions of RxJS\n- To model/follow the [Observable Spec Proposal](https://github.com/zenparsing/es-observable) to the observable\n- Provide more modular file structure in a variety of formats\n- Provide more debuggable call stacks than preceding versions of RxJS\n\n## Building/Testing\n\n- `yarn compile` build everything\n- `npm test` run tests\n- `yarn dtslint` run dtslint tests\n\n## Adding documentation\n\nWe appreciate all contributions to the documentation of any type. All of the information needed to get the docs app up and running locally as well as how to contribute can be found in the [documentation directory](apps/rxjs.dev).\n"
  },
  {
    "path": "packages/rxjs/integration/import/fixtures/browser/browser-test.js",
    "content": "import { Observable, from, map } from './node_modules/rxjs/dist/esm/index.js';\nimport { ajax } from './node_modules/rxjs/dist/esm/ajax/index.js';\nimport { webSocket } from './node_modules/rxjs/dist/esm/webSocket/index.js';\nimport { fromFetch } from './node_modules/rxjs/dist/esm/fetch/index.js';\nimport { TestScheduler } from './node_modules/rxjs/dist/esm/testing/index.js';\n\nlet success = true;\n\nconst assert = (condition, message) => {\n  if (condition) {\n    // show a green check mark emoji\n    console.log(`✅ ${message}`);\n  } else {\n    success = false;\n    console.log(`❌ ${message}`);\n  }\n};\n\nconsole.log('Hello from the browser!');\n\nassert(Observable, 'Observable should exist');\nassert(map, 'map should exist');\nassert(ajax, 'ajax should exist');\nassert(webSocket, 'webSocket should exist');\nassert(fromFetch, 'fromFetch should exist');\nassert(TestScheduler, 'TestScheduler should exist');\n\nconst results = [];\nfrom([1, 2, 3]).subscribe((x) => {\n  results.push(x);\n});\n\nassert(results.length === 3, 'from should work');\n\nwindow.reportDone(success);\n"
  },
  {
    "path": "packages/rxjs/integration/import/fixtures/browser/index.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"UTF-8\" />\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" />\n    <title>RxJS Import Integration Test</title>\n  </head>\n  <script type=\"importmap\">\n    {\n      \"imports\": {\n        \"@rxjs/observable\": \"./node_modules/@rxjs/observable/dist/browser/index.js\"\n      }\n    }\n  </script>\n  <body>\n    <script type=\"module\" src=\"./browser-test.js\"></script>\n  </body>\n</html>\n"
  },
  {
    "path": "packages/rxjs/integration/import/fixtures/browser/index.mjs",
    "content": "import puppeteer from 'puppeteer';\nimport { join, dirname } from 'node:path';\nimport { fileURLToPath } from 'node:url';\n\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = dirname(__filename);\n\nasync function main() {\n  console.log('Starting puppeteer...');\n  const timeout = setTimeout(() => {\n    console.error('Operation timed out.');\n    browser.close();\n    process.exit(1);\n  }, 10000);\n\n  const browser = await puppeteer.launch({\n    args: ['--allow-file-access-from-files'],\n    // headless: false,\n  });\n\n  const page = await browser.newPage();\n\n  page.on('pageerror', (error) => {\n    console.error('Page error:', error.message);\n    browser.close();\n    process.exit(1);\n  });\n\n  // Listen for console events\n  page.on('console', async (msg) => {\n    const type = msg.type();\n    if (type === 'error') {\n      console.error('JS Error:', msg.text());\n      // Handle or throw error here\n    } else {\n      console.log(`${type.toUpperCase()}:`, msg.text());\n    }\n  });\n\n  // Expose a function to the page for signaling success\n  await page.exposeFunction('reportDone', (success) => {\n    clearTimeout(timeout);\n    browser.close();\n    if (success) {\n      console.log('Script executed successfully!');\n      process.exit(0);\n    } else {\n      console.error('Browser script failed!');\n      process.exit(1);\n    }\n  });\n\n  const url = `file://${join(__dirname, './index.html')}`;\n  console.log(`Navigating to ${url}...`);\n  await page.goto(url);\n}\n\nmain().catch((error) => {\n  console.error('Error:', error);\n  process.exit(1);\n});\n"
  },
  {
    "path": "packages/rxjs/integration/import/fixtures/browser/package.json",
    "content": "{\n  \"name\": \"rxjs-import-test\",\n  \"private\": true,\n  \"version\": \"0.0.1\",\n  \"module\": \"./index.mjs\",\n  \"scripts\": {\n    \"test\": \"node ./index.mjs\"\n  },\n  \"dependencies\": {\n    \"puppeteer\": \"^21.4.1\"\n  }\n}\n"
  },
  {
    "path": "packages/rxjs/integration/import/fixtures/commonjs/index.js",
    "content": "const assert = require('assert').strict;\n\nconst rx = require('rxjs');\nconst operators = require('rxjs/operators');\nconst ajax = require('rxjs/ajax');\nconst webSocket = require('rxjs/webSocket');\nconst rxFetch = require('rxjs/fetch');\nconst testing = require('rxjs/testing');\n\nconst coldObservable = require('rxjs/internal/testing/ColdObservable');\n\nassert.ok(rx, 'main export should exists');\nassert.ok(operators, 'operator export should exists');\nassert.ok(coldObservable, 'internal can be imported');\nassert.ok(ajax, 'ajax can be imported');\nassert.ok(webSocket, 'webSocket can be imported');\nassert.ok(rxFetch, 'rxFetch can be imported');\nassert.ok(testing, 'testing can be imported');\n\n// Assert a few key things exist in each of the imported modules\nassert.ok(rx.Observable, 'Observable should exist');\nassert.ok(operators.map, 'map should exist');\nassert.ok(ajax.ajax, 'ajax should exist');\nassert.ok(webSocket.webSocket, 'webSocket should exist');\nassert.ok(rxFetch.fromFetch, 'fromFetch should exist');\nassert.ok(testing.TestScheduler, 'TestScheduler should exist');\n"
  },
  {
    "path": "packages/rxjs/integration/import/fixtures/commonjs/package.json",
    "content": "{\n  \"name\": \"rxjs-import-test\",\n  \"private\": true,\n  \"version\": \"0.0.1\",\n  \"main\": \"./index.js\",\n  \"scripts\": {\n    \"test\": \"node ./index.js\"\n  },\n  \"dependencies\": {}\n}\n"
  },
  {
    "path": "packages/rxjs/integration/import/fixtures/esm/index.mjs",
    "content": "import { strict as assert } from 'assert';\nimport * as rx from 'rxjs';\nimport * as operators from 'rxjs/operators';\nimport * as ajax from 'rxjs/ajax';\nimport * as webSocket from 'rxjs/webSocket';\nimport * as rxFetch from 'rxjs/fetch';\nimport * as testing from 'rxjs/testing';\nimport * as coldObservable from 'rxjs/internal/testing/ColdObservable';\n\nassert.ok(rx, 'main export should exists');\nassert.ok(operators, 'operator export should exists');\nassert.ok(coldObservable, 'internal can be imported');\nassert.ok(ajax, 'ajax can be imported');\nassert.ok(webSocket, 'webSocket can be imported');\nassert.ok(rxFetch, 'rxFetch can be imported');\nassert.ok(testing, 'testing can be imported');\n\n// Assert a few key things exist in each of the imported modules\nassert.ok(rx.Observable, 'Observable should exist');\nassert.ok(operators.map, 'map should exist');\nassert.ok(ajax.ajax, 'ajax should exist');\nassert.ok(webSocket.webSocket, 'webSocket should exist');\nassert.ok(rxFetch.fromFetch, 'fromFetch should exist');\nassert.ok(testing.TestScheduler, 'TestScheduler should exist');\n"
  },
  {
    "path": "packages/rxjs/integration/import/fixtures/esm/package.json",
    "content": "{\n  \"name\": \"rxjs-import-test\",\n  \"private\": true,\n  \"module\": \"./index.mjs\",\n  \"version\": \"0.0.1\",\n  \"scripts\": {\n    \"test\": \"node ./index.mjs\"\n  },\n  \"dependencies\": {}\n}\n"
  },
  {
    "path": "packages/rxjs/integration/import/fixtures/vite-bundle/.gitignore",
    "content": "# Logs\nlogs\n*.log\nnpm-debug.log*\nyarn-debug.log*\nyarn-error.log*\npnpm-debug.log*\nlerna-debug.log*\n\nnode_modules\ndist\ndist-ssr\n*.local\n\n# Editor directories and files\n.vscode/*\n!.vscode/extensions.json\n.idea\n.DS_Store\n*.suo\n*.ntvs*\n*.njsproj\n*.sln\n*.sw?\n"
  },
  {
    "path": "packages/rxjs/integration/import/fixtures/vite-bundle/index.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"UTF-8\" />\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" />\n    <title>Vite + TS Import Test</title>\n  </head>\n  <body>\n    <script type=\"module\" src=\"/src/main.ts\"></script>\n  </body>\n</html>\n"
  },
  {
    "path": "packages/rxjs/integration/import/fixtures/vite-bundle/package.json",
    "content": "{\n  \"name\": \"vite-bundle\",\n  \"private\": true,\n  \"version\": \"0.0.0\",\n  \"type\": \"module\",\n  \"scripts\": {\n    \"test\": \"node test.mjs\",\n    \"dev\": \"vite\",\n    \"build\": \"tsc && vite build\",\n    \"preview\": \"vite preview\"\n  },\n  \"devDependencies\": {\n    \"typescript\": \"^5.0.2\",\n    \"vite\": \"^4.4.5\"\n  },\n  \"dependencies\": {\n    \"puppeteer\": \"^21.4.1\"\n  }\n}\n"
  },
  {
    "path": "packages/rxjs/integration/import/fixtures/vite-bundle/src/main.ts",
    "content": "import * as rx from 'rxjs';\nimport * as operators from 'rxjs/operators';\nimport * as ajax from 'rxjs/ajax';\nimport * as webSocket from 'rxjs/webSocket';\nimport * as rxFetch from 'rxjs/fetch';\nimport * as testing from 'rxjs/testing';\nimport * as coldObservable from 'rxjs/internal/testing/ColdObservable';\n\ndeclare global {\n  interface Window {\n    reportDone: any;\n  }\n}\n\nfunction runTest() {\n  let success = true;\n\n  const assert = (condition: any, message: string) => {\n    if (condition) {\n      // show a green check mark emoji\n      console.log(`✅ ${message}`);\n    } else {\n      success = false;\n      console.log(`❌ ${message}`);\n    }\n  };\n\n  assert(rx, 'main export should exists');\n  assert(operators, 'operator export should exists');\n  assert(coldObservable, 'internal can be imported');\n  assert(ajax, 'ajax can be imported');\n  assert(webSocket, 'webSocket can be imported');\n  assert(rxFetch, 'rxFetch can be imported');\n  assert(testing, 'testing can be imported');\n\n  // Assert a few key things exist in each of the imported modules\n  assert(rx.Observable, 'Observable should exist');\n  assert(operators.map, 'map should exist');\n  assert(ajax.ajax, 'ajax should exist');\n  assert(webSocket.webSocket, 'webSocket should exist');\n  assert(rxFetch.fromFetch, 'fromFetch should exist');\n  assert(testing.TestScheduler, 'TestScheduler should exist');\n\n  window.reportDone(success);\n}\n\nconst testButton = document.createElement('button');\ntestButton.id = 'run-test';\ntestButton.textContent = 'Run Test';\ntestButton.addEventListener('click', runTest);\ndocument.body.appendChild(testButton);\n"
  },
  {
    "path": "packages/rxjs/integration/import/fixtures/vite-bundle/src/vite-env.d.ts",
    "content": "/// <reference types=\"vite/client\" />\n"
  },
  {
    "path": "packages/rxjs/integration/import/fixtures/vite-bundle/test.mjs",
    "content": "import puppeteer from 'puppeteer';\nimport { dirname } from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport { createServer } from 'vite';\n\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = dirname(__filename);\n\nasync function main() {\n  console.log('Starting puppeteer...');\n  const timeout = setTimeout(() => {\n    console.error('Operation timed out.');\n    browser.close();\n    process.exit(1);\n  }, 10000);\n\n  const viteServer = await createServer({\n    server: {},\n  });\n\n  await viteServer.listen();\n\n  console.log('Vite server listening on port', viteServer.config.server.port);\n\n  const browser = await puppeteer.launch({\n    // args: ['--allow-file-access-from-files'],\n    // headless: false,\n  });\n\n  const page = await browser.newPage();\n\n  page.on('pageerror', (error) => {\n    console.error('Page error:', error.message);\n    browser.close();\n    process.exit(1);\n  });\n\n  // Listen for console events\n  page.on('console', async (msg) => {\n    const type = msg.type();\n    if (type === 'error') {\n      console.error('JS Error:', msg.text());\n      // Handle or throw error here\n    } else {\n      console.log(`${type.toUpperCase()}:`, msg.text());\n    }\n  });\n\n  // Expose a function to the page for signaling success\n  await page.exposeFunction('reportDone', (success) => {\n    clearTimeout(timeout);\n    browser.close();\n    if (success) {\n      console.log('Script executed successfully!');\n      process.exit(0);\n    } else {\n      console.error('Browser script failed!');\n      process.exit(1);\n    }\n  });\n\n  const url = `http://localhost:${viteServer.config.server.port}/`;\n  console.log(`Navigating to ${url}...`);\n  await page.goto(url);\n\n  await page.click('#run-test');\n}\n\nmain().catch((error) => {\n  console.error('Error:', error);\n  process.exit(1);\n});\n"
  },
  {
    "path": "packages/rxjs/integration/import/fixtures/vite-bundle/tsconfig.json",
    "content": "{\n  \"compilerOptions\": {\n    \"target\": \"ES2020\",\n    \"useDefineForClassFields\": true,\n    \"module\": \"ESNext\",\n    \"lib\": [\"ES2020\", \"DOM\", \"DOM.Iterable\"],\n    \"skipLibCheck\": true,\n\n    /* Bundler mode */\n    \"moduleResolution\": \"bundler\",\n    \"allowImportingTsExtensions\": true,\n    \"resolveJsonModule\": true,\n    \"isolatedModules\": true,\n    \"noEmit\": true,\n\n    /* Linting */\n    \"strict\": true,\n    \"noUnusedLocals\": true,\n    \"noUnusedParameters\": true,\n    \"noFallthroughCasesInSwitch\": true\n  },\n  \"include\": [\"src\"]\n}\n"
  },
  {
    "path": "packages/rxjs/integration/import/fixtures/webpack-bundle/index.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"UTF-8\" />\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" />\n    <title>Vite + TS Import Test</title>\n  </head>\n  <body>\n    <script type=\"module\" src=\"bundle.js\"></script>\n  </body>\n</html>\n"
  },
  {
    "path": "packages/rxjs/integration/import/fixtures/webpack-bundle/package.json",
    "content": "{\n  \"name\": \"rxjs-import-test\",\n  \"private\": true,\n  \"version\": \"0.0.1\",\n  \"scripts\": {\n    \"test\": \"node ./test.js\"\n  },\n  \"dependencies\": {\n    \"html-webpack-plugin\": \"^5.5.3\",\n    \"puppeteer\": \"^21.4.1\",\n    \"ts-loader\": \"^9.5.0\",\n    \"typescript\": \"^5.2.2\",\n    \"webpack\": \"^5.89.0\",\n    \"webpack-cli\": \"^5.1.4\",\n    \"webpack-dev-server\": \"^4.15.1\"\n  }\n}\n"
  },
  {
    "path": "packages/rxjs/integration/import/fixtures/webpack-bundle/src/main.ts",
    "content": "import * as rx from 'rxjs';\nimport * as operators from 'rxjs/operators';\nimport * as ajax from 'rxjs/ajax';\nimport * as webSocket from 'rxjs/webSocket';\nimport * as rxFetch from 'rxjs/fetch';\nimport * as testing from 'rxjs/testing';\nimport * as coldObservable from 'rxjs/internal/testing/ColdObservable';\n\ndeclare global {\n  interface Window {\n    reportDone: any;\n  }\n}\n\nfunction runTest() {\n  let success = true;\n\n  const assert = (condition: any, message: string) => {\n    if (condition) {\n      // show a green check mark emoji\n      console.log(`✅ ${message}`);\n    } else {\n      success = false;\n      console.log(`❌ ${message}`);\n    }\n  };\n\n  assert(rx, 'main export should exists');\n  assert(operators, 'operator export should exists');\n  assert(coldObservable, 'internal can be imported');\n  assert(ajax, 'ajax can be imported');\n  assert(webSocket, 'webSocket can be imported');\n  assert(rxFetch, 'rxFetch can be imported');\n  assert(testing, 'testing can be imported');\n\n  // Assert a few key things exist in each of the imported modules\n  assert(rx.Observable, 'Observable should exist');\n  assert(operators.map, 'map should exist');\n  assert(ajax.ajax, 'ajax should exist');\n  assert(webSocket.webSocket, 'webSocket should exist');\n  assert(rxFetch.fromFetch, 'fromFetch should exist');\n  assert(testing.TestScheduler, 'TestScheduler should exist');\n\n  window.reportDone(success);\n}\n\nconst testButton = document.createElement('button');\ntestButton.id = 'run-test';\ntestButton.textContent = 'Run Test';\ntestButton.addEventListener('click', runTest);\ndocument.body.appendChild(testButton);\n"
  },
  {
    "path": "packages/rxjs/integration/import/fixtures/webpack-bundle/test.js",
    "content": "const puppeteer = require('puppeteer');\nconst Webpack = require('webpack');\nconst WebpackDevServer = require('webpack-dev-server');\nconst webpackConfig = require('./webpack.config.js');\n\n// const __filename = fileURLToPath(import.meta.url);\n// const __dirname = dirname(__filename);\n\nasync function main() {\n  console.log('Starting Webpack Server...');\n  const compiler = Webpack(webpackConfig);\n  const devServerOptions = { ...webpackConfig.devServer, open: false };\n  const server = new WebpackDevServer(devServerOptions, compiler);\n  await server.start();\n\n  console.log('Webpack server listening on port', 8080);\n\n  console.log('Starting puppeteer...');\n  const timeout = setTimeout(() => {\n    console.error('Operation timed out.');\n    browser.close();\n    process.exit(1);\n  }, 10000);\n\n  const browser = await puppeteer.launch({\n    // args: ['--allow-file-access-from-files'],\n    // headless: false,\n  });\n\n  const page = await browser.newPage();\n\n  page.on('pageerror', (error) => {\n    console.error('Page error:', error.message);\n    browser.close();\n    process.exit(1);\n  });\n\n  // Listen for console events\n  page.on('console', async (msg) => {\n    const type = msg.type();\n    if (type === 'error') {\n      console.error('JS Error:', msg.text());\n      // Handle or throw error here\n    } else {\n      console.log(`${type.toUpperCase()}:`, msg.text());\n    }\n  });\n\n  // Expose a function to the page for signaling success\n  await page.exposeFunction('reportDone', (success) => {\n    clearTimeout(timeout);\n    browser.close();\n    if (success) {\n      console.log('Script executed successfully!');\n      process.exit(0);\n    } else {\n      console.error('Browser script failed!');\n      process.exit(1);\n    }\n  });\n\n  const url = `http://localhost:${webpackConfig.devServer.port}/`;\n  console.log(`Navigating to ${url}...`);\n  await page.goto(url);\n\n  await page.click('#run-test');\n}\n\nmain().catch((error) => {\n  console.error('Error:', error);\n  process.exit(1);\n});\n"
  },
  {
    "path": "packages/rxjs/integration/import/fixtures/webpack-bundle/tsconfig.json",
    "content": "{\n  \"compilerOptions\": {\n    \"target\": \"ES2020\",\n    \"useDefineForClassFields\": true,\n    \"module\": \"ESNext\",\n    \"lib\": [\"ES2020\", \"DOM\", \"DOM.Iterable\"],\n    \"skipLibCheck\": true,\n\n    /* Bundler mode */\n    \"moduleResolution\": \"node\",\n    // \"allowImportingTsExtensions\": true,\n    // \"resolveJsonModule\": true,\n    // \"isolatedModules\": true,\n    // \"noEmit\": true,\n\n    // /* Linting */\n    // \"strict\": true,\n    // \"noUnusedLocals\": true,\n    // \"noUnusedParameters\": true,\n    // \"noFallthroughCasesInSwitch\": true\n  },\n  \"include\": [\"src\"]\n}\n"
  },
  {
    "path": "packages/rxjs/integration/import/fixtures/webpack-bundle/webpack.config.js",
    "content": "const path = require('path');\nconst HtmlWebpackPlugin = require('html-webpack-plugin');\n\nmodule.exports = {\n  mode: 'development',\n  entry: './src/main.ts',\n  output: {\n    path: path.resolve(__dirname, 'dist'),\n    filename: 'bundle.js',\n  },\n  module: {\n    rules: [\n      {\n        test: /\\.ts$/,\n        use: 'ts-loader',\n        exclude: /node_modules/,\n      },\n    ],\n  },\n  resolve: {\n    extensions: ['.ts', '.js'],\n  },\n  plugins: [\n    new HtmlWebpackPlugin({\n      template: 'index.html',\n    }),\n  ],\n  devServer: {\n    port: 8080,\n  },\n};\n"
  },
  {
    "path": "packages/rxjs/integration/import/runner.js",
    "content": "const path = require('path');\nconst fs = require('fs');\nconst { spawn } = require('child_process');\nconst projectRoot = process.cwd();\nconst rxjsRoot = path.join(__dirname, '../../');\nconst rxjsObservableRoot = path.join(__dirname, '../../../observable');\nconst fixturesDirectory = path.join(__dirname, 'fixtures');\nconst rxjsVersion = require(path.join(rxjsRoot, 'package.json')).version;\nconst tgzPath = path.join(rxjsRoot, `rxjs-${rxjsVersion}.tgz`);\nconst rxjsObservableTgzPath = path.join(rxjsObservableRoot, `rxjs-observable-${rxjsVersion}.tgz`);\n\n// These are the fixtures to run the import test against\n// they map to directories in the fixtures directory\nconst FIXTURES = [\n  //\n  'commonjs',\n  'esm',\n  'browser',\n  'vite-bundle',\n  'webpack-bundle',\n];\n\n/**\n * Executes a command in a child process and streams the output to the console\n * @param {string} cmd The command to execute\n * @param {string} cwd The working directory to execute the command in\n * @returns a promise that resolves when the command completes\n */\nfunction execAsync(cmd, cwd = '.') {\n  return new Promise((resolve, reject) => {\n    console.log(`${cwd}$ ${cmd}`);\n\n    // Split the cmd into base command and arguments for spawn\n    const [command, ...args] = cmd.split(' ');\n    const child = spawn(command, args, { cwd, shell: true });\n\n    // Stream child process stdout to the console\n    child.stdout.on('data', (data) => {\n      process.stdout.write(data);\n    });\n\n    // Stream child process stderr to the console\n    child.stderr.on('data', (data) => {\n      process.stderr.write(data);\n    });\n\n    child.on('close', (code) => {\n      if (code !== 0) {\n        reject(new Error(`Command failed with exit code ${code}`));\n      } else {\n        resolve({ code });\n      }\n    });\n\n    child.on('error', (error) => {\n      reject(error);\n    });\n  });\n}\n\nasync function main() {\n  try {\n    console.log('Building and packaging @rxjs/observable...');\n    try {\n      await execAsync('yarn build && npm pack', rxjsObservableRoot);\n    } catch (err) {\n      console.error('❌ Failed to build and package @rxjs/observable!');\n      console.error(err);\n      throw err;\n    }\n    console.log('Building and packaging RxJS...');\n    try {\n      await execAsync('yarn build && npm pack', rxjsRoot);\n    } catch (err) {\n      console.error('❌ Failed to build and package RxJS!');\n      console.error(err);\n      throw err;\n    }\n\n    // We want to allow all of the fixtures to run, so we don't want to throw\n    // instead we want to collect the failed fixtures and throw at the end\n    const failedFixtures = [];\n\n    for (const fixtureName of FIXTURES) {\n      const fixturePath = path.join(fixturesDirectory, fixtureName);\n\n      try {\n        console.log('\\n');\n        console.log(`Running ${fixtureName}...`);\n\n        console.log('Setting custom dependency resolution for local @rxjs/observable...');\n        addYarnResolution(fixturePath, '@rxjs/observable', `file:${path.relative(fixturePath, rxjsObservableTgzPath)}`);\n\n        await execAsync(`yarn install && yarn add ${tgzPath}`, fixturePath);\n        await execAsync('yarn test', fixturePath);\n        console.log(`✅ ${fixtureName} import test passed!`);\n      } catch (err) {\n        console.error(`❌ ${fixtureName} import test failed!`);\n        console.error(err);\n\n        // This fixture failed, so add it to the failed fixtures list\n        failedFixtures.push(fixtureName);\n      } finally {\n        try {\n          await execAsync('yarn remove rxjs', fixturePath);\n          await execAsync('rm -rf ./node_modules ./package-lock.json ./yarn.lock', fixturePath);\n          removeYarnResolution(fixturePath, '@rxjs/observable');\n        } catch (err) {\n          console.warn('fixtured not cleaned up', err);\n        }\n      }\n    }\n\n    if (failedFixtures.length) {\n      // If any of the fixtures failed, throw an error\n      throw new Error(`${failedFixtures.length} fixture(s) failed!`);\n    }\n  } finally {\n    await execAsync(`rm ${tgzPath}`, projectRoot);\n    await execAsync(`rm ${rxjsObservableTgzPath}`, rxjsObservableRoot);\n  }\n}\n\nmain();\n\nfunction addYarnResolution(fixturePath, name, version) {\n  const fixturePackageJson = fs.readFileSync(path.join(fixturePath, 'package.json'));\n  const fixturePackageJsonObj = JSON.parse(fixturePackageJson);\n  fixturePackageJsonObj.resolutions = fixturePackageJsonObj.resolutions || {};\n  fixturePackageJsonObj.resolutions[name] = version;\n  fs.writeFileSync(path.join(fixturePath, 'package.json'), JSON.stringify(fixturePackageJsonObj, null, 2));\n}\n\nfunction removeYarnResolution(fixturePath, name) {\n  const fixturePackageJson = fs.readFileSync(path.join(fixturePath, 'package.json'));\n  const fixturePackageJsonObj = JSON.parse(fixturePackageJson);\n  delete fixturePackageJsonObj.resolutions[name];\n  if (!Object.keys(fixturePackageJsonObj.resolutions).length) {\n    delete fixturePackageJsonObj.resolutions;\n  }\n  fs.writeFileSync(path.join(fixturePath, 'package.json'), JSON.stringify(fixturePackageJsonObj, null, 2) + '\\n');\n}\n"
  },
  {
    "path": "packages/rxjs/package.json",
    "content": "{\n  \"name\": \"rxjs\",\n  \"version\": \"8.0.0-alpha.14\",\n  \"description\": \"Reactive Extensions for modern JavaScript\",\n  \"main\": \"./dist/cjs/index.js\",\n  \"module\": \"./dist/esm/index.js\",\n  \"types\": \"index.d.ts\",\n  \"typesVersions\": {\n    \">=4.2\": {\n      \"*\": [\n        \"dist/types/*\"\n      ]\n    }\n  },\n  \"sideEffects\": false,\n  \"exports\": {\n    \".\": {\n      \"types\": \"./dist/types/index.d.ts\",\n      \"node\": \"./dist/cjs/index.js\",\n      \"require\": \"./dist/cjs/index.js\",\n      \"default\": \"./dist/esm/index.js\"\n    },\n    \"./ajax\": {\n      \"types\": \"./dist/types/ajax/index.d.ts\",\n      \"node\": \"./dist/cjs/ajax/index.js\",\n      \"require\": \"./dist/cjs/ajax/index.js\",\n      \"default\": \"./dist/esm/ajax/index.js\"\n    },\n    \"./fetch\": {\n      \"types\": \"./dist/types/fetch/index.d.ts\",\n      \"node\": \"./dist/cjs/fetch/index.js\",\n      \"require\": \"./dist/cjs/fetch/index.js\",\n      \"default\": \"./dist/esm/fetch/index.js\"\n    },\n    \"./operators\": {\n      \"types\": \"./dist/types/operators/index.d.ts\",\n      \"node\": \"./dist/cjs/operators/index.js\",\n      \"require\": \"./dist/cjs/operators/index.js\",\n      \"default\": \"./dist/esm/operators/index.js\"\n    },\n    \"./testing\": {\n      \"types\": \"./dist/types/testing/index.d.ts\",\n      \"node\": \"./dist/cjs/testing/index.js\",\n      \"require\": \"./dist/cjs/testing/index.js\",\n      \"default\": \"./dist/esm/testing/index.js\"\n    },\n    \"./webSocket\": {\n      \"types\": \"./dist/types/webSocket/index.d.ts\",\n      \"node\": \"./dist/cjs/webSocket/index.js\",\n      \"require\": \"./dist/cjs/webSocket/index.js\",\n      \"default\": \"./dist/esm/webSocket/index.js\"\n    },\n    \"./internal/*\": {\n      \"types\": \"./dist/types/internal/*.d.ts\",\n      \"node\": \"./dist/cjs/internal/*.js\",\n      \"require\": \"./dist/cjs/internal/*.js\",\n      \"default\": \"./dist/esm/internal/*.js\"\n    },\n    \"./package.json\": \"./package.json\"\n  },\n  \"scripts\": {\n    \"lint\": \"eslint --ext=ts,js src spec spec-dtslint\",\n    \"dtslint\": \"npm run lint && tsc -b ./src/tsconfig.types.json\",\n    \"test\": \"cross-env TS_NODE_PROJECT=tsconfig.mocha.json mocha --config spec/support/.mocharc.js \\\"spec/**/*-spec.ts\\\"\",\n    \"test:esm\": \"node spec/module-test-spec.mjs\",\n    \"test:circular\": \"dependency-cruiser --validate .dependency-cruiser.json -x \\\"^node_modules\\\" dist/esm\",\n    \"test:import\": \"node integration/import/runner.js\",\n    \"compile\": \"tsc -b ./src/tsconfig.cjs.json ./src/tsconfig.cjs.spec.json ./src/tsconfig.esm.json ./src/tsconfig.types.json ./src/tsconfig.types.spec.json ./spec/tsconfig.json\",\n    \"build:clean\": \"shx rm -rf ./dist\",\n    \"build\": \"yarn build:clean && yarn compile && node ./tools/generate-alias.js\",\n    \"watch\": \"nodemon -w \\\"src/\\\" -w \\\"spec/\\\" -e ts -x npm test\",\n    \"watch:dtslint\": \"nodemon -w \\\"src/\\\" -w \\\"spec-dtslint/\\\" -e ts -x yarn dtslint\",\n    \"copy_common_package_files\": \"node ../../scripts/copy-common-package-files.js\"\n  },\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"https://github.com/ReactiveX/rxjs.git\",\n    \"directory\": \"packages/rxjs\"\n  },\n  \"keywords\": [\n    \"Rx\",\n    \"RxJS\",\n    \"ReactiveX\",\n    \"ReactiveExtensions\",\n    \"Streams\",\n    \"Observables\",\n    \"Observable\",\n    \"Stream\"\n  ],\n  \"author\": \"Ben Lesh <ben@benlesh.com>\",\n  \"contributors\": [\n    {\n      \"name\": \"Ben Lesh\",\n      \"email\": \"ben@benlesh.com\"\n    },\n    {\n      \"name\": \"Paul Taylor\",\n      \"email\": \"paul.e.taylor@me.com\"\n    },\n    {\n      \"name\": \"Jeff Cross\",\n      \"email\": \"crossj@google.com\"\n    },\n    {\n      \"name\": \"Matthew Podwysocki\",\n      \"email\": \"matthewp@microsoft.com\"\n    },\n    {\n      \"name\": \"OJ Kwon\",\n      \"email\": \"kwon.ohjoong@gmail.com\"\n    },\n    {\n      \"name\": \"Andre Staltz\",\n      \"email\": \"andre@staltz.com\"\n    }\n  ],\n  \"license\": \"Apache-2.0\",\n  \"bugs\": {\n    \"url\": \"https://github.com/ReactiveX/RxJS/issues\"\n  },\n  \"homepage\": \"https://rxjs.dev\",\n  \"dependencies\": {\n    \"@rxjs/observable\": \"8.0.0-alpha.14\"\n  },\n  \"devDependencies\": {\n    \"@swc/core\": \"^1.2.128\",\n    \"@swc/helpers\": \"^0.3.2\",\n    \"@types/chai\": \"^4.2.11\",\n    \"@types/lodash\": \"^4.14.198\",\n    \"@types/mocha\": \"^10.0.1\",\n    \"@types/node\": \"^14.14.6\",\n    \"@types/shelljs\": \"^0.8.8\",\n    \"@types/sinon\": \"^10.0.13\",\n    \"@types/sinon-chai\": \"^3.2.9\",\n    \"chai\": \"^4.3.7\",\n    \"color\": \"3.0.0\",\n    \"colors\": \"1.1.2\",\n    \"cross-env\": \"5.1.3\",\n    \"dependency-cruiser\": \"^9.12.0\",\n    \"form-data\": \"^3.0.0\",\n    \"fs-extra\": \"^8.1.0\",\n    \"lodash\": \"^4.17.21\",\n    \"mocha\": \"^10.2.0\",\n    \"nodemon\": \"^1.9.2\",\n    \"npm-run-all\": \"4.1.2\",\n    \"prettier\": \"^2.5.1\",\n    \"shelljs\": \"^0.8.4\",\n    \"shx\": \"^0.3.2\",\n    \"sinon\": \"^15.0.1\",\n    \"sinon-chai\": \"^3.7.0\",\n    \"source-map-support\": \"0.5.3\",\n    \"web-streams-polyfill\": \"^3.0.2\"\n  },\n  \"files\": [\n    \"dist/cjs/**/!(*.tsbuildinfo)\",\n    \"dist/esm/**/!(*.tsbuildinfo)\",\n    \"dist/types/**/!(*.tsbuildinfo)\",\n    \"ajax\",\n    \"fetch\",\n    \"operators\",\n    \"testing\",\n    \"webSocket\",\n    \"src\",\n    \"CHANGELOG.md\",\n    \"CODE_OF_CONDUCT.md\",\n    \"LICENSE.txt\",\n    \"package.json\",\n    \"README.md\",\n    \"tsconfig.json\"\n  ],\n  \"nx\": {\n    \"targets\": {\n      \"test\": {\n        \"dependsOn\": [\n          \"build\"\n        ],\n        \"cache\": false\n      },\n      \"compile\": {\n        \"dependsOn\": [\n          \"^build\"\n        ]\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "packages/rxjs/spec/Observable-spec.ts",
    "content": "import { expect } from 'chai';\n// import * as sinon from 'sinon';\nimport { Observable, config, Subscription, Subject, of, throwError, EMPTY } from 'rxjs';\nimport { map, tap, catchError } from 'rxjs/operators';\nimport { TestScheduler } from 'rxjs/testing';\nimport { observableMatcher } from './helpers/observableMatcher';\n\n// function expectFullObserver(val: any) {\n//   expect(val).to.be.a('object');\n//   expect(val.next).to.be.a('function');\n//   expect(val.error).to.be.a('function');\n//   expect(val.complete).to.be.a('function');\n//   expect(val.closed).to.be.a('boolean');\n// }\n\n/** @test {Observable} */\ndescribe('Observable', () => {\n  let rxTestScheduler: TestScheduler;\n\n  beforeEach(() => {\n    rxTestScheduler = new TestScheduler(observableMatcher);\n  });\n\n  // it('should be constructed with a subscriber function', (done) => {\n  //   const source = new Observable<number>(function (observer) {\n  //     expectFullObserver(observer);\n  //     observer.next(1);\n  //     observer.complete();\n  //   });\n\n  //   source.subscribe({\n  //     next: function (x) {\n  //       expect(x).to.equal(1);\n  //     },\n  //     complete: done,\n  //   });\n  // });\n\n  // it('should send errors thrown in the constructor down the error path', (done) => {\n  //   new Observable<number>(() => {\n  //     throw new Error('this should be handled');\n  //   }).subscribe({\n  //     error(err) {\n  //       expect(err).to.exist.and.be.instanceof(Error).and.have.property('message', 'this should be handled');\n  //       done();\n  //     },\n  //   });\n  // });\n\n  it('should allow empty ctor, which is effectively a never-observable', () => {\n    rxTestScheduler.run(({ expectObservable }) => {\n      const result = new Observable<any>();\n      expectObservable(result).toBe('-');\n    });\n  });\n\n  describe('forEach', () => {\n    it('should iterate and return a Promise', (done) => {\n      const expected = [1, 2, 3];\n      const result = of(1, 2, 3)\n        .forEach((x) => {\n          expect(x).to.equal(expected.shift());\n        })\n        .then(() => {\n          done();\n        });\n\n      expect(result.then).to.be.a('function');\n    });\n\n    it('should reject promise when in error', (done) => {\n      throwError(() => 'bad')\n        .forEach(() => {\n          done(new Error('should not be called'));\n        })\n        .then(\n          () => {\n            done(new Error('should not complete'));\n          },\n          (err) => {\n            expect(err).to.equal('bad');\n            done();\n          }\n        );\n    });\n\n    it('should reject promise if nextHandler throws', (done) => {\n      const results: number[] = [];\n\n      of(1, 2, 3)\n        .forEach((x) => {\n          if (x === 3) {\n            throw new Error('NO THREES!');\n          }\n          results.push(x);\n        })\n        .then(\n          () => {\n            done(new Error('should not be called'));\n          },\n          (err) => {\n            expect(err).to.be.an('error', 'NO THREES!');\n            expect(results).to.deep.equal([1, 2]);\n          }\n        )\n        .then(() => {\n          done();\n        });\n    });\n\n    // it('should handle a synchronous throw from the next handler', () => {\n    //   const expected = new Error('I told, you Bobby Boucher, threes are the debil!');\n    //   const syncObservable = new Observable<number>((observer) => {\n    //     observer.next(1);\n    //     observer.next(2);\n    //     observer.next(3);\n    //     observer.next(4);\n    //   });\n\n    //   const results: Array<number | Error> = [];\n\n    //   return syncObservable\n    //     .forEach((x) => {\n    //       results.push(x);\n    //       if (x === 3) {\n    //         throw expected;\n    //       }\n    //     })\n    //     .then(\n    //       () => {\n    //         throw new Error('should not be called');\n    //       },\n    //       (err) => {\n    //         results.push(err);\n    //         // The error should unsubscribe from the source, meaning we\n    //         // should not see the number 4.\n    //         expect(results).to.deep.equal([1, 2, 3, expected]);\n    //       }\n    //     );\n    // });\n\n    // it('should handle an asynchronous throw from the next handler and tear down', () => {\n    //   const expected = new Error('I told, you Bobby Boucher, twos are the debil!');\n    //   const asyncObservable = new Observable<number>((observer) => {\n    //     let i = 1;\n    //     const id = setInterval(() => observer.next(i++), 1);\n\n    //     return () => {\n    //       clearInterval(id);\n    //     };\n    //   });\n\n    //   const results: Array<number | Error> = [];\n\n    //   return asyncObservable\n    //     .forEach((x) => {\n    //       results.push(x);\n    //       if (x === 2) {\n    //         throw expected;\n    //       }\n    //     })\n    //     .then(\n    //       () => {\n    //         throw new Error('should not be called');\n    //       },\n    //       (err) => {\n    //         results.push(err);\n    //         expect(results).to.deep.equal([1, 2, expected]);\n    //       }\n    //     );\n    // });\n  });\n\n  describe('subscribe', () => {\n    it('should work with handlers with hacked bind methods', () => {\n      const source = of('Hi');\n      const results: any[] = [];\n      const next = function (value: string) {\n        results.push(value);\n      };\n      next.bind = () => {\n        /* lol */\n      };\n\n      const complete = function () {\n        results.push('done');\n      };\n      complete.bind = () => {\n        /* lol */\n      };\n\n      source.subscribe({ next, complete });\n      expect(results).to.deep.equal(['Hi', 'done']);\n    });\n\n    it('should work with handlers with hacked bind methods, in the error case', () => {\n      const source = throwError(() => 'an error');\n      const results: any[] = [];\n      const error = function (value: string) {\n        results.push(value);\n      };\n\n      source.subscribe({ error });\n      expect(results).to.deep.equal(['an error']);\n    });\n\n    // it('should be synchronous', () => {\n    //   let subscribed = false;\n    //   let nexted: string;\n    //   let completed: boolean;\n    //   const source = new Observable<string>((observer) => {\n    //     subscribed = true;\n    //     observer.next('wee');\n    //     expect(nexted).to.equal('wee');\n    //     observer.complete();\n    //     expect(completed).to.be.true;\n    //   });\n\n    //   expect(subscribed).to.be.false;\n\n    //   let mutatedByNext = false;\n    //   let mutatedByComplete = false;\n\n    //   source.subscribe({\n    //     next: (x) => {\n    //       nexted = x;\n    //       mutatedByNext = true;\n    //     },\n    //     complete: () => {\n    //       completed = true;\n    //       mutatedByComplete = true;\n    //     },\n    //   });\n\n    //   expect(mutatedByNext).to.be.true;\n    //   expect(mutatedByComplete).to.be.true;\n    // });\n\n    // it('should work when subscribe is called with no arguments', () => {\n    //   const source = new Observable<string>((subscriber) => {\n    //     subscriber.next('foo');\n    //     subscriber.complete();\n    //   });\n\n    //   source.subscribe();\n    // });\n\n    it('should not be unsubscribed when other empty subscription completes', () => {\n      let unsubscribeCalled = false;\n      const source = new Observable<number>(() => {\n        return () => {\n          unsubscribeCalled = true;\n        };\n      });\n\n      source.subscribe();\n\n      expect(unsubscribeCalled).to.be.false;\n\n      EMPTY.subscribe();\n\n      expect(unsubscribeCalled).to.be.false;\n    });\n\n    it('should not be unsubscribed when other subscription with same observer completes', () => {\n      let unsubscribeCalled = false;\n      const source = new Observable<number>(() => {\n        return () => {\n          unsubscribeCalled = true;\n        };\n      });\n\n      const observer = {\n        next: function () {\n          /*noop*/\n        },\n      };\n\n      source.subscribe(observer);\n\n      expect(unsubscribeCalled).to.be.false;\n\n      EMPTY.subscribe(observer);\n\n      expect(unsubscribeCalled).to.be.false;\n    });\n\n    // it('should run unsubscription logic when an error is sent asynchronously and subscribe is called with no arguments', (done) => {\n    //   const sandbox = sinon.createSandbox();\n    //   const fakeTimer = sandbox.useFakeTimers();\n\n    //   let unsubscribeCalled = false;\n    //   const source = new Observable<number>((observer) => {\n    //     const id = setInterval(() => {\n    //       observer.error(0);\n    //     }, 1);\n    //     return () => {\n    //       clearInterval(id);\n    //       unsubscribeCalled = true;\n    //     };\n    //   });\n\n    //   source.subscribe({\n    //     error() {\n    //       /* noop: expected error */\n    //     },\n    //   });\n\n    //   setTimeout(() => {\n    //     let err;\n    //     let errHappened = false;\n    //     try {\n    //       expect(unsubscribeCalled).to.be.true;\n    //     } catch (e) {\n    //       err = e;\n    //       errHappened = true;\n    //     } finally {\n    //       if (!errHappened) {\n    //         done();\n    //       } else {\n    //         done(err);\n    //       }\n    //     }\n    //   }, 100);\n\n    //   fakeTimer.tick(110);\n    //   sandbox.restore();\n    // });\n\n    // it('should return a Subscription that calls the unsubscribe function returned by the subscriber', () => {\n    //   let unsubscribeCalled = false;\n\n    //   const source = new Observable<number>(() => {\n    //     return () => {\n    //       unsubscribeCalled = true;\n    //     };\n    //   });\n\n    //   const sub = source.subscribe(() => {\n    //     //noop\n    //   });\n    //   expect(sub instanceof Subscription).to.be.true;\n    //   expect(unsubscribeCalled).to.be.false;\n    //   expect(sub.unsubscribe).to.be.a('function');\n\n    //   sub.unsubscribe();\n    //   expect(unsubscribeCalled).to.be.true;\n    // });\n\n    it('should ignore next messages after unsubscription', (done) => {\n      let times = 0;\n\n      const subscription = new Observable<number>((observer) => {\n        let i = 0;\n        const id = setInterval(() => {\n          observer.next(i++);\n        });\n\n        return () => {\n          clearInterval(id);\n          expect(times).to.equal(2);\n          done();\n        };\n      })\n        .pipe(tap(() => (times += 1)))\n        .subscribe(function () {\n          if (times === 2) {\n            subscription.unsubscribe();\n          }\n        });\n    });\n\n    it('should ignore error messages after unsubscription', (done) => {\n      let times = 0;\n      let errorCalled = false;\n\n      const subscription = new Observable<number>((observer) => {\n        let i = 0;\n        const id = setInterval(() => {\n          observer.next(i++);\n          if (i === 3) {\n            observer.error(new Error());\n          }\n        });\n\n        return () => {\n          clearInterval(id);\n          expect(times).to.equal(2);\n          expect(errorCalled).to.be.false;\n          done();\n        };\n      })\n        .pipe(tap(() => (times += 1)))\n        .subscribe({\n          next: function () {\n            if (times === 2) {\n              subscription.unsubscribe();\n            }\n          },\n          error: function () {\n            errorCalled = true;\n          },\n        });\n    });\n\n    it('should ignore complete messages after unsubscription', (done) => {\n      let times = 0;\n      let completeCalled = false;\n\n      const subscription = new Observable<number>((observer) => {\n        let i = 0;\n        const id = setInterval(() => {\n          observer.next(i++);\n          if (i === 3) {\n            observer.complete();\n          }\n        });\n\n        return () => {\n          clearInterval(id);\n          expect(times).to.equal(2);\n          expect(completeCalled).to.be.false;\n          done();\n        };\n      })\n        .pipe(tap(() => (times += 1)))\n        .subscribe({\n          next: function () {\n            if (times === 2) {\n              subscription.unsubscribe();\n            }\n          },\n          complete: function () {\n            completeCalled = true;\n          },\n        });\n    });\n\n    describe('when called with an anonymous observer', () => {\n      it(\n        'should accept an anonymous observer with just a next function and call the next function in the context' +\n          ' of the anonymous observer',\n        (done) => {\n          //intentionally not using lambda to avoid typescript's this context capture\n          const o = {\n            myValue: 'foo',\n            next(x: any) {\n              expect(this.myValue).to.equal('foo');\n              expect(x).to.equal(1);\n              done();\n            },\n          };\n\n          of(1).subscribe(o);\n        }\n      );\n\n      it(\n        'should accept an anonymous observer with just an error function and call the error function in the context' +\n          ' of the anonymous observer',\n        (done) => {\n          //intentionally not using lambda to avoid typescript's this context capture\n          const o = {\n            myValue: 'foo',\n            error(err: any) {\n              expect(this.myValue).to.equal('foo');\n              expect(err).to.equal('bad');\n              done();\n            },\n          };\n\n          throwError(() => 'bad').subscribe(o);\n        }\n      );\n\n      it(\n        'should accept an anonymous observer with just a complete function and call the complete function in the' +\n          ' context of the anonymous observer',\n        (done) => {\n          //intentionally not using lambda to avoid typescript's this context capture\n          const o = {\n            myValue: 'foo',\n            complete: function complete() {\n              expect(this.myValue).to.equal('foo');\n              done();\n            },\n          };\n\n          EMPTY.subscribe(o);\n        }\n      );\n\n      it('should accept an anonymous observer with no functions at all', () => {\n        expect(() => {\n          EMPTY.subscribe(<any>{});\n        }).not.to.throw();\n      });\n\n      it('should ignore next messages after unsubscription', (done) => {\n        let times = 0;\n\n        const subscription = new Observable<number>((observer) => {\n          let i = 0;\n          const id = setInterval(() => {\n            observer.next(i++);\n          });\n\n          return () => {\n            clearInterval(id);\n            expect(times).to.equal(2);\n            done();\n          };\n        })\n          .pipe(tap(() => (times += 1)))\n          .subscribe({\n            next() {\n              if (times === 2) {\n                subscription.unsubscribe();\n              }\n            },\n          });\n      });\n\n      it('should ignore error messages after unsubscription', (done) => {\n        let times = 0;\n        let errorCalled = false;\n\n        const subscription = new Observable<number>((observer) => {\n          let i = 0;\n          const id = setInterval(() => {\n            observer.next(i++);\n            if (i === 3) {\n              observer.error(new Error());\n            }\n          });\n          return () => {\n            clearInterval(id);\n            expect(times).to.equal(2);\n            expect(errorCalled).to.be.false;\n            done();\n          };\n        })\n          .pipe(tap(() => (times += 1)))\n          .subscribe({\n            next() {\n              if (times === 2) {\n                subscription.unsubscribe();\n              }\n            },\n            error() {\n              errorCalled = true;\n            },\n          });\n      });\n\n      it('should ignore complete messages after unsubscription', (done) => {\n        let times = 0;\n        let completeCalled = false;\n\n        const subscription = new Observable<number>((observer) => {\n          let i = 0;\n          const id = setInterval(() => {\n            observer.next(i++);\n            if (i === 3) {\n              observer.complete();\n            }\n          });\n\n          return () => {\n            clearInterval(id);\n            expect(times).to.equal(2);\n            expect(completeCalled).to.be.false;\n            done();\n          };\n        })\n          .pipe(tap(() => (times += 1)))\n          .subscribe({\n            next() {\n              if (times === 2) {\n                subscription.unsubscribe();\n              }\n            },\n            complete() {\n              completeCalled = true;\n            },\n          });\n      });\n    });\n\n    // it('should finalize even with a synchronous thrown error', () => {\n    //   let called = false;\n    //   const badObservable = new Observable((subscriber) => {\n    //     subscriber.add(() => {\n    //       called = true;\n    //     });\n\n    //     throw new Error('bad');\n    //   });\n\n    //   badObservable.subscribe({\n    //     error: () => {\n    //       /* do nothing */\n    //     },\n    //   });\n\n    //   expect(called).to.be.true;\n    // });\n\n    // it('should handle empty string sync errors', () => {\n    //   const badObservable = new Observable(() => {\n    //     throw '';\n    //   });\n\n    //   let caught = false;\n    //   badObservable.subscribe({\n    //     error: (err) => {\n    //       caught = true;\n    //       expect(err).to.equal('');\n    //     },\n    //   });\n    //   expect(caught).to.be.true;\n    // });\n  });\n\n  describe('pipe', () => {\n    it('should exist', () => {\n      const source = of('test');\n      expect(source.pipe).to.be.a('function');\n    });\n\n    it('should pipe multiple operations', (done) => {\n      of('test')\n        .pipe(\n          map((x) => x + x),\n          map((x) => x + '!!!')\n        )\n        .subscribe({\n          next: (x) => {\n            expect(x).to.equal('testtest!!!');\n          },\n          complete: done,\n        });\n    });\n\n    it('should return the same observable if there are no arguments', () => {\n      const source = of('test');\n      const result = source.pipe();\n      expect(result).to.equal(source);\n    });\n\n    it('should allow any kind of piped function', () => {\n      const source = of('test');\n      const result = source.pipe(\n        (source) => source instanceof Observable,\n        (isObservable) => (isObservable ? 'Well hello, there.' : 'Huh?')\n      );\n      expect(result).to.equal('Well hello, there.');\n    });\n  });\n\n  // it('should not swallow internal errors', (done) => {\n  //   config.onStoppedNotification = (notification) => {\n  //     expect(notification.kind).to.equal('E');\n  //     expect(notification).to.have.property('error', 'bad');\n  //     config.onStoppedNotification = null;\n  //     done();\n  //   };\n\n  //   new Observable((subscriber) => {\n  //     subscriber.error('test');\n  //     throw 'bad';\n  //   }).subscribe({\n  //     error: (err) => {\n  //       expect(err).to.equal('test');\n  //     },\n  //   });\n  // });\n\n  // Discussion here: https://github.com/ReactiveX/rxjs/issues/5370\n  it.skip('should handle sync errors within a test scheduler', () => {\n    const observable = of(4).pipe(\n      map((n) => {\n        if (n === 4) {\n          throw 'four!';\n        }\n        return n;\n      }),\n      catchError((err, source) => source)\n    );\n\n    rxTestScheduler.run((helpers) => {\n      const { expectObservable } = helpers;\n      expectObservable(observable).toBe('-');\n    });\n  });\n\n  // it('should emit an error for unhandled synchronous exceptions from something like a stack overflow', () => {\n  //   const source = new Observable(() => {\n  //     const boom = (): unknown => boom();\n  //     boom();\n  //   });\n\n  //   let thrownError: any = undefined;\n  //   source.subscribe({\n  //     error: (err) => (thrownError = err),\n  //   });\n\n  //   expect(thrownError).to.be.an.instanceOf(RangeError);\n  //   expect(thrownError.message).to.equal('Maximum call stack size exceeded');\n  // });\n\n  describe('As an async iterable', () => {\n    // it('should be able to be used with for-await-of', async () => {\n    //   const source = new Observable<number>((subscriber) => {\n    //     subscriber.next(1);\n    //     subscriber.next(2);\n    //     subscriber.next(3);\n    //     subscriber.complete();\n    //   });\n\n    //   const results: number[] = [];\n    //   for await (const value of source) {\n    //     results.push(value);\n    //   }\n\n    //   expect(results).to.deep.equal([1, 2, 3]);\n    // });\n\n    // it('should unsubscribe if the for-await-of loop is broken', async () => {\n    //   let activeSubscriptions = 0;\n\n    //   const source = new Observable<number>((subscriber) => {\n    //     activeSubscriptions++;\n\n    //     subscriber.next(1);\n    //     subscriber.next(2);\n\n    //     // NOTE that we are NOT calling `subscriber.complete()` here.\n    //     // therefore the teardown below would never be called naturally\n    //     // by the observable unless it was unsubscribed.\n    //     return () => {\n    //       activeSubscriptions--;\n    //     };\n    //   });\n\n    //   const results: number[] = [];\n    //   for await (const value of source) {\n    //     results.push(value);\n    //     break;\n    //   }\n\n    //   expect(results).to.deep.equal([1]);\n    //   expect(activeSubscriptions).to.equal(0);\n    // });\n\n    // it('should unsubscribe if the for-await-of loop is broken with a thrown error', async () => {\n    //   const source = new Observable<number>((subscriber) => {\n    //     subscriber.next(1);\n    //     subscriber.next(2);\n    //     subscriber.next(3);\n    //     subscriber.complete();\n    //   });\n\n    //   const results: number[] = [];\n\n    //   try {\n    //     for await (const value of source) {\n    //       results.push(value);\n    //       throw new Error('wee');\n    //     }\n    //   } catch {\n    //     // Ignore\n    //   }\n\n    //   expect(results).to.deep.equal([1]);\n    // });\n\n    // it('should cause the async iterator to throw if the observable errors', async () => {\n    //   const source = new Observable<number>((subscriber) => {\n    //     subscriber.next(1);\n    //     subscriber.next(2);\n    //     subscriber.error(new Error('wee'));\n    //   });\n\n    //   const results: number[] = [];\n    //   let thrownError: any;\n\n    //   try {\n    //     for await (const value of source) {\n    //       results.push(value);\n    //     }\n    //   } catch (err: any) {\n    //     thrownError = err;\n    //   }\n\n    //   expect(thrownError?.message).to.equal('wee');\n    //   expect(results).to.deep.equal([1, 2]);\n    // });\n\n    it('should handle situations where many promises are nexted out of the async iterator, but not awaited', async () => {\n      const subject = new Subject<number>();\n\n      const results: any[] = [];\n\n      const asyncIterator = subject[Symbol.asyncIterator]();\n\n      // Queue up three promises, but don't await them.\n      const first = asyncIterator.next().then((result) => {\n        results.push(result.value);\n      });\n\n      const second = asyncIterator.next().then((result) => {\n        results.push(result.value);\n      });\n\n      const third = asyncIterator.next().then((result) => {\n        results.push(result.value);\n      });\n\n      // Now let's progressively supply values to the promises.\n      expect(results).to.deep.equal([]);\n\n      subject.next(1);\n      await first;\n      expect(results).to.deep.equal([1]);\n\n      subject.next(2);\n      await second;\n      expect(results).to.deep.equal([1, 2]);\n\n      subject.next(3);\n      await third;\n      expect(results).to.deep.equal([1, 2, 3]);\n    });\n\n    it('should handle situations where values from the observable are arriving faster than the are being consumed by the async iterator', async () => {\n      const subject = new Subject<number>();\n\n      const results: any[] = [];\n\n      const asyncIterator = subject[Symbol.asyncIterator]();\n\n      // start the subscription\n      const first = asyncIterator.next().then((result) => {\n        results.push(result.value);\n      });\n      subject.next(1);\n      await first;\n      expect(results).to.deep.equal([1]);\n\n      // push values through the observable that aren't yet consumed by the async iterator\n      subject.next(2);\n      subject.next(3);\n\n      // now consume the values that were pushed through the observable\n      results.push((await asyncIterator.next()).value);\n      expect(results).to.deep.equal([1, 2]);\n\n      results.push((await asyncIterator.next()).value);\n      expect(results).to.deep.equal([1, 2, 3]);\n    });\n\n    it('should resolve all pending promises from the async iterable if the observable completes', async () => {\n      const subject = new Subject<number>();\n\n      const results: any[] = [];\n\n      const asyncIterator = subject[Symbol.asyncIterator]();\n\n      // Queue up three promises, but don't await them.\n      const allPending = Promise.all([asyncIterator.next(), asyncIterator.next(), asyncIterator.next()]).then((allResults) => {\n        results.push(...allResults);\n      });\n\n      expect(results).to.deep.equal([]);\n\n      // Complete and make sure those promises are resolved.\n      subject.complete();\n      await allPending;\n      expect(results).to.deep.equal([\n        { value: undefined, done: true },\n        { value: undefined, done: true },\n        { value: undefined, done: true },\n      ]);\n    });\n\n    it('should reject all pending promises from the async iterable if the observable errors', async () => {\n      const subject = new Subject<number>();\n\n      const results: any[] = [];\n\n      const asyncIterator = subject[Symbol.asyncIterator]();\n\n      // Queue up three promises, but don't await them.\n      const allPending = Promise.all([\n        asyncIterator.next().catch((err: any) => results.push(err)),\n        asyncIterator.next().catch((err: any) => results.push(err)),\n        asyncIterator.next().catch((err: any) => results.push(err)),\n      ]);\n\n      expect(results).to.deep.equal([]);\n\n      // Complete and make sure those promises are resolved.\n      subject.error(new Error('wee'));\n      await allPending;\n      expect(results.length).to.equal(3);\n      expect(results[0]).to.be.an.instanceof(Error);\n      expect(results[0].message).to.equal('wee');\n      expect(results[1]).to.be.an.instanceOf(Error);\n      expect(results[1].message).to.equal('wee');\n      expect(results[2]).to.be.an.instanceOf(Error);\n      expect(results[2].message).to.equal('wee');\n    });\n\n    // it('should unsubscribe from the source observable if `return` is called on the generator returned by Symbol.asyncIterator', async () => {\n    //   let state = 'idle';\n    //   const source = new Observable<number>((subscriber) => {\n    //     state = 'subscribed';\n    //     return () => {\n    //       state = 'unsubscribed';\n    //     };\n    //   });\n\n    //   const asyncIterator = source[Symbol.asyncIterator]();\n    //   expect(state).to.equal('idle');\n    //   asyncIterator.next();\n    //   expect(state).to.equal('subscribed');\n    //   asyncIterator.return();\n    //   expect(state).to.equal('unsubscribed');\n    // });\n\n    // it('should unsubscribe from the source observable if `throw` is called on the generator returned by Symbol.asyncIterator', async () => {\n    //   let state = 'idle';\n    //   const source = new Observable<number>((subscriber) => {\n    //     state = 'subscribed';\n    //     subscriber.next(0);\n    //     return () => {\n    //       state = 'unsubscribed';\n    //     };\n    //   });\n\n    //   const asyncIterator = source[Symbol.asyncIterator]();\n    //   expect(state).to.equal('idle');\n    //   await asyncIterator.next();\n    //   expect(state).to.equal('subscribed');\n    //   try {\n    //     await asyncIterator.throw(new Error('wee!'));\n    //   } catch (err: any) {\n    //     expect(err.message).to.equal('wee!');\n    //   }\n    //   expect(state).to.equal('unsubscribed');\n    // });\n  });\n});\n"
  },
  {
    "path": "packages/rxjs/spec/Scheduler-spec.ts",
    "content": "import { expect } from 'chai';\nimport { queueScheduler as queue } from 'rxjs';\nimport type { QueueScheduler } from 'rxjs/internal/scheduler/QueueScheduler';\n\n/** @test {Scheduler} */\ndescribe('Scheduler.queue', () => {\n  it('should schedule things recursively', () => {\n    let call1 = false;\n    let call2 = false;\n    (queue as QueueScheduler)._active = false;\n    queue.schedule(() => {\n      call1 = true;\n      queue.schedule(() => {\n        call2 = true;\n      });\n    });\n    expect(call1).to.be.true;\n    expect(call2).to.be.true;\n  });\n\n  it('should schedule things recursively via this.schedule', () => {\n    let call1 = false;\n    let call2 = false;\n    (queue as QueueScheduler)._active = false;\n    queue.schedule(function (state) {\n      call1 = state!.call1;\n      call2 = state!.call2;\n      if (!call2) {\n        this.schedule({ call1: true, call2: true });\n      }\n    }, 0, { call1: true, call2: false });\n    expect(call1).to.be.true;\n    expect(call2).to.be.true;\n  });\n\n  it('should schedule things in the future too', (done) => {\n    let called = false;\n    queue.schedule(() => {\n      called = true;\n    }, 60);\n\n    setTimeout(() => {\n      expect(called).to.be.false;\n    }, 20);\n\n    setTimeout(() => {\n      expect(called).to.be.true;\n      done();\n    }, 100);\n  });\n\n  it('should be reusable after an error is thrown during execution', (done) => {\n    const results: number[] = [];\n\n    expect(() => {\n      queue.schedule(() => {\n        results.push(1);\n      });\n\n      queue.schedule(() => {\n        throw new Error('bad');\n      });\n    }).to.throw(Error, 'bad');\n\n    setTimeout(() => {\n      queue.schedule(() => {\n        results.push(2);\n        done();\n      });\n    }, 0);\n  });\n});\n"
  },
  {
    "path": "packages/rxjs/spec/Subject-spec.ts",
    "content": "import { expect } from 'chai';\nimport type { Subscription} from 'rxjs';\nimport { Subject, Observable, AsyncSubject, of, config, Subscriber, noop, operate } from 'rxjs';\nimport { delay } from 'rxjs/operators';\nimport { TestScheduler } from 'rxjs/testing';\nimport { observableMatcher } from './helpers/observableMatcher';\n\n/** @test {Subject} */\ndescribe('Subject', () => {\n  let rxTestScheduler: TestScheduler;\n\n  beforeEach(() => {\n    rxTestScheduler = new TestScheduler(observableMatcher);\n  });\n\n  it('should allow next with undefined or any when created with no type', (done) => {\n    const subject = new Subject();\n    subject.subscribe({\n      next: (x) => {\n        expect(x).to.be.a('undefined');\n      },\n      complete: done,\n    });\n\n    const data: any = undefined;\n    subject.next(undefined);\n    subject.next(data);\n    subject.complete();\n  });\n\n  it('should allow empty next when created with void type', (done) => {\n    const subject = new Subject<void>();\n    subject.subscribe({\n      next: (x) => {\n        expect(x).to.be.a('undefined');\n      },\n      complete: done,\n    });\n\n    subject.next();\n    subject.complete();\n  });\n\n  it('should pump values right on through itself', (done) => {\n    const subject = new Subject<string>();\n    const expected = ['foo', 'bar'];\n\n    subject.subscribe({\n      next: (x: string) => {\n        expect(x).to.equal(expected.shift());\n      },\n      complete: done,\n    });\n\n    subject.next('foo');\n    subject.next('bar');\n    subject.complete();\n  });\n\n  it('should pump values to multiple subscribers', (done) => {\n    const subject = new Subject<string>();\n    const expected = ['foo', 'bar'];\n\n    let i = 0;\n    let j = 0;\n\n    subject.subscribe(function (x) {\n      expect(x).to.equal(expected[i++]);\n    });\n\n    subject.subscribe({\n      next: function (x) {\n        expect(x).to.equal(expected[j++]);\n      },\n      complete: done,\n    });\n\n    expect(subject.observers.length).to.equal(2);\n    subject.next('foo');\n    subject.next('bar');\n    subject.complete();\n  });\n\n  it('should handle subscribers that arrive and leave at different times, ' + 'subject does not complete', () => {\n    const subject = new Subject<number>();\n    const results1: (number | string)[] = [];\n    const results2: (number | string)[] = [];\n    const results3: (number | string)[] = [];\n\n    subject.next(1);\n    subject.next(2);\n    subject.next(3);\n    subject.next(4);\n\n    const subscription1 = subject.subscribe({\n      next: function (x) {\n        results1.push(x);\n      },\n      error: function (e) {\n        results1.push('E');\n      },\n      complete: () => {\n        results1.push('C');\n      },\n    });\n\n    subject.next(5);\n\n    const subscription2 = subject.subscribe({\n      next: function (x) {\n        results2.push(x);\n      },\n      error: function (e) {\n        results2.push('E');\n      },\n      complete: () => {\n        results2.push('C');\n      },\n    });\n\n    subject.next(6);\n    subject.next(7);\n\n    subscription1.unsubscribe();\n\n    subject.next(8);\n\n    subscription2.unsubscribe();\n\n    subject.next(9);\n    subject.next(10);\n\n    const subscription3 = subject.subscribe({\n      next: function (x) {\n        results3.push(x);\n      },\n      error: function (e) {\n        results3.push('E');\n      },\n      complete: () => {\n        results3.push('C');\n      },\n    });\n\n    subject.next(11);\n\n    subscription3.unsubscribe();\n\n    expect(results1).to.deep.equal([5, 6, 7]);\n    expect(results2).to.deep.equal([6, 7, 8]);\n    expect(results3).to.deep.equal([11]);\n  });\n\n  it('should handle subscribers that arrive and leave at different times, ' + 'subject completes', () => {\n    const subject = new Subject<number>();\n    const results1: (number | string)[] = [];\n    const results2: (number | string)[] = [];\n    const results3: (number | string)[] = [];\n\n    subject.next(1);\n    subject.next(2);\n    subject.next(3);\n    subject.next(4);\n\n    const subscription1 = subject.subscribe({\n      next: function (x) {\n        results1.push(x);\n      },\n      error: function (e) {\n        results1.push('E');\n      },\n      complete: () => {\n        results1.push('C');\n      },\n    });\n\n    subject.next(5);\n\n    const subscription2 = subject.subscribe({\n      next: function (x) {\n        results2.push(x);\n      },\n      error: function (e) {\n        results2.push('E');\n      },\n      complete: () => {\n        results2.push('C');\n      },\n    });\n\n    subject.next(6);\n    subject.next(7);\n\n    subscription1.unsubscribe();\n\n    subject.complete();\n\n    subscription2.unsubscribe();\n\n    const subscription3 = subject.subscribe({\n      next: function (x) {\n        results3.push(x);\n      },\n      error: function (e) {\n        results3.push('E');\n      },\n      complete: () => {\n        results3.push('C');\n      },\n    });\n\n    subscription3.unsubscribe();\n\n    expect(results1).to.deep.equal([5, 6, 7]);\n    expect(results2).to.deep.equal([6, 7, 'C']);\n    expect(results3).to.deep.equal(['C']);\n  });\n\n  it('should handle subscribers that arrive and leave at different times, ' + 'subject terminates with an error', () => {\n    const subject = new Subject<number>();\n    const results1: (number | string)[] = [];\n    const results2: (number | string)[] = [];\n    const results3: (number | string)[] = [];\n\n    subject.next(1);\n    subject.next(2);\n    subject.next(3);\n    subject.next(4);\n\n    const subscription1 = subject.subscribe({\n      next: function (x) {\n        results1.push(x);\n      },\n      error: function (e) {\n        results1.push('E');\n      },\n      complete: () => {\n        results1.push('C');\n      },\n    });\n\n    subject.next(5);\n\n    const subscription2 = subject.subscribe({\n      next: function (x) {\n        results2.push(x);\n      },\n      error: function (e) {\n        results2.push('E');\n      },\n      complete: () => {\n        results2.push('C');\n      },\n    });\n\n    subject.next(6);\n    subject.next(7);\n\n    subscription1.unsubscribe();\n\n    subject.error(new Error('err'));\n\n    subscription2.unsubscribe();\n\n    const subscription3 = subject.subscribe({\n      next: function (x) {\n        results3.push(x);\n      },\n      error: function (e) {\n        results3.push('E');\n      },\n      complete: () => {\n        results3.push('C');\n      },\n    });\n\n    subscription3.unsubscribe();\n\n    expect(results1).to.deep.equal([5, 6, 7]);\n    expect(results2).to.deep.equal([6, 7, 'E']);\n    expect(results3).to.deep.equal(['E']);\n  });\n\n  it('should handle subscribers that arrive and leave at different times, ' + 'subject completes before nexting any value', () => {\n    const subject = new Subject<number>();\n    const results1: (number | string)[] = [];\n    const results2: (number | string)[] = [];\n    const results3: (number | string)[] = [];\n\n    const subscription1 = subject.subscribe({\n      next: function (x) {\n        results1.push(x);\n      },\n      error: function (e) {\n        results1.push('E');\n      },\n      complete: () => {\n        results1.push('C');\n      },\n    });\n\n    const subscription2 = subject.subscribe({\n      next: function (x) {\n        results2.push(x);\n      },\n      error: function (e) {\n        results2.push('E');\n      },\n      complete: () => {\n        results2.push('C');\n      },\n    });\n\n    subscription1.unsubscribe();\n\n    subject.complete();\n\n    subscription2.unsubscribe();\n\n    const subscription3 = subject.subscribe({\n      next: function (x) {\n        results3.push(x);\n      },\n      error: function (e) {\n        results3.push('E');\n      },\n      complete: () => {\n        results3.push('C');\n      },\n    });\n\n    subscription3.unsubscribe();\n\n    expect(results1).to.deep.equal([]);\n    expect(results2).to.deep.equal(['C']);\n    expect(results3).to.deep.equal(['C']);\n  });\n\n  it('should disallow new subscriber once subject has been disposed', () => {\n    const subject = new Subject<number>();\n    const results1: (number | string)[] = [];\n    const results2: (number | string)[] = [];\n    const results3: (number | string)[] = [];\n\n    const subscription1 = subject.subscribe({\n      next: function (x) {\n        results1.push(x);\n      },\n      error: function (e) {\n        results1.push('E');\n      },\n      complete: () => {\n        results1.push('C');\n      },\n    });\n\n    subject.next(1);\n    subject.next(2);\n\n    const subscription2 = subject.subscribe({\n      next: function (x) {\n        results2.push(x);\n      },\n      error: function (e) {\n        results2.push('E');\n      },\n      complete: () => {\n        results2.push('C');\n      },\n    });\n\n    subject.next(3);\n    subject.next(4);\n    subject.next(5);\n\n    subscription1.unsubscribe();\n    subscription2.unsubscribe();\n    subject.unsubscribe();\n\n    const subscription = subject.subscribe({\n      next: function (x) {\n        results3.push(x);\n      },\n      error: function (err) {\n        expect(false).to.equal('should not throw error: ' + err.toString());\n      },\n    });\n\n    expect(subscription.closed).to.be.true;\n\n    expect(results1).to.deep.equal([1, 2, 3, 4, 5]);\n    expect(results2).to.deep.equal([3, 4, 5]);\n    expect(results3).to.deep.equal([]);\n  });\n\n  it('should not allow values to be nexted after it is unsubscribed', () => {\n    const subject = new Subject<string>();\n    const results: any[] = [];\n    subject.subscribe((x) => results.push(x));\n\n    subject.next('foo');\n    subject.unsubscribe();\n    subject.next('bar');\n\n    expect(results).to.deep.equal(['foo']);\n  });\n\n  it('should clean out unsubscribed subscribers', (done) => {\n    const subject = new Subject();\n\n    const sub1 = subject.subscribe(function (x) {\n      //noop\n    });\n\n    const sub2 = subject.subscribe(function (x) {\n      //noop\n    });\n\n    expect(subject.observers.length).to.equal(2);\n    sub1.unsubscribe();\n    expect(subject.observers.length).to.equal(1);\n    sub2.unsubscribe();\n    expect(subject.observers.length).to.equal(0);\n    done();\n  });\n\n  it('should expose observed status', () => {\n    const subject = new Subject();\n\n    expect(subject.observed).to.equal(false);\n\n    const sub1 = subject.subscribe(function (x) {\n      //noop\n    });\n\n    expect(subject.observed).to.equal(true);\n\n    const sub2 = subject.subscribe(function (x) {\n      //noop\n    });\n\n    expect(subject.observed).to.equal(true);\n    sub1.unsubscribe();\n    expect(subject.observed).to.equal(true);\n    sub2.unsubscribe();\n    expect(subject.observed).to.equal(false);\n    subject.unsubscribe();\n    expect(subject.observed).to.equal(false);\n  });\n\n  it('should be an Observer which can be given to Observable.subscribe', (done) => {\n    const source = of(1, 2, 3, 4, 5);\n    const subject = new Subject<number>();\n    const expected = [1, 2, 3, 4, 5];\n\n    subject.subscribe({\n      next: function (x) {\n        expect(x).to.equal(expected.shift());\n      },\n      error: (x) => {\n        done(new Error('should not be called'));\n      },\n      complete: () => {\n        done();\n      },\n    });\n\n    source.subscribe(subject);\n  });\n\n  it('should be usable as an Observer of a finite delayed Observable', (done) => {\n    const source = of(1, 2, 3).pipe(delay(50));\n    const subject = new Subject<number>();\n\n    const expected = [1, 2, 3];\n\n    subject.subscribe({\n      next: function (x) {\n        expect(x).to.equal(expected.shift());\n      },\n      error: (x) => {\n        done(new Error('should not be called'));\n      },\n      complete: () => {\n        done();\n      },\n    });\n\n    source.subscribe(subject);\n  });\n\n  it('should be closed after unsubscribed', () => {\n    const subject = new Subject<string>();\n    subject.unsubscribe();\n    expect(subject.closed).to.be.true;\n  });\n\n  it('should be closed after error', () => {\n    const subject = new Subject<string>();\n    subject.error('bad');\n    expect(subject.closed).to.be.true;\n  });\n\n  it('should be closed after complete', () => {\n    const subject = new Subject<string>();\n    subject.complete();\n    expect(subject.closed).to.be.true;\n  });\n\n  it('should not next after completed', () => {\n    const subject = new Subject<string>();\n    const results: string[] = [];\n    subject.subscribe({ next: (x) => results.push(x), complete: () => results.push('C') });\n    subject.next('a');\n    subject.complete();\n    subject.next('b');\n    expect(results).to.deep.equal(['a', 'C']);\n  });\n\n  it('should not next after error', () => {\n    const error = new Error('wut?');\n    const subject = new Subject<string>();\n    const results: string[] = [];\n    subject.subscribe({ next: (x) => results.push(x), error: (err) => results.push(err) });\n    subject.next('a');\n    subject.error(error);\n    subject.next('b');\n    expect(results).to.deep.equal(['a', error]);\n  });\n\n  describe('asObservable', () => {\n    it('should hide subject', () => {\n      const subject = new Subject();\n      const observable = subject.asObservable();\n\n      expect(subject).not.to.equal(observable);\n\n      expect(observable instanceof Observable).to.be.true;\n      expect(observable instanceof Subject).to.be.false;\n    });\n\n    it('should handle subject never emits', () => {\n      rxTestScheduler.run(({ hot, expectObservable }) => {\n        const observable = hot('-').asObservable();\n\n        expectObservable(observable).toBe('-');\n      });\n    });\n\n    it('should handle subject completes without emits', () => {\n      rxTestScheduler.run(({ hot, expectObservable }) => {\n        const observable = hot('--^--|').asObservable();\n        const expected = '        ---|';\n\n        expectObservable(observable).toBe(expected);\n      });\n    });\n\n    it('should handle subject throws', () => {\n      rxTestScheduler.run(({ hot, expectObservable }) => {\n        const observable = hot('--^--#').asObservable();\n        const expected = '        ---#';\n\n        expectObservable(observable).toBe(expected);\n      });\n    });\n\n    it('should handle subject emits', () => {\n      rxTestScheduler.run(({ hot, expectObservable }) => {\n        const observable = hot('--^--x--|').asObservable();\n        const expected = '        ---x--|';\n\n        expectObservable(observable).toBe(expected);\n      });\n    });\n\n    it('should work with inherited subject', () => {\n      const results: (number | string)[] = [];\n      const subject = new AsyncSubject<number>();\n\n      subject.next(42);\n      subject.complete();\n\n      const observable = subject.asObservable();\n\n      observable.subscribe({ next: (x) => results.push(x), complete: () => results.push('done') });\n\n      expect(results).to.deep.equal([42, 'done']);\n    });\n  });\n\n  describe('error thrown scenario', () => {\n    afterEach(() => {\n      config.onUnhandledError = null;\n    });\n\n    it('should not synchronously error when nexted into', (done) => {\n      config.onUnhandledError = (err) => {\n        expect(err.message).to.equal('Boom!');\n        done();\n      };\n\n      const source = new Subject<number>();\n      source.subscribe();\n      source.subscribe(() => {\n        throw new Error('Boom!');\n      });\n      source.subscribe();\n      try {\n        source.next(42);\n      } catch (err) {\n        // This should not happen!\n        expect(true).to.be.false;\n      }\n      expect(true).to.be.true;\n    });\n  });\n\n  describe('many subscribers', () => {\n    it('should be able to subscribe and unsubscribe huge amounts of subscribers', () => {\n      let numResultsReceived = 0;\n      const allSubscriptions: Subscription[] = [];\n      const source = new Subject<number>();\n      const numSubscribers = 100000;\n      for (let index = 0; index !== numSubscribers; ++index) {\n        allSubscriptions.push(\n          source.subscribe(() => {\n            ++numResultsReceived;\n          })\n        );\n      }\n      expect(numResultsReceived).to.eq(0);\n      expect(source.observed).to.be.true;\n      source.next(42);\n      expect(numResultsReceived).to.eq(numSubscribers);\n      expect(source.observed).to.be.true;\n      for (const subscription of allSubscriptions) {\n        subscription.unsubscribe();\n      }\n      expect(numResultsReceived).to.eq(numSubscribers);\n      expect(source.observed).to.be.false;\n    });\n  });\n\n  describe('re-rentrant subscribers', () => {\n    it('should handle re-entrant subscribers', () => {\n      const seenValues: number[] = [];\n      const source = new Subject<number>();\n      source.subscribe((value) => {\n        seenValues.push(value);\n        source.subscribe((nestedValue) => {\n          seenValues.push(nestedValue);\n        });\n      });\n      source.next(1);\n      source.next(2);\n      source.next(3);\n      expect(seenValues).to.deep.eq([1, 2, 2, 3, 3, 3]);\n    });\n  });\n\n  it('should behave properly when subscribed to more than once by the same operator subscriber returned by `operate`', () => {\n    const subject = new Subject<number>();\n    const destination = new Subscriber();\n    const results: any[] = [];\n    const subscriber = operate({\n      destination,\n      next: (value) => {\n        results.push(value);\n      },\n      error: noop,\n      complete: () => {\n        results.push('complete');\n      },\n    });\n\n    subject.subscribe(subscriber);\n    subject.subscribe(subscriber);\n    subject.next(1);\n    subject.next(2);\n    subject.complete();\n\n    expect(results).to.deep.equal([1, 1, 2, 2, 'complete']);\n  });\n});\n"
  },
  {
    "path": "packages/rxjs/spec/Subscriber-spec.ts",
    "content": "import { expect } from 'chai';\nimport type { Observer} from 'rxjs';\nimport { Subscriber, Observable, of, config, operate } from 'rxjs';\nimport * as sinon from 'sinon';\nimport { asInteropSubscriber } from './helpers/interop-helper';\nimport { getRegisteredFinalizers } from './helpers/subscription';\n\n/** @test {Subscriber} */\ndescribe('Subscriber', () => {\n  it('should ignore next messages after unsubscription', () => {\n    let times = 0;\n\n    const sub = new Subscriber<void>({\n      next() {\n        times += 1;\n      },\n    });\n\n    sub.next();\n    sub.next();\n    sub.unsubscribe();\n    sub.next();\n\n    expect(times).to.equal(2);\n  });\n\n  it('should ignore error messages after unsubscription', () => {\n    let times = 0;\n    let errorCalled = false;\n\n    const sub = new Subscriber<void>({\n      next() {\n        times += 1;\n      },\n      error() {\n        errorCalled = true;\n      },\n    });\n\n    sub.next();\n    sub.next();\n    sub.unsubscribe();\n    sub.next();\n    sub.error();\n\n    expect(times).to.equal(2);\n    expect(errorCalled).to.be.false;\n  });\n\n  it('should ignore complete messages after unsubscription', () => {\n    let times = 0;\n    let completeCalled = false;\n\n    const sub = new Subscriber<void>({\n      next() {\n        times += 1;\n      },\n      complete() {\n        completeCalled = true;\n      },\n    });\n\n    sub.next();\n    sub.next();\n    sub.unsubscribe();\n    sub.next();\n    sub.complete();\n\n    expect(times).to.equal(2);\n    expect(completeCalled).to.be.false;\n  });\n\n  it('should not be closed when other subscriber with same observer instance completes', () => {\n    const observer = {\n      next: function () {\n        /*noop*/\n      },\n    };\n\n    const sub1 = new Subscriber(observer);\n    const sub2 = new Subscriber(observer);\n\n    sub2.complete();\n\n    expect(sub1.closed).to.be.false;\n    expect(sub2.closed).to.be.true;\n  });\n\n  it('should call complete observer without any arguments', () => {\n    let argument: Array<any> | null = null;\n\n    const observer = {\n      complete: (...args: Array<any>) => {\n        argument = args;\n      },\n    };\n\n    const sub1 = new Subscriber(observer);\n    sub1.complete();\n\n    expect(argument).to.have.lengthOf(0);\n  });\n\n  it('should chain interop unsubscriptions', () => {\n    let observableUnsubscribed = false;\n    let subscriberUnsubscribed = false;\n    let subscriptionUnsubscribed = false;\n\n    const subscriber = new Subscriber();\n    subscriber.add(() => (subscriberUnsubscribed = true));\n\n    const source = new Observable<void>(() => () => (observableUnsubscribed = true));\n    const subscription = source.subscribe(asInteropSubscriber(subscriber));\n    subscription.add(() => (subscriptionUnsubscribed = true));\n    subscriber.unsubscribe();\n\n    expect(observableUnsubscribed).to.be.true;\n    expect(subscriberUnsubscribed).to.be.true;\n    expect(subscriptionUnsubscribed).to.be.true;\n  });\n\n  it('should have idempotent unsubscription', () => {\n    let count = 0;\n    const subscriber = new Subscriber();\n    subscriber.add(() => ++count);\n    expect(count).to.equal(0);\n\n    subscriber.unsubscribe();\n    expect(count).to.equal(1);\n\n    subscriber.unsubscribe();\n    expect(count).to.equal(1);\n  });\n\n  it('should close, unsubscribe, and unregister all finalizers after complete', () => {\n    let isUnsubscribed = false;\n    const subscriber = new Subscriber();\n    subscriber.add(() => (isUnsubscribed = true));\n    subscriber.complete();\n    expect(isUnsubscribed).to.be.true;\n    expect(subscriber.closed).to.be.true;\n    expect(getRegisteredFinalizers(subscriber).length).to.equal(0);\n  });\n\n  it('should close, unsubscribe, and unregister all finalizers after error', () => {\n    let isTornDown = false;\n    const subscriber = new Subscriber({\n      error: () => {\n        // Mischief managed!\n        // Adding this handler here to prevent the call to error from\n        // throwing, since it will have an error handler now.\n      },\n    });\n    subscriber.add(() => (isTornDown = true));\n    subscriber.error(new Error('test'));\n    expect(isTornDown).to.be.true;\n    expect(subscriber.closed).to.be.true;\n    expect(getRegisteredFinalizers(subscriber).length).to.equal(0);\n  });\n\n  it('should finalize and unregister all finalizers after complete', () => {\n    let isTornDown = false;\n    const subscriber = new Subscriber();\n    subscriber.add(() => {\n      isTornDown = true;\n    });\n    subscriber.complete();\n    expect(isTornDown).to.be.true;\n    expect(getRegisteredFinalizers(subscriber).length).to.equal(0);\n  });\n\n  it('should NOT break this context on next methods from unfortunate consumers', () => {\n    // This is a contrived class to illustrate that we can pass another\n    // object that is \"observer shaped\" and not have it lose its context\n    // as it would have in v5 - v6.\n    class CustomConsumer {\n      valuesProcessed: string[] = [];\n\n      // In here, we access instance state and alter it.\n      next(value: string) {\n        if (value === 'reset') {\n          this.valuesProcessed = [];\n        } else {\n          this.valuesProcessed.push(value);\n        }\n      }\n    }\n\n    const consumer = new CustomConsumer();\n\n    of('old', 'old', 'reset', 'new', 'new').subscribe(consumer);\n\n    expect(consumer.valuesProcessed).not.to.equal(['new', 'new']);\n  });\n\n  describe('error reporting for destination observers', () => {\n    afterEach(() => {\n      config.onUnhandledError = null;\n    });\n\n    it('should report errors thrown from next', (done) => {\n      config.onUnhandledError = (err) => {\n        expect(err).to.be.an.instanceOf(Error);\n        expect(err.message).to.equal('test');\n        done();\n      };\n\n      const subscriber = new Subscriber<void>({\n        next() {\n          throw new Error('test');\n        },\n      });\n\n      subscriber.next();\n    });\n\n    it('should report errors thrown from complete', (done) => {\n      config.onUnhandledError = (err) => {\n        expect(err).to.be.an.instanceOf(Error);\n        expect(err.message).to.equal('test');\n        done();\n      };\n\n      const subscriber = new Subscriber<void>({\n        complete() {\n          throw new Error('test');\n        },\n      });\n\n      subscriber.complete();\n    });\n\n    it('should report errors thrown from error', (done) => {\n      config.onUnhandledError = (err) => {\n        expect(err).to.be.an.instanceOf(Error);\n        expect(err.message).to.equal('test');\n        done();\n      };\n\n      const subscriber = new Subscriber<void>({\n        error() {\n          throw new Error('test');\n        },\n      });\n\n      subscriber.error();\n    });\n\n    it('should report errors thrown from a full observer', (done) => {\n      config.onUnhandledError = (err) => {\n        expect(err).to.be.an.instanceOf(Error);\n        expect(err.message).to.equal('thrown from next');\n        done();\n      };\n\n      const subscriber = new Subscriber<void>({\n        next() {\n          throw new Error('thrown from next');\n        },\n        error() {\n          throw new Error('thrown from error');\n        },\n        complete() {\n          throw new Error('thrown from complete');\n        },\n      });\n\n      subscriber.next();\n    });\n\n    it('should report errors thrown from a full observer even if it is also shaped like a subscription', (done) => {\n      config.onUnhandledError = (err) => {\n        expect(err).to.be.an.instanceOf(Error);\n        expect(err.message).to.equal('thrown from next');\n        done();\n      };\n\n      const subscriber = new Subscriber<void>({\n        next() {\n          throw new Error('thrown from next');\n        },\n        error() {\n          throw new Error('thrown from error');\n        },\n        complete() {\n          throw new Error('thrown from complete');\n        },\n        add() {\n          // lol\n        },\n        remove() {\n          // haha, fooled you\n        },\n        unsubscribe() {\n          // eat it, old RxJS!\n        },\n        closed: false,\n      });\n\n      subscriber.next();\n    });\n  });\n\n  const FinalizationRegistry = (global as any).FinalizationRegistry;\n  if (FinalizationRegistry && global.gc) {\n    it('should not leak the destination', (done) => {\n      let observer: Observer<number> | undefined = {\n        next() {\n          /* noop */\n        },\n        error() {\n          /* noop */\n        },\n        complete() {\n          /* noop */\n        },\n      };\n\n      const registry = new FinalizationRegistry((value: any) => {\n        expect(value).to.equal('observer');\n        done();\n      });\n      registry.register(observer, 'observer');\n\n      const subscription = of(42).subscribe(observer);\n\n      observer = undefined;\n      global.gc?.();\n    });\n  } else {\n    console.warn(`No support for FinalizationRegistry in Node ${process.version}`);\n  }\n});\n\ndescribe('operate', () => {\n  it('should create a Subscriber that passes next calls through to the destination by default', () => {\n    const next = sinon.spy();\n    const destination = new Subscriber<string>({\n      next,\n    });\n\n    const subscriber = operate({\n      destination,\n    });\n\n    subscriber.next('foo');\n    expect(next).to.have.been.calledOnceWithExactly('foo');\n  });\n\n  it('should catch any errors in the next override, and pass them to the error handler on the destination', () => {\n    const error = sinon.spy();\n    const destination = new Subscriber<string>({\n      error,\n    });\n\n    const subscriber = operate({\n      destination,\n      next() {\n        throw 'boop!';\n      },\n    });\n\n    subscriber.next('foo');\n    expect(error).to.have.been.calledOnceWithExactly('boop!');\n  });\n\n  it('should pass errors passed to the result through to the destination error handler by default', () => {\n    const error = sinon.spy();\n    const finalizer = sinon.spy();\n\n    const destination = new Subscriber<string>({\n      error,\n    });\n    destination.add(finalizer);\n\n    const subscriber = operate({\n      destination,\n    });\n\n    subscriber.error('boop!');\n    expect(error).to.have.been.calledOnceWithExactly('boop!');\n    expect(finalizer).to.have.been.calledOnce;\n  });\n\n  it('should pass errors that are thrown by the error override through to the destination, and finalize the subscriber', () => {\n    const error = sinon.spy();\n    const finalizer = sinon.spy();\n\n    const destination = new Subscriber<string>({\n      error,\n    });\n    destination.add(finalizer);\n\n    const subscriber = operate({\n      destination,\n      error() {\n        throw 'boop!';\n      },\n    });\n\n    subscriber.error('no boop for you');\n    expect(error).to.have.been.calledOnceWithExactly('boop!');\n    expect(finalizer).to.have.been.calledOnce;\n  });\n\n  it('should pass complete calls through to the destination by default', () => {\n    const complete = sinon.spy();\n    const finalizer = sinon.spy();\n\n    const destination = new Subscriber<string>({\n      complete,\n    });\n    destination.add(finalizer);\n\n    const subscriber = operate({\n      destination,\n    });\n\n    subscriber.complete();\n    expect(complete).to.have.been.calledOnce;\n    expect(finalizer).to.have.been.calledOnce;\n  });\n\n  it('should catch any errors in the complete override and pass them to the destination complete handler and finalize', () => {\n    const complete = sinon.spy();\n    const finalizer = sinon.spy();\n    const error = sinon.spy();\n\n    const destination = new Subscriber<string>({\n      complete,\n      error,\n    });\n    destination.add(finalizer);\n\n    const subscriber = operate({\n      destination,\n      complete() {\n        throw 'boop!';\n      },\n    });\n\n    subscriber.complete();\n    expect(complete).not.to.have.been.called;\n    expect(finalizer).to.have.been.calledOnce;\n    expect(error).to.have.been.calledOnceWithExactly('boop!');\n  });\n\n  it('should return a subscriber that, when unsubscribed, will finalize the destination', () => {\n    const finalizer = sinon.spy();\n    const destination = new Subscriber<string>({});\n    destination.add(finalizer);\n\n    const subscriber = operate({\n      destination,\n    });\n\n    destination.unsubscribe();\n    expect(finalizer).to.have.been.calledOnce;\n  });\n});\n"
  },
  {
    "path": "packages/rxjs/spec/Subscription-spec.ts",
    "content": "import { expect } from 'chai';\nimport { Observable, UnsubscriptionError, Subscription, merge } from 'rxjs';\nimport sinon = require('sinon');\n\n/** @test {Subscription} */\ndescribe('Subscription', () => {\n  describe('add()', () => {\n    it('should unsubscribe child subscriptions', () => {\n      const main = new Subscription();\n\n      let isCalled = false;\n      const child = new Subscription(() => {\n        isCalled = true;\n      });\n      main.add(child);\n      main.unsubscribe();\n\n      expect(isCalled).to.equal(true);\n    });\n\n    it('should unsubscribe child subscriptions if it has already been unsubscribed', () => {\n      const main = new Subscription();\n      main.unsubscribe();\n\n      let isCalled = false;\n      const child = new Subscription(() => {\n        isCalled = true;\n      });\n      main.add(child);\n\n      expect(isCalled).to.equal(true);\n    });\n\n    it('should unsubscribe a finalizer function that was passed', () => {\n      let isCalled = false;\n      const main = new Subscription();\n      main.add(() => {\n        isCalled = true;\n      });\n      main.unsubscribe();\n      expect(isCalled).to.be.true;\n    });\n\n    it('should unsubscribe a finalizer function that was passed immediately if it has been unsubscribed', () => {\n      let isCalled = false;\n      const main = new Subscription();\n      main.unsubscribe();\n      main.add(() => {\n        isCalled = true;\n      });\n      expect(isCalled).to.be.true;\n    });\n\n    it('should unsubscribe an Unsubscribable when unsubscribed', () => {\n      let isCalled = false;\n      const main = new Subscription();\n      main.add({\n        unsubscribe() {\n          isCalled = true;\n        }\n      });\n      main.unsubscribe();\n      expect(isCalled).to.be.true;\n    });\n\n    it('should unsubscribe an Unsubscribable if it is already unsubscribed', () => {\n      let isCalled = false;\n      const main = new Subscription();\n      main.unsubscribe();\n      main.add({\n        unsubscribe() {\n          isCalled = true;\n        }\n      });\n      expect(isCalled).to.be.true;\n    });\n  });\n\n  describe('remove()', () => {\n    it('should remove added Subscriptions', () => {\n      let isCalled = false;\n      const main = new Subscription();\n      const child = new Subscription(() => {\n        isCalled = true;\n      });\n      main.add(child);\n      main.remove(child);\n      main.unsubscribe();\n      expect(isCalled).to.be.false;\n    });\n\n    it('should remove added functions', () => {\n      let isCalled = false;\n      const main = new Subscription();\n      const finalizer = () => {\n        isCalled = true;\n      };\n      main.add(finalizer);\n      main.remove(finalizer);\n      main.unsubscribe();\n      expect(isCalled).to.be.false;\n    });\n\n    it('should remove added unsubscribables', () => {\n      let isCalled = false;\n      const main = new Subscription();\n      const unsubscribable = {\n        unsubscribe() {\n          isCalled = true;\n        }\n      }\n      main.add(unsubscribable);\n      main.remove(unsubscribable);\n      main.unsubscribe();\n      expect(isCalled).to.be.false;\n    });\n  });\n\n  describe('unsubscribe()', () => {\n    it('should unsubscribe from all subscriptions, when some of them throw', (done) => {\n      const finalizers: number[] = [];\n\n      const source1 = new Observable(() => {\n        return () => {\n          finalizers.push(1);\n        };\n      });\n\n      const source2 = new Observable(() => {\n        return () => {\n          finalizers.push(2);\n          throw new Error('oops, I am a bad unsubscribe!');\n        };\n      });\n\n      const source3 = new Observable(() => {\n        return () => {\n          finalizers.push(3);\n        };\n      });\n\n      const subscription = merge(source1, source2, source3).subscribe();\n\n      setTimeout(() => {\n        expect(() => {\n          subscription.unsubscribe();\n        }).to.throw(UnsubscriptionError);\n        expect(finalizers).to.deep.equal([1, 2, 3]);\n        done();\n      });\n    });\n\n    it('should unsubscribe from all subscriptions, when adding a bad custom subscription to a subscription', (done) => {\n      const finalizers: number[] = [];\n\n      const sub = new Subscription();\n\n      const source1 = new Observable(() => {\n        return () => {\n          finalizers.push(1);\n        };\n      });\n\n      const source2 = new Observable(() => {\n        return () => {\n          finalizers.push(2);\n          sub.add(<any>({\n            unsubscribe: () => {\n              expect(sub.closed).to.be.true;\n              throw new Error('Who is your daddy, and what does he do?');\n            }\n          }));\n        };\n      });\n\n      const source3 = new Observable(() => {\n        return () => {\n          finalizers.push(3);\n        };\n      });\n\n      sub.add(merge(source1, source2, source3).subscribe());\n\n      setTimeout(() => {\n        expect(() => {\n          sub.unsubscribe();\n        }).to.throw(UnsubscriptionError);\n        expect(finalizers).to.deep.equal([1, 2, 3]);\n        done();\n      });\n    });\n\n    it('should have idempotent unsubscription', () => {\n      let count = 0;\n      const subscription = new Subscription(() => ++count);\n      expect(count).to.equal(0);\n\n      subscription.unsubscribe();\n      expect(count).to.equal(1);\n\n      subscription.unsubscribe();\n      expect(count).to.equal(1);\n    });\n\n    it('should unsubscribe from all parents', () => {\n      // https://github.com/ReactiveX/rxjs/issues/6351\n      const a = new Subscription(() => { /* noop */});\n      const b = new Subscription(() => { /* noop */});\n      const c = new Subscription(() => { /* noop */});\n      const d = new Subscription(() => { /* noop */});\n      a.add(d);\n      b.add(d);\n      c.add(d);\n      // When d is added to the subscriptions, it's added as a finalizer. The\n      // length is 1 because the finalizers passed to the ctors are stored in a\n      // separate property.\n      expect((a as any)._finalizers).to.have.length(1);\n      expect((b as any)._finalizers).to.have.length(1);\n      expect((c as any)._finalizers).to.have.length(1);\n      d.unsubscribe();\n      // When d is unsubscribed, it should remove itself from each of its\n      // parents.\n      expect((a as any)._finalizers).to.have.length(0);\n      expect((b as any)._finalizers).to.have.length(0);\n      expect((c as any)._finalizers).to.have.length(0);\n    });\n  });\n});\n\ndescribe('Subscription[Symbol.dispose] implementation', () => {\n  it('should be the same as unsubscribe', () => {\n    const subscription = new Subscription();\n    expect(subscription[Symbol.dispose]).to.equal(subscription.unsubscribe);\n  });\n\n  it('should call a teardown when unsubscribed', () => {\n    // This is just a sanity check.\n    const callback = sinon.spy();\n    const subscription = new Subscription();\n    \n    subscription.add(callback);\n    subscription[Symbol.dispose]();\n    expect(callback).to.have.been.calledOnce;\n    expect(subscription.closed).to.be.true;\n  });\n});\n\n"
  },
  {
    "path": "packages/rxjs/spec/ajax/index-spec.ts",
    "content": "import * as index from 'rxjs/ajax';\nimport { expect } from 'chai';\n\ndescribe('index', () => {\n  it('should export static ajax observable creator functions', () => {\n    expect(index.ajax).to.exist;\n  });\n\n  it('should export Ajax data classes', () => {\n    expect(index.AjaxError).to.exist;\n    expect(index.AjaxTimeoutError).to.exist;\n    // Interfaces can be checked by creating a variable of that type\n    let ajaxRequest: index.AjaxRequest;\n    let ajaxResponse: index.AjaxResponse<object>;\n  });\n});\n"
  },
  {
    "path": "packages/rxjs/spec/config-spec.ts",
    "content": "/** @prettier */\n\nimport { expect } from 'chai';\nimport { Observable, config } from 'rxjs';\nimport { timeoutProvider } from 'rxjs/internal/scheduler/timeoutProvider';\n\ndescribe('config', () => {\n  describe('onUnhandledError', () => {\n    afterEach(() => {\n      config.onUnhandledError = null;\n    });\n\n    it('should default to null', () => {\n      expect(config.onUnhandledError).to.be.null;\n    });\n\n    it('should call asynchronously if an error is emitted and not handled by the consumer observer', (done) => {\n      let called = false;\n      const results: any[] = [];\n\n      config.onUnhandledError = (err) => {\n        called = true;\n        expect(err).to.equal('bad');\n        done();\n      };\n\n      const source = new Observable<number>((subscriber) => {\n        subscriber.next(1);\n        subscriber.error('bad');\n      });\n\n      source.subscribe({\n        next: (value) => results.push(value),\n      });\n      expect(called).to.be.false;\n      expect(results).to.deep.equal([1]);\n    });\n\n    it('should call asynchronously if an error is emitted and not handled by the consumer next callback', (done) => {\n      let called = false;\n      const results: any[] = [];\n\n      config.onUnhandledError = (err) => {\n        called = true;\n        expect(err).to.equal('bad');\n        done();\n      };\n\n      const source = new Observable<number>((subscriber) => {\n        subscriber.next(1);\n        subscriber.error('bad');\n      });\n\n      source.subscribe((value) => results.push(value));\n      expect(called).to.be.false;\n      expect(results).to.deep.equal([1]);\n    });\n\n    it('should call asynchronously if an error is emitted and not handled by the consumer in the empty case', (done) => {\n      let called = false;\n      config.onUnhandledError = (err) => {\n        called = true;\n        expect(err).to.equal('bad');\n        done();\n      };\n\n      const source = new Observable((subscriber) => {\n        subscriber.error('bad');\n      });\n\n      source.subscribe();\n      expect(called).to.be.false;\n    });\n\n    /**\n     * This test is added so people know this behavior is _intentional_. It's part of the contract of observables\n     * and, while I'm not sure I like it, it might start surfacing untold numbers of errors, and break\n     * node applications if we suddenly changed this to start throwing errors on other jobs for instances\n     * where users accidentally called `subscriber.error` twice. Likewise, would we report an error\n     * for two calls of `complete`? This is really something a build-time tool like a linter should\n     * capture. Not a run time error reporting event.\n     */\n    it('should not be called if two errors are sent to the subscriber', (done) => {\n      let called = false;\n      config.onUnhandledError = () => {\n        called = true;\n      };\n\n      const source = new Observable((subscriber) => {\n        subscriber.error('handled');\n        subscriber.error('swallowed');\n      });\n\n      let syncSentError: any;\n      source.subscribe({\n        error: (err) => {\n          syncSentError = err;\n        },\n      });\n\n      expect(syncSentError).to.equal('handled');\n      // When called, onUnhandledError is called on a timeout, so delay the\n      // the assertion of the expectation until after the point at which\n      // onUnhandledError would have been called.\n      timeoutProvider.setTimeout(() => {\n        expect(called).to.be.false;\n        done();\n      });\n    });\n  });\n\n  describe('onStoppedNotification', () => {\n    afterEach(() => {\n      config.onStoppedNotification = null;\n    });\n\n    it('should default to null', () => {\n      expect(config.onStoppedNotification).to.be.null;\n    });\n\n    it('should be called asynchronously if a subscription setup errors after the subscription is closed by an error', (done) => {\n      let called = false;\n      config.onStoppedNotification = (notification) => {\n        called = true;\n        expect(notification.kind).to.equal('E');\n        expect(notification).to.have.property('error', 'bad');\n        done();\n      };\n\n      const source = new Observable((subscriber) => {\n        subscriber.error('handled');\n        throw 'bad';\n      });\n\n      let syncSentError: any;\n      source.subscribe({\n        error: (err) => {\n          syncSentError = err;\n        },\n      });\n\n      expect(syncSentError).to.equal('handled');\n      expect(called).to.be.false;\n    });\n\n    it('should be called asynchronously if a subscription setup errors after the subscription is closed by a completion', (done) => {\n      let called = false;\n      let completed = false;\n      config.onStoppedNotification = (notification) => {\n        called = true;\n        expect(notification.kind).to.equal('E');\n        expect(notification).to.have.property('error', 'bad');\n        done();\n      };\n\n      const source = new Observable((subscriber) => {\n        subscriber.complete();\n        throw 'bad';\n      });\n\n      source.subscribe({\n        error: () => {\n          throw 'should not be called';\n        },\n        complete: () => {\n          completed = true;\n        },\n      });\n\n      expect(completed).to.be.true;\n      expect(called).to.be.false;\n    });\n\n    it('should be called if a next is sent to the stopped subscriber', (done) => {\n      let called = false;\n      config.onStoppedNotification = (notification) => {\n        called = true;\n        expect(notification.kind).to.equal('N');\n        expect(notification).to.have.property('value', 2);\n        done();\n      };\n\n      const source = new Observable((subscriber) => {\n        subscriber.next(1);\n        subscriber.complete();\n        subscriber.next(2);\n      });\n\n      let syncSentValue: any;\n      source.subscribe({\n        next: (value) => {\n          syncSentValue = value;\n        },\n      });\n\n      expect(syncSentValue).to.equal(1);\n      expect(called).to.be.false;\n    });\n\n    it('should be called if two errors are sent to the subscriber', (done) => {\n      let called = false;\n      config.onStoppedNotification = (notification) => {\n        called = true;\n        expect(notification.kind).to.equal('E');\n        expect(notification).to.have.property('error', 'swallowed');\n        done();\n      };\n\n      const source = new Observable((subscriber) => {\n        subscriber.error('handled');\n        subscriber.error('swallowed');\n      });\n\n      let syncSentError: any;\n      source.subscribe({\n        error: (err) => {\n          syncSentError = err;\n        },\n      });\n\n      expect(syncSentError).to.equal('handled');\n      expect(called).to.be.false;\n    });\n\n    it('should be called if two completes are sent to the subscriber', (done) => {\n      let called = false;\n      config.onStoppedNotification = (notification) => {\n        called = true;\n        expect(notification.kind).to.equal('C');\n        done();\n      };\n\n      const source = new Observable((subscriber) => {\n        subscriber.complete();\n        subscriber.complete();\n      });\n\n      source.subscribe();\n\n      expect(called).to.be.false;\n    });\n  });\n});\n"
  },
  {
    "path": "packages/rxjs/spec/exports-spec.ts.disabled",
    "content": "import { expect } from 'chai';\nimport { bindCallback, bindNodeCallback, combineLatest, concat, defer, empty, forkJoin, from, fromEvent, fromEventPattern,\n  iif, interval, merge, of, onErrorResumeNext, pairs, race, range, throwError, timer, using, zip } from 'rxjs';\nimport * as Rx from 'rxjs/Rx';\n\ndescribe('exports', () => {\n  it('should have rxjs/observable/bindCallback', () => {\n    expect(bindCallback).to.equal(Rx.Observable.bindCallback);\n  });\n\n  it('should have rxjs/observable/bindNodeCallback', () => {\n    expect(bindNodeCallback).to.equal(Rx.Observable.bindNodeCallback);\n  });\n\n  it('should have rxjs/observable/combineLatest', () => {\n    expect(combineLatest).to.equal(Rx.Observable.combineLatest);\n  });\n\n  it('should have rxjs/observable/concat', () => {\n    expect(concat).to.equal(Rx.Observable.concat);\n  });\n\n  it('should have rxjs/observable/defer', () => {\n    expect(defer).to.equal(Rx.Observable.defer);\n  });\n\n  it('should have rxjs/observable/empty', () => {\n    expect(empty).to.equal(Rx.Observable.empty);\n  });\n\n  it('should have rxjs/observable/forkJoin', () => {\n    expect(forkJoin).to.equal(Rx.Observable.forkJoin);\n  });\n\n  it('should have rxjs/observable/from', () => {\n    expect(from).to.equal(Rx.Observable.from);\n  });\n\n  it('should have rxjs/observable/fromEvent', () => {\n    expect(fromEvent).to.equal(Rx.Observable.fromEvent);\n  });\n\n  it('should have rxjs/observable/fromEventPattern', () => {\n    expect(fromEventPattern).to.equal(Rx.Observable.fromEventPattern);\n  });\n\n  it('should have rxjs/observable/fromPromise', () => {\n    expect(from).to.equal(Rx.Observable.fromPromise);\n  });\n\n  it('should have rxjs/observable/iif', () => {\n    expect(iif).to.equal(Rx.Observable.if);\n  });\n\n  it('should have rxjs/observable/interval', () => {\n    expect(interval).to.equal(Rx.Observable.interval);\n  });\n\n  it('should have rxjs/observable/merge', () => {\n    expect(merge).to.equal(Rx.Observable.merge);\n  });\n\n  it('should have rxjs/observable/of', () => {\n    expect(of).to.equal(Rx.Observable.of);\n  });\n\n  it('should have rxjs/observable/onErrorResumeNext', () => {\n    expect(onErrorResumeNext).to.equal(Rx.Observable.onErrorResumeNext);\n  });\n\n  it('should have rxjs/observable/pairs', () => {\n    expect(pairs).to.equal(Rx.Observable.pairs);\n  });\n\n  it('should have rxjs/observable/race', () => {\n    expect(race).to.equal(Rx.Observable.race);\n  });\n\n  it('should have rxjs/observable/range', () => {\n    expect(range).to.equal(Rx.Observable.range);\n  });\n\n  it('should have rxjs/observable/throwError', () => {\n    expect(throwError).to.equal(Rx.Observable.throw);\n  });\n\n  it('should have rxjs/observable/timer', () => {\n    expect(timer).to.equal(Rx.Observable.timer);\n  });\n\n  it('should have rxjs/observable/using', () => {\n    expect(using).to.equal(Rx.Observable.using);\n  });\n\n  it('should have rxjs/observable/zip', () => {\n    expect(zip).to.equal(Rx.Observable.zip);\n  });\n});\n"
  },
  {
    "path": "packages/rxjs/spec/firstValueFrom-spec.ts",
    "content": "import { interval, firstValueFrom, EMPTY, EmptyError, throwError, of, Observable } from 'rxjs';\nimport { expect } from 'chai';\nimport { finalize } from 'rxjs/operators';\n\ndescribe('firstValueFrom', () => {\n  it('should emit the first value as a promise', async () => {\n    let finalized = false;\n    const source = interval(10).pipe(finalize(() => (finalized = true)));\n    const result = await firstValueFrom(source);\n    expect(result).to.equal(0);\n    expect(finalized).to.be.true;\n  });\n\n  it('should support a default value', async () => {\n    const source = EMPTY;\n    const result = await firstValueFrom(source, { defaultValue: 0 });\n    expect(result).to.equal(0);\n  });\n\n  it('should support an undefined config', async () => {\n    const source = EMPTY;\n    let error: any = null;\n    try {\n      await firstValueFrom(source, undefined as any);\n    } catch (err) {\n      error = err;\n    }\n    expect(error).to.be.an.instanceOf(EmptyError);\n  });\n\n  it('should error for empty observables', async () => {\n    const source = EMPTY;\n    let error: any = null;\n    try {\n      await firstValueFrom(source);\n    } catch (err) {\n      error = err;\n    }\n    expect(error).to.be.an.instanceOf(EmptyError);\n  });\n\n  it('should error for errored observables', async () => {\n    const source = throwError(() => new Error('blorp!'));\n    let error: any = null;\n    try {\n      await firstValueFrom(source);\n    } catch (err) {\n      error = err;\n    }\n    expect(error).to.be.an.instanceOf(Error);\n    expect(error.message).to.equal('blorp!');\n  });\n\n  it('should work with a synchronous observable', async () => {\n    let finalized = false;\n    const source = of('apples', 'bananas').pipe(finalize(() => (finalized = true)));\n    const result = await firstValueFrom(source);\n    expect(result).to.equal('apples');\n    expect(finalized).to.be.true;\n  });\n\n  it('should stop listening to a synchronous observable when resolved', async () => {\n    const sideEffects: number[] = [];\n    const synchronousObservable = new Observable<number>(subscriber => {\n      // This will check to see if the subscriber was closed on each loop\n      // when the unsubscribe hits (from the `take`), it should be closed\n      for (let i = 0; !subscriber.closed && i < 10; i++) {\n        sideEffects.push(i);\n        subscriber.next(i);\n      }\n    });\n\n    const result = await firstValueFrom(synchronousObservable);\n    expect(sideEffects).to.deep.equal([0]);\n  });\n});\n"
  },
  {
    "path": "packages/rxjs/spec/helpers/interop-helper-spec.ts",
    "content": "import { expect } from 'chai';\nimport { Observable, of, Subscriber } from 'rxjs';\nimport { asInteropObservable, asInteropSubscriber } from './interop-helper';\n\ndescribe('interop helper', () => {\n  it('should simulate interop observables', () => {\n    const observable: any = asInteropObservable(of(42));\n    expect(observable).to.not.be.instanceOf(Observable);\n    expect(observable[Symbol.observable ?? '@@observable']).to.be.a('function');\n  });\n\n  it('should simulate interop subscribers', () => {\n    const subscriber: any = asInteropSubscriber(new Subscriber());\n    expect(subscriber).to.not.be.instanceOf(Subscriber);\n  });\n});\n"
  },
  {
    "path": "packages/rxjs/spec/helpers/interop-helper.ts",
    "content": "import type { Observable, Subject, Subscription } from 'rxjs';\nimport { Subscriber } from 'rxjs';\n\n/**\n * Returns an observable that will be deemed by this package's implementation\n * to be an observable that requires interop. The returned observable will fail\n * the `instanceof Observable` test and will deem any `Subscriber` passed to\n * its `subscribe` method to be untrusted.\n */\nexport function asInteropObservable<T>(observable: Observable<T>): Observable<T> {\n  return new Proxy(observable, {\n    get(target: Observable<T>, key: string | number | symbol) {\n      if (key === 'subscribe') {\n        const { subscribe } = target;\n        return interopSubscribe(subscribe);\n      }\n      return Reflect.get(target, key);\n    },\n    getPrototypeOf(target: Observable<T>) {\n      const { lift, subscribe, ...rest } = Object.getPrototypeOf(target);\n      return {\n        ...rest,\n        subscribe: interopSubscribe(subscribe)\n      };\n    }\n  });\n}\n\n/**\n * Returns a subject that will be deemed by this package's implementation to\n * be untrusted. The returned subject will not include the symbol that\n * identifies trusted subjects.\n */\nexport function asInteropSubject<T>(subject: Subject<T>): Subject<T> {\n  return asInteropSubscriber(subject as any) as any;\n}\n\n/**\n * Returns a subscriber that will be deemed by this package's implementation to\n * be untrusted. The returned subscriber will fail the `instanceof Subscriber`\n * test and will not include the symbol that identifies trusted subscribers.\n */\nexport function asInteropSubscriber<T>(subscriber: Subscriber<T>): Subscriber<T> {\n  return new Proxy(subscriber, {\n    get(target: Subscriber<T>, key: string | number | symbol) {\n      return Reflect.get(target, key);\n    },\n    getPrototypeOf(target: Subscriber<T>) {\n      const { ...rest } = Object.getPrototypeOf(target);\n      return rest;\n    }\n  });\n}\n\nfunction interopSubscribe<T>(subscribe: (...args: any[]) => Subscription) {\n  return function (this: Observable<T>, ...args: any[]): Subscription {\n    const [arg] = args;\n    if (arg instanceof Subscriber) {\n      return subscribe.call(this, asInteropSubscriber(arg));\n    }\n    return subscribe.apply(this, args);\n  };\n}\n"
  },
  {
    "path": "packages/rxjs/spec/helpers/marble-testing.ts",
    "content": "import type { Observable } from 'rxjs';\nimport type { SubscriptionLog } from '../../src/internal/testing/subscription-logging';\nimport type { ColdObservable } from '../../src/internal/testing/ColdObservable';\nimport type { HotObservable } from '../../src/internal/testing/HotObservable';\nimport type { observableToBeFn, subscriptionLogsToBeFn } from '../../src/internal/testing/TestScheduler';\n\ndeclare const global: any;\n\nexport function hot(marbles: string, values?: void, error?: any): HotObservable<string>;\nexport function hot<V>(marbles: string, values?: { [index: string]: V }, error?: any): HotObservable<V>;\nexport function hot<V>(marbles: string, values?: { [index: string]: V } | void, error?: any): HotObservable<any> {\n  if (!global.rxTestScheduler) {\n    throw 'tried to use hot() in async test';\n  }\n  return global.rxTestScheduler.createHotObservable.call(global.rxTestScheduler, marbles, values, error);\n}\n\nexport function cold(marbles: string, values?: void, error?: any): ColdObservable<string>;\nexport function cold<V>(marbles: string, values?: { [index: string]: V }, error?: any): ColdObservable<V>;\nexport function cold(marbles: string, values?: any, error?: any): ColdObservable<any> {\n  if (!global.rxTestScheduler) {\n    throw 'tried to use cold() in async test';\n  }\n  return global.rxTestScheduler.createColdObservable.call(global.rxTestScheduler, marbles, values, error);\n}\n\nexport function expectObservable(observable: Observable<any>, unsubscriptionMarbles: string | null = null): { toBe: observableToBeFn } {\n  if (!global.rxTestScheduler) {\n    throw 'tried to use expectObservable() in async test';\n  }\n  return global.rxTestScheduler.expectObservable.call(global.rxTestScheduler, observable, unsubscriptionMarbles);\n}\n\nexport function expectSubscriptions(actualSubscriptionLogs: SubscriptionLog[]): { toBe: subscriptionLogsToBeFn } {\n  if (!global.rxTestScheduler) {\n    throw 'tried to use expectSubscriptions() in async test';\n  }\n  return global.rxTestScheduler.expectSubscriptions.call(global.rxTestScheduler, actualSubscriptionLogs);\n}\n\nexport function time(marbles: string): number {\n  if (!global.rxTestScheduler) {\n    throw 'tried to use time() in async test';\n  }\n  return global.rxTestScheduler.createTime.call(global.rxTestScheduler, marbles);\n}\n"
  },
  {
    "path": "packages/rxjs/spec/helpers/observableMatcher.ts",
    "content": "import * as _ from 'lodash';\nimport * as chai from 'chai';\n\nfunction stringify(x: any): string {\n  return JSON.stringify(x, function (key: string, value: any) {\n    if (Array.isArray(value)) {\n      return '[' + value\n        .map(function (i) {\n          return '\\n\\t' + stringify(i);\n        }) + '\\n]';\n    }\n    return value;\n  })\n  .replace(/\\\\\"/g, '\"')\n  .replace(/\\\\t/g, '\\t')\n  .replace(/\\\\n/g, '\\n');\n}\n\nfunction deleteErrorNotificationStack(marble: any) {\n  const { notification } = marble;\n  if (notification) {\n    const { kind, error } = notification;\n    if (kind === 'E' && error instanceof Error) {\n      notification.error = { name: error.name, message: error.message };\n    }\n  }\n  return marble;\n}\n\nexport function observableMatcher(actual: any, expected: any) {\n  if (Array.isArray(actual) && Array.isArray(expected)) {\n    actual = actual.map(deleteErrorNotificationStack);\n    expected = expected.map(deleteErrorNotificationStack);\n    const passed = _.isEqual(actual, expected);\n    if (passed) {\n      return;\n    }\n\n    let message = '\\nExpected \\n';\n    actual.forEach((x: any) => message += `\\t${stringify(x)}\\n`);\n\n    message += '\\t\\nto deep equal \\n';\n    expected.forEach((x: any) => message += `\\t${stringify(x)}\\n`);\n\n    chai.assert(passed, message);\n  } else {\n    chai.assert.deepEqual(actual, expected);\n  }\n}\n"
  },
  {
    "path": "packages/rxjs/spec/helpers/setup.ts",
    "content": "/**\n * Setup globals for the mocha unit tests such as injecting polyfills\n **/\n\nimport * as chai from 'chai';\nimport * as sinonChai from 'sinon-chai';\n\nif (typeof Symbol !== 'function') {\n  let id = 0;\n  const symbolFn: any = (description: string) =>\n    `Symbol_${id++} ${description} (RxJS Testing Polyfill)`;\n\n  // eslint-disable-next-line no-global-assign\n  Symbol = symbolFn;\n}\n\nif (!(Symbol as any).observable) {\n  (Symbol as any).observable = Symbol('Symbol.observable polyfill from RxJS Testing');\n}\n\n/** Polyfill requestAnimationFrame for testing animationFrameScheduler scheduler in Node */\n// http://paulirish.com/2011/requestanimationframe-for-smart-animating/\n// http://my.opera.com/emoller/blog/2011/12/20/requestanimationframe-for-smart-er-animating\n\n// requestAnimationFrame polyfill by Erik Möller. fixes from Paul Irish and Tino Zijdel\n\n// MIT license\n\n(function(this: any, window: any) {\n  window = window || this;\n  let lastTime = 0;\n  const vendors = ['ms', 'moz', 'webkit', 'o'];\n  for (let x = 0; x < vendors.length && !window.requestAnimationFrame; ++x) {\n      window.requestAnimationFrame = window[vendors[x] + 'RequestAnimationFrame'];\n      window.cancelAnimationFrame = window[vendors[x] + 'CancelAnimationFrame']\n                                 || window[vendors[x] + 'CancelRequestAnimationFrame'];\n  }\n\n  if (!window.requestAnimationFrame) {\n      window.requestAnimationFrame = (callback: (...args: unknown[]) => any, element: any) => {\n          const currTime = new Date().getTime();\n          const timeToCall = Math.max(0, 16 - (currTime - lastTime));\n          const id = window.setTimeout(() => { callback(currTime + timeToCall); },\n            timeToCall);\n          lastTime = currTime + timeToCall;\n          return id;\n      };\n  }\n\n  if (!window.cancelAnimationFrame) {\n      window.cancelAnimationFrame = (id: number) => {\n          clearTimeout(id);\n      };\n  }\n}(global));\n\n// Polyfill Symbol.dispose for testing\nif (typeof Symbol.dispose !== 'symbol') {\n  (Symbol as any).dispose = Symbol('dispose polyfill');\n}\n\n\n//setup sinon-chai\nchai.use(sinonChai);\n"
  },
  {
    "path": "packages/rxjs/spec/helpers/subscription.ts",
    "content": "/** @prettier */\nimport type { TeardownLogic } from 'rxjs';\n\nexport function getRegisteredFinalizers(subscription: any): Exclude<TeardownLogic, void>[] {\n  if ('_finalizers' in subscription) {\n    return subscription._finalizers ?? [];\n  } else {\n    throw new TypeError('Invalid Subscription');\n  }\n}\n"
  },
  {
    "path": "packages/rxjs/spec/helpers/test-helper.ts",
    "content": "import type { Observable, ObservableInput } from 'rxjs';\nimport { of, asyncScheduler, scheduled } from 'rxjs';\nimport { iterator } from 'rxjs/internal/symbol/iterator';\n\nif (process && process.on) {\n  /**\n   * With async/await functions in Node, mocha seems to allow\n   * tests to pass, even they shouldn't there's something about how\n   * it handles the rejected promise where it does not notice\n   * that the test failed.\n   */\n  process.on('unhandledRejection', (err) => {\n    console.error(err);\n    process.exit(1);\n  });\n}\n\nexport function lowerCaseO<T>(...args: Array<any>): Observable<T> {\n  const o: any = {\n    subscribe(observer: any) {\n      args.forEach((v) => observer.next(v));\n      observer.complete();\n      return {\n        unsubscribe() {\n          /* do nothing */\n        },\n      };\n    },\n  };\n\n  o[Symbol.observable ?? '@@observable'] = function (this: any) {\n    return this;\n  };\n\n  return <any>o;\n}\n\nexport const createObservableInputs = <T>(value: T) =>\n  of(\n    of(value),\n    scheduled([value], asyncScheduler),\n    [value],\n    Promise.resolve(value),\n    {\n      [iterator]: () => {\n        const iteratorResults = [{ value, done: false }, { done: true }];\n        return {\n          next: () => {\n            return iteratorResults.shift();\n          },\n        };\n      },\n    } as any as Iterable<T>,\n    {\n      [Symbol.observable ?? '@@observable']: () => of(value),\n    } as any\n  ) as Observable<ObservableInput<T>>;\n\n/**\n * Used to signify no subscriptions took place to `expectSubscriptions` assertions.\n */\nexport const NO_SUBS: string[] = [];\n"
  },
  {
    "path": "packages/rxjs/spec/index-spec.ts",
    "content": "/** @prettier */\nimport * as index from 'rxjs';\nimport { expect } from 'chai';\n\ndescribe('index', () => {\n  it('should export Observable', () => {\n    expect(index.Observable).to.exist;\n    // Interfaces can be checked by creating a variable of that type\n    let operator: index.Operator<any, any>;\n  });\n\n  it('should export the Subject types', () => {\n    expect(index.Subject).to.exist;\n    expect(index.BehaviorSubject).to.exist;\n    expect(index.ReplaySubject).to.exist;\n    expect(index.AsyncSubject).to.exist;\n  });\n\n  it('should export the schedulers', () => {\n    expect(index.asapScheduler).to.exist;\n    expect(index.asyncScheduler).to.exist;\n    expect(index.queueScheduler).to.exist;\n    expect(index.animationFrameScheduler).to.exist;\n    expect(index.VirtualTimeScheduler).to.exist;\n    expect(index.VirtualAction).to.exist;\n  });\n\n  it('should export Subscription', () => {\n    expect(index.Subscription).to.exist;\n    expect(index.Subscriber).to.exist;\n  });\n\n  it('should export the appropriate utilities', () => {\n    expect(index.pipe).to.exist;\n    expect(index.noop).to.exist;\n    expect(index.identity).to.exist;\n  });\n\n  it('should export error types', () => {\n    expect(index.ArgumentOutOfRangeError).to.exist;\n    expect(index.EmptyError).to.exist;\n    expect(index.UnsubscriptionError).to.exist;\n    expect(index.TimeoutError).to.exist;\n  });\n\n  it('should export constants', () => {\n    expect(index.EMPTY).to.exist;\n    expect(index.NEVER).to.exist;\n  });\n\n  it('should export static observable creator functions', () => {\n    expect(index.bindCallback).to.exist;\n    expect(index.bindNodeCallback).to.exist;\n    expect(index.combineLatest).to.exist;\n    expect(index.concat).to.exist;\n    expect(index.defer).to.exist;\n    expect(index.forkJoin).to.exist;\n    expect(index.from).to.exist;\n    expect(index.fromEvent).to.exist;\n    expect(index.fromEventPattern).to.exist;\n    expect(index.generate).to.exist;\n    expect(index.iif).to.exist;\n    expect(index.interval).to.exist;\n    expect(index.merge).to.exist;\n    expect(index.of).to.exist;\n    expect(index.onErrorResumeNext).to.exist;\n    expect(index.race).to.exist;\n    expect(index.range).to.exist;\n    expect(index.throwError).to.exist;\n    expect(index.timer).to.exist;\n    expect(index.using).to.exist;\n    expect(index.zip).to.exist;\n  });\n\n  it('should export all of the operators', () => {\n    expect(index.audit).to.exist;\n    expect(index.auditTime).to.exist;\n    expect(index.buffer).to.exist;\n    expect(index.bufferCount).to.exist;\n    expect(index.bufferTime).to.exist;\n    expect(index.bufferToggle).to.exist;\n    expect(index.bufferWhen).to.exist;\n    expect(index.catchError).to.exist;\n    expect(index.combineLatestAll).to.exist;\n    expect(index.combineLatestWith).to.exist;\n    expect(index.concatAll).to.exist;\n    expect(index.concatMap).to.exist;\n    expect(index.concatMapTo).to.exist;\n    expect(index.concatWith).to.exist;\n    expect(index.connect).to.exist;\n    expect(index.count).to.exist;\n    expect(index.debounce).to.exist;\n    expect(index.debounceTime).to.exist;\n    expect(index.defaultIfEmpty).to.exist;\n    expect(index.delay).to.exist;\n    expect(index.delayWhen).to.exist;\n    expect(index.dematerialize).to.exist;\n    expect(index.distinct).to.exist;\n    expect(index.distinctUntilChanged).to.exist;\n    expect(index.distinctUntilKeyChanged).to.exist;\n    expect(index.elementAt).to.exist;\n    expect(index.endWith).to.exist;\n    expect(index.every).to.exist;\n    expect(index.exhaustAll).to.exist;\n    expect(index.exhaustMap).to.exist;\n    expect(index.expand).to.exist;\n    expect(index.filter).to.exist;\n    expect(index.finalize).to.exist;\n    expect(index.find).to.exist;\n    expect(index.findIndex).to.exist;\n    expect(index.first).to.exist;\n    expect(index.groupBy).to.exist;\n    expect(index.ignoreElements).to.exist;\n    expect(index.isEmpty).to.exist;\n    expect(index.last).to.exist;\n    expect(index.map).to.exist;\n    expect(index.mapTo).to.exist;\n    expect(index.materialize).to.exist;\n    expect(index.max).to.exist;\n    expect(index.mergeAll).to.exist;\n    expect(index.mergeMap).to.exist;\n    expect(index.mergeMapTo).to.exist;\n    expect(index.mergeScan).to.exist;\n    expect(index.mergeWith).to.exist;\n    expect(index.min).to.exist;\n    expect(index.observeOn).to.exist;\n    expect(index.pairwise).to.exist;\n    expect(index.raceWith).to.exist;\n    expect(index.reduce).to.exist;\n    expect(index.repeat).to.exist;\n    expect(index.repeatWhen).to.exist;\n    expect(index.retry).to.exist;\n    expect(index.retryWhen).to.exist;\n    expect(index.sample).to.exist;\n    expect(index.sampleTime).to.exist;\n    expect(index.scan).to.exist;\n    expect(index.sequenceEqual).to.exist;\n    expect(index.share).to.exist;\n    expect(index.shareReplay).to.exist;\n    expect(index.single).to.exist;\n    expect(index.skip).to.exist;\n    expect(index.skipLast).to.exist;\n    expect(index.skipUntil).to.exist;\n    expect(index.skipWhile).to.exist;\n    expect(index.startWith).to.exist;\n    expect(index.subscribeOn).to.exist;\n    expect(index.switchAll).to.exist;\n    expect(index.switchMap).to.exist;\n    expect(index.switchMapTo).to.exist;\n    expect(index.switchScan).to.exist;\n    expect(index.take).to.exist;\n    expect(index.takeLast).to.exist;\n    expect(index.takeUntil).to.exist;\n    expect(index.takeWhile).to.exist;\n    expect(index.tap).to.exist;\n    expect(index.throttle).to.exist;\n    expect(index.throttleTime).to.exist;\n    expect(index.throwIfEmpty).to.exist;\n    expect(index.timeInterval).to.exist;\n    expect(index.timeout).to.exist;\n    expect(index.timeoutWith).to.exist;\n    expect(index.timestamp).to.exist;\n    expect(index.toArray).to.exist;\n    expect(index.window).to.exist;\n    expect(index.windowCount).to.exist;\n    expect(index.windowTime).to.exist;\n    expect(index.windowToggle).to.exist;\n    expect(index.windowWhen).to.exist;\n    expect(index.withLatestFrom).to.exist;\n    expect(index.zipAll).to.exist;\n    expect(index.zipWith).to.exist;\n  });\n\n  it('should expose configuration', () => {\n    expect(index.config).to.exist;\n  });\n});\n"
  },
  {
    "path": "packages/rxjs/spec/lastValueFrom-spec.ts",
    "content": "import { interval, lastValueFrom, EMPTY, EmptyError, throwError, of } from 'rxjs';\nimport { expect } from 'chai';\nimport { finalize, take } from 'rxjs/operators';\n\ndescribe('lastValueFrom', () => {\n  it('should emit the last value as a promise', async () => {\n    let finalized = false;\n    const source = interval(2).pipe(\n      take(10),\n      finalize(() => (finalized = true))\n    );\n    const result = await lastValueFrom(source);\n    expect(result).to.equal(9);\n    expect(finalized).to.be.true;\n  });\n\n  it('should support a default value', async () => {\n    const source = EMPTY;\n    const result = await lastValueFrom(source, { defaultValue: 0 });\n    expect(result).to.equal(0);\n  });\n\n  it('should support an undefined config', async () => {\n    const source = EMPTY;\n    let error: any = null;\n    try {\n      await lastValueFrom(source, undefined as any);\n    } catch (err) {\n      error = err;\n    }\n    expect(error).to.be.an.instanceOf(EmptyError);\n  });\n\n  it('should error for empty observables', async () => {\n    const source = EMPTY;\n    let error: any = null;\n    try {\n      await lastValueFrom(source);\n    } catch (err) {\n      error = err;\n    }\n    expect(error).to.be.an.instanceOf(EmptyError);\n  });\n\n  it('should error for errored observables', async () => {\n    const source = throwError(() => new Error('blorp!'));\n    let error: any = null;\n    try {\n      await lastValueFrom(source);\n    } catch (err) {\n      error = err;\n    }\n    expect(error).to.be.an.instanceOf(Error);\n    expect(error.message).to.equal('blorp!');\n  });\n\n  it('should work with a synchronous observable', async () => {\n    let finalized = false;\n    const source = of('apples', 'bananas').pipe(finalize(() => (finalized = true)));\n    const result = await lastValueFrom(source);\n    expect(result).to.equal('bananas');\n    expect(finalized).to.be.true;\n  });\n});\n"
  },
  {
    "path": "packages/rxjs/spec/module-test-spec.mjs",
    "content": "/* Test file to ensure rxjs can be loaded from esm\n\nhttps://github.com/ReactiveX/rxjs/pull/6192\nIf this fails node will error when running this with an error like\nnode:internal/process/esm_loader:74\n    internalBinding('errors').triggerUncaughtException(\n*/\nimport {Observable} from 'rxjs';\nimport * as o from 'rxjs/operators';\nimport * as a from 'rxjs/ajax';\nimport * as f from 'rxjs/fetch';\nimport * as t from 'rxjs/testing';\nimport * as w from 'rxjs/webSocket';\n"
  },
  {
    "path": "packages/rxjs/spec/observables/bindCallback-spec.ts",
    "content": "/** @prettier */\nimport { expect } from 'chai';\nimport * as sinon from 'sinon';\nimport { bindCallback } from 'rxjs';\nimport { TestScheduler } from 'rxjs/testing';\nimport { observableMatcher } from '../helpers/observableMatcher';\n\n/** @test {bindCallback} */\ndescribe('bindCallback', () => {\n  describe('when not scheduled', () => {\n    it('should emit undefined from a callback without arguments', () => {\n      function callback(cb: () => void) {\n        cb();\n      }\n      const boundCallback = bindCallback(callback);\n      const results: Array<string | number> = [];\n\n      boundCallback().subscribe({\n        next: (x: any) => {\n          results.push(typeof x);\n        },\n        complete: () => {\n          results.push('done');\n        },\n      });\n\n      expect(results).to.deep.equal(['undefined', 'done']);\n    });\n\n    it('should support a resultSelector', () => {\n      function callback(datum: number, cb: (v: unknown) => void) {\n        cb(datum);\n      }\n\n      const boundCallback = bindCallback(callback, (datum: any) => datum + 1);\n\n      const results: Array<string | number> = [];\n\n      boundCallback(42).subscribe({\n        next(value) {\n          results.push(value);\n        },\n        complete() {\n          results.push('done');\n        },\n      });\n\n      expect(results).to.deep.equal([43, 'done']);\n    });\n\n    it('should support a resultSelector if its void', () => {\n      function callback(datum: number, cb: (v: unknown) => void) {\n        cb(datum);\n      }\n\n      const boundCallback = bindCallback(callback, void 0);\n\n      const results: Array<string | number> = [];\n\n      boundCallback(42).subscribe({\n        next(value: any) {\n          results.push(value);\n        },\n        complete() {\n          results.push('done');\n        },\n      });\n\n      expect(results).to.deep.equal([42, 'done']);\n    });\n\n    it('should emit one value from a callback', () => {\n      function callback(datum: number, cb: (result: number) => void) {\n        cb(datum);\n      }\n      const boundCallback = bindCallback(callback);\n      const results: Array<string | number> = [];\n\n      boundCallback(42).subscribe({\n        next: (x) => {\n          results.push(x);\n        },\n        complete: () => {\n          results.push('done');\n        },\n      });\n\n      expect(results).to.deep.equal([42, 'done']);\n    });\n\n    it('should set callback function context to context of returned function', () => {\n      function callback(this: any, cb: (arg: number) => void) {\n        cb(this.datum);\n      }\n\n      const boundCallback = bindCallback(callback);\n      const results: Array<string | number> = [];\n\n      boundCallback.apply({ datum: 5 }).subscribe({ next: (x: number) => results.push(x), complete: () => results.push('done') });\n\n      expect(results).to.deep.equal([5, 'done']);\n    });\n\n    it('should not emit, throw or complete if immediately unsubscribed', (done) => {\n      const nextSpy = sinon.spy();\n      const throwSpy = sinon.spy();\n      const completeSpy = sinon.spy();\n      let timeout: ReturnType<typeof setTimeout>;\n      function callback(datum: number, cb: (v: unknown) => void) {\n        // Need to cb async in order for the unsub to trigger\n        timeout = setTimeout(() => {\n          cb(datum);\n        }, 0);\n      }\n      const subscription = bindCallback(callback)(42).subscribe({ next: nextSpy, error: throwSpy, complete: completeSpy });\n      subscription.unsubscribe();\n\n      setTimeout(() => {\n        expect(nextSpy).not.have.been.called;\n        expect(throwSpy).not.have.been.called;\n        expect(completeSpy).not.have.been.called;\n\n        clearTimeout(timeout);\n        done();\n      });\n    });\n\n    it('should create a separate internal subject for each call', () => {\n      function callback(datum: number, cb: (result: number) => void) {\n        cb(datum);\n      }\n      const boundCallback = bindCallback(callback);\n      const results: Array<string | number> = [];\n\n      boundCallback(42).subscribe({\n        next: (x) => {\n          results.push(x);\n        },\n        complete: () => {\n          results.push('done');\n        },\n      });\n      boundCallback(54).subscribe({\n        next: (x) => {\n          results.push(x);\n        },\n        complete: () => {\n          results.push('done');\n        },\n      });\n\n      expect(results).to.deep.equal([42, 'done', 54, 'done']);\n    });\n  });\n\n  describe('when scheduled', () => {\n    let rxTestScheduler: TestScheduler;\n\n    beforeEach(() => {\n      rxTestScheduler = new TestScheduler(observableMatcher);\n    });\n\n    it('should emit undefined from a callback without arguments', () => {\n      function callback(cb: () => void) {\n        cb();\n      }\n      const boundCallback = bindCallback(callback, rxTestScheduler);\n      const results: Array<string | number> = [];\n\n      boundCallback().subscribe({\n        next: (x) => {\n          results.push(typeof x);\n        },\n        complete: () => {\n          results.push('done');\n        },\n      });\n\n      rxTestScheduler.flush();\n\n      expect(results).to.deep.equal(['undefined', 'done']);\n    });\n\n    it('should emit one value from a callback', () => {\n      function callback(datum: number, cb: (result: number) => void) {\n        cb(datum);\n      }\n      const boundCallback = bindCallback(callback, rxTestScheduler);\n      const results: Array<string | number> = [];\n\n      boundCallback(42).subscribe({\n        next: (x) => {\n          results.push(x);\n        },\n        complete: () => {\n          results.push('done');\n        },\n      });\n\n      rxTestScheduler.flush();\n\n      expect(results).to.deep.equal([42, 'done']);\n    });\n\n    it('should set callback function context to context of returned function', () => {\n      function callback(this: { datum: number }, cb: (num: number) => void) {\n        cb(this.datum);\n      }\n\n      const boundCallback = bindCallback(callback, rxTestScheduler);\n      const results: Array<string | number> = [];\n\n      boundCallback.apply({ datum: 5 }).subscribe({ next: (x: number) => results.push(x), complete: () => results.push('done') });\n\n      rxTestScheduler.flush();\n\n      expect(results).to.deep.equal([5, 'done']);\n    });\n\n    it('should error if callback throws', () => {\n      const expected = new Error('haha no callback for you');\n      function callback(datum: number, cb: () => void): never {\n        throw expected;\n      }\n      const boundCallback = bindCallback(callback, rxTestScheduler);\n\n      boundCallback(42).subscribe({\n        next: (x) => {\n          throw new Error('should not next');\n        },\n        error: (err: any) => {\n          expect(err).to.equal(expected);\n        },\n        complete: () => {\n          throw new Error('should not complete');\n        },\n      });\n\n      rxTestScheduler.flush();\n    });\n\n    it('should pass multiple inner arguments as an array', () => {\n      function callback(datum: number, cb: (a: number, b: number, c: number, d: number) => void) {\n        cb(datum, 1, 2, 3);\n      }\n      const boundCallback = bindCallback(callback, rxTestScheduler);\n      const results: Array<string | number[]> = [];\n\n      boundCallback(42).subscribe({\n        next: (x) => {\n          results.push(x);\n        },\n        complete: () => {\n          results.push('done');\n        },\n      });\n\n      rxTestScheduler.flush();\n\n      expect(results).to.deep.equal([[42, 1, 2, 3], 'done']);\n    });\n\n    it('should cache value for next subscription and not call callbackFunc again', () => {\n      let calls = 0;\n      function callback(datum: number, cb: (x: number) => void) {\n        calls++;\n        cb(datum);\n      }\n      const boundCallback = bindCallback(callback, rxTestScheduler);\n      const results1: Array<number | string> = [];\n      const results2: Array<number | string> = [];\n\n      const source = boundCallback(42);\n\n      source.subscribe({\n        next: (x) => {\n          results1.push(x);\n        },\n        complete: () => {\n          results1.push('done');\n        },\n      });\n\n      source.subscribe({\n        next: (x) => {\n          results2.push(x);\n        },\n        complete: () => {\n          results2.push('done');\n        },\n      });\n\n      rxTestScheduler.flush();\n\n      expect(calls).to.equal(1);\n      expect(results1).to.deep.equal([42, 'done']);\n      expect(results2).to.deep.equal([42, 'done']);\n    });\n\n    it('should not even call the callbackFn if scheduled and immediately unsubscribed', () => {\n      let calls = 0;\n      function callback(datum: number, cb: (v: unknown) => void) {\n        calls++;\n        cb(datum);\n      }\n      const boundCallback = bindCallback(callback, rxTestScheduler);\n      const results1: Array<number | string> = [];\n\n      const source = boundCallback(42);\n\n      const subscription = source.subscribe({\n        next: (x: any) => {\n          results1.push(x);\n        },\n        complete: () => {\n          results1.push('done');\n        },\n      });\n\n      subscription.unsubscribe();\n\n      rxTestScheduler.flush();\n\n      expect(calls).to.equal(0);\n    });\n  });\n\n  it('should emit post-callback errors', () => {\n    function badFunction(callback: (answer: number) => void): void {\n      callback(42);\n      throw 'kaboom';\n    }\n    let receivedError: any;\n\n    bindCallback(badFunction)().subscribe({\n      error: (err) => (receivedError = err),\n    });\n\n    expect(receivedError).to.equal('kaboom');\n  });\n});\n"
  },
  {
    "path": "packages/rxjs/spec/observables/bindNodeCallback-spec.ts",
    "content": "/** @prettier */\nimport { expect } from 'chai';\nimport * as sinon from 'sinon';\nimport { bindNodeCallback } from 'rxjs';\nimport { TestScheduler } from 'rxjs/testing';\nimport { observableMatcher } from '../helpers/observableMatcher';\n\n/** @test {bindNodeCallback} */\ndescribe('bindNodeCallback', () => {\n  let rxTestScheduler: TestScheduler;\n\n  beforeEach(() => {\n    rxTestScheduler = new TestScheduler(observableMatcher);\n  });\n\n  describe('when not scheduled', () => {\n    it('should emit undefined when callback is called without success arguments', () => {\n      function callback(cb: (v: unknown) => void) {\n        cb(null);\n      }\n\n      const boundCallback = bindNodeCallback(callback);\n      const results: Array<number | string> = [];\n\n      boundCallback().subscribe({\n        next: (x: any) => {\n          results.push(typeof x);\n        },\n        complete: () => {\n          results.push('done');\n        },\n      });\n\n      expect(results).to.deep.equal(['undefined', 'done']);\n    });\n\n    it('should a resultSelector', () => {\n      function callback(cb: (err: any, n: number) => any) {\n        cb(null, 42);\n      }\n\n      const boundCallback = bindNodeCallback(callback, (x: number) => x + 1);\n      const results: Array<number | string> = [];\n\n      boundCallback().subscribe({\n        next: (x) => {\n          results.push(x);\n        },\n        complete: () => {\n          results.push('done');\n        },\n      });\n\n      expect(results).to.deep.equal([43, 'done']);\n    });\n\n    it('should emit one value from a callback', () => {\n      function callback(datum: number, cb: (err: any, n: number) => void) {\n        cb(null, datum);\n      }\n      const boundCallback = bindNodeCallback(callback);\n      const results: Array<number | string> = [];\n\n      boundCallback(42).subscribe({\n        next: (x) => {\n          results.push(x);\n        },\n        complete: () => {\n          results.push('done');\n        },\n      });\n\n      expect(results).to.deep.equal([42, 'done']);\n    });\n\n    it('should set context of callback to context of boundCallback', () => {\n      function callback(this: { datum: number }, cb: (err: any, n: number) => void) {\n        cb(null, this.datum);\n      }\n      const boundCallback = bindNodeCallback(callback);\n      const results: Array<number | string> = [];\n\n      boundCallback.call({ datum: 42 }).subscribe({ next: (x: number) => results.push(x), complete: () => results.push('done') });\n\n      expect(results).to.deep.equal([42, 'done']);\n    });\n\n    it('should raise error from callback', () => {\n      const error = new Error();\n\n      function callback(cb: (v: unknown) => void) {\n        cb(error);\n      }\n\n      const boundCallback = bindNodeCallback(callback);\n      const results: Array<number | string> = [];\n\n      boundCallback().subscribe({\n        next: () => {\n          throw new Error('should not next');\n        },\n        error: (err: any) => {\n          results.push(err);\n        },\n        complete: () => {\n          throw new Error('should not complete');\n        },\n      });\n\n      expect(results).to.deep.equal([error]);\n    });\n\n    it('should not emit, throw or complete if immediately unsubscribed', (done) => {\n      const nextSpy = sinon.spy();\n      const throwSpy = sinon.spy();\n      const completeSpy = sinon.spy();\n      let timeout: ReturnType<typeof setTimeout>;\n      function callback(datum: number, cb: (err: any, n: number) => void) {\n        // Need to cb async in order for the unsub to trigger\n        timeout = setTimeout(() => {\n          cb(null, datum);\n        }, 0);\n      }\n      const subscription = bindNodeCallback(callback)(42).subscribe({ next: nextSpy, error: throwSpy, complete: completeSpy });\n      subscription.unsubscribe();\n\n      setTimeout(() => {\n        expect(nextSpy).not.have.been.called;\n        expect(throwSpy).not.have.been.called;\n        expect(completeSpy).not.have.been.called;\n\n        clearTimeout(timeout);\n        done();\n      });\n    });\n\n    it('should create a separate internal subject for each call', () => {\n      function callback(datum: number, cb: (err: any, n: number) => void) {\n        cb(null, datum);\n      }\n      const boundCallback = bindNodeCallback(callback);\n      const results: Array<number | string> = [];\n\n      boundCallback(42).subscribe({\n        next: (x) => {\n          results.push(x);\n        },\n        complete: () => {\n          results.push('done');\n        },\n      });\n      boundCallback(54).subscribe({\n        next: (x) => {\n          results.push(x);\n        },\n        complete: () => {\n          results.push('done');\n        },\n      });\n\n      expect(results).to.deep.equal([42, 'done', 54, 'done']);\n    });\n  });\n\n  describe('when scheduled', () => {\n    it('should emit undefined when callback is called without success arguments', () => {\n      function callback(cb: (v: unknown) => void) {\n        cb(null);\n      }\n\n      const boundCallback = bindNodeCallback(callback, rxTestScheduler);\n      const results: Array<number | string> = [];\n\n      boundCallback().subscribe({\n        next: (x: any) => {\n          results.push(typeof x);\n        },\n        complete: () => {\n          results.push('done');\n        },\n      });\n\n      rxTestScheduler.flush();\n\n      expect(results).to.deep.equal(['undefined', 'done']);\n    });\n\n    it('should emit one value from a callback', () => {\n      function callback(datum: number, cb: (err: any, n: number) => void) {\n        cb(null, datum);\n      }\n      const boundCallback = bindNodeCallback(callback, rxTestScheduler);\n      const results: Array<number | string> = [];\n\n      boundCallback(42).subscribe({\n        next: (x) => {\n          results.push(x);\n        },\n        complete: () => {\n          results.push('done');\n        },\n      });\n\n      rxTestScheduler.flush();\n\n      expect(results).to.deep.equal([42, 'done']);\n    });\n\n    it('should set context of callback to context of boundCallback', () => {\n      function callback(this: { datum: number }, cb: (err: any, n: number) => void) {\n        cb(null, this.datum);\n      }\n      const boundCallback = bindNodeCallback(callback, rxTestScheduler);\n      const results: Array<number | string> = [];\n\n      boundCallback.call({ datum: 42 }).subscribe({ next: (x: number) => results.push(x), complete: () => results.push('done') });\n\n      rxTestScheduler.flush();\n\n      expect(results).to.deep.equal([42, 'done']);\n    });\n\n    it('should error if callback throws', () => {\n      const expected = new Error('haha no callback for you');\n      function callback(datum: number, cb: (err: any, n: number) => void) {\n        throw expected;\n      }\n      const boundCallback = bindNodeCallback(callback, rxTestScheduler);\n\n      boundCallback(42).subscribe({\n        next: (x) => {\n          throw new Error('should not next');\n        },\n        error: (err: any) => {\n          expect(err).to.equal(expected);\n        },\n        complete: () => {\n          throw new Error('should not complete');\n        },\n      });\n\n      rxTestScheduler.flush();\n    });\n\n    it('should raise error from callback', () => {\n      const error = new Error();\n\n      function callback(cb: (v: unknown) => void) {\n        cb(error);\n      }\n\n      const boundCallback = bindNodeCallback(callback, rxTestScheduler);\n      const results: Array<number | string> = [];\n\n      boundCallback().subscribe({\n        next: () => {\n          throw new Error('should not next');\n        },\n        error: (err: any) => {\n          results.push(err);\n        },\n        complete: () => {\n          throw new Error('should not complete');\n        },\n      });\n\n      rxTestScheduler.flush();\n\n      expect(results).to.deep.equal([error]);\n    });\n  });\n\n  it('should pass multiple inner arguments as an array', () => {\n    function callback(datum: number, cb: (err: any, a: number, b: number, c: number, d: number) => void) {\n      cb(null, datum, 1, 2, 3);\n    }\n    const boundCallback = bindNodeCallback(callback, rxTestScheduler);\n    const results: Array<number[] | string> = [];\n\n    boundCallback(42).subscribe({\n      next: (x) => {\n        results.push(x);\n      },\n      complete: () => {\n        results.push('done');\n      },\n    });\n\n    rxTestScheduler.flush();\n\n    expect(results).to.deep.equal([[42, 1, 2, 3], 'done']);\n  });\n\n  it('should cache value for next subscription and not call callbackFunc again', () => {\n    let calls = 0;\n    function callback(datum: number, cb: (err: any, n: number) => void) {\n      calls++;\n      cb(null, datum);\n    }\n    const boundCallback = bindNodeCallback(callback, rxTestScheduler);\n    const results1: Array<number | string> = [];\n    const results2: Array<number | string> = [];\n\n    const source = boundCallback(42);\n\n    source.subscribe({\n      next: (x) => {\n        results1.push(x);\n      },\n      complete: () => {\n        results1.push('done');\n      },\n    });\n\n    source.subscribe({\n      next: (x) => {\n        results2.push(x);\n      },\n      complete: () => {\n        results2.push('done');\n      },\n    });\n\n    rxTestScheduler.flush();\n\n    expect(calls).to.equal(1);\n    expect(results1).to.deep.equal([42, 'done']);\n    expect(results2).to.deep.equal([42, 'done']);\n  });\n\n  it('should emit post callback errors', () => {\n    function badFunction(callback: (error: Error, answer: number) => void): void {\n      callback(null as any, 42);\n      throw 'kaboom';\n    }\n    let receivedError: any;\n    bindNodeCallback(badFunction)().subscribe({\n      error: (err) => (receivedError = err),\n    });\n\n    expect(receivedError).to.equal('kaboom');\n  });\n\n  it('should not call the function if subscribed twice in a row before it resolves', () => {\n    let executeCallback: any;\n    let calls = 0;\n    function myFunc(callback: (error: any, result: any) => void) {\n      calls++;\n      if (calls > 1) {\n        throw new Error('too many calls to myFunc');\n      }\n      executeCallback = callback;\n    }\n\n    const source$ = bindNodeCallback(myFunc)();\n\n    let result1: any;\n    let result2: any;\n    source$.subscribe((value) => (result1 = value));\n    source$.subscribe((value) => (result2 = value));\n\n    expect(calls).to.equal(1);\n    executeCallback(null, 'test');\n    expect(result1).to.equal('test');\n    expect(result2).to.equal('test');\n    expect(calls).to.equal(1);\n  });\n\n  it('should not even call the callbackFn if scheduled and immediately unsubscribed', () => {\n    let calls = 0;\n    function callback(datum: number, cb: (a: unknown, b: number) => void) {\n      calls++;\n      cb(null, datum);\n    }\n    const boundCallback = bindNodeCallback(callback, rxTestScheduler);\n    const results1: Array<number | string> = [];\n\n    const source = boundCallback(42);\n\n    const subscription = source.subscribe({\n      next: (x: any) => {\n        results1.push(x);\n      },\n      complete: () => {\n        results1.push('done');\n      },\n    });\n\n    subscription.unsubscribe();\n\n    rxTestScheduler.flush();\n\n    expect(calls).to.equal(0);\n  });\n});\n"
  },
  {
    "path": "packages/rxjs/spec/observables/combineLatest-spec.ts",
    "content": "import { expect } from 'chai';\nimport { combineLatest, of } from 'rxjs';\nimport { map, mergeMap } from 'rxjs/operators';\nimport { TestScheduler } from 'rxjs/testing';\nimport { observableMatcher } from '../helpers/observableMatcher';\n\n/** @test {combineLatest} */\ndescribe('static combineLatest', () => {\n  let rxTestScheduler: TestScheduler;\n\n  beforeEach(() => {\n    rxTestScheduler = new TestScheduler(observableMatcher);\n  });\n\n  it('should return EMPTY if passed an empty array as the only argument', () => {\n    const results: string[] = [];\n    combineLatest([]).subscribe({\n      next: () => {\n        throw new Error('should not emit');\n      },\n      complete: () => {\n        results.push('done');\n      },\n    });\n\n    expect(results).to.deep.equal(['done']);\n  });\n\n  it('should return EMPTY if passed an empty POJO as the only argument', () => {\n    const results: string[] = [];\n    combineLatest({}).subscribe({\n      next: () => {\n        throw new Error('should not emit');\n      },\n      complete: () => {\n        results.push('done');\n      },\n    });\n\n    expect(results).to.deep.equal(['done']);\n  });\n\n  it('should accept array of observables', () => {\n    rxTestScheduler.run(({ hot, expectObservable }) => {\n      const firstSource = hot(' ----a----b----c----|');\n      const secondSource = hot('--d--e--f--g--|');\n      const expected = '        ----uv--wx-y--z----|';\n\n      const combined = combineLatest([firstSource, secondSource], (a: string, b: string) => '' + a + b);\n\n      expectObservable(combined).toBe(expected, { u: 'ad', v: 'ae', w: 'af', x: 'bf', y: 'bg', z: 'cg' });\n    });\n  });\n\n  it('should accept a dictionary of observables', () => {\n    rxTestScheduler.run(({ hot, expectObservable }) => {\n      const firstSource = hot('----a----b----c----|');\n      const secondSource = hot('--d--e--f--g--|');\n      const expected = '        ----uv--wx-y--z----|';\n\n      const combined = combineLatest({ a: firstSource, b: secondSource }).pipe(map(({ a, b }) => '' + a + b));\n\n      expectObservable(combined).toBe(expected, { u: 'ad', v: 'ae', w: 'af', x: 'bf', y: 'bg', z: 'cg' });\n    });\n  });\n\n  it('should work with two nevers', () => {\n    rxTestScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' -');\n      const e1subs = '  ^';\n      const e2 = cold(' -');\n      const e2subs = '  ^';\n      const expected = '-';\n\n      const result = combineLatest([e1, e2], (x, y) => x + y);\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should work with never and empty', () => {\n    rxTestScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' -');\n      const e1subs = '  ^';\n      const e2 = cold(' |');\n      const e2subs = '  (^!)';\n      const expected = '-';\n\n      const result = combineLatest([e1, e2], (x, y) => x + y);\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should work with empty and never', () => {\n    rxTestScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' |');\n      const e1subs = '  (^!)';\n      const e2 = cold(' -');\n      const e2subs = '  ^';\n      const expected = '-';\n\n      const result = combineLatest([e1, e2], (x, y) => x + y);\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should work with empty and empty', () => {\n    rxTestScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' |');\n      const e1subs = '  (^!)';\n      const e2 = cold(' |');\n      const e2subs = '  (^!)';\n      const expected = '|';\n\n      const result = combineLatest([e1, e2], (x, y) => x + y);\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should work with hot-empty and hot-single', () => {\n    rxTestScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const values = {\n        a: 1,\n        b: 2,\n        c: 3,\n        r: 1 + 3, //a + c\n      };\n      const e1 = hot('-a-^-|', values);\n      const e1subs = '   ^-!';\n      const e2 = hot('-b-^-c-|', values);\n      const e2subs = '   ^---!';\n      const expected = ' ----|';\n\n      const result = combineLatest([e1, e2], (x, y) => x + y);\n\n      expectObservable(result).toBe(expected, values);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should work with hot-single and hot-empty', () => {\n    rxTestScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const values = {\n        a: 1,\n        b: 2,\n        c: 3,\n      };\n      const e1 = hot('-a-^-|', values);\n      const e1subs = '   ^-!';\n      const e2 = hot('-b-^-c-|', values);\n      const e2subs = '   ^---!';\n      const expected = ' ----|';\n\n      const result = combineLatest([e2, e1], (x, y) => x + y);\n\n      expectObservable(result).toBe(expected, values);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should work with hot-single and never', () => {\n    rxTestScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const values = {\n        a: 1,\n      };\n      const e1 = hot('-a-^-|', values);\n      const e1subs = '   ^-!';\n      const e2 = hot('------', values); //never\n      const e2subs = '   ^  ';\n      const expected = ' -'; //never\n\n      const result = combineLatest([e1, e2], (x, y) => x + y);\n\n      expectObservable(result).toBe(expected, values);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should work with never and hot-single', () => {\n    rxTestScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const values = {\n        a: 1,\n        b: 2,\n      };\n      const e1 = hot('--------', values); //never\n      const e1subs = '   ^----';\n      const e2 = hot('-a-^-b-|', values);\n      const e2subs = '   ^---!';\n      const expected = ' -----'; //never\n\n      const result = combineLatest([e1, e2], (x, y) => x + y);\n\n      expectObservable(result).toBe(expected, values);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should work with hot and hot', () => {\n    rxTestScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('--a--^--b--c--|', { a: 'a', b: 'b', c: 'c' });\n      const e1subs = '     ^--------!';\n      const e2 = hot('---e-^---f--g--|', { e: 'e', f: 'f', g: 'g' });\n      const e2subs = '     ^---------!';\n      const expected = '   ----x-yz--|';\n\n      const result = combineLatest([e1, e2], (x, y) => x + y);\n\n      expectObservable(result).toBe(expected, { x: 'bf', y: 'cf', z: 'cg' });\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should work with empty and error', () => {\n    rxTestScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  ----------|'); //empty\n      const e1subs = '  ^-----!';\n      const e2 = hot('  ------#', undefined, 'shazbot!'); //error\n      const e2subs = '  ^-----!';\n      const expected = '------#';\n\n      const result = combineLatest([e1, e2], (x, y) => x + y);\n\n      expectObservable(result).toBe(expected, null, 'shazbot!');\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should work with error and empty', () => {\n    rxTestScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('--^---#', undefined, 'too bad, honk'); //error\n      const e1subs = '  ^---!';\n      const e2 = hot('--^--------|'); //empty\n      const e2subs = '  ^---!';\n      const expected = '----#';\n\n      const result = combineLatest([e1, e2], (x, y) => x + y);\n\n      expectObservable(result).toBe(expected, null, 'too bad, honk');\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should work with hot and throw', () => {\n    rxTestScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('-a-^--b--c--|', { a: 1, b: 2, c: 3 });\n      const e1subs = '   ^-!';\n      const e2 = hot('---^-#', undefined, 'bazinga');\n      const e2subs = '   ^-!';\n      const expected = ' --#';\n\n      const result = combineLatest([e1, e2], (x, y) => x + y);\n\n      expectObservable(result).toBe(expected, null, 'bazinga');\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should work with throw and hot', () => {\n    rxTestScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('---^-#', undefined, 'bazinga');\n      const e1subs = '   ^-!';\n      const e2 = hot('-a-^--b--c--|', { a: 1, b: 2, c: 3 });\n      const e2subs = '   ^-!';\n      const expected = ' --#';\n\n      const result = combineLatest([e1, e2], (x, y) => x + y);\n\n      expectObservable(result).toBe(expected, null, 'bazinga');\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should work with throw and throw', () => {\n    rxTestScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('---^----#', undefined, 'jenga');\n      const e1subs = '   ^-!';\n      const e2 = hot('---^-#', undefined, 'bazinga');\n      const e2subs = '   ^-!';\n      const expected = ' --#';\n\n      const result = combineLatest([e1, e2], (x, y) => x + y);\n\n      expectObservable(result).toBe(expected, null, 'bazinga');\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should work with error and throw', () => {\n    rxTestScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('-a-^--b--#', { a: 1, b: 2 }, 'wokka wokka');\n      const e1subs = '   ^-!';\n      const e2 = hot('---^-#', undefined, 'flurp');\n      const e2subs = '   ^-!';\n      const expected = ' --#';\n\n      const result = combineLatest([e1, e2], (x, y) => x + y);\n\n      expectObservable(result).toBe(expected, null, 'flurp');\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should work with throw and error', () => {\n    rxTestScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('---^-#', undefined, 'flurp');\n      const e1subs = '   ^-!';\n      const e2 = hot('-a-^--b--#', { a: 1, b: 2 }, 'wokka wokka');\n      const e2subs = '   ^-!';\n      const expected = ' --#';\n\n      const result = combineLatest([e1, e2], (x, y) => x + y);\n\n      expectObservable(result).toBe(expected, null, 'flurp');\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should work with never and throw', () => {\n    rxTestScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('---^-----------');\n      const e1subs = '   ^-----!';\n      const e2 = hot('---^-----#', undefined, 'wokka wokka');\n      const e2subs = '   ^-----!';\n      const expected = ' ------#';\n\n      const result = combineLatest([e1, e2], (x, y) => x + y);\n\n      expectObservable(result).toBe(expected, null, 'wokka wokka');\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should work with throw and never', () => {\n    rxTestScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('---^----#', undefined, 'wokka wokka');\n      const e1subs = '   ^----!';\n      const e2 = hot('---^-----------');\n      const e2subs = '   ^----!';\n      const expected = ' -----#';\n\n      const result = combineLatest([e1, e2], (x, y) => x + y);\n\n      expectObservable(result).toBe(expected, null, 'wokka wokka');\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should work with some and throw', () => {\n    rxTestScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('---^----a---b--|', { a: 1, b: 2 });\n      const e1subs = '   ^--!';\n      const e2 = hot('---^--#', undefined, 'wokka wokka');\n      const e2subs = '   ^--!';\n      const expected = ' ---#';\n\n      const result = combineLatest([e1, e2], (x, y) => x + y);\n\n      expectObservable(result).toBe(expected, { a: 1, b: 2 }, 'wokka wokka');\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should work with throw and some', () => {\n    rxTestScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('---^--#', undefined, 'wokka wokka');\n      const e1subs = '   ^--!';\n      const e2 = hot('---^----a---b--|', { a: 1, b: 2 });\n      const e2subs = '   ^--!';\n      const expected = ' ---#';\n\n      const result = combineLatest([e1, e2], (x, y) => x + y);\n\n      expectObservable(result).toBe(expected, { a: 1, b: 2 }, 'wokka wokka');\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should handle throw after complete left', () => {\n    rxTestScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const left = hot(' --a--^--b---|', { a: 1, b: 2 });\n      const leftSubs = '      ^------!';\n      const right = hot('-----^--------#', undefined, 'bad things');\n      const rightSubs = '     ^--------!';\n      const expected = '      ---------#';\n\n      const result = combineLatest([left, right], (x, y) => x + y);\n\n      expectObservable(result).toBe(expected, null, 'bad things');\n      expectSubscriptions(left.subscriptions).toBe(leftSubs);\n      expectSubscriptions(right.subscriptions).toBe(rightSubs);\n    });\n  });\n\n  it('should handle throw after complete right', () => {\n    rxTestScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const left = hot(' -----^--------#', undefined, 'bad things');\n      const leftSubs = '      ^--------!';\n      const right = hot('--a--^--b---|', { a: 1, b: 2 });\n      const rightSubs = '     ^------!';\n      const expected = '      ---------#';\n\n      const result = combineLatest([left, right], (x, y) => x + y);\n\n      expectObservable(result).toBe(expected, null, 'bad things');\n      expectSubscriptions(left.subscriptions).toBe(leftSubs);\n      expectSubscriptions(right.subscriptions).toBe(rightSubs);\n    });\n  });\n\n  it('should handle interleaved with tail', () => {\n    rxTestScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('-a--^--b---c---|', { a: 'a', b: 'b', c: 'c' });\n      const e1subs = '    ^----------!';\n      const e2 = hot('--d-^----e---f--|', { d: 'd', e: 'e', f: 'f' });\n      const e2subs = '    ^-----------!';\n      const expected = '  -----x-y-z--|';\n\n      const result = combineLatest([e1, e2], (x, y) => x + y);\n\n      expectObservable(result).toBe(expected, { x: 'be', y: 'ce', z: 'cf' });\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should handle two consecutive hot observables', () => {\n    rxTestScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('--a--^--b--c--|', { a: 'a', b: 'b', c: 'c' });\n      const e1subs = '     ^--------!';\n      const e2 = hot('-----^----------d--e--f--|', { d: 'd', e: 'e', f: 'f' });\n      const e2subs = '     ^-------------------!';\n      const expected = '   -----------x--y--z--|';\n\n      const result = combineLatest([e1, e2], (x, y) => x + y);\n\n      expectObservable(result).toBe(expected, { x: 'cd', y: 'ce', z: 'cf' });\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should handle two consecutive hot observables with error left', () => {\n    rxTestScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const left = hot(' --a--^--b--c--#', { a: 'a', b: 'b', c: 'c' }, 'jenga');\n      const leftSubs = '      ^--------!';\n      const right = hot('-----^----------d--e--f--|', { d: 'd', e: 'e', f: 'f' });\n      const rightSubs = '     ^--------!';\n      const expected = '      ---------#';\n\n      const result = combineLatest([left, right], (x, y) => x + y);\n\n      expectObservable(result).toBe(expected, null, 'jenga');\n      expectSubscriptions(left.subscriptions).toBe(leftSubs);\n      expectSubscriptions(right.subscriptions).toBe(rightSubs);\n    });\n  });\n\n  it('should handle two consecutive hot observables with error right', () => {\n    rxTestScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const left = hot(' --a--^--b--c--|', { a: 'a', b: 'b', c: 'c' });\n      const leftSubs = '      ^--------!';\n      const right = hot('-----^----------d--e--f--#', { d: 'd', e: 'e', f: 'f' }, 'dun dun dun');\n      const rightSubs = '     ^-------------------!';\n      const expected = '      -----------x--y--z--#';\n\n      const result = combineLatest([left, right], (x, y) => x + y);\n\n      expectObservable(result).toBe(expected, { x: 'cd', y: 'ce', z: 'cf' }, 'dun dun dun');\n      expectSubscriptions(left.subscriptions).toBe(leftSubs);\n      expectSubscriptions(right.subscriptions).toBe(rightSubs);\n    });\n  });\n\n  it('should handle selector throwing', () => {\n    rxTestScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('--a--^--b--|', { a: 1, b: 2 });\n      const e1subs = '     ^--!';\n      const e2 = hot('--c--^--d--|', { c: 3, d: 4 });\n      const e2subs = '     ^--!';\n      const expected = '   ---#';\n\n      const result = combineLatest([e1, e2], (x, y) => {\n        throw 'ha ha ' + x + ', ' + y;\n      });\n\n      expectObservable(result).toBe(expected, null, 'ha ha 2, 4');\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should allow unsubscribing early and explicitly', () => {\n    rxTestScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('--a--^--b--c---d-| ');\n      const e1subs = '     ^--------!    ';\n      const e2 = hot('---e-^---f--g---h-|');\n      const e2subs = '     ^--------!    ';\n      const expected = '   ----x-yz--    ';\n      const unsub = '      ---------!    ';\n      const values = { x: 'bf', y: 'cf', z: 'cg' };\n\n      const result = combineLatest([e1, e2], (x, y) => x + y);\n\n      expectObservable(result, unsub).toBe(expected, values);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should not break unsubscription chains when unsubscribed explicitly', () => {\n    rxTestScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('--a--^--b--c---d-| ');\n      const e1subs = '     ^--------!    ';\n      const e2 = hot('---e-^---f--g---h-|');\n      const e2subs = '     ^--------!    ';\n      const expected = '   ----x-yz--    ';\n      const unsub = '      ---------!    ';\n      const values = { x: 'bf', y: 'cf', z: 'cg' };\n\n      const result = combineLatest([e1.pipe(mergeMap((x) => of(x))), e2.pipe(mergeMap((x) => of(x)))], (x, y) => x + y).pipe(\n        mergeMap((x) => of(x))\n      );\n\n      expectObservable(result, unsub).toBe(expected, values);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n});\n"
  },
  {
    "path": "packages/rxjs/spec/observables/concat-spec.ts",
    "content": "/** @prettier */\nimport { expect } from 'chai';\nimport { lowerCaseO } from '../helpers/test-helper';\nimport { asyncScheduler, queueScheduler, concat, of, scheduled, defer, Observable } from 'rxjs';\nimport { mergeMap } from 'rxjs/operators';\nimport { TestScheduler } from 'rxjs/testing';\nimport { observableMatcher } from '../helpers/observableMatcher';\n\n/** @test {concat} */\ndescribe('static concat', () => {\n  let rxTestScheduler: TestScheduler;\n\n  beforeEach(() => {\n    rxTestScheduler = new TestScheduler(observableMatcher);\n  });\n\n  it('should emit elements from multiple sources', () => {\n    rxTestScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' -a-b-c-|');\n      const e1subs = '  ^------!';\n      const e2 = cold('        -0-1-|');\n      const e2subs = '  -------^----!';\n      const e3 = cold('             -w-x-y-z-|');\n      const e3subs = '  ------------^--------!';\n      const expected = '-a-b-c--0-1--w-x-y-z-|';\n\n      expectObservable(concat(e1, e2, e3)).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n      expectSubscriptions(e3.subscriptions).toBe(e3subs);\n    });\n  });\n\n  it('should concat the same cold observable multiple times', () => {\n    rxTestScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const inner = cold('--i-j-k-l-|');\n      const innersubs = [\n        '                 ^---------!                              ',\n        '                 ----------^---------!                    ',\n        '                 --------------------^---------!          ',\n        '                 ------------------------------^---------!',\n      ];\n      const expected = '  --i-j-k-l---i-j-k-l---i-j-k-l---i-j-k-l-|';\n\n      const result = concat(inner, inner, inner, inner);\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(inner.subscriptions).toBe(innersubs);\n    });\n  });\n\n  it('should concat the same cold observable multiple times, but the result is unsubscribed early', () => {\n    rxTestScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const innersubs: string[] = [];\n      const inner = cold('--i-j-k-l-|     ');\n      const unsub = '     ---------------!';\n      innersubs[0] = '    ^---------!     ';\n      innersubs[1] = '    ----------^----!';\n      const expected = '  --i-j-k-l---i-j-';\n\n      const result = concat(inner, inner, inner, inner);\n\n      expectObservable(result, unsub).toBe(expected);\n      expectSubscriptions(inner.subscriptions).toBe(innersubs);\n    });\n  });\n\n  it('should not break unsubscription chains when result is unsubscribed explicitly', () => {\n    rxTestScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const innersubs: string[] = [];\n      const inner = cold('--i-j-k-l-|');\n      innersubs[0] = '    ^---------!';\n      innersubs[1] = '    ----------^----!';\n      const expected = '  --i-j-k-l---i-j-';\n      const unsub = '     ---------------!';\n\n      const innerWrapped = inner.pipe(mergeMap((x) => of(x)));\n      const result = concat(innerWrapped, innerWrapped, innerWrapped, innerWrapped).pipe(mergeMap((x) => of(x)));\n\n      expectObservable(result, unsub).toBe(expected);\n      expectSubscriptions(inner.subscriptions).toBe(innersubs);\n    });\n  });\n\n  it('should complete without emit if both sources are empty', () => {\n    rxTestScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' --|');\n      const e1subs = '  ^-!';\n      const e2 = cold(' ----|');\n      const e2subs = '  --^---!';\n      const expected = '------|';\n\n      expectObservable(concat(e1, e2)).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should not complete if first source does not completes', () => {\n    rxTestScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' -');\n      const e1subs = '  ^';\n      const e2 = cold(' --|');\n      const e2subs = '  -';\n      const expected = '-';\n\n      expectObservable(concat(e1, e2)).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should not complete if second source does not completes', () => {\n    rxTestScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' --|');\n      const e1subs = '  ^-!';\n      const e2 = cold(' ---');\n      const e2subs = '  --^';\n      const expected = '---';\n\n      expectObservable(concat(e1, e2)).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should not complete if both sources do not complete', () => {\n    rxTestScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' -');\n      const e1subs = '  ^';\n      const e2 = cold(' -');\n      const e2subs = '  -';\n      const expected = '-';\n\n      expectObservable(concat(e1, e2)).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should raise error when first source is empty, second source raises error', () => {\n    rxTestScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' --|');\n      const e1subs = '  ^-!';\n      const e2 = cold(' ----#');\n      const e2subs = '  --^---!';\n      const expected = '------#';\n\n      expectObservable(concat(e1, e2)).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should raise error when first source raises error, second source is empty', () => {\n    rxTestScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' ---#');\n      const e1subs = '  ^--!';\n      const e2 = cold(' ----|');\n      const e2subs = '     -';\n      const expected = '---#';\n\n      expectObservable(concat(e1, e2)).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should raise first error when both source raise error', () => {\n    rxTestScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' ---#');\n      const e1subs = '  ^--!';\n      const e2 = cold(' ------#');\n      const e2subs = '     -';\n      const expected = '---#';\n\n      expectObservable(concat(e1, e2)).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should concat if first source emits once, second source is empty', () => {\n    rxTestScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' --a--|');\n      const e1subs = '  ^----!';\n      const e2 = cold(' --------|');\n      const e2subs = '  -----^-------!';\n      const expected = '--a----------|';\n\n      expectObservable(concat(e1, e2)).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should concat if first source is empty, second source emits once', () => {\n    rxTestScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' --|');\n      const e1subs = '  ^-!';\n      const e2 = cold(' --a--|');\n      const e2subs = '  --^----!';\n      const expected = '----a--|';\n\n      expectObservable(concat(e1, e2)).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should emit element from first source, and should not complete if second ' + 'source does not completes', () => {\n    rxTestScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' --a--|');\n      const e1subs = '  ^----!';\n      const e2 = cold(' -');\n      const e2subs = '  -----^';\n      const expected = '--a---';\n\n      expectObservable(concat(e1, e2)).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should not complete if first source does not complete', () => {\n    rxTestScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' -');\n      const e1subs = '  ^';\n      const e2 = cold(' --a--|');\n      const e2subs = '  -';\n      const expected = '-';\n\n      expectObservable(concat(e1, e2)).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should emit elements from each source when source emit once', () => {\n    rxTestScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' ---a|');\n      const e1subs = '  ^---!';\n      const e2 = cold('     -----b--|');\n      const e2subs = '  ----^-------!';\n      const expected = '---a-----b--|';\n\n      expectObservable(concat(e1, e2)).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should unsubscribe to inner source if outer is unsubscribed early', () => {\n    rxTestScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' ---a-a--a|            ');\n      const e1subs = '  ^--------!            ';\n      const e2 = cold('          -----b-b--b-|');\n      const e2subs = '  ---------^-------!    ';\n      const unsub = '   -----------------!    ';\n      const expected = '---a-a--a-----b-b-    ';\n\n      expectObservable(concat(e1, e2), unsub).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should raise error from first source and does not emit from second source', () => {\n    rxTestScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' --#');\n      const e1subs = '  ^-!';\n      const e2 = cold(' ----a--|');\n      const e2subs = '  -';\n      const expected = '--#';\n\n      expectObservable(concat(e1, e2)).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should emit element from first source then raise error from second source', () => {\n    rxTestScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' --a--|');\n      const e1subs = '  ^----!';\n      const e2 = cold(' -------#');\n      const e2subs = '  -----^------!';\n      const expected = '--a---------#';\n\n      expectObservable(concat(e1, e2)).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should emit all elements from both hot observable sources if first source ' + 'completes before second source starts emit', () => {\n    rxTestScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  --a--b-|');\n      const e1subs = '  ^------!';\n      const e2 = hot('  --------x--y--|');\n      const e2subs = '  -------^------!';\n      const expected = '--a--b--x--y--|';\n\n      expectObservable(concat(e1, e2)).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should emit elements from second source regardless of completion time ' + 'when second source is cold observable', () => {\n    rxTestScheduler.run(({ hot, cold, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  --a--b--c---|');\n      const e1subs = '  ^-----------!';\n      const e2 = cold('             -x-y-z-|');\n      const e2subs = '  ------------^------!';\n      const expected = '--a--b--c----x-y-z-|';\n\n      expectObservable(concat(e1, e2)).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should not emit collapsing element from second source', () => {\n    rxTestScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  --a--b--c--|');\n      const e1subs = '  ^----------!';\n      const e2 = hot('  --------x--y--z--|');\n      const e2subs = '  -----------^-----!';\n      const expected = '--a--b--c--y--z--|';\n\n      expectObservable(concat(e1, e2)).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should return empty if concatenating an empty source', () => {\n    rxTestScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold('|');\n      const e1subs = ['(^!)', '(^!)'];\n      const expected = '|';\n\n      const result = concat(e1, e1);\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should error immediately if given a just-throw source', () => {\n    rxTestScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' #');\n      const e1subs = '  (^!)';\n      const expected = '#';\n\n      const result = concat(e1, e1);\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should emit elements from second source regardless of completion time ' + 'when second source is cold observable', () => {\n    rxTestScheduler.run(({ hot, cold, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  --a--b--c---|');\n      const e1subs = '  ^-----------!';\n      const e2 = cold('             -x-y-z-|');\n      const e2subs = '  ------------^------!';\n      const expected = '--a--b--c----x-y-z-|';\n\n      expectObservable(concat(e1, e2)).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should not emit collapsing element from second source', () => {\n    rxTestScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  --a--b--c--|');\n      const e1subs = '  ^----------!';\n      const e2 = hot('  --------x--y--z--|');\n      const e2subs = '  -----------^-----!';\n      const expected = '--a--b--c--y--z--|';\n\n      expectObservable(concat(e1, e2)).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should concat an immediately-scheduled source with an immediately-scheduled second', (done) => {\n    const a = scheduled([1, 2, 3], queueScheduler);\n    const b = scheduled([4, 5, 6, 7, 8], queueScheduler);\n    const r = [1, 2, 3, 4, 5, 6, 7, 8];\n\n    concat(a, b, queueScheduler).subscribe({\n      next: (vals) => {\n        expect(vals).to.equal(r.shift());\n      },\n      complete: done,\n    });\n  });\n\n  it(\"should use the scheduler even when one Observable is concat'd\", (done) => {\n    let e1Subscribed = false;\n    const e1 = defer(() => {\n      e1Subscribed = true;\n      return of('a');\n    });\n\n    concat(e1, asyncScheduler).subscribe({\n      error: done,\n      complete: () => {\n        expect(e1Subscribed).to.be.true;\n        done();\n      },\n    });\n\n    expect(e1Subscribed).to.be.false;\n  });\n\n  it('should return passed observable if no scheduler was passed', () => {\n    rxTestScheduler.run(({ cold, expectObservable }) => {\n      const source = cold('--a---b----c---|');\n      const expected = '   --a---b----c---|';\n      const result = concat(source);\n\n      expectObservable(result).toBe(expected);\n    });\n  });\n\n  it('should return RxJS Observable when single lowerCaseO was passed', () => {\n    rxTestScheduler.run(({ expectObservable }) => {\n      const source = lowerCaseO('a', 'b', 'c');\n      const result = concat(source);\n\n      expect(result).to.be.an.instanceof(Observable);\n      expectObservable(result).toBe('(abc|)');\n    });\n  });\n});\n"
  },
  {
    "path": "packages/rxjs/spec/observables/connectable-spec.ts",
    "content": "/** @prettier */\nimport { expect } from 'chai';\nimport { connectable, of, ReplaySubject } from 'rxjs';\nimport { TestScheduler } from 'rxjs/testing';\nimport { observableMatcher } from '../helpers/observableMatcher';\n\ndescribe('connectable', () => {\n  let testScheduler: TestScheduler;\n\n  beforeEach(() => {\n    testScheduler = new TestScheduler(observableMatcher);\n  });\n\n  it('should mirror a simple source Observable', () => {\n    testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const source = cold('--1-2---3-4--5-|');\n      const sourceSubs = ' ^--------------!';\n      const expected = '   --1-2---3-4--5-|';\n\n      const obs = connectable(source);\n\n      expectObservable(obs).toBe(expected);\n      expectSubscriptions(source.subscriptions).toBe(sourceSubs);\n\n      obs.connect();\n    });\n  });\n\n  it('should do nothing if connect is not called, despite subscriptions', () => {\n    testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const source = cold('--1-2---3-4--5-|');\n      const sourceSubs: string[] = [];\n      const expected = '   -';\n\n      const obs = connectable(source);\n\n      expectObservable(obs).toBe(expected);\n      expectSubscriptions(source.subscriptions).toBe(sourceSubs);\n    });\n  });\n\n  it('should support resetOnDisconnect = true', () => {\n    const values: number[] = [];\n    const source = of(1, 2, 3);\n    const obs = connectable(source, {\n      connector: () => new ReplaySubject(1),\n      resetOnDisconnect: true,\n    });\n\n    obs.subscribe((value) => values.push(value));\n    const connection = obs.connect();\n    expect(values).to.deep.equal([1, 2, 3]);\n\n    connection.unsubscribe();\n\n    obs.subscribe((value) => values.push(value));\n    obs.connect();\n    expect(values).to.deep.equal([1, 2, 3, 1, 2, 3]);\n  });\n\n  it('should support resetOnDisconnect = false', () => {\n    const values: number[] = [];\n    const source = of(1, 2, 3);\n    const obs = connectable(source, {\n      connector: () => new ReplaySubject(1),\n      resetOnDisconnect: false,\n    });\n\n    obs.subscribe((value) => values.push(value));\n    const connection = obs.connect();\n    expect(values).to.deep.equal([1, 2, 3]);\n\n    connection.unsubscribe();\n\n    obs.subscribe((value) => values.push(value));\n    obs.connect();\n    expect(values).to.deep.equal([1, 2, 3, 3]);\n  });\n});\n"
  },
  {
    "path": "packages/rxjs/spec/observables/defer-spec.ts",
    "content": "/** @prettier */\nimport { expect } from 'chai';\nimport { defer, of } from 'rxjs';\nimport { mergeMap } from 'rxjs/operators';\nimport { TestScheduler } from 'rxjs/testing';\nimport { observableMatcher } from '../helpers/observableMatcher';\n\n/** @test {defer} */\ndescribe('defer', () => {\n  let rxTestScheduler: TestScheduler;\n\n  beforeEach(() => {\n    rxTestScheduler = new TestScheduler(observableMatcher);\n  });\n\n  it('should defer the creation of a simple Observable', () => {\n    rxTestScheduler.run(({ hot, cold, expectObservable, expectSubscriptions }) => {\n      const expected = '-a--b--c--|';\n      const e1 = defer(() => cold('-a--b--c--|'));\n      expectObservable(e1).toBe(expected);\n    });\n  });\n\n  it('should create an observable from the provided observable factory', () => {\n    rxTestScheduler.run(({ hot, cold, expectObservable, expectSubscriptions }) => {\n      const source = hot('--a--b--c--|');\n      const sourceSubs = '^----------!';\n      const expected = '  --a--b--c--|';\n\n      const e1 = defer(() => source);\n\n      expectObservable(e1).toBe(expected);\n      expectSubscriptions(source.subscriptions).toBe(sourceSubs);\n    });\n  });\n\n  it('should create an observable from completed', () => {\n    rxTestScheduler.run(({ hot, cold, expectObservable, expectSubscriptions }) => {\n      const source = hot('|');\n      const sourceSubs = '(^!)';\n      const expected = '  |';\n\n      const e1 = defer(() => source);\n\n      expectObservable(e1).toBe(expected);\n      expectSubscriptions(source.subscriptions).toBe(sourceSubs);\n    });\n  });\n\n  it('should accept factory returns promise resolves', (done) => {\n    const expected = 42;\n    const e1 = defer(() => {\n      return new Promise<number>((resolve: any) => {\n        resolve(expected);\n      });\n    });\n\n    e1.subscribe({\n      next: (x: number) => {\n        expect(x).to.equal(expected);\n        done();\n      },\n      error: (x: any) => {\n        done(new Error('should not be called'));\n      },\n    });\n  });\n\n  it('should accept factory returns promise rejects', (done) => {\n    const expected = 42;\n    const e1 = defer(() => {\n      return new Promise<number>((resolve: any, reject: any) => {\n        reject(expected);\n      });\n    });\n\n    e1.subscribe({\n      next: (x: number) => {\n        done(new Error('should not be called'));\n      },\n      error: (x: any) => {\n        expect(x).to.equal(expected);\n        done();\n      },\n      complete: () => {\n        done(new Error('should not be called'));\n      },\n    });\n  });\n\n  it('should create an observable from error', () => {\n    rxTestScheduler.run(({ hot, cold, expectObservable, expectSubscriptions }) => {\n      const source = hot('#');\n      const sourceSubs = '(^!)';\n      const expected = '  #';\n\n      const e1 = defer(() => source);\n\n      expectObservable(e1).toBe(expected);\n      expectSubscriptions(source.subscriptions).toBe(sourceSubs);\n    });\n  });\n\n  it('should create an observable when factory does not throw', () => {\n    rxTestScheduler.run(({ hot, cold, expectObservable, expectSubscriptions }) => {\n      const e1 = defer(() => {\n        if (1 !== Infinity) {\n          throw 'error';\n        }\n        return of();\n      });\n      const expected = '#';\n\n      expectObservable(e1).toBe(expected);\n    });\n  });\n\n  it('should error when factory throws', (done) => {\n    const e1 = defer(() => {\n      // eslint-disable-next-line no-constant-condition\n      if (1 + 2 === 3) {\n        throw 'error';\n      }\n      return of();\n    });\n    e1.subscribe({\n      error: () => done(),\n    });\n  });\n\n  it('should allow unsubscribing early and explicitly', () => {\n    rxTestScheduler.run(({ hot, cold, expectObservable, expectSubscriptions }) => {\n      const source = hot('--a--b--c--|');\n      const sourceSubs = '^-----!     ';\n      const expected = '  --a--b-     ';\n      const unsub = '     ------!     ';\n\n      const e1 = defer(() => source);\n\n      expectObservable(e1, unsub).toBe(expected);\n      expectSubscriptions(source.subscriptions).toBe(sourceSubs);\n    });\n  });\n\n  it('should not break unsubscription chains when result is unsubscribed explicitly', () => {\n    rxTestScheduler.run(({ hot, cold, expectObservable, expectSubscriptions }) => {\n      const source = hot('--a--b--c--|');\n      const sourceSubs = '^-----!     ';\n      const expected = '  --a--b-     ';\n      const unsub = '     ------!     ';\n\n      const e1 = defer(() =>\n        source.pipe(\n          mergeMap((x: string) => of(x)),\n          mergeMap((x: string) => of(x))\n        )\n      );\n\n      expectObservable(e1, unsub).toBe(expected);\n      expectSubscriptions(source.subscriptions).toBe(sourceSubs);\n    });\n  });\n});\n"
  },
  {
    "path": "packages/rxjs/spec/observables/dom/ajax-spec.ts",
    "content": "/** @prettier */\nimport { expect } from 'chai';\nimport * as sinon from 'sinon';\nimport type { AjaxConfig, AjaxResponse} from 'rxjs/ajax';\nimport { ajax, AjaxError, AjaxTimeoutError } from 'rxjs/ajax';\nimport { TestScheduler } from 'rxjs/testing';\nimport { noop } from 'rxjs';\nimport * as nodeFormData from 'form-data';\n\nconst root: any = (typeof globalThis !== 'undefined' && globalThis) || (typeof self !== 'undefined' && self) || global;\n\nif (typeof root.FormData === 'undefined') {\n  root.FormData = nodeFormData as any;\n}\n\n/** @test {ajax} */\ndescribe('ajax', () => {\n  let rXHR: XMLHttpRequest;\n\n  let sandbox: sinon.SinonSandbox;\n\n  beforeEach(() => {\n    sandbox = sinon.createSandbox();\n    rXHR = root.XMLHttpRequest;\n    root.XMLHttpRequest = MockXMLHttpRequest;\n  });\n\n  afterEach(() => {\n    sandbox.restore();\n    MockXMLHttpRequest.clearRequest();\n\n    root.XMLHttpRequest = rXHR;\n    root.XDomainRequest = null;\n    root.ActiveXObject = null;\n  });\n\n  it('should create default XMLHttpRequest for non CORS', () => {\n    const obj: AjaxConfig = {\n      url: '/',\n      method: '',\n    };\n\n    ajax(obj).subscribe();\n    expect(MockXMLHttpRequest.mostRecent.withCredentials).to.be.false;\n  });\n\n  it('should raise an error if not able to create XMLHttpRequest', () => {\n    root.XMLHttpRequest = null;\n    root.ActiveXObject = null;\n\n    const obj: AjaxConfig = {\n      url: '/',\n      method: '',\n    };\n\n    ajax(obj).subscribe({ error: (err) => expect(err).to.exist });\n  });\n\n  it('should create XMLHttpRequest for CORS', () => {\n    const obj: AjaxConfig = {\n      url: '/',\n      method: '',\n      crossDomain: true,\n      withCredentials: true,\n    };\n\n    ajax(obj).subscribe();\n    expect(MockXMLHttpRequest.mostRecent.withCredentials).to.be.true;\n  });\n\n  it('should raise an error if not able to create CORS request', () => {\n    root.XMLHttpRequest = null;\n    root.XDomainRequest = null;\n\n    const obj: AjaxConfig = {\n      url: '/',\n      method: '',\n      crossDomain: true,\n      withCredentials: true,\n    };\n\n    ajax(obj).subscribe({\n      error: (err) => expect(err).to.exist,\n    });\n  });\n\n  it('should set headers', () => {\n    const obj: AjaxConfig = {\n      url: '/talk-to-me-goose',\n      headers: {\n        'Content-Type': 'kenny/loggins',\n        'Fly-Into-The': 'Dangah Zone!',\n        'Take-A-Ride-Into-The': 'Danger ZoooOoone!',\n      },\n      method: '',\n    };\n\n    ajax(obj).subscribe();\n\n    const request = MockXMLHttpRequest.mostRecent;\n\n    expect(request.url).to.equal('/talk-to-me-goose');\n    expect(request.requestHeaders).to.deep.equal({\n      'content-type': 'kenny/loggins',\n      'fly-into-the': 'Dangah Zone!',\n      'take-a-ride-into-the': 'Danger ZoooOoone!',\n      'x-requested-with': 'XMLHttpRequest',\n    });\n    // Did not mutate the headers passed\n    expect(obj.headers).to.deep.equal({\n      'Content-Type': 'kenny/loggins',\n      'Fly-Into-The': 'Dangah Zone!',\n      'Take-A-Ride-Into-The': 'Danger ZoooOoone!',\n    });\n  });\n\n  describe('ajax XSRF cookie in custom header', () => {\n    beforeEach(() => {\n      (global as any).document = {\n        cookie: 'foo=bar',\n      } as Document;\n    });\n\n    afterEach(() => {\n      delete (global as any).document;\n    });\n\n    it('should send the cookie with a custom header to the same domain', () => {\n      const obj: AjaxConfig = {\n        url: '/some/path',\n        xsrfCookieName: 'foo',\n        xsrfHeaderName: 'Custom-Header-Name',\n      };\n\n      ajax(obj).subscribe();\n\n      const request = MockXMLHttpRequest.mostRecent;\n\n      expect(request.url).to.equal('/some/path');\n      expect(request.requestHeaders).to.deep.equal({\n        'Custom-Header-Name': 'bar',\n        'x-requested-with': 'XMLHttpRequest',\n      });\n    });\n\n    it('should send the cookie cross-domain with a custom header when withCredentials is set', () => {\n      const obj: AjaxConfig = {\n        url: 'https://some.subresource.net/some/page',\n        xsrfCookieName: 'foo',\n        xsrfHeaderName: 'Custom-Header-Name',\n        crossDomain: true,\n        withCredentials: true,\n      };\n\n      ajax(obj).subscribe();\n\n      const request = MockXMLHttpRequest.mostRecent;\n\n      expect(request.url).to.equal('https://some.subresource.net/some/page');\n      expect(request.requestHeaders).to.deep.equal({\n        'Custom-Header-Name': 'bar',\n      });\n    });\n\n    it('should not send the cookie cross-domain with a custom header when withCredentials is not set', () => {\n      const obj: AjaxConfig = {\n        url: 'https://some.subresource.net/some/page',\n        xsrfCookieName: 'foo',\n        xsrfHeaderName: 'Custom-Header-Name',\n        crossDomain: true,\n      };\n\n      ajax(obj).subscribe();\n\n      const request = MockXMLHttpRequest.mostRecent;\n\n      expect(request.url).to.equal('https://some.subresource.net/some/page');\n      expect(request.requestHeaders).to.deep.equal({});\n    });\n\n    it('should not send the cookie if there is no xsrfHeaderName option', () => {\n      const obj: AjaxConfig = {\n        url: '/some/page',\n        xsrfCookieName: 'foo',\n      };\n\n      ajax(obj).subscribe();\n\n      const request = MockXMLHttpRequest.mostRecent;\n\n      expect(request.url).to.equal('/some/page');\n      expect(request.requestHeaders).to.deep.equal({\n        'x-requested-with': 'XMLHttpRequest',\n      });\n    });\n  });\n\n  it('should set the X-Requested-With if crossDomain is false', () => {\n    ajax({\n      url: '/test/monkey',\n      method: 'GET',\n      crossDomain: false,\n    }).subscribe();\n\n    const request = MockXMLHttpRequest.mostRecent;\n\n    expect(request.requestHeaders).to.deep.equal({\n      'x-requested-with': 'XMLHttpRequest',\n    });\n  });\n\n  it('should NOT set the X-Requested-With if crossDomain is true', () => {\n    ajax({\n      url: '/test/monkey',\n      method: 'GET',\n      crossDomain: true,\n    }).subscribe();\n\n    const request = MockXMLHttpRequest.mostRecent;\n\n    expect(request.requestHeaders).to.not.have.key('x-requested-with');\n  });\n\n  it('should not alter user-provided X-Requested-With header, even if crossDomain is true', () => {\n    ajax({\n      url: '/test/monkey',\n      method: 'GET',\n      crossDomain: true,\n      headers: {\n        'x-requested-with': 'Custom-XMLHttpRequest',\n      },\n    }).subscribe();\n\n    const request = MockXMLHttpRequest.mostRecent;\n\n    expect(request.requestHeaders['x-requested-with']).to.equal('Custom-XMLHttpRequest');\n  });\n\n  it('should not set default Content-Type header when no body is sent', () => {\n    const obj: AjaxConfig = {\n      url: '/talk-to-me-goose',\n      method: 'GET',\n    };\n\n    ajax(obj).subscribe();\n\n    const request = MockXMLHttpRequest.mostRecent;\n\n    expect(request.url).to.equal('/talk-to-me-goose');\n    expect(request.requestHeaders).to.not.have.keys('Content-Type');\n  });\n\n  it('should error if createXHR throws', () => {\n    let error;\n\n    ajax({\n      url: '/flibbertyJibbet',\n      responseType: 'text',\n      createXHR: () => {\n        throw new Error('wokka wokka');\n      },\n    }).subscribe({\n      next: () => {\n        throw new Error('should not next');\n      },\n      error: (err: any) => {\n        error = err;\n      },\n      complete: () => {\n        throw new Error('should not complete');\n      },\n    });\n\n    expect(error).to.be.an('error', 'wokka wokka');\n  });\n\n  it('should error if send request throws', (done) => {\n    const expected = new Error('xhr send failure');\n\n    ajax({\n      url: '/flibbertyJibbet',\n      responseType: 'text',\n      method: '',\n      createXHR: () => {\n        const ret = new MockXMLHttpRequest();\n        ret.send = () => {\n          throw expected;\n        };\n        return ret as any;\n      },\n    }).subscribe({\n      next: () => {\n        done(new Error('should not be called'));\n      },\n      error: (e: Error) => {\n        expect(e).to.be.equal(expected);\n        done();\n      },\n      complete: () => {\n        done(new Error('should not be called'));\n      },\n    });\n  });\n\n  it('should succeed on 200', () => {\n    const expected = { foo: 'bar' };\n    let result: AjaxResponse<any>;\n    let complete = false;\n\n    ajax({\n      url: '/flibbertyJibbet',\n      method: '',\n    }).subscribe({\n      next: (x: any) => {\n        result = x;\n      },\n      complete: () => {\n        complete = true;\n      },\n    });\n\n    expect(MockXMLHttpRequest.mostRecent.url).to.equal('/flibbertyJibbet');\n\n    MockXMLHttpRequest.mostRecent.respondWith({\n      status: 200,\n      responseText: JSON.stringify(expected),\n    });\n\n    expect(result!.xhr).exist;\n    expect(result!.response).to.deep.equal({ foo: 'bar' });\n    expect(complete).to.be.true;\n  });\n\n  it('should fail on 404', () => {\n    let error: any;\n    const obj: AjaxConfig = {\n      url: '/flibbertyJibbet',\n      responseType: 'text',\n      method: '',\n    };\n\n    ajax(obj).subscribe({\n      next: () => {\n        throw new Error('should not next');\n      },\n      error: (err: any) => {\n        error = err;\n      },\n      complete: () => {\n        throw new Error('should not complete');\n      },\n    });\n\n    expect(MockXMLHttpRequest.mostRecent.url).to.equal('/flibbertyJibbet');\n\n    MockXMLHttpRequest.mostRecent.respondWith({\n      status: 404,\n      responseText: 'Wee! I am text!',\n    });\n\n    expect(error instanceof AjaxError).to.be.true;\n    expect(error.name).to.equal('AjaxError');\n    expect(error.message).to.equal('ajax error 404');\n    expect(error.status).to.equal(404);\n  });\n\n  it('should succeed on 300', () => {\n    let result: AjaxResponse<any>;\n    let complete = false;\n    const obj: AjaxConfig = {\n      url: '/flibbertyJibbet',\n      responseType: 'text',\n      method: '',\n    };\n\n    ajax(obj).subscribe({\n      next: (x: any) => {\n        result = x;\n      },\n      complete: () => {\n        complete = true;\n      },\n    });\n\n    expect(MockXMLHttpRequest.mostRecent.url).to.equal('/flibbertyJibbet');\n\n    MockXMLHttpRequest.mostRecent.respondWith({\n      status: 300,\n      responseText: 'Wee! I am text!',\n    });\n\n    expect(result!.xhr).exist;\n    expect(result!.response).to.deep.equal('Wee! I am text!');\n    expect(complete).to.be.true;\n  });\n\n  it('should not fail if fails to parse error response', () => {\n    let error: any;\n    const obj: AjaxConfig = {\n      url: '/flibbertyJibbet',\n      responseType: 'json',\n      method: '',\n    };\n\n    ajax(obj).subscribe({\n      next: () => {\n        throw new Error('should not next');\n      },\n      error: (err: any) => {\n        error = err;\n      },\n      complete: () => {\n        throw new Error('should not complete');\n      },\n    });\n\n    MockXMLHttpRequest.mostRecent.respondWith({\n      status: 404,\n      responseText: 'Unparsable as json',\n    });\n\n    expect(error instanceof AjaxError).to.be.true;\n    // The default behavior of XHR if you get something back that you can't\n    // parse as JSON, but you have a requestType of \"json\" is to\n    // have `response` set to `null`.\n    expect(error.response).to.be.null;\n  });\n\n  it('should succeed no settings', () => {\n    const expected = JSON.stringify({ foo: 'bar' });\n\n    ajax('/flibbertyJibbet').subscribe({\n      next: (x: any) => {\n        expect(x.status).to.equal(200);\n        expect(x.xhr.method).to.equal('GET');\n        expect(x.xhr.responseText).to.equal(expected);\n      },\n      error: () => {\n        throw 'should not have been called';\n      },\n    });\n\n    expect(MockXMLHttpRequest.mostRecent.url).to.equal('/flibbertyJibbet');\n    MockXMLHttpRequest.mostRecent.respondWith({\n      status: 200,\n      responseText: expected,\n    });\n  });\n\n  it('should fail no settings', () => {\n    const expected = JSON.stringify({ foo: 'bar' });\n\n    ajax('/flibbertyJibbet').subscribe({\n      next: () => {\n        throw 'should not have been called';\n      },\n      error: (x: any) => {\n        expect(x.status).to.equal(500);\n        expect(x.xhr.method).to.equal('GET');\n        expect(x.xhr.responseText).to.equal(expected);\n      },\n      complete: () => {\n        throw 'should not have been called';\n      },\n    });\n\n    expect(MockXMLHttpRequest.mostRecent.url).to.equal('/flibbertyJibbet');\n    MockXMLHttpRequest.mostRecent.respondWith({\n      status: 500,\n      responseText: expected,\n    });\n  });\n\n  it('should create an asynchronous request', () => {\n    const obj: AjaxConfig = {\n      url: '/flibbertyJibbet',\n      responseType: 'text',\n      timeout: 10,\n    };\n\n    ajax(obj).subscribe({\n      next: (x: any) => {\n        expect(x.status).to.equal(200);\n        expect(x.xhr.method).to.equal('GET');\n        expect(x.xhr.async).to.equal(true);\n        expect(x.xhr.timeout).to.equal(10);\n        expect(x.xhr.responseType).to.equal('text');\n      },\n      error: () => {\n        throw 'should not have been called';\n      },\n    });\n\n    const request = MockXMLHttpRequest.mostRecent;\n\n    expect(request.url).to.equal('/flibbertyJibbet');\n\n    request.respondWith({\n      status: 200,\n      responseText: 'Wee! I am text!',\n    });\n  });\n\n  it('should error on timeout of asynchronous request', () => {\n    const rxTestScheduler = new TestScheduler(noop);\n\n    const obj: AjaxConfig = {\n      url: '/flibbertyJibbet',\n      responseType: 'text',\n      timeout: 10,\n    };\n\n    ajax(obj).subscribe({\n      next: () => {\n        throw 'should not have been called';\n      },\n      error: (e) => {\n        expect(e.status).to.equal(0);\n        expect(e.xhr.method).to.equal('GET');\n        expect(e.xhr.async).to.equal(true);\n        expect(e.xhr.timeout).to.equal(10);\n        expect(e.xhr.responseType).to.equal('text');\n      },\n    });\n\n    const request = MockXMLHttpRequest.mostRecent;\n\n    expect(request.url).to.equal('/flibbertyJibbet');\n\n    rxTestScheduler.schedule(() => {\n      request.respondWith({\n        status: 200,\n        responseText: 'Wee! I am text!',\n      });\n    }, 1000);\n\n    rxTestScheduler.flush();\n  });\n\n  it('should create a synchronous request', () => {\n    const obj: AjaxConfig = {\n      url: '/flibbertyJibbet',\n      responseType: 'text',\n      timeout: 10,\n      async: false,\n    };\n\n    ajax(obj).subscribe();\n\n    const mockXHR = MockXMLHttpRequest.mostRecent;\n\n    expect(mockXHR.url).to.equal('/flibbertyJibbet');\n    // Open was called with async `false`.\n    expect(mockXHR.async).to.be.false;\n\n    mockXHR.respondWith({\n      status: 200,\n      responseText: 'Wee! I am text!',\n    });\n  });\n\n  describe('ajax request body', () => {\n    it('can take string body', () => {\n      const obj = {\n        url: '/flibbertyJibbet',\n        method: 'POST',\n        body: 'foobar',\n      };\n\n      ajax(obj).subscribe();\n\n      expect(MockXMLHttpRequest.mostRecent.url).to.equal('/flibbertyJibbet');\n      expect(MockXMLHttpRequest.mostRecent.data).to.equal('foobar');\n    });\n\n    it('can take FormData body', () => {\n      const body = new root.FormData();\n      const obj = {\n        url: '/flibbertyJibbet',\n        method: 'POST',\n        body: body,\n      };\n\n      ajax(obj).subscribe();\n\n      expect(MockXMLHttpRequest.mostRecent.url).to.equal('/flibbertyJibbet');\n      expect(MockXMLHttpRequest.mostRecent.data).to.equal(body);\n      expect(MockXMLHttpRequest.mostRecent.requestHeaders).to.deep.equal({\n        'x-requested-with': 'XMLHttpRequest',\n      });\n    });\n\n    it('should send the URLSearchParams straight through to the body', () => {\n      const body = new URLSearchParams({\n        '🌟': '🚀',\n      });\n      const obj = {\n        url: '/flibbertyJibbet',\n        method: 'POST',\n        body: body,\n      };\n\n      ajax(obj).subscribe();\n\n      expect(MockXMLHttpRequest.mostRecent.url).to.equal('/flibbertyJibbet');\n      expect(MockXMLHttpRequest.mostRecent.data).to.equal(body);\n    });\n\n    it('should send by JSON', () => {\n      const body = {\n        '🌟': '🚀',\n      };\n      const obj = {\n        url: '/flibbertyJibbet',\n        method: 'POST',\n        body: body,\n      };\n\n      ajax(obj).subscribe();\n\n      expect(MockXMLHttpRequest.mostRecent.url).to.equal('/flibbertyJibbet');\n      expect(MockXMLHttpRequest.mostRecent.data).to.equal('{\"🌟\":\"🚀\"}');\n    });\n\n    it('should send json body not mattered on case-sensitivity of HTTP headers', () => {\n      const body = {\n        hello: 'world',\n      };\n\n      const requestObj = {\n        url: '/flibbertyJibbet',\n        method: '',\n        body: body,\n        headers: {\n          'cOnTeNt-TyPe': 'application/json;charset=UTF-8',\n        },\n      };\n\n      ajax(requestObj).subscribe();\n\n      expect(MockXMLHttpRequest.mostRecent.url).to.equal('/flibbertyJibbet');\n      expect(MockXMLHttpRequest.mostRecent.data).to.equal('{\"hello\":\"world\"}');\n    });\n\n    it('should error if send request throws', (done) => {\n      const expected = new Error('xhr send failure');\n\n      const obj: AjaxConfig = {\n        url: '/flibbertyJibbet',\n        responseType: 'text',\n        method: '',\n        body: 'foobar',\n        createXHR: () => {\n          const ret = new MockXMLHttpRequest();\n          ret.send = () => {\n            throw expected;\n          };\n          return ret as any;\n        },\n      };\n\n      ajax(obj).subscribe({\n        next: () => {\n          done(new Error('should not be called'));\n        },\n        error: (e: Error) => {\n          expect(e).to.be.equal(expected);\n          done();\n        },\n        complete: () => {\n          done(new Error('should not be called'));\n        },\n      });\n    });\n  });\n\n  describe('ajax.get', () => {\n    it('should succeed on 200', () => {\n      const expected = { foo: 'bar' };\n      let result;\n      let complete = false;\n\n      ajax.get('/flibbertyJibbet').subscribe({\n        next: (x) => {\n          result = x.response;\n        },\n        complete: () => {\n          complete = true;\n        },\n      });\n\n      const request = MockXMLHttpRequest.mostRecent;\n\n      expect(request.url).to.equal('/flibbertyJibbet');\n\n      request.respondWith({\n        status: 200,\n        responseText: JSON.stringify(expected),\n      });\n\n      expect(result).to.deep.equal(expected);\n      expect(complete).to.be.true;\n    });\n\n    it('should succeed on 204 No Content', () => {\n      let result;\n      let complete = false;\n\n      ajax.get('/flibbertyJibbet').subscribe({\n        next: (x) => {\n          result = x.response;\n        },\n        complete: () => {\n          complete = true;\n        },\n      });\n\n      const request = MockXMLHttpRequest.mostRecent;\n\n      expect(request.url).to.equal('/flibbertyJibbet');\n\n      request.respondWith({\n        status: 204,\n        responseText: '',\n      });\n\n      // Response will get set to null by the browser XHR\n      // This is sort of arbitrarily determined by our test harness\n      // but we want to be as accurate as possible.\n      expect(result).to.be.null;\n      expect(complete).to.be.true;\n    });\n\n    it('should able to select json response via getJSON', () => {\n      const expected = { foo: 'bar' };\n      let result;\n      let complete = false;\n\n      ajax.getJSON('/flibbertyJibbet').subscribe({\n        next: (x) => {\n          result = x;\n        },\n        complete: () => {\n          complete = true;\n        },\n      });\n\n      const request = MockXMLHttpRequest.mostRecent;\n\n      expect(request.url).to.equal('/flibbertyJibbet');\n\n      request.respondWith({\n        status: 200,\n        responseText: JSON.stringify(expected),\n      });\n\n      expect(result).to.deep.equal(expected);\n      expect(complete).to.be.true;\n    });\n  });\n\n  describe('ajax.post', () => {\n    it('should succeed on 200', () => {\n      const expected = { foo: 'bar', hi: 'there you' };\n      let result: AjaxResponse<any>;\n      let complete = false;\n\n      ajax.post('/flibbertyJibbet', expected).subscribe({\n        next: (x) => {\n          result = x;\n        },\n        complete: () => {\n          complete = true;\n        },\n      });\n\n      const request = MockXMLHttpRequest.mostRecent;\n\n      expect(request.method).to.equal('POST');\n      expect(request.url).to.equal('/flibbertyJibbet');\n      expect(request.requestHeaders).to.deep.equal({\n        'content-type': 'application/json;charset=utf-8',\n        'x-requested-with': 'XMLHttpRequest',\n      });\n\n      request.respondWith({\n        status: 200,\n        responseText: JSON.stringify(expected),\n      });\n\n      expect(request.data).to.equal(JSON.stringify(expected));\n      expect(result!.response).to.deep.equal(expected);\n      expect(complete).to.be.true;\n    });\n\n    it('should succeed on 204 No Content', () => {\n      let result: AjaxResponse<any>;\n      let complete = false;\n\n      ajax.post('/flibbertyJibbet', undefined).subscribe({\n        next: (x) => {\n          result = x;\n        },\n        complete: () => {\n          complete = true;\n        },\n      });\n\n      const request = MockXMLHttpRequest.mostRecent;\n\n      expect(request.method).to.equal('POST');\n      expect(request.url).to.equal('/flibbertyJibbet');\n      expect(request.requestHeaders).to.deep.equal({\n        'x-requested-with': 'XMLHttpRequest',\n      });\n\n      request.respondWith({\n        status: 204,\n        responseText: '',\n      });\n\n      // Since the default setting for `responseType` is \"json\",\n      // and our `responseText` is an empty string (which isn't parsable as JSON),\n      // response should be `null` here.\n      expect(result!.response).to.be.null;\n      expect(complete).to.be.true;\n    });\n\n    it('should allow partial progressSubscriber ', function () {\n      const spy = sinon.spy();\n      const progressSubscriber: any = {\n        next: spy,\n      };\n\n      ajax({\n        url: '/flibbertyJibbet',\n        progressSubscriber,\n      }).subscribe();\n\n      const request = MockXMLHttpRequest.mostRecent;\n\n      request.respondWith(\n        {\n          status: 200,\n          responseText: JSON.stringify({}),\n        },\n        { uploadProgressTimes: 3 }\n      );\n\n      expect(spy).to.be.called.callCount(4);\n    });\n\n    it('should emit progress event when progressSubscriber is specified', function () {\n      const spy = sinon.spy();\n      const progressSubscriber = <any>{\n        next: spy,\n        error: () => {\n          // noop\n        },\n        complete: () => {\n          // noop\n        },\n      };\n\n      ajax({\n        url: '/flibbertyJibbet',\n        progressSubscriber,\n      }).subscribe();\n\n      const request = MockXMLHttpRequest.mostRecent;\n\n      request.respondWith(\n        {\n          status: 200,\n          responseText: JSON.stringify({}),\n        },\n        { uploadProgressTimes: 3 }\n      );\n\n      expect(spy).to.be.called.callCount(4);\n    });\n  });\n\n  describe('ajax.patch', () => {\n    it('should create an AjaxObservable with correct options', () => {\n      const expected = { foo: 'bar', hi: 'there you' };\n      let result: AjaxResponse<any>;\n      let complete = false;\n\n      ajax.patch('/flibbertyJibbet', expected).subscribe({\n        next: (x) => {\n          result = x;\n        },\n        complete: () => {\n          complete = true;\n        },\n      });\n\n      const request = MockXMLHttpRequest.mostRecent;\n\n      expect(request.method).to.equal('PATCH');\n      expect(request.url).to.equal('/flibbertyJibbet');\n      expect(request.requestHeaders).to.deep.equal({\n        'content-type': 'application/json;charset=utf-8',\n        'x-requested-with': 'XMLHttpRequest',\n      });\n\n      request.respondWith({\n        status: 200,\n        responseText: JSON.stringify(expected),\n      });\n\n      expect(request.data).to.equal(JSON.stringify(expected));\n      expect(result!.response).to.deep.equal(expected);\n      expect(complete).to.be.true;\n    });\n  });\n\n  describe('ajax error classes', () => {\n    describe('AjaxError', () => {\n      it('should extend Error class', () => {\n        const error = new AjaxError('Test error', new XMLHttpRequest(), {\n          url: '/',\n          method: 'GET',\n          responseType: 'json',\n          headers: {},\n          withCredentials: false,\n          async: true,\n          timeout: 0,\n          crossDomain: false,\n        });\n        expect(error).to.be.an.instanceOf(Error);\n      });\n    });\n\n    describe('AjaxTimeoutError', () => {\n      it('should extend Error class', () => {\n        const error = new AjaxTimeoutError(new XMLHttpRequest(), {\n          url: '/',\n          method: 'GET',\n          responseType: 'json',\n          headers: {},\n          withCredentials: false,\n          async: true,\n          timeout: 0,\n          crossDomain: false,\n        });\n        expect(error).to.be.an.instanceOf(Error);\n      });\n\n      it('should extend AjaxError class', () => {\n        const error = new AjaxTimeoutError(new XMLHttpRequest(), {\n          url: '/',\n          method: 'GET',\n          responseType: 'json',\n          headers: {},\n          withCredentials: false,\n          async: true,\n          timeout: 0,\n          crossDomain: false,\n        });\n        expect(error).to.be.an.instanceOf(AjaxError);\n      });\n    });\n  });\n\n  it('should error if aborted early', () => {\n    let thrown: any = null;\n\n    ajax({\n      method: 'GET',\n      url: '/flibbertyJibbett',\n    }).subscribe({\n      next: () => {\n        throw new Error('should not be called');\n      },\n      error: (err) => {\n        thrown = err;\n      },\n    });\n\n    const mockXHR = MockXMLHttpRequest.mostRecent;\n    expect(thrown).to.be.null;\n\n    mockXHR.triggerEvent('abort', { type: 'abort' });\n    expect(thrown).to.be.an.instanceOf(AjaxError);\n    expect(thrown.message).to.equal('aborted');\n  });\n\n  describe('with includeDownloadProgress', () => {\n    it('should emit download progress', () => {\n      const results: any[] = [];\n\n      ajax({\n        method: 'GET',\n        url: '/flibbertyJibbett',\n        includeDownloadProgress: true,\n      }).subscribe({\n        next: (value) => results.push(value),\n        complete: () => results.push('done'),\n      });\n\n      const mockXHR = MockXMLHttpRequest.mostRecent;\n      mockXHR.respondWith(\n        {\n          status: 200,\n          total: 5,\n          loaded: 5,\n          responseText: JSON.stringify({ boo: 'I am a ghost' }),\n        },\n        { uploadProgressTimes: 5, downloadProgressTimes: 5 }\n      );\n\n      const request = {\n        async: true,\n        body: undefined,\n        crossDomain: false,\n        headers: {\n          'x-requested-with': 'XMLHttpRequest',\n        },\n        includeDownloadProgress: true,\n        method: 'GET',\n        responseType: 'json',\n        timeout: 0,\n        url: '/flibbertyJibbett',\n        withCredentials: false,\n      };\n\n      expect(results).to.deep.equal([\n        {\n          type: 'download_loadstart',\n          responseHeaders: {},\n          responseType: 'json',\n          response: undefined,\n          loaded: 0,\n          total: 5,\n          request,\n          status: 0,\n          xhr: mockXHR,\n          originalEvent: { type: 'loadstart', loaded: 0, total: 5 },\n        },\n        {\n          type: 'download_progress',\n          responseHeaders: {},\n          responseType: 'json',\n          response: undefined,\n          loaded: 1,\n          total: 5,\n          request,\n          status: 0,\n          xhr: mockXHR,\n          originalEvent: { type: 'progress', loaded: 1, total: 5 },\n        },\n        {\n          type: 'download_progress',\n          responseHeaders: {},\n          responseType: 'json',\n          response: undefined,\n          loaded: 2,\n          total: 5,\n          request,\n          status: 0,\n          xhr: mockXHR,\n          originalEvent: { type: 'progress', loaded: 2, total: 5 },\n        },\n        {\n          type: 'download_progress',\n          responseHeaders: {},\n          responseType: 'json',\n          response: undefined,\n          loaded: 3,\n          total: 5,\n          request,\n          status: 0,\n          xhr: mockXHR,\n          originalEvent: { type: 'progress', loaded: 3, total: 5 },\n        },\n        {\n          type: 'download_progress',\n          responseHeaders: {},\n          responseType: 'json',\n          response: undefined,\n          loaded: 4,\n          total: 5,\n          request,\n          status: 0,\n          xhr: mockXHR,\n          originalEvent: { type: 'progress', loaded: 4, total: 5 },\n        },\n        {\n          type: 'download_progress',\n          responseHeaders: {},\n          responseType: 'json',\n          response: undefined,\n          loaded: 5,\n          total: 5,\n          request,\n          status: 0,\n          xhr: mockXHR,\n          originalEvent: { type: 'progress', loaded: 5, total: 5 },\n        },\n        {\n          type: 'download_load',\n          loaded: 5,\n          total: 5,\n          request,\n          originalEvent: { type: 'load', loaded: 5, total: 5 },\n          xhr: mockXHR,\n          response: { boo: 'I am a ghost' },\n          responseHeaders: {},\n          responseType: 'json',\n          status: 200,\n        },\n        'done', // from completion.\n      ]);\n    });\n\n    it('should emit upload and download progress', () => {\n      const results: any[] = [];\n\n      ajax({\n        method: 'GET',\n        url: '/flibbertyJibbett',\n        includeUploadProgress: true,\n        includeDownloadProgress: true,\n      }).subscribe({\n        next: (value) => results.push(value),\n        complete: () => results.push('done'),\n      });\n\n      const mockXHR = MockXMLHttpRequest.mostRecent;\n      mockXHR.respondWith(\n        {\n          status: 200,\n          total: 5,\n          loaded: 5,\n          responseText: JSON.stringify({ boo: 'I am a ghost' }),\n        },\n        { uploadProgressTimes: 5, downloadProgressTimes: 5 }\n      );\n\n      const request = {\n        async: true,\n        body: undefined,\n        crossDomain: false,\n        headers: {\n          'x-requested-with': 'XMLHttpRequest',\n        },\n        includeUploadProgress: true,\n        includeDownloadProgress: true,\n        method: 'GET',\n        responseType: 'json',\n        timeout: 0,\n        url: '/flibbertyJibbett',\n        withCredentials: false,\n      };\n\n      expect(results).to.deep.equal([\n        {\n          type: 'upload_loadstart',\n          loaded: 0,\n          total: 5,\n          request,\n          status: 0,\n          response: undefined,\n          responseHeaders: {},\n          responseType: 'json',\n          xhr: mockXHR,\n          originalEvent: { type: 'loadstart', loaded: 0, total: 5 },\n        },\n        {\n          type: 'upload_progress',\n          loaded: 1,\n          total: 5,\n          request,\n          status: 0,\n          response: undefined,\n          responseHeaders: {},\n          responseType: 'json',\n          xhr: mockXHR,\n          originalEvent: { type: 'progress', loaded: 1, total: 5 },\n        },\n        {\n          type: 'upload_progress',\n          loaded: 2,\n          total: 5,\n          request,\n          status: 0,\n          response: undefined,\n          responseHeaders: {},\n          responseType: 'json',\n          xhr: mockXHR,\n          originalEvent: { type: 'progress', loaded: 2, total: 5 },\n        },\n        {\n          type: 'upload_progress',\n          loaded: 3,\n          total: 5,\n          request,\n          status: 0,\n          response: undefined,\n          responseHeaders: {},\n          responseType: 'json',\n          xhr: mockXHR,\n          originalEvent: { type: 'progress', loaded: 3, total: 5 },\n        },\n        {\n          type: 'upload_progress',\n          loaded: 4,\n          total: 5,\n          request,\n          status: 0,\n          response: undefined,\n          responseHeaders: {},\n          responseType: 'json',\n          xhr: mockXHR,\n          originalEvent: { type: 'progress', loaded: 4, total: 5 },\n        },\n        {\n          type: 'upload_progress',\n          loaded: 5,\n          total: 5,\n          request,\n          status: 0,\n          response: undefined,\n          responseHeaders: {},\n          responseType: 'json',\n          xhr: mockXHR,\n          originalEvent: { type: 'progress', loaded: 5, total: 5 },\n        },\n        {\n          type: 'upload_load',\n          loaded: 5,\n          total: 5,\n          request,\n          status: 0,\n          response: undefined,\n          responseHeaders: {},\n          responseType: 'json',\n          xhr: mockXHR,\n          originalEvent: { type: 'load', loaded: 5, total: 5 },\n        },\n        {\n          type: 'download_loadstart',\n          responseHeaders: {},\n          responseType: 'json',\n          response: undefined,\n          loaded: 0,\n          total: 5,\n          request,\n          status: 0,\n          xhr: mockXHR,\n          originalEvent: { type: 'loadstart', loaded: 0, total: 5 },\n        },\n        {\n          type: 'download_progress',\n          responseHeaders: {},\n          responseType: 'json',\n          response: undefined,\n          loaded: 1,\n          total: 5,\n          request,\n          status: 0,\n          xhr: mockXHR,\n          originalEvent: { type: 'progress', loaded: 1, total: 5 },\n        },\n        {\n          type: 'download_progress',\n          responseHeaders: {},\n          responseType: 'json',\n          response: undefined,\n          loaded: 2,\n          total: 5,\n          request,\n          status: 0,\n          xhr: mockXHR,\n          originalEvent: { type: 'progress', loaded: 2, total: 5 },\n        },\n        {\n          type: 'download_progress',\n          responseHeaders: {},\n          responseType: 'json',\n          response: undefined,\n          loaded: 3,\n          total: 5,\n          request,\n          status: 0,\n          xhr: mockXHR,\n          originalEvent: { type: 'progress', loaded: 3, total: 5 },\n        },\n        {\n          type: 'download_progress',\n          responseHeaders: {},\n          responseType: 'json',\n          response: undefined,\n          loaded: 4,\n          total: 5,\n          request,\n          status: 0,\n          xhr: mockXHR,\n          originalEvent: { type: 'progress', loaded: 4, total: 5 },\n        },\n        {\n          type: 'download_progress',\n          responseHeaders: {},\n          responseType: 'json',\n          response: undefined,\n          loaded: 5,\n          total: 5,\n          request,\n          status: 0,\n          xhr: mockXHR,\n          originalEvent: { type: 'progress', loaded: 5, total: 5 },\n        },\n        {\n          type: 'download_load',\n          loaded: 5,\n          total: 5,\n          request,\n          originalEvent: { type: 'load', loaded: 5, total: 5 },\n          xhr: mockXHR,\n          response: { boo: 'I am a ghost' },\n          responseHeaders: {},\n          responseType: 'json',\n          status: 200,\n        },\n        'done', // from completion.\n      ]);\n    });\n  });\n\n  it('should return an object that allows access to response headers', () => {\n    const sentResponseHeaders = {\n      'content-type': 'application/json',\n      'x-custom-header': 'test',\n      'x-headers-are-fun': '<whatever/> {\"weird\": \"things\"}',\n    };\n\n    ajax({\n      method: 'GET',\n      url: '/whatever',\n    }).subscribe((response) => {\n      expect(response.responseHeaders).to.deep.equal(sentResponseHeaders);\n    });\n\n    const mockXHR = MockXMLHttpRequest.mostRecent;\n\n    mockXHR.respondWith({\n      status: 200,\n      headers: sentResponseHeaders,\n      responseText: JSON.stringify({ iam: 'tired', and: 'should go to bed', but: 'I am doing open source for no good reason' }),\n    });\n\n    expect(mockXHR.getAllResponseHeaders()).to.equal(`content-type: application/json\nx-custom-header: test\nx-headers-are-fun: <whatever/> {\"weird\": \"things\"}`);\n  });\n\n  describe('with queryParams', () => {\n    it('should allow passing of search queryParams as a dictionary', () => {\n      ajax({\n        method: 'GET',\n        url: '/whatever',\n        queryParams: { foo: 'bar', whatever: '123' },\n      }).subscribe();\n\n      const mockXHR = MockXMLHttpRequest.mostRecent;\n\n      mockXHR.respondWith({\n        status: 200,\n        responseText: JSON.stringify({ whatever: 'I want' }),\n      });\n\n      expect(mockXHR.url).to.equal('/whatever?foo=bar&whatever=123');\n    });\n\n    it('should allow passing of search queryParams as an entries array', () => {\n      ajax({\n        method: 'GET',\n        url: '/whatever',\n        queryParams: [\n          ['foo', 'bar'],\n          ['whatever', '123'],\n        ],\n      }).subscribe();\n\n      const mockXHR = MockXMLHttpRequest.mostRecent;\n\n      mockXHR.respondWith({\n        status: 200,\n        responseText: JSON.stringify({ whatever: 'I want' }),\n      });\n\n      expect(mockXHR.url).to.equal('/whatever?foo=bar&whatever=123');\n    });\n\n    it('should allow passing of search queryParams as a string', () => {\n      ajax({\n        method: 'GET',\n        url: '/whatever',\n        queryParams: '?foo=bar&whatever=123',\n      }).subscribe();\n\n      const mockXHR = MockXMLHttpRequest.mostRecent;\n\n      mockXHR.respondWith({\n        status: 200,\n        responseText: JSON.stringify({ whatever: 'I want' }),\n      });\n\n      expect(mockXHR.url).to.equal('/whatever?foo=bar&whatever=123');\n    });\n\n    it('should allow passing of search queryParams as a URLSearchParams object', () => {\n      const queryParams = new URLSearchParams();\n      queryParams.set('foo', 'bar');\n      queryParams.set('whatever', '123');\n      ajax({\n        method: 'GET',\n        url: '/whatever',\n        queryParams,\n      }).subscribe();\n\n      const mockXHR = MockXMLHttpRequest.mostRecent;\n\n      mockXHR.respondWith({\n        status: 200,\n        responseText: JSON.stringify({ whatever: 'I want' }),\n      });\n\n      expect(mockXHR.url).to.equal('/whatever?foo=bar&whatever=123');\n    });\n\n    it('should not screw things up if there is an existing search string in the url passed', () => {\n      ajax({\n        method: 'GET',\n        url: '/whatever?jays_face=is+a+param&lol=haha',\n        queryParams: { foo: 'bar', whatever: '123' },\n      }).subscribe();\n\n      const mockXHR = MockXMLHttpRequest.mostRecent;\n\n      mockXHR.respondWith({\n        status: 200,\n        responseText: JSON.stringify({ whatever: 'I want' }),\n      });\n\n      expect(mockXHR.url).to.equal('/whatever?jays_face=is+a+param&lol=haha&foo=bar&whatever=123');\n    });\n\n    it('should overwrite existing args from existing search strings in the url passed', () => {\n      ajax({\n        method: 'GET',\n        url: '/whatever?terminator=2&uncle_bob=huh',\n        queryParams: { uncle_bob: '...okayyyyyyy', movie_quote: 'yes' },\n      }).subscribe();\n\n      const mockXHR = MockXMLHttpRequest.mostRecent;\n\n      mockXHR.respondWith({\n        status: 200,\n        responseText: JSON.stringify({ whatever: 'I want' }),\n      });\n\n      expect(mockXHR.url).to.equal('/whatever?terminator=2&uncle_bob=...okayyyyyyy&movie_quote=yes');\n    });\n\n    it('should properly encode values', () => {\n      ajax({\n        method: 'GET',\n        url: '/whatever',\n        queryParams: { 'this is a weird param name': '?#* value here rofl !!!' },\n      }).subscribe();\n\n      const mockXHR = MockXMLHttpRequest.mostRecent;\n\n      mockXHR.respondWith({\n        status: 200,\n        responseText: JSON.stringify({ whatever: 'I want' }),\n      });\n\n      expect(mockXHR.url).to.equal('/whatever?this+is+a+weird+param+name=%3F%23*+value+here+rofl+%21%21%21');\n    });\n\n    it('should handle dictionaries that have numbers, booleans, and arrays of numbers, strings or booleans', () => {\n      ajax({\n        method: 'GET',\n        url: '/whatever',\n        queryParams: { a: 123, b: true, c: ['one', 'two', 'three'], d: [1, 3, 3, 7], e: [true, false, true] },\n      }).subscribe();\n\n      const mockXHR = MockXMLHttpRequest.mostRecent;\n\n      mockXHR.respondWith({\n        status: 200,\n        responseText: JSON.stringify({ whatever: 'I want' }),\n      });\n\n      expect(mockXHR.url).to.equal('/whatever?a=123&b=true&c=one%2Ctwo%2Cthree&d=1%2C3%2C3%2C7&e=true%2Cfalse%2Ctrue');\n    });\n\n    it('should handle entries that have numbers, booleans, and arrays of numbers, strings or booleans', () => {\n      ajax({\n        method: 'GET',\n        url: '/whatever',\n        queryParams: [\n          ['a', 123],\n          ['b', true],\n          ['c', ['one', 'two', 'three']],\n          ['d', [1, 3, 3, 7]],\n          ['e', [true, false, true]],\n        ],\n      }).subscribe();\n\n      const mockXHR = MockXMLHttpRequest.mostRecent;\n\n      mockXHR.respondWith({\n        status: 200,\n        responseText: JSON.stringify({ whatever: 'I want' }),\n      });\n\n      expect(mockXHR.url).to.equal('/whatever?a=123&b=true&c=one%2Ctwo%2Cthree&d=1%2C3%2C3%2C7&e=true%2Cfalse%2Ctrue');\n    });\n  });\n});\n\n// Some of the older versions of node we test on don't have EventTarget.\nclass MockXHREventTarget {\n  private registry = new Map<string, Set<(e: ProgressEvent) => void>>();\n\n  addEventListener(type: string, handler: (e: ProgressEvent) => void) {\n    let handlers = this.registry.get(type);\n    if (!handlers) {\n      this.registry.set(type, (handlers = new Set()));\n    }\n    handlers.add(handler);\n  }\n\n  removeEventListener(type: string, handler: (e: ProgressEvent) => void) {\n    this.registry.get(type)?.delete(handler);\n  }\n\n  dispatchEvent(event: ProgressEvent) {\n    const { type } = event;\n    const handlers = this.registry.get(type);\n    if (handlers) {\n      for (const handler of handlers) {\n        handler(event);\n      }\n    }\n  }\n}\nclass MockXMLHttpRequest extends MockXHREventTarget {\n  static readonly DONE = 4;\n\n  private static requests: Array<MockXMLHttpRequest> = [];\n  private static recentRequest: MockXMLHttpRequest;\n\n  static get mostRecent(): MockXMLHttpRequest {\n    return MockXMLHttpRequest.recentRequest;\n  }\n\n  static get allRequests(): Array<MockXMLHttpRequest> {\n    return MockXMLHttpRequest.requests;\n  }\n\n  static clearRequest(): void {\n    MockXMLHttpRequest.requests.length = 0;\n    MockXMLHttpRequest.recentRequest = null!;\n  }\n\n  protected responseType: string = '';\n  private readyState: number = 0;\n\n  /**\n   * Used to test if `open` was called with `async` true or false.\n   */\n  public async: boolean = true;\n\n  protected status: any;\n  protected responseText: string | undefined;\n  protected response: any = undefined;\n\n  url: any;\n  method: any;\n  data: any;\n  requestHeaders: any = {};\n  withCredentials: boolean = false;\n\n  onreadystatechange!: (e: ProgressEvent) => any;\n  onerror!: (e: ErrorEvent) => any;\n  onprogress!: (e: ProgressEvent) => any;\n  ontimeout!: (e: ProgressEvent) => any;\n\n  upload: XMLHttpRequestUpload = new MockXHREventTarget() as any;\n\n  constructor() {\n    super();\n    MockXMLHttpRequest.recentRequest = this;\n    MockXMLHttpRequest.requests.push(this);\n  }\n\n  timeout!: number;\n\n  send(data: any): void {\n    this.data = data;\n    if (this.timeout && this.timeout > 0) {\n      setTimeout(() => {\n        if (this.readyState != 4) {\n          this.readyState = 4;\n          this.status = 0;\n          this.triggerEvent('readystatechange');\n          this.triggerEvent('timeout');\n        }\n      }, this.timeout);\n    }\n  }\n\n  abort() {\n    // noop\n  }\n\n  open(method: any, url: any, async: any): void {\n    this.method = method;\n    this.url = url;\n    this.async = async;\n    this.readyState = 1;\n    this.triggerEvent('readystatechange');\n    const originalProgressHandler = this.upload.onprogress;\n    Object.defineProperty(this.upload, 'progress', {\n      get() {\n        return originalProgressHandler;\n      },\n    });\n  }\n\n  setRequestHeader(key: any, value: any): void {\n    this.requestHeaders[key] = value;\n  }\n\n  private _responseHeaders: any;\n\n  getAllResponseHeaders() {\n    return this._responseHeaders\n      ? Object.entries(this._responseHeaders)\n          .map((entryParts) => entryParts.join(': '))\n          .join('\\n')\n      : '';\n  }\n\n  respondWith(\n    response: {\n      status?: number;\n      headers?: any;\n      responseText?: string | undefined;\n      total?: number;\n      loaded?: number;\n    },\n    config?: { uploadProgressTimes?: number; downloadProgressTimes?: number }\n  ): void {\n    const { uploadProgressTimes = 0, downloadProgressTimes = 0 } = config ?? {};\n\n    // Fake our upload progress first, if requested by the test.\n    if (uploadProgressTimes) {\n      this.triggerUploadEvent('loadstart', { type: 'loadstart', total: uploadProgressTimes, loaded: 0 });\n      for (let i = 1; i <= uploadProgressTimes; i++) {\n        this.triggerUploadEvent('progress', { type: 'progress', total: uploadProgressTimes, loaded: i });\n      }\n      this.triggerUploadEvent('load', { type: 'load', total: uploadProgressTimes, loaded: uploadProgressTimes });\n    }\n\n    // Fake our download progress\n    if (downloadProgressTimes) {\n      this.triggerEvent('loadstart', { type: 'loadstart', total: downloadProgressTimes, loaded: 0 });\n      for (let i = 1; i <= downloadProgressTimes; i++) {\n        this.triggerEvent('progress', { type: 'progress', total: downloadProgressTimes, loaded: i });\n      }\n    }\n\n    // Store our headers locally. This is used in `getAllResponseHeaders` mock impl.\n    this._responseHeaders = response.headers;\n\n    // Set the readyState to DONE (4)\n    this.readyState = 4;\n\n    // Default to OK\n    this.status = response.status || 200;\n    this.responseText = response.responseText;\n\n    switch (this.responseType) {\n      case 'json':\n        try {\n          this.response = JSON.parse(response.responseText!);\n        } catch (err) {\n          // Ignore this is for testing if we get an invalid server\n          // response somehow, where responseType is \"json\" but the responseText\n          // is not JSON. In truth, we need to invert these tests to just use\n          // response, because `responseText` is a legacy path.\n          this.response = null;\n        }\n        break;\n      case 'arraybuffer':\n      case 'document':\n      case 'blob':\n        throw new Error('Test harness does not support the responseType: ' + this.responseType);\n      case 'text':\n      case '':\n      default:\n        this.response = response.responseText;\n        break;\n    }\n\n    this.triggerEvent('load', { type: 'load', total: response.total ?? 0, loaded: response.loaded ?? 0 });\n    this.triggerEvent('readystatechange', { type: 'readystatechange' });\n  }\n\n  triggerEvent(this: any, name: any, eventObj?: any): void {\n    // TODO: create a better default event\n    const e: any = eventObj || { type: name };\n\n    this.dispatchEvent({ type: name, ...eventObj });\n\n    if (this['on' + name]) {\n      this['on' + name](e);\n    }\n  }\n\n  triggerUploadEvent(this: any, name: any, eventObj?: any): void {\n    // TODO: create a better default event\n    const e: any = eventObj || {};\n\n    this.upload.dispatchEvent({ type: name, ...eventObj });\n\n    if (this.upload['on' + name]) {\n      this.upload['on' + name](e);\n    }\n  }\n}\n"
  },
  {
    "path": "packages/rxjs/spec/observables/dom/animationFrames-spec.ts",
    "content": "/** @prettier */\nimport { expect } from 'chai';\nimport * as sinon from 'sinon';\nimport { animationFrames } from 'rxjs';\nimport { mergeMapTo, take, takeUntil } from 'rxjs/operators';\nimport { TestScheduler } from 'rxjs/testing';\nimport { observableMatcher } from '../../helpers/observableMatcher';\nimport { animationFrameProvider } from 'rxjs/internal/scheduler/animationFrameProvider';\n\ndescribe('animationFrames', () => {\n  let testScheduler: TestScheduler;\n\n  beforeEach(() => {\n    testScheduler = new TestScheduler(observableMatcher);\n  });\n\n  it('should animate', function () {\n    testScheduler.run(({ animate, cold, expectObservable, time }) => {\n      animate('            ---x---x---x');\n      const mapped = cold('-m          ');\n      const tm = time('    -|          ');\n      const ta = time('    ---|        ');\n      const tb = time('    -------|    ');\n      const tc = time('    -----------|');\n      const expected = '   ---a---b---c';\n      const subs = '       ^----------!';\n\n      const result = mapped.pipe(mergeMapTo(animationFrames()));\n      expectObservable(result, subs).toBe(expected, {\n        a: { elapsed: ta - tm, timestamp: ta },\n        b: { elapsed: tb - tm, timestamp: tb },\n        c: { elapsed: tc - tm, timestamp: tc },\n      });\n    });\n  });\n\n  it('should use any passed timestampProvider', () => {\n    let i = 0;\n    const timestampProvider = {\n      now: sinon.stub().callsFake(() => {\n        return [50, 100, 200, 300][i++];\n      }),\n    };\n\n    testScheduler.run(({ animate, cold, expectObservable }) => {\n      animate('            ---x---x---x');\n      const mapped = cold('-m          ');\n      const expected = '   ---a---b---c';\n      const subs = '       ^----------!';\n\n      const result = mapped.pipe(mergeMapTo(animationFrames(timestampProvider)));\n      expectObservable(result, subs).toBe(expected, {\n        a: { elapsed: 50, timestamp: 100 },\n        b: { elapsed: 150, timestamp: 200 },\n        c: { elapsed: 250, timestamp: 300 },\n      });\n    });\n  });\n\n  it('should compose with take', () => {\n    testScheduler.run(({ animate, cold, expectObservable, time }) => {\n      const requestSpy = sinon.spy(animationFrameProvider.delegate!, 'requestAnimationFrame');\n      const cancelSpy = sinon.spy(animationFrameProvider.delegate!, 'cancelAnimationFrame');\n\n      animate('            ---x---x---x');\n      const mapped = cold('-m          ');\n      const tm = time('    -|          ');\n      const ta = time('    ---|        ');\n      const tb = time('    -------|    ');\n      const expected = '   ---a---b    ';\n\n      const result = mapped.pipe(mergeMapTo(animationFrames().pipe(take(2))));\n      expectObservable(result).toBe(expected, {\n        a: { elapsed: ta - tm, timestamp: ta },\n        b: { elapsed: tb - tm, timestamp: tb },\n      });\n\n      testScheduler.flush();\n      // Requests are made at times tm and ta\n      expect(requestSpy.callCount).to.equal(2);\n      // No request cancellation is effected, as unsubscription occurs before rescheduling\n      expect(cancelSpy.callCount).to.equal(0);\n    });\n  });\n\n  it('should compose with takeUntil', () => {\n    testScheduler.run(({ animate, cold, expectObservable, hot, time }) => {\n      const requestSpy = sinon.spy(animationFrameProvider.delegate!, 'requestAnimationFrame');\n      const cancelSpy = sinon.spy(animationFrameProvider.delegate!, 'cancelAnimationFrame');\n\n      animate('            ---x---x---x');\n      const mapped = cold('-m          ');\n      const tm = time('    -|          ');\n      const ta = time('    ---|        ');\n      const tb = time('    -------|    ');\n      const signal = hot(' ^--------s--');\n      const expected = '   ---a---b    ';\n\n      const result = mapped.pipe(mergeMapTo(animationFrames().pipe(takeUntil(signal))));\n      expectObservable(result).toBe(expected, {\n        a: { elapsed: ta - tm, timestamp: ta },\n        b: { elapsed: tb - tm, timestamp: tb },\n      });\n\n      testScheduler.flush();\n      // Requests are made at times tm and ta and tb\n      expect(requestSpy.callCount).to.equal(3);\n      // Unsubscription effects request cancellation when signalled\n      expect(cancelSpy.callCount).to.equal(1);\n    });\n  });\n});\n"
  },
  {
    "path": "packages/rxjs/spec/observables/dom/fetch-spec.ts",
    "content": "import { fromFetch } from 'rxjs/fetch';\nimport { expect } from 'chai';\n\nconst root: any = (typeof globalThis !== 'undefined' && globalThis)\n  || (typeof self !== 'undefined' && self)\n  || global;\n\nconst OK_RESPONSE = {\n  ok: true,\n} as Response;\n\nfunction mockFetchImpl(input: string | Request, init?: RequestInit): Promise<Response> {\n  (mockFetchImpl as MockFetch).calls.push({ input, init });\n  return new Promise<any>((resolve, reject) => {\n    if (init) {\n      if (init.signal) {\n        if (init.signal.aborted) {\n          reject(new MockDOMException());\n          return;\n        }\n        init.signal.addEventListener('abort', () => {\n          reject(new MockDOMException());\n        });\n      }\n    }\n    Promise.resolve(null).then(() => {\n      resolve((mockFetchImpl as any).respondWith);\n    });\n  });\n}\n(mockFetchImpl as MockFetch).reset = function (this: any) {\n  this.calls = [] as any[];\n  this.respondWith = OK_RESPONSE;\n};\n(mockFetchImpl as MockFetch).reset();\n\nconst mockFetch: MockFetch = mockFetchImpl as MockFetch;\n\nclass MockDOMException {}\n\nclass MockAbortController {\n  readonly signal = new MockAbortSignal();\n\n  abort() {\n    this.signal._signal();\n  }\n\n  constructor() {\n    MockAbortController.created++;\n  }\n\n  static created = 0;\n\n  static reset() {\n    MockAbortController.created = 0;\n  }\n}\n\nclass MockAbortSignal {\n  private _listeners: Array<() => unknown> = [];\n\n  aborted = false;\n\n  addEventListener(name: 'abort', handler: () => unknown) {\n    this._listeners.push(handler);\n  }\n\n  removeEventListener(name: 'abort', handler: () => unknown) {\n    const index = this._listeners.indexOf(handler);\n    if (index >= 0) {\n      this._listeners.splice(index, 1);\n    }\n  }\n\n  _signal() {\n    this.aborted = true;\n    while (this._listeners.length > 0) {\n      this._listeners.shift()!();\n    }\n  }\n}\n\ninterface MockFetch {\n  (input: string | Request, init?: RequestInit): Promise<Response>;\n  calls: { input: string | Request, init: RequestInit | undefined }[];\n  reset(): void;\n  respondWith: Response;\n}\n\ndescribe('fromFetch', () => {\n  let _fetch: typeof fetch;\n  let _AbortController: AbortController;\n\n  beforeEach(() => {\n    mockFetch.reset();\n    if (root.fetch) {\n      _fetch = root.fetch;\n    }\n    root.fetch = mockFetch;\n\n    MockAbortController.reset();\n    if (root.AbortController) {\n      _AbortController = root.AbortController;\n    }\n    root.AbortController = MockAbortController;\n  });\n\n  afterEach(() => {\n    root.fetch = _fetch;\n    root.AbortController = _AbortController;\n  });\n\n  it('should exist', () => {\n    expect(fromFetch).to.be.a('function');\n  });\n\n  it('should fetch', (done) => {\n    const fetch$ = fromFetch('/foo');\n    expect(mockFetch.calls.length).to.equal(0);\n    expect(MockAbortController.created).to.equal(0);\n\n    fetch$.subscribe({\n      next: response => {\n        expect(response).to.equal(OK_RESPONSE);\n      },\n      error: done,\n      complete: () => {\n        // Wait until the complete and the subsequent unsubscribe are finished\n        // before testing these expectations:\n        setTimeout(() => {\n          expect(MockAbortController.created).to.equal(1);\n          expect(mockFetch.calls.length).to.equal(1);\n          expect(mockFetch.calls[0].input).to.equal('/foo');\n          expect(mockFetch.calls[0].init!.signal).not.to.be.undefined;\n          expect(mockFetch.calls[0].init!.signal!.aborted).to.be.false;\n          done();\n        }, 0);\n      }\n    });\n  });\n\n  it('should handle Response that is not `ok`', (done) => {\n    mockFetch.respondWith = {\n      ok: false,\n      status: 400,\n      body: 'Bad stuff here'\n    } as any as Response;\n\n    const fetch$ = fromFetch('/foo');\n    expect(mockFetch.calls.length).to.equal(0);\n    expect(MockAbortController.created).to.equal(0);\n\n    fetch$.subscribe({\n      next: response => {\n        expect(response).to.equal(mockFetch.respondWith);\n      },\n      complete: done,\n      error: done\n    });\n\n    expect(MockAbortController.created).to.equal(1);\n    expect(mockFetch.calls.length).to.equal(1);\n    expect(mockFetch.calls[0].input).to.equal('/foo');\n    expect(mockFetch.calls[0].init!.signal).not.to.be.undefined;\n    expect(mockFetch.calls[0].init!.signal!.aborted).to.be.false;\n  });\n\n  it('should abort when unsubscribed', () => {\n    const fetch$ = fromFetch('/foo');\n    expect(mockFetch.calls.length).to.equal(0);\n    expect(MockAbortController.created).to.equal(0);\n    const subscription = fetch$.subscribe();\n\n    expect(MockAbortController.created).to.equal(1);\n    expect(mockFetch.calls.length).to.equal(1);\n    expect(mockFetch.calls[0].input).to.equal('/foo');\n    expect(mockFetch.calls[0].init!.signal).not.to.be.undefined;\n    expect(mockFetch.calls[0].init!.signal!.aborted).to.be.false;\n\n    subscription.unsubscribe();\n    expect(mockFetch.calls[0].init!.signal!.aborted).to.be.true;\n  });\n\n  it('should not immediately abort repeat subscribers', () => {\n    const fetch$ = fromFetch('/foo');\n    expect(mockFetch.calls.length).to.equal(0);\n    expect(MockAbortController.created).to.equal(0);\n    let subscription = fetch$.subscribe();\n    expect(MockAbortController.created).to.equal(1);\n    expect(mockFetch.calls[0].init!.signal!.aborted).to.be.false;\n\n    subscription.unsubscribe();\n    expect(mockFetch.calls[0].init!.signal!.aborted).to.be.true;\n\n    subscription = fetch$.subscribe();\n    expect(MockAbortController.created).to.equal(2);\n    expect(mockFetch.calls[1].init!.signal!.aborted).to.be.false;\n\n    subscription.unsubscribe();\n    expect(mockFetch.calls[1].init!.signal!.aborted).to.be.true;\n  });\n\n  it('should allow passing of init object', (done) => {\n    const fetch$ = fromFetch('/foo', {method: 'HEAD'});\n    fetch$.subscribe({\n      error: done,\n      complete: done,\n    });\n    expect(mockFetch.calls[0].init!.method).to.equal('HEAD');\n  });\n\n  it('should add a signal to internal init object without mutating the passed init object', (done) => {\n    const myInit = {method: 'DELETE'};\n    const fetch$ = fromFetch('/bar', myInit);\n    fetch$.subscribe({\n      error: done,\n      complete: done,\n    });\n    expect(mockFetch.calls[0].init!.method).to.equal(myInit.method);\n    expect(mockFetch.calls[0].init).not.to.equal(myInit);\n    expect(mockFetch.calls[0].init!.signal).not.to.be.undefined;\n  });\n\n  it('should treat passed signals as a cancellation token which triggers an error', (done) => {\n    const controller = new MockAbortController();\n    const signal = controller.signal as any;\n    const fetch$ = fromFetch('/foo', { signal });\n    const subscription = fetch$.subscribe({\n      error: err => {\n        expect(err).to.be.instanceof(MockDOMException);\n        done();\n      }\n    });\n    controller.abort();\n    expect(mockFetch.calls[0].init!.signal!.aborted).to.be.true;\n    // The subscription will not be closed until the error fires when the promise resolves.\n    expect(subscription.closed).to.be.false;\n  });\n\n  it('should treat passed already aborted signals as a cancellation token which triggers an error', (done) => {\n    const controller = new MockAbortController();\n    controller.abort();\n    const signal = controller.signal as any;\n    const fetch$ = fromFetch('/foo', { signal });\n    const subscription = fetch$.subscribe({\n      error: err => {\n        expect(err).to.be.instanceof(MockDOMException);\n        done();\n      }\n    });\n    expect(mockFetch.calls[0].init!.signal!.aborted).to.be.true;\n    // The subscription will not be closed until the error fires when the promise resolves.\n    expect(subscription.closed).to.be.false;\n  });\n\n  it('should not leak listeners added to the passed in signal', (done) => {\n    const controller = new MockAbortController();\n    const signal = controller.signal as any;\n    const fetch$ = fromFetch('/foo', { signal });\n    const subscription = fetch$.subscribe();\n    subscription.add(() => {\n      try {\n        expect(signal._listeners).to.be.empty;\n        done();\n      } catch (error) {\n        done(error);\n      }\n    });\n  });\n\n  it('should support a selector', (done) => {\n    mockFetch.respondWith = {\n      ...OK_RESPONSE,\n      text: () => Promise.resolve('bar')\n    };\n    const fetch$ = fromFetch('/foo', {\n      selector: response => response.text()\n    });\n    expect(mockFetch.calls.length).to.equal(0);\n    expect(MockAbortController.created).to.equal(0);\n\n    fetch$.subscribe({\n      next: text => {\n        expect(text).to.equal('bar');\n      },\n      error: done,\n      complete: () => {\n        // Wait until the complete and the subsequent unsubscribe are finished\n        // before testing these expectations:\n        setTimeout(() => {\n          expect(MockAbortController.created).to.equal(1);\n          expect(mockFetch.calls.length).to.equal(1);\n          expect(mockFetch.calls[0].input).to.equal('/foo');\n          expect(mockFetch.calls[0].init!.signal).not.to.be.undefined;\n          expect(mockFetch.calls[0].init!.signal!.aborted).to.be.false;\n          done();\n        }, 0);\n      }\n    });\n  });\n\n  it('should abort when unsubscribed and a selector is specified', () => {\n    mockFetch.respondWith = {\n      ...OK_RESPONSE,\n      text: () => Promise.resolve('bar')\n    };\n    const fetch$ = fromFetch('/foo', {\n      selector: response => response.text()\n    });\n    expect(mockFetch.calls.length).to.equal(0);\n    expect(MockAbortController.created).to.equal(0);\n    const subscription = fetch$.subscribe();\n\n    expect(MockAbortController.created).to.equal(1);\n    expect(mockFetch.calls.length).to.equal(1);\n    expect(mockFetch.calls[0].input).to.equal('/foo');\n    expect(mockFetch.calls[0].init!.signal).not.to.be.undefined;\n    expect(mockFetch.calls[0].init!.signal!.aborted).to.be.false;\n\n    subscription.unsubscribe();\n    expect(mockFetch.calls[0].init!.signal!.aborted).to.be.true;\n  });\n});\n"
  },
  {
    "path": "packages/rxjs/spec/observables/dom/webSocket-spec.ts",
    "content": "import { expect } from 'chai';\nimport * as sinon from 'sinon';\nimport { webSocket } from 'rxjs/webSocket';\nimport { map, retry, take, repeat, takeWhile } from 'rxjs/operators';\n\nconst root: any = (typeof globalThis !== 'undefined' && globalThis) || (typeof self !== 'undefined' && self) || global;\n\nenum WebSocketState {\n  CONNECTING = 0,\n  OPEN = 1,\n  CLOSING = 2,\n  CLOSED = 3,\n}\n\n/** @test {webSocket}  */\ndescribe('webSocket', () => {\n  let __ws: any;\n\n  function setupMockWebSocket() {\n    __ws = root.WebSocket;\n    root.WebSocket = MockWebSocket;\n  }\n\n  function teardownMockWebSocket() {\n    root.WebSocket = __ws;\n    MockWebSocket.clearSockets();\n  }\n\n  describe('basic behavior', () => {\n    beforeEach(() => {\n      setupMockWebSocket();\n    });\n\n    afterEach(() => {\n      teardownMockWebSocket();\n    });\n\n    it('should send and receive messages', () => {\n      let messageReceived = false;\n      const subject = webSocket<string>('ws://mysocket');\n\n      subject.next('ping');\n\n      subject.subscribe((x) => {\n        expect(x).to.equal('pong');\n        messageReceived = true;\n      });\n\n      const socket = MockWebSocket.lastSocket;\n      expect(socket.url).to.equal('ws://mysocket');\n\n      socket.open();\n      expect(socket.lastMessageSent).to.equal(JSON.stringify('ping'));\n\n      socket.triggerMessage(JSON.stringify('pong'));\n      expect(messageReceived).to.be.true;\n\n      subject.unsubscribe();\n    });\n\n    it('should allow use of operators and subscribe', () => {\n      const subject = webSocket<string>('ws://mysocket');\n      const results: any[] = [];\n\n      subject.pipe(map((x) => x + '!')).subscribe((x) => results.push(x));\n\n      MockWebSocket.lastSocket.triggerMessage(JSON.stringify('ngconf 2018 bug'));\n\n      expect(results).to.deep.equal(['ngconf 2018 bug!']);\n    });\n\n    it('receive multiple messages', () => {\n      const expected = ['what', 'do', 'you', 'do', 'with', 'a', 'drunken', 'sailor?'];\n      const results: string[] = [];\n      const subject = webSocket<string>('ws://mysocket');\n\n      subject.subscribe((x) => {\n        results.push(x);\n      });\n\n      const socket = MockWebSocket.lastSocket;\n\n      socket.open();\n\n      expected.forEach((x) => {\n        socket.triggerMessage(JSON.stringify(x));\n      });\n\n      expect(results).to.deep.equal(expected);\n\n      subject.unsubscribe();\n    });\n\n    it('should queue messages prior to subscription', () => {\n      const expected = ['make', 'him', 'walk', 'the', 'plank'];\n      const subject = webSocket<string>('ws://mysocket');\n\n      expected.forEach((x) => {\n        subject.next(x);\n      });\n\n      let socket = MockWebSocket.lastSocket;\n      expect(socket).not.exist;\n\n      subject.subscribe();\n\n      socket = MockWebSocket.lastSocket;\n      expect(socket.sent.length).to.equal(0);\n\n      socket.open();\n      expect(socket.sent.length).to.equal(expected.length);\n\n      subject.unsubscribe();\n    });\n\n    it('should send messages immediately if already open', () => {\n      const subject = webSocket<string>('ws://mysocket');\n      subject.subscribe();\n      const socket = MockWebSocket.lastSocket;\n      socket.open();\n\n      subject.next('avast!');\n      expect(socket.lastMessageSent).to.equal(JSON.stringify('avast!'));\n      subject.next('ye swab!');\n      expect(socket.lastMessageSent).to.equal(JSON.stringify('ye swab!'));\n\n      subject.unsubscribe();\n    });\n\n    it('should close the socket when completed', () => {\n      const subject = webSocket<string>('ws://mysocket');\n      subject.subscribe();\n      const socket = MockWebSocket.lastSocket;\n      socket.open();\n\n      expect(socket.readyState).to.equal(WebSocketState.OPEN);\n\n      sinon.spy(socket, 'close');\n\n      expect(socket.close).not.have.been.called;\n\n      subject.complete();\n      expect(socket.close).have.been.called;\n      expect(socket.readyState).to.equal(WebSocketState.CLOSING);\n\n      socket.triggerClose({ wasClean: true });\n      expect(socket.readyState).to.equal(WebSocketState.CLOSED);\n\n      subject.unsubscribe();\n      (<any>socket.close).restore();\n    });\n\n    it('should close the socket when unsubscribed before socket open', () => {\n      const subject = webSocket<string>('ws://mysocket');\n      subject.subscribe();\n      subject.unsubscribe();\n      const socket = MockWebSocket.lastSocket;\n      sinon.spy(socket, 'close');\n      socket.open();\n\n      expect(socket.close).have.been.called;\n      expect(socket.readyState).to.equal(WebSocketState.CLOSING);\n\n      (<any>socket.close).restore();\n    });\n\n    it('should close the socket when subscription is cancelled before socket open', () => {\n      const subject = webSocket<string>('ws://mysocket');\n      const subscription = subject.subscribe();\n      subscription.unsubscribe();\n      const socket = MockWebSocket.lastSocket;\n      sinon.spy(socket, 'close');\n      socket.open();\n\n      expect(socket.close).have.been.called;\n      expect(socket.readyState).to.equal(WebSocketState.CLOSING);\n\n      (<any>socket.close).restore();\n    });\n\n    it('should close the socket when unsubscribed while connecting', () => {\n      const subject = webSocket<string>('ws://mysocket');\n      subject.subscribe();\n      const socket = MockWebSocket.lastSocket;\n      sinon.spy(socket, 'close');\n      subject.unsubscribe();\n\n      expect(socket.close).have.been.called;\n      expect(socket.readyState).to.equal(WebSocketState.CLOSING);\n\n      (<any>socket.close).restore();\n    });\n\n    it('should close the socket when subscription is cancelled while connecting', () => {\n      const subject = webSocket<string>('ws://mysocket');\n      const subscription = subject.subscribe();\n      const socket = MockWebSocket.lastSocket;\n      sinon.spy(socket, 'close');\n      subscription.unsubscribe();\n\n      expect(socket.close).have.been.called;\n      expect(socket.readyState).to.equal(WebSocketState.CLOSING);\n\n      (<any>socket.close).restore();\n    });\n\n    it('should close a socket that opens before the previous socket has closed', () => {\n      const subject = webSocket<string>('ws://mysocket');\n      const subscription = subject.subscribe();\n      const socket = MockWebSocket.lastSocket;\n      sinon.spy(socket, 'close');\n      subscription.unsubscribe();\n\n      expect(socket.close).have.been.called;\n      expect(socket.readyState).to.equal(WebSocketState.CLOSING);\n\n      const subscription2 = subject.subscribe();\n      const socket2 = MockWebSocket.lastSocket;\n      sinon.spy(socket2, 'close');\n\n      // Close socket after socket2 has opened\n      socket2.open();\n      expect(socket2.readyState).to.equal(WebSocketState.OPEN);\n      socket.triggerClose({ wasClean: true });\n\n      expect(socket.readyState).to.equal(WebSocketState.CLOSED);\n      expect(socket2.close).have.not.been.called;\n\n      subscription2.unsubscribe();\n      expect(socket2.close).have.been.called;\n      expect(socket2.readyState).to.equal(WebSocketState.CLOSING);\n\n      (<any>socket.close).restore();\n    });\n\n    it('should close the socket with a code and a reason when errored', () => {\n      const subject = webSocket<string>('ws://mysocket');\n      subject.subscribe();\n      const socket = MockWebSocket.lastSocket;\n      socket.open();\n\n      sinon.spy(socket, 'close');\n      expect(socket.close).not.have.been.called;\n\n      subject.error({ code: 1337, reason: 'Too bad, so sad :(' });\n      expect(socket.close).have.been.calledWith(1337, 'Too bad, so sad :(');\n\n      subject.unsubscribe();\n      (<any>socket.close).restore();\n    });\n\n    it('should allow resubscription after closure via complete', () => {\n      const subject = webSocket<string>('ws://mysocket');\n      subject.subscribe();\n      const socket1 = MockWebSocket.lastSocket;\n      socket1.open();\n      subject.complete();\n\n      subject.next('a mariner yer not. yarrr.');\n      subject.subscribe();\n      const socket2 = MockWebSocket.lastSocket;\n      socket2.open();\n\n      expect(socket2).not.to.equal(socket1);\n      expect(socket2.lastMessageSent).to.equal(JSON.stringify('a mariner yer not. yarrr.'));\n\n      subject.unsubscribe();\n    });\n\n    it('should allow resubscription after closure via error', () => {\n      const subject = webSocket<string>('ws://mysocket');\n      subject.subscribe();\n      const socket1 = MockWebSocket.lastSocket;\n      socket1.open();\n      subject.error({ code: 1337 });\n\n      subject.next('yo-ho! yo-ho!');\n      subject.subscribe();\n      const socket2 = MockWebSocket.lastSocket;\n      socket2.open();\n\n      expect(socket2).not.to.equal(socket1);\n      expect(socket2.lastMessageSent).to.equal(JSON.stringify('yo-ho! yo-ho!'));\n\n      subject.unsubscribe();\n    });\n\n    it('should have a default resultSelector that parses message data as JSON', () => {\n      let result;\n      const expected = { mork: 'shazbot!' };\n      const subject = webSocket<string>('ws://mysocket');\n\n      subject.subscribe((x: any) => {\n        result = x;\n      });\n\n      const socket = MockWebSocket.lastSocket;\n      socket.open();\n      socket.triggerMessage(JSON.stringify(expected));\n\n      expect(result).to.deep.equal(expected);\n\n      subject.unsubscribe();\n    });\n  });\n\n  describe('with a config object', () => {\n    beforeEach(() => {\n      setupMockWebSocket();\n    });\n\n    afterEach(() => {\n      teardownMockWebSocket();\n    });\n\n    it('should send and receive messages', () => {\n      let messageReceived = false;\n      const subject = webSocket<string>({ url: 'ws://mysocket' });\n\n      subject.next('ping');\n\n      subject.subscribe((x) => {\n        expect(x).to.equal('pong');\n        messageReceived = true;\n      });\n\n      const socket = MockWebSocket.lastSocket;\n      expect(socket.url).to.equal('ws://mysocket');\n\n      socket.open();\n      expect(socket.lastMessageSent).to.equal(JSON.stringify('ping'));\n\n      socket.triggerMessage(JSON.stringify('pong'));\n      expect(messageReceived).to.be.true;\n\n      subject.unsubscribe();\n    });\n\n    it('should take a protocol and set it properly on the web socket', () => {\n      const subject = webSocket<string>({\n        url: 'ws://mysocket',\n        protocol: 'someprotocol',\n      });\n\n      subject.subscribe();\n\n      const socket = MockWebSocket.lastSocket;\n      expect(socket.protocol).to.equal('someprotocol');\n\n      subject.unsubscribe();\n    });\n\n    it('should take a binaryType and set it properly on the web socket', () => {\n      const subject = webSocket<string>({\n        url: 'ws://mysocket',\n        binaryType: 'blob',\n      });\n\n      subject.subscribe();\n\n      const socket = MockWebSocket.lastSocket;\n      expect(socket.binaryType).to.equal('blob');\n\n      subject.unsubscribe();\n    });\n\n    it('should take a deserializer', () => {\n      const results = [] as string[];\n\n      const subject = webSocket<string>({\n        url: 'ws://mysocket',\n        deserializer: (e: any) => {\n          return e.data + '!';\n        },\n      });\n\n      subject.subscribe((x: any) => {\n        results.push(x);\n      });\n\n      const socket = MockWebSocket.lastSocket;\n      socket.open();\n      ['ahoy', 'yarr', 'shove off'].forEach((x: any) => {\n        socket.triggerMessage(x);\n      });\n\n      expect(results).to.deep.equal(['ahoy!', 'yarr!', 'shove off!']);\n\n      subject.unsubscribe();\n    });\n\n    it('if the deserializer fails it should go down the error path', () => {\n      const subject = webSocket<string>({\n        url: 'ws://mysocket',\n        deserializer: (e: any) => {\n          throw new Error('I am a bad error');\n        },\n      });\n\n      subject.subscribe({\n        next: (x: any) => {\n          expect(x).to.equal('this should not happen');\n        },\n        error: (err: any) => {\n          expect(err).to.be.an('error', 'I am a bad error');\n        },\n      });\n\n      const socket = MockWebSocket.lastSocket;\n      socket.open();\n      socket.triggerMessage('weee!');\n\n      subject.unsubscribe();\n    });\n\n    it('should accept a closingObserver', () => {\n      let calls = 0;\n      const subject = webSocket<string>(<any>{\n        url: 'ws://mysocket',\n        closingObserver: {\n          next(x: any) {\n            calls++;\n            expect(x).to.be.an('undefined');\n          },\n        },\n      });\n\n      subject.subscribe();\n      let socket = MockWebSocket.lastSocket;\n      socket.open();\n\n      expect(calls).to.equal(0);\n\n      subject.complete();\n      expect(calls).to.equal(1);\n\n      subject.subscribe();\n      socket = MockWebSocket.lastSocket;\n      socket.open();\n\n      subject.error({ code: 1337 });\n      expect(calls).to.equal(2);\n\n      subject.unsubscribe();\n    });\n\n    it('should accept a closeObserver', () => {\n      const expected = [{ wasClean: true }, { wasClean: false }];\n      const closes = [] as any[];\n      const subject = webSocket<string>(<any>{\n        url: 'ws://mysocket',\n        closeObserver: {\n          next(e: any) {\n            closes.push(e);\n          },\n        },\n      });\n\n      subject.subscribe();\n      let socket = MockWebSocket.lastSocket;\n      socket.open();\n\n      expect(closes.length).to.equal(0);\n\n      socket.triggerClose(expected[0]);\n      expect(closes.length).to.equal(1);\n\n      subject.subscribe({\n        error: function (err) {\n          expect(err).to.equal(expected[1]);\n        },\n      });\n\n      socket = MockWebSocket.lastSocket;\n      socket.open();\n\n      socket.triggerClose(expected[1]);\n      expect(closes.length).to.equal(2);\n\n      expect(closes[0]).to.equal(expected[0]);\n      expect(closes[1]).to.equal(expected[1]);\n\n      subject.unsubscribe();\n    });\n\n    it('should handle constructor errors', () => {\n      const subject = webSocket<string>(<any>{\n        url: 'bad_url',\n        WebSocketCtor: (url: string, protocol?: string | string[]): WebSocket => {\n          throw new Error(`connection refused`);\n        },\n      });\n\n      subject.subscribe({\n        next: (x: any) => {\n          expect(x).to.equal('this should not happen');\n        },\n        error: (err: any) => {\n          expect(err).to.be.an('error', 'connection refused');\n        },\n      });\n\n      subject.unsubscribe();\n    });\n  });\n\n  describe('multiplex', () => {\n    beforeEach(() => {\n      setupMockWebSocket();\n    });\n\n    afterEach(() => {\n      teardownMockWebSocket();\n    });\n\n    it('should be retryable', () => {\n      const results = [] as string[];\n      const subject = webSocket<{ sub: string } | { unsub: string }, { name: string; value: string }>('ws://websocket');\n      const source = subject.multiplex(\n        () => ({ sub: 'foo' }),\n        () => ({ unsub: 'foo' }),\n        (value) => value.name === 'foo'\n      );\n\n      source\n        .pipe(\n          retry(1),\n          map((x) => x.value),\n          take(2)\n        )\n        .subscribe((x) => {\n          results.push(x);\n        });\n\n      const socket = MockWebSocket.lastSocket;\n      socket.open();\n\n      expect(socket.lastMessageSent).to.deep.equal(JSON.stringify({ sub: 'foo' }));\n      socket.triggerClose({ wasClean: false }); // Bad connection\n\n      const socket2 = MockWebSocket.lastSocket;\n      expect(socket2).not.to.equal(socket);\n\n      socket2.open();\n      expect(socket2.lastMessageSent).to.deep.equal(JSON.stringify({ sub: 'foo' }));\n\n      socket2.triggerMessage(JSON.stringify({ name: 'foo', value: 'test' }));\n      socket2.triggerMessage(JSON.stringify({ name: 'foo', value: 'this' }));\n\n      expect(results).to.deep.equal(['test', 'this']);\n    });\n\n    it('should be repeatable', () => {\n      const results = [] as string[];\n      const subject = webSocket<{ sub: string } | { unsub: string }, { name: string; value: string }>('ws://websocket');\n\n      const source = subject.multiplex(\n        () => ({ sub: 'foo' }),\n        () => ({ unsub: 'foo' }),\n        (value) => value.name === 'foo'\n      );\n\n      source\n        .pipe(\n          repeat(2),\n          map((x) => x.value)\n        )\n        .subscribe((x) => {\n          results.push(x);\n        });\n\n      const socket = MockWebSocket.lastSocket;\n      socket.open();\n\n      expect(socket.lastMessageSent).to.deep.equal(JSON.stringify({ sub: 'foo' }), 'first multiplexed sub');\n      socket.triggerMessage(JSON.stringify({ name: 'foo', value: 'test' }));\n      socket.triggerMessage(JSON.stringify({ name: 'foo', value: 'this' }));\n      socket.triggerClose({ wasClean: true });\n\n      const socket2 = MockWebSocket.lastSocket;\n      expect(socket2).not.to.equal(socket, 'a new socket was not created');\n\n      socket2.open();\n      expect(socket2.lastMessageSent).to.deep.equal(JSON.stringify({ sub: 'foo' }), 'second multiplexed sub');\n      socket2.triggerMessage(JSON.stringify({ name: 'foo', value: 'test' }));\n      socket2.triggerMessage(JSON.stringify({ name: 'foo', value: 'this' }));\n      socket2.triggerClose({ wasClean: true });\n\n      expect(results).to.deep.equal(['test', 'this', 'test', 'this'], 'results were not equal');\n    });\n\n    it('should multiplex over the webSocket', () => {\n      const results = [] as Array<{ value: number; name: string }>;\n      const subject = webSocket<{ sub: string } | { unsub: string }, { value: number; name: string }>('ws://websocket');\n      const source = subject.multiplex(\n        () => ({ sub: 'foo' }),\n        () => ({ unsub: 'foo' }),\n        (value) => value.name === 'foo'\n      );\n\n      const sub = source.subscribe(function (x: any) {\n        results.push(x.value);\n      });\n      const socket = MockWebSocket.lastSocket;\n      socket.open();\n\n      expect(socket.lastMessageSent).to.deep.equal(JSON.stringify({ sub: 'foo' }));\n\n      [1, 2, 3, 4, 5]\n        .map((x: number) => {\n          return {\n            name: x % 3 === 0 ? 'bar' : 'foo',\n            value: x,\n          };\n        })\n        .forEach((x: any) => {\n          socket.triggerMessage(JSON.stringify(x));\n        });\n\n      expect(results).to.deep.equal([1, 2, 4, 5]);\n\n      sinon.spy(socket, 'close');\n      sub.unsubscribe();\n      expect(socket.lastMessageSent).to.deep.equal(JSON.stringify({ unsub: 'foo' }));\n\n      expect(socket.close).have.been.called;\n      (<any>socket.close).restore();\n    });\n\n    it('should keep the same socket for multiple multiplex subscriptions', () => {\n      const socketSubject = webSocket<string>({ url: 'ws://mysocket' });\n      const results = [] as string[];\n      const socketMessages = [{ id: 'A' }, { id: 'B' }, { id: 'A' }, { id: 'B' }, { id: 'B' }];\n\n      const sub1 = socketSubject\n        .multiplex(\n          () => 'no-op',\n          () => (results.push('A unsub'), 'no-op'),\n          (req: any) => req.id === 'A'\n        )\n        .pipe(takeWhile((req: any) => !req.complete))\n        .subscribe({\n          next: () => results.push('A next'),\n          error: (e) => results.push('A error ' + e),\n          complete: () => results.push('A complete'),\n        });\n\n      socketSubject\n        .multiplex(\n          () => 'no-op',\n          () => (results.push('B unsub'), 'no-op'),\n          (req: any) => req.id === 'B'\n        )\n        .subscribe({\n          next: () => results.push('B next'),\n          error: (e) => results.push('B error ' + e),\n          complete: () => results.push('B complete'),\n        });\n\n      // Setup socket and send messages\n      const socket = MockWebSocket.lastSocket;\n      socket.open();\n      socketMessages.forEach((msg, i) => {\n        if (i === 1) {\n          sub1.unsubscribe();\n          expect((socketSubject as any)._socket).to.equal(socket);\n        }\n        socket.triggerMessage(JSON.stringify(msg));\n      });\n      socket.triggerClose({ wasClean: true });\n\n      expect(results).to.deep.equal(['A next', 'A unsub', 'B next', 'B next', 'B next', 'B complete', 'B unsub']);\n    });\n\n    it('should not close the socket until all subscriptions complete', () => {\n      const socketSubject = webSocket<string, { id: string; complete: boolean }>({ url: 'ws://mysocket' });\n      const results = [] as string[];\n      const socketMessages = [{ id: 'A' }, { id: 'B' }, { id: 'A', complete: true }, { id: 'B' }, { id: 'B', complete: true }];\n\n      socketSubject\n        .multiplex(\n          () => 'no-op',\n          () => (results.push('A unsub'), 'no-op'),\n          (req) => req.id === 'A'\n        )\n        .pipe(takeWhile((req) => !req.complete))\n        .subscribe({\n          next: () => results.push('A next'),\n          error: (e) => results.push('A error ' + e),\n          complete: () => results.push('A complete'),\n        });\n\n      socketSubject\n        .multiplex(\n          () => 'no-op',\n          () => (results.push('B unsub'), 'no-op'),\n          (req) => req.id === 'B'\n        )\n        .pipe(takeWhile((req) => !req.complete))\n        .subscribe({\n          next: () => results.push('B next'),\n          error: (e) => results.push('B error ' + e),\n          complete: () => results.push('B complete'),\n        });\n\n      // Setup socket and send messages\n      const socket = MockWebSocket.lastSocket;\n      socket.open();\n      socketMessages.forEach((msg) => {\n        socket.triggerMessage(JSON.stringify(msg));\n      });\n\n      expect(results).to.deep.equal(['A next', 'B next', 'A unsub', 'A complete', 'B next', 'B unsub', 'B complete']);\n    });\n  });\n\n  describe('node constructor', () => {\n    it('should send and receive messages', () => {\n      let messageReceived = false;\n      const subject = webSocket<string>(<any>{\n        url: 'ws://mysocket',\n        WebSocketCtor: MockWebSocket,\n      });\n\n      subject.next('ping');\n\n      subject.subscribe((x) => {\n        expect(x).to.equal('pong');\n        messageReceived = true;\n      });\n\n      const socket = MockWebSocket.lastSocket;\n      expect(socket.url).to.equal('ws://mysocket');\n\n      socket.open();\n      expect(socket.lastMessageSent).to.equal(JSON.stringify('ping'));\n\n      socket.triggerMessage(JSON.stringify('pong'));\n      expect(messageReceived).to.be.true;\n\n      subject.unsubscribe();\n    });\n\n    it('should handle constructor errors if no WebSocketCtor', () => {\n      expect(() => {\n        const subject = webSocket<string>(<any>{\n          url: 'ws://mysocket',\n        });\n      }).to.throw('no WebSocket constructor can be found');\n    });\n  });\n});\n\nclass MockWebSocket {\n  static sockets: Array<MockWebSocket> = [];\n  static get lastSocket(): MockWebSocket {\n    const socket = MockWebSocket.sockets;\n    const length = socket.length;\n    return length > 0 ? socket[length - 1] : undefined!;\n  }\n\n  static clearSockets(): void {\n    MockWebSocket.sockets.length = 0;\n  }\n\n  sent: string[] = [];\n  handlers: any = {};\n  readyState: WebSocketState = WebSocketState.CONNECTING;\n  closeCode: any;\n  closeReason: any;\n  binaryType?: string;\n\n  constructor(public url: string, public protocol: string) {\n    MockWebSocket.sockets.push(this);\n  }\n\n  send(data: string): void {\n    this.sent.push(data);\n  }\n\n  get lastMessageSent(): string {\n    const sent = this.sent;\n    const length = sent.length;\n    return length > 0 ? sent[length - 1] : undefined!;\n  }\n\n  triggerClose(e: Partial<CloseEvent>): void {\n    this.readyState = WebSocketState.CLOSED;\n    this.trigger('close', e);\n  }\n\n  triggerMessage(data: any): void {\n    const messageEvent = {\n      data: data,\n      origin: 'mockorigin',\n      ports: undefined as any,\n      source: root,\n    };\n\n    this.trigger('message', messageEvent);\n  }\n\n  open(): void {\n    this.readyState = WebSocketState.OPEN;\n    this.trigger('open', {});\n  }\n\n  close(code: any, reason: any): void {\n    if (this.readyState < WebSocketState.CLOSING) {\n      this.readyState = WebSocketState.CLOSING;\n      this.closeCode = code;\n      this.closeReason = reason;\n    }\n  }\n\n  trigger(this: any, name: string, e: any) {\n    if (this['on' + name]) {\n      this['on' + name](e);\n    }\n\n    const lookup = this.handlers[name];\n    if (lookup) {\n      for (let i = 0; i < lookup.length; i++) {\n        lookup[i](e);\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "packages/rxjs/spec/observables/empty-spec.ts",
    "content": "/** @prettier */\nimport { expect } from 'chai';\nimport { EMPTY } from 'rxjs';\nimport { TestScheduler } from 'rxjs/testing';\nimport { observableMatcher } from '../helpers/observableMatcher';\n\n/** @test {empty} */\ndescribe('empty', () => {\n  let rxTestScheduler: TestScheduler;\n\n  beforeEach(() => {\n    rxTestScheduler = new TestScheduler(observableMatcher);\n  });\n\n  it('should only complete', () => {\n    rxTestScheduler.run(({ expectObservable }) => {\n      const expected = '|';\n      expectObservable(EMPTY).toBe(expected);\n    });\n  });\n\n  it('should be synchronous', () => {\n    let hit = false;\n    EMPTY.subscribe({\n      complete() {\n        hit = true;\n      },\n    });\n    expect(hit).to.be.true;\n  });\n});\n"
  },
  {
    "path": "packages/rxjs/spec/observables/forkJoin-spec.ts",
    "content": "/** @prettier */\nimport { expect } from 'chai';\nimport { EmptyError, finalize, forkJoin, map, of, timer } from 'rxjs';\nimport { lowerCaseO } from '../helpers/test-helper';\nimport { TestScheduler } from 'rxjs/testing';\nimport { observableMatcher } from '../helpers/observableMatcher';\n\n/** @test {forkJoin} */\ndescribe('forkJoin', () => {\n  let rxTestScheduler: TestScheduler;\n\n  beforeEach(() => {\n    rxTestScheduler = new TestScheduler(observableMatcher);\n  });\n\n  it('should join the last values of the provided observables into an array', () => {\n    rxTestScheduler.run(({ hot, cold, expectObservable }) => {\n      const s1 = hot('  -a--b-----c-d-e-|');\n      const s2 = hot('  --------f--g-h-i--j-|');\n      const s3 = cold(' --1--2-3-4---|');\n      const e1 = forkJoin([s1, s2, s3]);\n      const expected = '--------------------(x|)';\n\n      expectObservable(e1).toBe(expected, { x: ['e', 'j', '4'] });\n    });\n  });\n\n  it('should support a resultSelector with an Array of ObservableInputs', () => {\n    const results: Array<number | string> = [];\n    forkJoin([of(1, 2, 3), of(4, 5, 6), of(7, 8, 9)], (a: number, b: number, c: number) => a + b + c).subscribe({\n      next(value) {\n        results.push(value);\n      },\n      error(err) {\n        throw err;\n      },\n      complete() {\n        results.push('done');\n      },\n    });\n\n    expect(results).to.deep.equal([18, 'done']);\n  });\n\n  it('should support a resultSelector with a spread of ObservableInputs', () => {\n    const results: Array<number | string> = [];\n    forkJoin(of(1, 2, 3), of(4, 5, 6), of(7, 8, 9), (a: number, b: number, c: number) => a + b + c).subscribe({\n      next(value) {\n        results.push(value);\n      },\n      error(err) {\n        throw err;\n      },\n      complete() {\n        results.push('done');\n      },\n    });\n\n    expect(results).to.deep.equal([18, 'done']);\n  });\n\n  it('should accept single observable', () => {\n    rxTestScheduler.run(({ hot, expectObservable }) => {\n      const e1 = forkJoin(hot('--a--b--c--d--|'));\n      const expected = '       --------------(x|)';\n\n      expectObservable(e1).toBe(expected, { x: ['d'] });\n    });\n  });\n\n  describe('forkJoin([input1, input2, input3])', () => {\n    it('should join the last values of the provided observables into an array', () => {\n      rxTestScheduler.run(({ hot, expectObservable }) => {\n        const s1 = hot('  --a--b--c--d--|');\n        const s2 = hot('  (b|)');\n        const s3 = hot('  --1--2--3--|');\n        const e1 = forkJoin([s1, s2, s3]);\n        const expected = '--------------(x|)';\n\n        expectObservable(e1).toBe(expected, { x: ['d', 'b', '3'] });\n      });\n    });\n\n    it('should allow emit null or undefined', () => {\n      rxTestScheduler.run(({ hot, expectObservable }) => {\n        const e2 = forkJoin([\n          hot('            --a--b--c--d--|', { d: null }),\n          hot('            (b|)'),\n          hot('            --1--2--3--|'),\n          hot('            -----r--t--u--|', { u: undefined }),\n        ]);\n        const expected2 = '--------------(x|)';\n\n        expectObservable(e2).toBe(expected2, { x: [null, 'b', '3', undefined] });\n      });\n    });\n\n    it('should accept array of observable contains single', () => {\n      rxTestScheduler.run(({ hot, expectObservable }) => {\n        const s1 = hot('  --a--b--c--d--|');\n        const e1 = forkJoin([s1]);\n        const expected = '--------------(x|)';\n\n        expectObservable(e1).toBe(expected, { x: ['d'] });\n      });\n    });\n\n    it('should accept lowercase-o observables', () => {\n      rxTestScheduler.run(({ hot, expectObservable }) => {\n        const s1 = hot('  --a--b--c--d--|');\n        const s2 = hot('  (b|)');\n        const s3 = lowerCaseO('1', '2', '3');\n        const e1 = forkJoin([s1, s2, s3]);\n        const expected = '--------------(x|)';\n\n        expectObservable(e1).toBe(expected, { x: ['d', 'b', '3'] });\n      });\n    });\n\n    it('should accept empty lowercase-o observables', () => {\n      rxTestScheduler.run(({ hot, expectObservable }) => {\n        const s1 = hot('  --a--b--c--d--|');\n        const s2 = hot('  (b|)');\n        const s3 = lowerCaseO();\n        const e1 = forkJoin([s1, s2, s3]);\n        const expected = '#';\n\n        expectObservable(e1).toBe(expected, undefined, new EmptyError());\n      });\n    });\n\n    it('should accept promise', (done) => {\n      rxTestScheduler.run(() => {\n        const e1 = forkJoin([of(1), Promise.resolve(2)]);\n\n        e1.subscribe({\n          next: (x) => expect(x).to.deep.equal([1, 2]),\n          complete: done,\n        });\n      });\n    });\n\n    it('should accept array of observables', () => {\n      rxTestScheduler.run(({ hot, expectObservable }) => {\n        const s1 = hot('  --a--b--c--d--|');\n        const s2 = hot('  (b|)');\n        const s3 = hot('  --1--2--3--|');\n        const e1 = forkJoin([s1, s2, s3]);\n        const expected = '--------------(x|)';\n\n        expectObservable(e1).toBe(expected, { x: ['d', 'b', '3'] });\n      });\n    });\n\n    it('should not emit if any of source observable is empty', () => {\n      rxTestScheduler.run(({ hot, expectObservable }) => {\n        const s1 = hot('  --a--b--c--d--|');\n        const s2 = hot('  (b|)');\n        const s3 = hot('  ------------------|');\n        const e1 = forkJoin([s1, s2, s3]);\n        const expected = '------------------#';\n\n        expectObservable(e1).toBe(expected, undefined, new EmptyError());\n      });\n    });\n\n    it('should error with EmptyError if any of source is empty and completes before than others', () => {\n      rxTestScheduler.run(({ hot, expectObservable }) => {\n        const s1 = hot('  --a--b--c--d--|');\n        const s2 = hot('  (b|)');\n        const s3 = hot('  ---------|');\n        const e1 = forkJoin([s1, s2, s3]);\n        const expected = '---------#';\n\n        expectObservable(e1).toBe(expected, undefined, new EmptyError());\n      });\n    });\n\n    it('should error on the first empty source', () => {\n      rxTestScheduler.run(({ hot, expectObservable }) => {\n        const s1 = hot('  --------------|');\n        const s2 = hot('  ---------|');\n        const e1 = forkJoin([s1, s2]);\n        const expected = '---------#';\n\n        expectObservable(e1).toBe(expected, undefined, new EmptyError());\n      });\n    });\n\n    it('should not complete when only source never completes', () => {\n      rxTestScheduler.run(({ hot, expectObservable }) => {\n        const e1 = forkJoin([hot('--------------')]);\n        const expected = '        --------------';\n\n        expectObservable(e1).toBe(expected);\n      });\n    });\n\n    it('should not complete when one of the sources never completes', () => {\n      rxTestScheduler.run(({ hot, expectObservable }) => {\n        const s1 = hot('--------------');\n        const s2 = hot('-a---b--c--|');\n        const e1 = forkJoin([s1, s2]);\n        const expected = '-';\n\n        expectObservable(e1).toBe(expected);\n      });\n    });\n\n    it('should complete when one of the sources never completes but other completes without values', () => {\n      rxTestScheduler.run(({ hot, expectObservable }) => {\n        const s1 = hot('  --------------');\n        const s2 = hot('  ------|');\n        const e1 = forkJoin([s1, s2]);\n        const expected = '------#';\n\n        expectObservable(e1).toBe(expected, undefined, new EmptyError());\n      });\n    });\n\n    it('should complete if source is not provided', () => {\n      rxTestScheduler.run(({ expectObservable }) => {\n        const e1 = forkJoin();\n        const expected = '|';\n\n        expectObservable(e1).toBe(expected);\n      });\n    });\n\n    it('should complete if sources list is empty', () => {\n      rxTestScheduler.run(({ expectObservable }) => {\n        const e1 = forkJoin([]);\n        const expected = '|';\n\n        expectObservable(e1).toBe(expected);\n      });\n    });\n\n    it('should raise error when any of source raises error with empty observable', () => {\n      rxTestScheduler.run(({ hot, expectObservable }) => {\n        const s1 = hot('  ------#');\n        const s2 = hot('  ---------|');\n        const e1 = forkJoin([s1, s2]);\n        const expected = '------#';\n\n        expectObservable(e1).toBe(expected);\n      });\n    });\n\n    it('should raise error when any of source raises error with source that never completes', () => {\n      rxTestScheduler.run(({ hot, expectObservable }) => {\n        const s1 = hot('  ------#');\n        const s2 = hot('  ----------');\n        const e1 = forkJoin([s1, s2]);\n        const expected = '------#';\n\n        expectObservable(e1).toBe(expected);\n      });\n    });\n\n    it('should raise error when source raises error', () => {\n      rxTestScheduler.run(({ hot, expectObservable }) => {\n        const s1 = hot('  ------#');\n        const s2 = hot('  ---a-----|');\n        const e1 = forkJoin([s1, s2]);\n        const expected = '------#';\n\n        expectObservable(e1).toBe(expected);\n      });\n    });\n\n    it('should allow unsubscribing early and explicitly', () => {\n      rxTestScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n        const e1 = hot('--a--^--b--c---d-| ');\n        const e1subs = '     ^--------!    ';\n        const e2 = hot('---e-^---f--g---h-|');\n        const e2subs = '     ^--------!    ';\n        const expected = '   ----------    ';\n        const unsub = '      ---------!    ';\n\n        const result = forkJoin([e1, e2]);\n\n        expectObservable(result, unsub).toBe(expected);\n        expectSubscriptions(e1.subscriptions).toBe(e1subs);\n        expectSubscriptions(e2.subscriptions).toBe(e2subs);\n      });\n    });\n\n    it('should unsubscribe other Observables, when one of them errors', () => {\n      rxTestScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n        const e1 = hot('--a--^--b--c---d-| ');\n        const e1subs = '     ^--------!    ';\n        const e2 = hot('---e-^---f--g-#');\n        const e2subs = '     ^--------!    ';\n        const expected = '   ---------#    ';\n\n        const result = forkJoin([e1, e2]);\n\n        expectObservable(result).toBe(expected);\n        expectSubscriptions(e1.subscriptions).toBe(e1subs);\n        expectSubscriptions(e2.subscriptions).toBe(e2subs);\n      });\n    });\n  });\n\n  it('should finalize in the proper order', () => {\n    const results: any[] = [];\n    const source = forkJoin(\n      [1, 2, 3, 4].map((n) =>\n        timer(100, rxTestScheduler).pipe(\n          map(() => n),\n          finalize(() => results.push(`finalized ${n}`))\n        )\n      )\n    );\n\n    source.subscribe((value) => results.push(value));\n    rxTestScheduler.flush();\n    expect(results).to.deep.equal(['finalized 1', 'finalized 2', 'finalized 3', 'finalized 4', [1, 2, 3, 4]]);\n  });\n\n  describe('forkJoin({ foo, bar, baz })', () => {\n    it('should join the last values of the provided observables into an array', () => {\n      rxTestScheduler.run(({ hot, expectObservable }) => {\n        const e1 = forkJoin({\n          foo: hot('      --a--b--c--d--|'),\n          bar: hot('      (b|)'),\n          baz: hot('      --1--2--3--|'),\n        });\n        const expected = '--------------(x|)';\n\n        expectObservable(e1).toBe(expected, { x: { foo: 'd', bar: 'b', baz: '3' } });\n      });\n    });\n\n    it('should allow emit null or undefined', () => {\n      rxTestScheduler.run(({ hot, expectObservable }) => {\n        const e2 = forkJoin({\n          foo: hot('       --a--b--c--d--|', { d: null }),\n          bar: hot('       (b|)'),\n          baz: hot('       --1--2--3--|'),\n          qux: hot('       -----r--t--u--|', { u: undefined }),\n        });\n        const expected2 = '--------------(x|)';\n\n        expectObservable(e2).toBe(expected2, { x: { foo: null, bar: 'b', baz: '3', qux: undefined } });\n      });\n    });\n\n    it('should accept array of observable contains single', () => {\n      rxTestScheduler.run(({ hot, expectObservable }) => {\n        const e1 = forkJoin({\n          foo: hot('      --a--b--c--d--|'),\n        });\n        const expected = '--------------(x|)';\n\n        expectObservable(e1).toBe(expected, { x: { foo: 'd' } });\n      });\n    });\n\n    it('should accept lowercase-o observables', () => {\n      rxTestScheduler.run(({ hot, expectObservable }) => {\n        const e1 = forkJoin({\n          foo: hot('      --a--b--c--d--|'),\n          bar: hot('      (b|)'),\n          baz: lowerCaseO('1', '2', '3'),\n        });\n        const expected = '--------------(x|)';\n\n        expectObservable(e1).toBe(expected, { x: { foo: 'd', bar: 'b', baz: '3' } });\n      });\n    });\n\n    it('should error for empty lowercase-o observables', () => {\n      rxTestScheduler.run(({ hot, expectObservable }) => {\n        const e1 = forkJoin({\n          foo: hot('      --a--b--c--d--|'),\n          bar: hot('      (b|)'),\n          baz: lowerCaseO(),\n        });\n        const expected = '#';\n\n        expectObservable(e1).toBe(expected, undefined, new EmptyError());\n      });\n    });\n\n    it('should accept promise', (done) => {\n      const e1 = forkJoin({\n        foo: of(1),\n        bar: Promise.resolve(2),\n      });\n\n      e1.subscribe({\n        next: (x) => expect(x).to.deep.equal({ foo: 1, bar: 2 }),\n        complete: done,\n      });\n    });\n\n    it('should accept an object of observables', () => {\n      rxTestScheduler.run(({ hot, expectObservable }) => {\n        const e1 = forkJoin({\n          foo: hot('      --a--b--c--d--|'),\n          bar: hot('      (b|)'),\n          baz: hot('      --1--2--3--|'),\n        });\n        const expected = '--------------(x|)';\n\n        expectObservable(e1).toBe(expected, { x: { foo: 'd', bar: 'b', baz: '3' } });\n      });\n    });\n\n    it('should error with EmptyError if any of source observable is empty', () => {\n      rxTestScheduler.run(({ hot, expectObservable }) => {\n        const e1 = forkJoin({\n          foo: hot('      --a--b--c--d--|'),\n          bar: hot('      (b|)'),\n          baz: hot('      ------------------|'),\n        });\n        const expected = '------------------#';\n\n        expectObservable(e1).toBe(expected, undefined, new EmptyError());\n      });\n    });\n\n    it('should error with EmptyError if any of source is empty and completes before than others', () => {\n      rxTestScheduler.run(({ hot, expectObservable }) => {\n        const e1 = forkJoin({\n          foo: hot('      --a--b--c--d--|'),\n          bar: hot('      (b|)'),\n          baz: hot('      ---------|'),\n        });\n        const expected = '---------#';\n\n        expectObservable(e1).toBe(expected, undefined, new EmptyError());\n      });\n    });\n\n    it('should error when the first source returns that is empty, even if all sources are empty', () => {\n      rxTestScheduler.run(({ hot, expectObservable }) => {\n        const e1 = forkJoin({\n          foo: hot('      --------------|'),\n          bar: hot('      ---------|'),\n        });\n        const expected = '---------#';\n\n        expectObservable(e1).toBe(expected, undefined, new EmptyError());\n      });\n    });\n\n    it('should not complete when only source never completes', () => {\n      rxTestScheduler.run(({ hot, expectObservable }) => {\n        const e1 = forkJoin({\n          foo: hot('      --------------'),\n        });\n        const expected = '--------------';\n\n        expectObservable(e1).toBe(expected);\n      });\n    });\n\n    it('should not complete when one of the sources never completes', () => {\n      rxTestScheduler.run(({ hot, expectObservable }) => {\n        const e1 = forkJoin({\n          foo: hot('      --------------'),\n          bar: hot('      -a---b--c--|'),\n        });\n        const expected = '--------------';\n\n        expectObservable(e1).toBe(expected);\n      });\n    });\n\n    it('should error when one of the sources never completes but other completes without values', () => {\n      rxTestScheduler.run(({ hot, expectObservable }) => {\n        const e1 = forkJoin({\n          foo: hot('      --------------'),\n          bar: hot('      ------|'),\n        });\n        const expected = '------#';\n\n        expectObservable(e1).toBe(expected, undefined, new EmptyError());\n      });\n    });\n\n    // TODO(benlesh): this is the wrong behavior, it should probably throw right away.\n    it('should have same v5/v6 throwing behavior full argument of null', (done) => {\n      rxTestScheduler.run(() => {\n        // It doesn't throw when you pass null\n        expect(() => forkJoin(null as any)).not.to.throw();\n\n        // It doesn't even throw if you subscribe to forkJoin(null).\n        expect(() =>\n          forkJoin(null as any).subscribe({\n            // It sends the error to the subscription.\n            error: () => done(),\n          })\n        ).not.to.throw();\n      });\n    });\n\n    it('should complete if sources object is empty', () => {\n      rxTestScheduler.run(({ expectObservable }) => {\n        const e1 = forkJoin({});\n        const expected = '|';\n\n        expectObservable(e1).toBe(expected);\n      });\n    });\n\n    it('should raise error when any of source raises error with empty observable', () => {\n      rxTestScheduler.run(({ hot, expectObservable }) => {\n        const e1 = forkJoin({\n          lol: hot('      ------#'),\n          wut: hot('      ---------|'),\n        });\n        const expected = '------#';\n\n        expectObservable(e1).toBe(expected);\n      });\n    });\n\n    it('should raise error when any of source raises error with source that never completes', () => {\n      rxTestScheduler.run(({ hot, expectObservable }) => {\n        const e1 = forkJoin({\n          lol: hot('      ------#'),\n          wut: hot('      ----------'),\n        });\n        const expected = '------#';\n\n        expectObservable(e1).toBe(expected);\n      });\n    });\n\n    it('should raise error when source raises error', () => {\n      rxTestScheduler.run(({ hot, expectObservable }) => {\n        const e1 = forkJoin({\n          lol: hot('      ------#'),\n          foo: hot('      ---a-----|'),\n        });\n        const expected = '------#';\n\n        expectObservable(e1).toBe(expected);\n      });\n    });\n\n    it('should allow unsubscribing early and explicitly', () => {\n      rxTestScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n        const e1 = hot('--a--^--b--c---d-| ');\n        const e1subs = '     ^--------!    ';\n        const e2 = hot('---e-^---f--g---h-|');\n        const e2subs = '     ^--------!    ';\n        const expected = '   ----------    ';\n        const unsub = '      ---------!    ';\n\n        const result = forkJoin({\n          e1,\n          e2,\n        });\n\n        expectObservable(result, unsub).toBe(expected);\n        expectSubscriptions(e1.subscriptions).toBe(e1subs);\n        expectSubscriptions(e2.subscriptions).toBe(e2subs);\n      });\n    });\n\n    it('should unsubscribe other Observables, when one of them errors', () => {\n      rxTestScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n        const e1 = hot('  --a--^--b--c---d-| ');\n        const e1subs = '       ^--------!    ';\n        const e2 = hot('  ---e-^---f--g-#');\n        const e2subs = '       ^--------!    ';\n        const expected = '     ---------#    ';\n\n        const result = forkJoin({\n          e1,\n          e2,\n        });\n\n        expectObservable(result).toBe(expected);\n        expectSubscriptions(e1.subscriptions).toBe(e1subs);\n        expectSubscriptions(e2.subscriptions).toBe(e2subs);\n      });\n    });\n\n    it('should accept promise as the first arg', (done) => {\n      const e1 = forkJoin(Promise.resolve(1));\n      const values: number[][] = [];\n\n      e1.subscribe({\n        next: (x) => values.push(x),\n        complete: () => {\n          expect(values).to.deep.equal([[1]]);\n          done();\n        },\n      });\n    });\n\n    it('should error on early completion of an inner observable', () => {\n      rxTestScheduler.run(({ hot, expectObservable }) => {\n        const e1 = forkJoin({\n          foo: hot('      --a--b--c--d--|'),\n          bar: hot('      ---|'),\n          baz: hot('      --1--2--3--|'),\n        });\n        const expected = '---#';\n\n        expectObservable(e1).toBe(expected, null, new EmptyError());\n      });\n    });\n  });\n});\n"
  },
  {
    "path": "packages/rxjs/spec/observables/from-promise-spec.ts",
    "content": "import { expect } from 'chai';\nimport * as sinon from 'sinon';\nimport { from } from 'rxjs';\n\n/** @test {fromPromise} */\ndescribe('from (fromPromise)', () => {\n  it('should emit one value from a resolved promise', (done) => {\n    const promise = Promise.resolve(42);\n    from(promise)\n      .subscribe(\n        { next: (x) => { expect(x).to.equal(42); }, error: (x) => {\n          done(new Error('should not be called'));\n        }, complete: () => {\n          done();\n        } });\n  });\n\n  it('should raise error from a rejected promise', (done) => {\n    const promise = Promise.reject('bad');\n    from(promise)\n      .subscribe({ next: (x) => {\n          done(new Error('should not be called'));\n        }, error: (e) => {\n          expect(e).to.equal('bad');\n          done();\n        }, complete: () => {\n         done(new Error('should not be called'));\n       } });\n  });\n\n  it('should share the underlying promise with multiple subscribers', (done) => {\n    const promise = Promise.resolve(42);\n    const observable = from(promise);\n\n    observable\n      .subscribe(\n        { next: (x) => { expect(x).to.equal(42); }, error: (x) => {\n          done(new Error('should not be called'));\n        } });\n    setTimeout(() => {\n      observable\n        .subscribe(\n          { next: (x) => { expect(x).to.equal(42); }, error: (x) => {\n            done(new Error('should not be called'));\n          }, complete: () => {\n            done();\n          } });\n    });\n  });\n\n  it('should accept already-resolved Promise', (done) => {\n    const promise = Promise.resolve(42);\n    promise.then((x) => {\n      expect(x).to.equal(42);\n      from(promise)\n        .subscribe(\n          { next: (y) => { expect(y).to.equal(42); }, error: (x) => {\n            done(new Error('should not be called'));\n          }, complete: () => {\n            done();\n          } });\n    }, () => {\n      done(new Error('should not be called'));\n    });\n  });\n\n  it('should accept PromiseLike object for interoperability', (done) => {\n    class CustomPromise<T> implements PromiseLike<T> {\n      constructor(private promise: PromiseLike<T>) {\n      }\n      then<TResult1 = T, TResult2 = T>(\n        onFulfilled?: ((value: T) => TResult1 | PromiseLike<TResult1>) | undefined | null,\n        onRejected?: ((reason: any) => TResult2 | PromiseLike<TResult2>) | undefined | null): PromiseLike<TResult1 | TResult2> {\n        return new CustomPromise(this.promise.then(onFulfilled, onRejected));\n      }\n    }\n    const promise = new CustomPromise(Promise.resolve(42));\n    from(promise)\n      .subscribe(\n        { next: (x) => { expect(x).to.equal(42); }, error: () => {\n          done(new Error('should not be called'));\n        }, complete: () => {\n          done();\n        } });\n  });\n\n  it('should not emit, throw or complete if immediately unsubscribed', (done) => {\n    const nextSpy = sinon.spy();\n    const throwSpy = sinon.spy();\n    const completeSpy = sinon.spy();\n    const promise = Promise.resolve(42);\n    const subscription = from(promise)\n      .subscribe({ next: nextSpy, error: throwSpy, complete: completeSpy });\n    subscription.unsubscribe();\n\n    setTimeout(() => {\n      expect(nextSpy).not.have.been.called;\n      expect(throwSpy).not.have.been.called;\n      expect(completeSpy).not.have.been.called;\n      done();\n    });\n  });\n});\n"
  },
  {
    "path": "packages/rxjs/spec/observables/from-spec.ts",
    "content": "/** @prettier */\nimport { expect } from 'chai';\nimport { TestScheduler } from 'rxjs/testing';\nimport type { Observer, Subscription } from 'rxjs';\nimport { of, from, Subject, noop } from 'rxjs';\nimport { first, concatMap, delay, take, tap } from 'rxjs/operators';\nimport { ReadableStream } from 'web-streams-polyfill';\nimport { observableMatcher } from '../helpers/observableMatcher';\n\nfunction getArguments<T>(...args: T[]) {\n  return args;\n}\n\n/** @test {from} */\ndescribe('from', () => {\n  let rxTestScheduler: TestScheduler;\n\n  beforeEach(() => {\n    rxTestScheduler = new TestScheduler(observableMatcher);\n  });\n\n  it('should create an observable from an array', () => {\n    rxTestScheduler.run(({ expectObservable, time }) => {\n      const delayTime = time('--|');\n      //                --|\n      //                  --|\n      const expected = 'x-y-(z|)';\n\n      const e1 = from([10, 20, 30]).pipe(\n        // for the purpose of making a nice diagram, spread out the synchronous emissions\n        concatMap((x, i) => of(x).pipe(delay(i === 0 ? 0 : delayTime)))\n      );\n\n      expectObservable(e1).toBe(expected, { x: 10, y: 20, z: 30 });\n    });\n  });\n\n  it('should throw for non observable object', () => {\n    const r = () => {\n      from({} as any).subscribe();\n    };\n\n    expect(r).to.throw();\n  });\n\n  it('should finalize an AsyncGenerator', (done) => {\n    const results: any[] = [];\n    const sideEffects: any[] = [];\n\n    async function* gen() {\n      try {\n        let i = 0;\n        while (true) {\n          sideEffects.push(i);\n          yield await i++;\n        }\n      } finally {\n        results.push('finalized generator');\n      }\n    }\n\n    const source = from(gen()).pipe(take(3));\n\n    source.subscribe({\n      next: (value) => results.push(value),\n      complete: () => {\n        results.push('done');\n        setTimeout(() => {\n          expect(sideEffects).to.deep.equal([0, 1, 2]);\n          expect(results).to.deep.equal([0, 1, 2, 'done', 'finalized generator']);\n          done();\n        });\n      },\n    });\n  });\n\n  it('should finalize an AsyncGenerator on error', (done) => {\n    const results: any[] = [];\n    const sideEffects: any[] = [];\n\n    async function* gen() {\n      try {\n        let i = 0;\n        while (true) {\n          sideEffects.push(i);\n          yield await i++;\n        }\n      } finally {\n        results.push('finalized generator');\n      }\n    }\n\n    const source = from(gen()).pipe(\n      tap({\n        next: (value) => {\n          if (value === 2) {\n            throw new Error('weee');\n          }\n        },\n      })\n    );\n\n    source.subscribe({\n      next: (value) => results.push(value),\n      error: () => {\n        results.push('in error');\n        setTimeout(() => {\n          expect(sideEffects).to.deep.equal([0, 1, 2]);\n          expect(results).to.deep.equal([0, 1, 'in error', 'finalized generator']);\n          done();\n        });\n      },\n    });\n  });\n\n  it('should finalize an AsyncGenerator on unsubscribe', (done) => {\n    const results: any[] = [];\n    const sideEffects: any[] = [];\n    // eslint-disable-next-line prefer-const\n    let subscription: Subscription;\n\n    async function* gen() {\n      try {\n        let i = 0;\n        while (true) {\n          sideEffects.push(i);\n          yield await i++;\n          if (i === 2) {\n            subscription.unsubscribe();\n          }\n        }\n      } finally {\n        results.push('finalized generator');\n        expect(sideEffects).to.deep.equal([0, 1, 2]);\n        expect(results).to.deep.equal([0, 1, 'finalized generator']);\n        done();\n      }\n    }\n\n    const source = from(gen());\n\n    subscription = source.subscribe((value) => results.push(value));\n  });\n\n  it('should finalize a generator', () => {\n    const results: any[] = [];\n\n    function* gen() {\n      try {\n        let i = 0;\n        while (true) {\n          yield i++;\n        }\n      } finally {\n        results.push('finalized generator');\n      }\n    }\n\n    const source = from(gen()).pipe(take(3));\n\n    source.subscribe({\n      next: (value) => results.push(value),\n      complete: () => results.push('done'),\n    });\n\n    expect(results).to.deep.equal([0, 1, 2, 'done', 'finalized generator']);\n  });\n\n  const fakervable = <T>(...values: T[]) => ({\n    [Symbol.observable ?? '@@observable']: () => ({\n      subscribe: (observer: Observer<T>) => {\n        for (const value of values) {\n          observer.next(value);\n        }\n        observer.complete();\n      },\n    }),\n  });\n\n  const fakeArrayObservable = <T>(...values: T[]) => {\n    const arr: any = ['bad array!'];\n    arr[Symbol.observable ?? '@@observable'] = () => {\n      return {\n        subscribe: (observer: Observer<T>) => {\n          for (const value of values) {\n            observer.next(value);\n          }\n          observer.complete();\n        },\n      };\n    };\n    return arr;\n  };\n\n  const fakerator = <T>(...values: T[]) => ({\n    [Symbol.iterator as symbol]: () => {\n      const clone = [...values];\n      return {\n        next: () => ({\n          done: clone.length <= 0,\n          value: clone.shift(),\n        }),\n      };\n    },\n  });\n\n  const sources: Array<{ name: string; createValue: () => any }> = [\n    { name: 'observable', createValue: () => of('x') },\n    { name: 'observable-like', createValue: () => fakervable('x') },\n    { name: 'observable-like-array', createValue: () => fakeArrayObservable('x') },\n    { name: 'array', createValue: () => ['x'] },\n    { name: 'promise', createValue: () => Promise.resolve('x') },\n    { name: 'iterator', createValue: () => fakerator('x') },\n    { name: 'array-like', createValue: () => ({ [0]: 'x', length: 1 }) },\n    // ReadableStreams are not lazy, so we have to have this createValue() thunk\n    // so that each tests gets a new one.\n    {\n      name: 'readable-stream-like',\n      createValue: () =>\n        new ReadableStream({\n          pull(controller) {\n            controller.enqueue('x');\n            controller.close();\n          },\n        }),\n    },\n    { name: 'string', createValue: () => 'x' },\n    { name: 'arguments', createValue: () => getArguments('x') },\n  ];\n\n  if (Symbol && Symbol.asyncIterator) {\n    const fakeAsyncIterator = (...values: any[]) => {\n      return {\n        [Symbol.asyncIterator]() {\n          let i = 0;\n          return {\n            next() {\n              const index = i++;\n              if (index < values.length) {\n                return Promise.resolve({ done: false, value: values[index] });\n              } else {\n                return Promise.resolve({ done: true });\n              }\n            },\n            [Symbol.asyncIterator]() {\n              return this;\n            },\n          };\n        },\n      };\n    };\n\n    sources.push({\n      name: 'async-iterator',\n      createValue: () => fakeAsyncIterator('x'),\n    });\n  }\n\n  for (const source of sources) {\n    it(`should accept ${source.name}`, (done) => {\n      let nextInvoked = false;\n      from(source.createValue()).subscribe({\n        next: (x) => {\n          nextInvoked = true;\n          expect(x).to.equal('x');\n        },\n        error: (x) => {\n          done(new Error('should not be called'));\n        },\n        complete: () => {\n          expect(nextInvoked).to.equal(true);\n          done();\n        },\n      });\n    });\n\n    it(`should accept a function that implements [Symbol.observable]`, (done) => {\n      const subject = new Subject<any>();\n      const handler: any = (arg: any) => subject.next(arg);\n      handler[Symbol.observable ?? '@@observable'] = () => subject;\n      let nextInvoked = false;\n\n      from(handler as any)\n        .pipe(first())\n        .subscribe({\n          next: (x) => {\n            nextInvoked = true;\n            expect(x).to.equal('x');\n          },\n          error: (x) => {\n            done(new Error('should not be called'));\n          },\n          complete: () => {\n            expect(nextInvoked).to.equal(true);\n            done();\n          },\n        });\n      handler('x');\n    });\n\n    it('should accept a thennable that happens to have a subscribe method', (done) => {\n      // There was an issue with our old `isPromise` check that caused this to fail\n      const input = Promise.resolve('test');\n      (input as any).subscribe = noop;\n      from(input).subscribe({\n        next: (x) => {\n          expect(x).to.equal('test');\n          done();\n        },\n      });\n    });\n  }\n\n  it('should appropriately handle errors from an iterator', () => {\n    const erroringIterator = (function* () {\n      for (let i = 0; i < 5; i++) {\n        if (i === 3) {\n          throw new Error('bad');\n        }\n        yield i;\n      }\n    })();\n\n    const results: any[] = [];\n\n    from(erroringIterator).subscribe({\n      next: (x) => results.push(x),\n      error: (err) => results.push(err.message),\n    });\n\n    expect(results).to.deep.equal([0, 1, 2, 'bad']);\n  });\n\n  it('should execute the finally block of a generator', () => {\n    let finallyExecuted = false;\n    const generator = (function* () {\n      try {\n        yield 'hi';\n      } finally {\n        finallyExecuted = true;\n      }\n    })();\n\n    from(generator).subscribe();\n\n    expect(finallyExecuted).to.be.true;\n  });\n\n  it('should support ReadableStream-like objects', (done) => {\n    const input = [0, 1, 2];\n    const output: number[] = [];\n\n    const readableStream = new ReadableStream({\n      pull(controller) {\n        if (input.length > 0) {\n          controller.enqueue(input.shift());\n\n          if (input.length === 0) {\n            controller.close();\n          }\n        }\n      },\n    });\n\n    from(readableStream).subscribe({\n      next: (value) => {\n        output.push(value);\n        expect(readableStream.locked).to.equal(true);\n      },\n      complete: () => {\n        expect(output).to.deep.equal([0, 1, 2]);\n        expect(readableStream.locked).to.equal(false);\n        done();\n      },\n    });\n  });\n\n  it('should lock and release ReadableStream-like objects', (done) => {\n    const input = [0, 1, 2];\n    const output: number[] = [];\n\n    const readableStream = new ReadableStream({\n      pull(controller) {\n        if (input.length > 0) {\n          controller.enqueue(input.shift());\n\n          if (input.length === 0) {\n            controller.close();\n          }\n        }\n      },\n    });\n\n    from(readableStream).subscribe({\n      next: (value) => {\n        output.push(value);\n        expect(readableStream.locked).to.equal(true);\n      },\n      complete: () => {\n        expect(output).to.deep.equal([0, 1, 2]);\n        expect(readableStream.locked).to.equal(false);\n        done();\n      },\n    });\n  });\n});\n"
  },
  {
    "path": "packages/rxjs/spec/observables/fromEvent-spec.ts",
    "content": "/** @prettier */\nimport { expect } from 'chai';\nimport { fromEvent, NEVER, timer } from 'rxjs';\nimport { mapTo, take, concatWith } from 'rxjs/operators';\nimport { TestScheduler } from 'rxjs/testing';\nimport { observableMatcher } from '../helpers/observableMatcher';\n\n/** @test {fromEvent} */\ndescribe('fromEvent', () => {\n  let rxTestScheduler: TestScheduler;\n\n  beforeEach(() => {\n    rxTestScheduler = new TestScheduler(observableMatcher);\n  });\n\n  it('should create an observable of click on the element', () => {\n    rxTestScheduler.run(({ expectObservable, time }) => {\n      const delay1 = time('-----|     ');\n      const delay2 = time('     --|   ');\n      const expected = '   -----x-x---';\n\n      const target = {\n        addEventListener: (eventType: any, listener: any) => {\n          // Here we're just simulating some event target that emits to events after delay1 and delay2.\n          timer(delay1, delay2).pipe(mapTo('ev'), take(2), concatWith(NEVER)).subscribe(listener);\n        },\n        removeEventListener: (): void => void 0,\n        dispatchEvent: (): void => void 0,\n      };\n      const e1 = fromEvent(target as any, 'click');\n      expectObservable(e1).toBe(expected, { x: 'ev' });\n    });\n  });\n\n  it('should setup an event observable on objects with \"on\" and \"off\" ', () => {\n    let onEventName;\n    let onHandler;\n    let offEventName;\n    let offHandler;\n\n    const obj = {\n      on: (a: string, b: (...args: unknown[]) => any) => {\n        onEventName = a;\n        onHandler = b;\n      },\n      off: (a: string, b: (...args: unknown[]) => any) => {\n        offEventName = a;\n        offHandler = b;\n      },\n    };\n\n    const subscription = fromEvent(obj, 'click').subscribe(() => {\n      //noop\n    });\n\n    subscription.unsubscribe();\n\n    expect(onEventName).to.equal('click');\n    expect(typeof onHandler).to.equal('function');\n    expect(offEventName).to.equal(onEventName);\n    expect(offHandler).to.equal(onHandler);\n  });\n\n  it('should setup an event observable on objects with \"addEventListener\" and \"removeEventListener\" ', () => {\n    let onEventName;\n    let onHandler;\n    let offEventName;\n    let offHandler;\n\n    const obj = {\n      addEventListener: (a: string, b: EventListenerOrEventListenerObject, useCapture?: boolean) => {\n        onEventName = a;\n        onHandler = b;\n      },\n      removeEventListener: (a: string, b: EventListenerOrEventListenerObject, useCapture?: boolean) => {\n        offEventName = a;\n        offHandler = b;\n      },\n    };\n\n    const subscription = fromEvent(<any>obj, 'click').subscribe(() => {\n      //noop\n    });\n\n    subscription.unsubscribe();\n\n    expect(onEventName).to.equal('click');\n    expect(typeof onHandler).to.equal('function');\n    expect(offEventName).to.equal(onEventName);\n    expect(offHandler).to.equal(onHandler);\n  });\n\n  it('should setup an event observable on objects with \"addListener\" and \"removeListener\" returning event emitter', () => {\n    let onEventName;\n    let onHandler;\n    let offEventName;\n    let offHandler;\n\n    const obj = {\n      addListener(a: string | symbol, b: (...args: any[]) => void) {\n        onEventName = a;\n        onHandler = b;\n        return this;\n      },\n      removeListener(a: string | symbol, b: (...args: any[]) => void) {\n        offEventName = a;\n        offHandler = b;\n        return this;\n      },\n    };\n\n    const subscription = fromEvent(obj, 'click').subscribe(() => {\n      //noop\n    });\n\n    subscription.unsubscribe();\n\n    expect(onEventName).to.equal('click');\n    expect(typeof onHandler).to.equal('function');\n    expect(offEventName).to.equal(onEventName);\n    expect(offHandler).to.equal(onHandler);\n  });\n\n  it('should pass symbol to \"addListener\" and \"removeListener\"', () => {\n    let onEventName;\n    let onHandler;\n    let offEventName;\n    let offHandler;\n\n    const SYMBOL_EVENT = Symbol();\n\n    const obj = {\n      addListener(a: string | symbol, b: (...args: any[]) => void) {\n        onEventName = a;\n        onHandler = b;\n        return this;\n      },\n      removeListener(a: string | symbol, b: (...args: any[]) => void) {\n        offEventName = a;\n        offHandler = b;\n        return this;\n      },\n    };\n\n    const subscription = fromEvent(obj, SYMBOL_EVENT).subscribe(() => {\n      //noop\n    });\n\n    subscription.unsubscribe();\n\n    expect(onEventName).to.equal(SYMBOL_EVENT);\n    expect(typeof onHandler).to.equal('function');\n    expect(offEventName).to.equal(onEventName);\n    expect(offHandler).to.equal(onHandler);\n  });\n\n  it('should setup an event observable on objects with \"addListener\" and \"removeListener\" returning nothing', () => {\n    let onEventName;\n    let onHandler;\n    let offEventName;\n    let offHandler;\n\n    const obj = {\n      addListener(a: string, b: (...args: any[]) => any, context?: any): { context: any } {\n        onEventName = a;\n        onHandler = b;\n        return { context: '' };\n      },\n      removeListener(a: string, b: (...args: any[]) => void) {\n        offEventName = a;\n        offHandler = b;\n      },\n    };\n\n    const subscription = fromEvent(obj, 'click').subscribe(() => {\n      //noop\n    });\n\n    subscription.unsubscribe();\n\n    expect(onEventName).to.equal('click');\n    expect(typeof onHandler).to.equal('function');\n    expect(offEventName).to.equal(onEventName);\n    expect(offHandler).to.equal(onHandler);\n  });\n\n  it('should setup an event observable on objects with \"addListener\" and \"removeListener\" and \"length\" ', () => {\n    let onEventName;\n    let onHandler;\n    let offEventName;\n    let offHandler;\n\n    const obj = {\n      addListener: (a: string, b: (...args: unknown[]) => any) => {\n        onEventName = a;\n        onHandler = b;\n      },\n      removeListener: (a: string, b: (...args: unknown[]) => any) => {\n        offEventName = a;\n        offHandler = b;\n      },\n      length: 1,\n    };\n\n    const subscription = fromEvent(obj, 'click').subscribe(() => {\n      //noop\n    });\n\n    subscription.unsubscribe();\n\n    expect(onEventName).to.equal('click');\n    expect(typeof onHandler).to.equal('function');\n    expect(offEventName).to.equal(onEventName);\n    expect(offHandler).to.equal(onHandler);\n  });\n\n  it('should throw if passed an invalid event target', () => {\n    const obj = {\n      addListener: () => {\n        //noop\n      },\n    };\n    expect(() => {\n      fromEvent(obj as any, 'click');\n    }).to.throw(/Invalid event target/);\n  });\n\n  it('should pass through options to addEventListener and removeEventListener', () => {\n    let onOptions;\n    let offOptions;\n    const expectedOptions = { capture: true, passive: true };\n\n    const obj = {\n      addEventListener: (a: string, b: EventListenerOrEventListenerObject, c?: any) => {\n        onOptions = c;\n      },\n      removeEventListener: (a: string, b: EventListenerOrEventListenerObject, c?: any) => {\n        offOptions = c;\n      },\n    };\n\n    const subscription = fromEvent(<any>obj, 'click', expectedOptions).subscribe(() => {\n      //noop\n    });\n\n    subscription.unsubscribe();\n\n    expect(onOptions).to.equal(expectedOptions);\n    expect(offOptions).to.equal(expectedOptions);\n  });\n\n  it('should pass through events that occur', (done) => {\n    let send: any;\n    const obj = {\n      on: (name: string, handler: (...args: unknown[]) => any) => {\n        send = handler;\n      },\n      off: () => {\n        //noop\n      },\n    };\n\n    fromEvent(obj, 'click')\n      .pipe(take(1))\n      .subscribe({\n        next: (e: any) => {\n          expect(e).to.equal('test');\n        },\n        error: (err: any) => {\n          done(new Error('should not be called'));\n        },\n        complete: () => {\n          done();\n        },\n      });\n\n    send('test');\n  });\n\n  it('should pass through events that occur and use the selector if provided', (done) => {\n    let send: any;\n    const obj = {\n      on: (name: string, handler: (t: string, ...args: unknown[]) => any) => {\n        send = handler;\n      },\n      off: () => {\n        //noop\n      },\n    };\n\n    function selector(x: string) {\n      return x + '!';\n    }\n\n    fromEvent(obj, 'click', selector)\n      .pipe(take(1))\n      .subscribe({\n        next: (e: any) => {\n          expect(e).to.equal('test!');\n        },\n        error: (err: any) => {\n          done(new Error('should not be called'));\n        },\n        complete: () => {\n          done();\n        },\n      });\n\n    send('test');\n  });\n\n  it('should not fail if no event arguments are passed and the selector does not return', (done) => {\n    let send: any;\n    const obj = {\n      on: (name: string, handler: (...args: unknown[]) => any) => {\n        send = handler;\n      },\n      off: () => {\n        //noop\n      },\n    };\n\n    function selector() {\n      //noop\n    }\n\n    fromEvent(obj, 'click', selector)\n      .pipe(take(1))\n      .subscribe({\n        next: (e: any) => {\n          expect(e).not.exist;\n        },\n        error: (err: any) => {\n          done(new Error('should not be called'));\n        },\n        complete: () => {\n          done();\n        },\n      });\n\n    send();\n  });\n\n  it('should return a value from the selector if no event arguments are passed', (done) => {\n    let send: any;\n    const obj = {\n      on: (name: string, handler: (...args: unknown[]) => any) => {\n        send = handler;\n      },\n      off: () => {\n        //noop\n      },\n    };\n\n    function selector() {\n      return 'no arguments';\n    }\n\n    fromEvent(obj, 'click', selector)\n      .pipe(take(1))\n      .subscribe({\n        next: (e: any) => {\n          expect(e).to.equal('no arguments');\n        },\n        error: (err: any) => {\n          done(new Error('should not be called'));\n        },\n        complete: () => {\n          done();\n        },\n      });\n\n    send();\n  });\n\n  it('should pass multiple arguments to selector from event emitter', (done) => {\n    let send: any;\n    const obj = {\n      on: (name: string, handler: (t: number, ...args: unknown[]) => any) => {\n        send = handler;\n      },\n      off: () => {\n        //noop\n      },\n    };\n\n    function selector(x: number, y: number, z: number) {\n      // eslint-disable-next-line prefer-rest-params\n      return [].slice.call(arguments);\n    }\n\n    fromEvent(obj, 'click', selector)\n      .pipe(take(1))\n      .subscribe({\n        next: (e: any) => {\n          expect(e).to.deep.equal([1, 2, 3]);\n        },\n        error: (err: any) => {\n          done(new Error('should not be called'));\n        },\n        complete: () => {\n          done();\n        },\n      });\n\n    send(1, 2, 3);\n  });\n\n  it('should emit multiple arguments from event as an array', (done) => {\n    let send: any;\n    const obj = {\n      on: (name: string, handler: (...args: unknown[]) => any) => {\n        send = handler;\n      },\n      off: () => {\n        //noop\n      },\n    };\n\n    fromEvent(obj, 'click')\n      .pipe(take(1))\n      .subscribe({\n        next: (e: any) => {\n          expect(e).to.deep.equal([1, 2, 3]);\n        },\n        error: (err: any) => {\n          done(new Error('should not be called'));\n        },\n        complete: () => {\n          done();\n        },\n      });\n\n    send(1, 2, 3);\n  });\n\n  it('should not throw an exception calling toString on obj with a null prototype', (done) => {\n    // NOTE: Can not test with Object.create(null) or `class Foo extends null`\n    // due to TypeScript bug. https://github.com/Microsoft/TypeScript/issues/1108\n    class NullProtoEventTarget {\n      on() {\n        /*noop*/\n      }\n      off() {\n        /*noop*/\n      }\n    }\n    NullProtoEventTarget.prototype.toString = null!;\n    const obj: NullProtoEventTarget = new NullProtoEventTarget();\n\n    expect(() => {\n      fromEvent(obj, 'foo').subscribe();\n      done();\n    }).to.not.throw(TypeError);\n  });\n\n  it('should throw on subscription if one of the items in an ArrayLike is not a valid event target', (done) => {\n    const nodeList = {\n      [0]: {\n        addEventListener() {\n          /* noop */\n        },\n        removeEventListener() {\n          /* noop */\n        },\n      },\n      [1]: {\n        addEventListener() {\n          /* noop */\n        },\n        removeEventListener() {\n          /* noop */\n        },\n      },\n      [2]: {\n        notAnEventTargetLOL: true,\n      },\n      [3]: {\n        addEventListener() {\n          /* noop */\n        },\n        removeEventListener() {\n          /* noop */\n        },\n      },\n      length: 4,\n    };\n\n    // @ts-expect-error We're testing this for the rebels that don't type check properly.\n    const source = fromEvent(nodeList, 'cool-event-name-bro');\n\n    source.subscribe({\n      error: (err) => {\n        expect(err).to.be.an.instanceOf(TypeError);\n        expect(err.message).to.equal('Invalid event target');\n        done();\n      },\n    });\n  });\n\n  it('should handle adding events to an arraylike of targets', () => {\n    const nodeList = {\n      [0]: {\n        addEventListener(...args: any[]) {\n          this._addEventListenerArgs = args;\n        },\n        removeEventListener(...args: any[]) {\n          this._removeEventListenerArgs = args;\n        },\n        _addEventListenerArgs: null as any,\n        _removeEventListenerArgs: null as any,\n      },\n      [1]: {\n        addEventListener(...args: any[]) {\n          this._addEventListenerArgs = args;\n        },\n        removeEventListener(...args: any[]) {\n          this._removeEventListenerArgs = args;\n        },\n        _addEventListenerArgs: null as any,\n        _removeEventListenerArgs: null as any,\n      },\n      length: 2,\n    };\n\n    const options = {};\n\n    const subscription = fromEvent(nodeList, 'click', options).subscribe();\n\n    expect(nodeList[0]._addEventListenerArgs[0]).to.equal('click');\n    expect(nodeList[0]._addEventListenerArgs[1]).to.be.a('function');\n    expect(nodeList[0]._addEventListenerArgs[2]).to.equal(options);\n\n    expect(nodeList[1]._addEventListenerArgs[0]).to.equal('click');\n    expect(nodeList[1]._addEventListenerArgs[1]).to.be.a('function');\n    expect(nodeList[1]._addEventListenerArgs[2]).to.equal(options);\n\n    expect(nodeList[0]._removeEventListenerArgs).to.be.null;\n    expect(nodeList[1]._removeEventListenerArgs).to.be.null;\n\n    subscription.unsubscribe();\n\n    expect(nodeList[0]._removeEventListenerArgs).to.deep.equal(nodeList[0]._addEventListenerArgs);\n    expect(nodeList[1]._removeEventListenerArgs).to.deep.equal(nodeList[1]._addEventListenerArgs);\n  });\n});\n"
  },
  {
    "path": "packages/rxjs/spec/observables/fromEventPattern-spec.ts",
    "content": "/** @prettier */\nimport { expect } from 'chai';\nimport * as sinon from 'sinon';\n\nimport { fromEventPattern, noop, NEVER, timer } from 'rxjs';\nimport { mapTo, take, concatWith } from 'rxjs/operators';\nimport { TestScheduler } from 'rxjs/testing';\nimport { observableMatcher } from '../helpers/observableMatcher';\n\n/** @test {fromEventPattern} */\ndescribe('fromEventPattern', () => {\n  let rxTestScheduler: TestScheduler;\n\n  beforeEach(() => {\n    rxTestScheduler = new TestScheduler(observableMatcher);\n  });\n\n  it('should create an observable from the handler API', () => {\n    rxTestScheduler.run(({ time, expectObservable }) => {\n      const time1 = time('-----|     ');\n      const time2 = time('     --|   ');\n      const expected = '  -----x-x---';\n\n      function addHandler(h: any) {\n        timer(time1, time2, rxTestScheduler).pipe(mapTo('ev'), take(2), concatWith(NEVER)).subscribe(h);\n      }\n      const e1 = fromEventPattern(addHandler);\n\n      expectObservable(e1).toBe(expected, { x: 'ev' });\n    });\n  });\n\n  it('should call addHandler on subscription', () => {\n    const addHandler = sinon.spy();\n    fromEventPattern(addHandler, noop).subscribe(noop);\n\n    const call = addHandler.getCall(0);\n    expect(addHandler).calledOnce;\n    expect(call.args[0]).to.be.a('function');\n  });\n\n  it('should call removeHandler on unsubscription', () => {\n    const removeHandler = sinon.spy();\n\n    fromEventPattern(noop, removeHandler).subscribe(noop).unsubscribe();\n\n    const call = removeHandler.getCall(0);\n    expect(removeHandler).calledOnce;\n    expect(call.args[0]).to.be.a('function');\n  });\n\n  it('should work without optional removeHandler', () => {\n    const addHandler: (h: () => any) => any = sinon.spy();\n    fromEventPattern(addHandler).subscribe(noop);\n\n    expect(addHandler).calledOnce;\n  });\n\n  it('should deliver return value of addHandler to removeHandler as signal', () => {\n    const expected = { signal: true };\n    const addHandler = () => expected;\n    const removeHandler = sinon.spy();\n    fromEventPattern(addHandler, removeHandler).subscribe(noop).unsubscribe();\n\n    const call = removeHandler.getCall(0);\n    expect(call).calledWith(sinon.match.any, expected);\n  });\n\n  it('should send errors in addHandler down the error path', (done) => {\n    fromEventPattern((h: any) => {\n      throw 'bad';\n    }, noop).subscribe({\n      next: () => done(new Error('should not be called')),\n      error: (err: any) => {\n        expect(err).to.equal('bad');\n        done();\n      },\n      complete: () => done(new Error('should not be called')),\n    });\n  });\n\n  it('should accept a selector that maps outgoing values', (done) => {\n    let target: any;\n    const trigger = function (...args: any[]) {\n      if (target) {\n        // eslint-disable-next-line prefer-spread\n        target.apply(null, args);\n      }\n    };\n\n    const addHandler = (handler: any) => {\n      target = handler;\n    };\n    const removeHandler = (handler: any) => {\n      target = null;\n    };\n    const selector = (a: any, b: any) => {\n      return a + b + '!';\n    };\n\n    fromEventPattern(addHandler, removeHandler, selector)\n      .pipe(take(1))\n      .subscribe({\n        next: (x: any) => {\n          expect(x).to.equal('testme!');\n        },\n        error: (err: any) => {\n          done(new Error('should not be called'));\n        },\n        complete: () => {\n          done();\n        },\n      });\n\n    trigger('test', 'me');\n  });\n\n  it('should send errors in the selector down the error path', (done) => {\n    let target: any;\n    const trigger = (value: any) => {\n      if (target) {\n        target(value);\n      }\n    };\n\n    const addHandler = (handler: any) => {\n      target = handler;\n    };\n    const removeHandler = (handler: any) => {\n      target = null;\n    };\n    const selector = (x: any) => {\n      throw 'bad';\n    };\n\n    fromEventPattern(addHandler, removeHandler, selector).subscribe({\n      next: (x: any) => {\n        done(new Error('should not be called'));\n      },\n      error: (err: any) => {\n        expect(err).to.equal('bad');\n        done();\n      },\n      complete: () => {\n        done(new Error('should not be called'));\n      },\n    });\n\n    trigger('test');\n  });\n});\n"
  },
  {
    "path": "packages/rxjs/spec/observables/generate-spec.ts",
    "content": "/** @prettier */\nimport { TestScheduler } from 'rxjs/testing';\nimport { expect } from 'chai';\nimport { generate } from 'rxjs';\nimport { take } from 'rxjs/operators';\nimport { Subscriber } from '@rxjs/observable';\nimport { observableMatcher } from '../helpers/observableMatcher';\n\nfunction err(): any {\n  throw 'error';\n}\n\ndescribe('generate', () => {\n  let rxTestScheduler: TestScheduler;\n\n  beforeEach(() => {\n    rxTestScheduler = new TestScheduler(observableMatcher);\n  });\n\n  it('should complete if condition does not meet', () => {\n    rxTestScheduler.run(({ expectObservable }) => {\n      const source = generate(\n        1,\n        (x) => false,\n        (x) => x + 1\n      );\n      const expected = '|';\n\n      expectObservable(source).toBe(expected);\n    });\n  });\n\n  it('should produce first value immediately', () => {\n    rxTestScheduler.run(({ expectObservable }) => {\n      const source = generate(\n        1,\n        (x) => x == 1,\n        (x) => x + 1\n      );\n      const expected = '(1|)';\n\n      expectObservable(source).toBe(expected, { '1': 1 });\n    });\n  });\n\n  it('should produce all values synchronously', () => {\n    rxTestScheduler.run(({ expectObservable }) => {\n      const source = generate(\n        1,\n        (x) => x < 3,\n        (x) => x + 1\n      );\n      const expected = '(12|)';\n\n      expectObservable(source).toBe(expected, { '1': 1, '2': 2 });\n    });\n  });\n\n  it('should use result selector', () => {\n    rxTestScheduler.run(({ expectObservable }) => {\n      const source = generate(\n        1,\n        (x) => x < 3,\n        (x) => x + 1,\n        (x) => (x + 1).toString()\n      );\n      const expected = '(23|)';\n\n      expectObservable(source).toBe(expected);\n    });\n  });\n\n  it('should allow omit condition', () => {\n    rxTestScheduler.run(({ expectObservable }) => {\n      const source = generate({\n        initialState: 1,\n        iterate: (x) => x + 1,\n        resultSelector: (x: number) => x.toString(),\n      }).pipe(take(5));\n      const expected = '(12345|)';\n\n      expectObservable(source).toBe(expected);\n    });\n  });\n\n  it('should stop producing when unsubscribed', () => {\n    const source = generate(\n      1,\n      (x) => x < 4,\n      (x) => x + 1\n    );\n    let count = 0;\n    const subscriber = new Subscriber<number>((x) => {\n      count++;\n      if (x == 2) {\n        subscriber.unsubscribe();\n      }\n    });\n    source.subscribe(subscriber);\n    expect(count).to.be.equal(2);\n  });\n\n  it('should accept a scheduler', () => {\n    rxTestScheduler.run(({ expectObservable }) => {\n      const source = generate({\n        initialState: 1,\n        condition: (x) => x < 4,\n        iterate: (x) => x + 1,\n        resultSelector: (x: number) => x,\n        scheduler: rxTestScheduler,\n      });\n      const expected = '(123|)';\n\n      let count = 0;\n      source.subscribe((x) => count++);\n\n      expect(count).to.be.equal(0);\n      rxTestScheduler.flush();\n      expect(count).to.be.equal(3);\n\n      expectObservable(source).toBe(expected, { '1': 1, '2': 2, '3': 3 });\n    });\n  });\n\n  it('should allow minimal possible options', () => {\n    rxTestScheduler.run(({ expectObservable }) => {\n      const source = generate({\n        initialState: 1,\n        iterate: (x) => x * 2,\n      }).pipe(take(3));\n      const expected = '(124|)';\n\n      expectObservable(source).toBe(expected, { '1': 1, '2': 2, '4': 4 });\n    });\n  });\n\n  it('should emit error if result selector throws', () => {\n    rxTestScheduler.run(({ expectObservable }) => {\n      const source = generate({\n        initialState: 1,\n        iterate: (x) => x * 2,\n        resultSelector: err,\n      });\n      const expected = '(#)';\n\n      expectObservable(source).toBe(expected);\n    });\n  });\n\n  it('should emit error if result selector throws on scheduler', () => {\n    rxTestScheduler.run(({ expectObservable }) => {\n      const source = generate({\n        initialState: 1,\n        iterate: (x) => x * 2,\n        resultSelector: err,\n        scheduler: rxTestScheduler,\n      });\n      const expected = '(#)';\n\n      expectObservable(source).toBe(expected);\n    });\n  });\n\n  it('should emit error after first value if iterate function throws', () => {\n    rxTestScheduler.run(({ expectObservable }) => {\n      const source = generate({\n        initialState: 1,\n        iterate: err,\n      });\n      const expected = '(1#)';\n\n      expectObservable(source).toBe(expected, { '1': 1 });\n    });\n  });\n\n  it('should emit error after first value if iterate function throws on scheduler', () => {\n    rxTestScheduler.run(({ expectObservable }) => {\n      const source = generate({\n        initialState: 1,\n        iterate: err,\n        scheduler: rxTestScheduler,\n      });\n      const expected = '(1#)';\n\n      expectObservable(source).toBe(expected, { '1': 1 });\n    });\n  });\n\n  it('should emit error if condition function throws', () => {\n    rxTestScheduler.run(({ expectObservable }) => {\n      const source = generate({\n        initialState: 1,\n        iterate: (x) => x + 1,\n        condition: err,\n      });\n      const expected = '(#)';\n\n      expectObservable(source).toBe(expected);\n    });\n  });\n\n  it('should emit error if condition function throws on scheduler', () => {\n    rxTestScheduler.run(({ expectObservable }) => {\n      const source = generate({\n        initialState: 1,\n        iterate: (x) => x + 1,\n        condition: err,\n        scheduler: rxTestScheduler,\n      });\n      const expected = '(#)';\n\n      expectObservable(source).toBe(expected);\n    });\n  });\n});\n"
  },
  {
    "path": "packages/rxjs/spec/observables/if-spec.ts",
    "content": "/** @prettier */\nimport { expect } from 'chai';\nimport { iif, of } from 'rxjs';\nimport { TestScheduler } from 'rxjs/testing';\nimport { observableMatcher } from '../helpers/observableMatcher';\n\ndescribe('iif', () => {\n  let rxTestScheduler: TestScheduler;\n\n  beforeEach(() => {\n    rxTestScheduler = new TestScheduler(observableMatcher);\n  });\n\n  it('should subscribe to thenSource when the conditional returns true', () => {\n    rxTestScheduler.run(({ expectObservable }) => {\n      const e1 = iif(() => true, of('a'), of());\n      const expected = '(a|)';\n\n      expectObservable(e1).toBe(expected);\n    });\n  });\n\n  it('should subscribe to elseSource when the conditional returns false', () => {\n    rxTestScheduler.run(({ expectObservable }) => {\n      const e1 = iif(() => false, of('a'), of('b'));\n      const expected = '(b|)';\n\n      expectObservable(e1).toBe(expected);\n    });\n  });\n\n  it('should complete without an elseSource when the conditional returns false', () => {\n    rxTestScheduler.run(({ expectObservable }) => {\n      const e1 = iif(() => false, of('a'), of());\n      const expected = '|';\n\n      expectObservable(e1).toBe(expected);\n    });\n  });\n\n  it('should raise error when conditional throws', () => {\n    rxTestScheduler.run(({ expectObservable }) => {\n      const e1 = iif(\n        (): boolean => {\n          throw 'error';\n        },\n        of('a'),\n        of()\n      );\n\n      const expected = '#';\n\n      expectObservable(e1).toBe(expected);\n    });\n  });\n\n  it('should accept resolved promise as thenSource', (done) => {\n    const expected = 42;\n    const e1 = iif(\n      () => true,\n      new Promise((resolve: any) => {\n        resolve(expected);\n      }),\n      of()\n    );\n\n    e1.subscribe({\n      next: (x) => {\n        expect(x).to.equal(expected);\n      },\n      error: (x) => {\n        done(new Error('should not be called'));\n      },\n      complete: () => {\n        done();\n      },\n    });\n  });\n\n  it('should accept resolved promise as elseSource', (done) => {\n    const expected = 42;\n    const e1 = iif(\n      () => false,\n      of('a'),\n      new Promise((resolve: any) => {\n        resolve(expected);\n      })\n    );\n\n    e1.subscribe({\n      next: (x) => {\n        expect(x).to.equal(expected);\n      },\n      error: (x) => {\n        done(new Error('should not be called'));\n      },\n      complete: () => {\n        done();\n      },\n    });\n  });\n\n  it('should accept rejected promise as elseSource', (done) => {\n    const expected = 42;\n    const e1 = iif(\n      () => false,\n      of('a'),\n      new Promise((resolve: any, reject: any) => {\n        reject(expected);\n      })\n    );\n\n    e1.subscribe({\n      next: (x) => {\n        done(new Error('should not be called'));\n      },\n      error: (x) => {\n        expect(x).to.equal(expected);\n        done();\n      },\n      complete: () => {\n        done(new Error('should not be called'));\n      },\n    });\n  });\n\n  it('should accept rejected promise as thenSource', (done) => {\n    const expected = 42;\n    const e1 = iif(\n      () => true,\n      new Promise((resolve: any, reject: any) => {\n        reject(expected);\n      }),\n      of()\n    );\n\n    e1.subscribe({\n      next: (x) => {\n        done(new Error('should not be called'));\n      },\n      error: (x) => {\n        expect(x).to.equal(expected);\n        done();\n      },\n      complete: () => {\n        done(new Error('should not be called'));\n      },\n    });\n  });\n});\n"
  },
  {
    "path": "packages/rxjs/spec/observables/interval-spec.ts",
    "content": "/** @prettier */\nimport { expect } from 'chai';\nimport { NEVER, interval, asapScheduler, animationFrameScheduler, queueScheduler } from 'rxjs';\nimport { TestScheduler } from 'rxjs/testing';\nimport { take } from 'rxjs/operators';\nimport * as sinon from 'sinon';\nimport { observableMatcher } from '../helpers/observableMatcher';\n\n/** @test {interval} */\ndescribe('interval', () => {\n  let rxTestScheduler: TestScheduler;\n\n  beforeEach(() => {\n    rxTestScheduler = new TestScheduler(observableMatcher);\n  });\n\n  it('should set up an interval', () => {\n    rxTestScheduler.run(({ expectObservable, time }) => {\n      const period = time('----------|                                                                 ');\n      //                             ----------|\n      //                                       ----------|\n      //                                                 ----------|\n      //                                                           ----------|\n      //                                                                     ----------|\n      //                                                                               ----------|\n      const unsubs = '     ---------------------------------------------------------------------------!';\n      const expected = '   ----------0---------1---------2---------3---------4---------5---------6-----';\n      expectObservable(interval(period), unsubs).toBe(expected, [0, 1, 2, 3, 4, 5, 6]);\n    });\n  });\n\n  it('should emit when relative interval set to zero', () => {\n    rxTestScheduler.run(({ expectObservable, time }) => {\n      const period = time('|         ');\n      const expected = '   (0123456|)';\n\n      const e1 = interval(period).pipe(take(7));\n      expectObservable(e1).toBe(expected, [0, 1, 2, 3, 4, 5, 6]);\n    });\n  });\n\n  it('should consider negative interval as zero', () => {\n    rxTestScheduler.run(({ expectObservable }) => {\n      const expected = '(0123456|)';\n      const e1 = interval(-1).pipe(take(7));\n      expectObservable(e1).toBe(expected, [0, 1, 2, 3, 4, 5, 6]);\n    });\n  });\n\n  it('should emit values until unsubscribed', (done) => {\n    const values: number[] = [];\n    const expected = [0, 1, 2, 3, 4, 5, 6];\n    const e1 = interval(5);\n    const subscription = e1.subscribe({\n      next: (x: number) => {\n        values.push(x);\n        if (x === 6) {\n          subscription.unsubscribe();\n          expect(values).to.deep.equal(expected);\n          done();\n        }\n      },\n      error: (err: any) => {\n        done(new Error('should not be called'));\n      },\n      complete: () => {\n        done(new Error('should not be called'));\n      },\n    });\n  });\n\n  it('should create an observable emitting periodically with the AsapScheduler', (done) => {\n    const sandbox = sinon.createSandbox();\n    const fakeTimer = sandbox.useFakeTimers();\n    const period = 10;\n    const events = [0, 1, 2, 3, 4, 5];\n    const source = interval(period, asapScheduler).pipe(take(6));\n    source.subscribe({\n      next(x) {\n        expect(x).to.equal(events.shift());\n      },\n      error(e) {\n        sandbox.restore();\n        done(e);\n      },\n      complete() {\n        expect(asapScheduler.actions.length).to.equal(0);\n        expect(asapScheduler._scheduled).to.equal(undefined);\n        sandbox.restore();\n        done();\n      },\n    });\n    let i = -1;\n    const n = events.length;\n    while (++i < n) {\n      fakeTimer.tick(period);\n    }\n  });\n\n  it('should create an observable emitting periodically with the QueueScheduler', (done) => {\n    const sandbox = sinon.createSandbox();\n    const fakeTimer = sandbox.useFakeTimers();\n    const period = 10;\n    const events = [0, 1, 2, 3, 4, 5];\n    const source = interval(period, queueScheduler).pipe(take(6));\n    source.subscribe({\n      next(x) {\n        expect(x).to.equal(events.shift());\n      },\n      error(e) {\n        sandbox.restore();\n        done(e);\n      },\n      complete() {\n        expect(queueScheduler.actions.length).to.equal(0);\n        expect(queueScheduler._scheduled).to.equal(undefined);\n        sandbox.restore();\n        done();\n      },\n    });\n    let i = -1;\n    const n = events.length;\n    while (++i < n) {\n      fakeTimer.tick(period);\n    }\n  });\n\n  it('should create an observable emitting periodically with the AnimationFrameScheduler', (done) => {\n    const sandbox = sinon.createSandbox();\n    const fakeTimer = sandbox.useFakeTimers();\n    const period = 10;\n    const events = [0, 1, 2, 3, 4, 5];\n    const source = interval(period, animationFrameScheduler).pipe(take(6));\n    source.subscribe({\n      next(x) {\n        expect(x).to.equal(events.shift());\n      },\n      error(e) {\n        sandbox.restore();\n        done(e);\n      },\n      complete() {\n        expect(animationFrameScheduler.actions.length).to.equal(0);\n        expect(animationFrameScheduler._scheduled).to.equal(undefined);\n        sandbox.restore();\n        done();\n      },\n    });\n    let i = -1;\n    const n = events.length;\n    while (++i < n) {\n      fakeTimer.tick(period);\n    }\n  });\n});\n"
  },
  {
    "path": "packages/rxjs/spec/observables/merge-spec.ts",
    "content": "/** @prettier */\nimport { expect } from 'chai';\nimport { lowerCaseO } from '../helpers/test-helper';\nimport { TestScheduler } from 'rxjs/testing';\nimport { merge, of, Observable, defer, asyncScheduler } from 'rxjs';\nimport { delay } from 'rxjs/operators';\nimport { observableMatcher } from '../helpers/observableMatcher';\n\n/** @test {merge} */\ndescribe('static merge(...observables)', () => {\n  let rxTestScheduler: TestScheduler;\n\n  beforeEach(() => {\n    rxTestScheduler = new TestScheduler(observableMatcher);\n  });\n\n  it('should merge cold and cold', () => {\n    rxTestScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' ---a-----b-----c----|   ');\n      const e1subs = '  ^-------------------!   ';\n      const e2 = cold(' ------x-----y-----z----|');\n      const e2subs = '  ^----------------------!';\n      const expected = '---a--x--b--y--c--z----|';\n\n      const result = merge(e1, e2);\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should return itself when try to merge single observable', () => {\n    const e1 = of('a');\n    const result = merge(e1);\n\n    expect(e1).to.equal(result);\n  });\n\n  it('should merge hot and hot', () => {\n    rxTestScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot(' ---a---^-b-----c----|   ');\n      const e1subs = '        ^------------!   ';\n      const e2 = hot(' -----x-^----y-----z----|');\n      const e2subs = '        ^---------------!';\n      const expected = '      --b--y--c--z----|';\n\n      const result = merge(e1, e2);\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should merge hot and cold', () => {\n    rxTestScheduler.run(({ hot, cold, expectObservable, expectSubscriptions }) => {\n      const e1 = hot(' ---a-^---b-----c----|    ');\n      const e1subs = '      ^--------------!    ';\n      const e2 = cold('     --x-----y-----z----|');\n      const e2subs = '      ^------------------!';\n      const expected = '    --x-b---y-c---z----|';\n\n      const result = merge(e1, e2);\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should merge parallel emissions', () => {\n    rxTestScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  ---a----b----c----|');\n      const e1subs = '  ^-----------------!';\n      const e2 = hot('  ---x----y----z----|');\n      const e2subs = '  ^-----------------!';\n      const expected = '---(ax)-(by)-(cz)-|';\n\n      const result = merge(e1, e2);\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should merge empty and empty', () => {\n    rxTestScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold('|   ');\n      const e1subs = ' (^!)';\n      const e2 = cold('|   ');\n      const e2subs = ' (^!)';\n      const expected = '|  ';\n\n      const result = merge(e1, e2);\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should merge three empties', () => {\n    rxTestScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold('|   ');\n      const e1subs = ' (^!)';\n      const e2 = cold('|   ');\n      const e2subs = ' (^!)';\n      const e3 = cold('|   ');\n      const e3subs = ' (^!)';\n      const expected = '|  ';\n\n      const result = merge(e1, e2, e3);\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n      expectSubscriptions(e3.subscriptions).toBe(e3subs);\n    });\n  });\n\n  it('should merge never and empty', () => {\n    rxTestScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold('-   ');\n      const e1subs = ' ^   ';\n      const e2 = cold('|   ');\n      const e2subs = ' (^!)';\n      const expected = '-  ';\n\n      const result = merge(e1, e2);\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should merge never and never', () => {\n    rxTestScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' -');\n      const e1subs = '  ^';\n      const e2 = cold(' -');\n      const e2subs = '  ^';\n      const expected = '-';\n\n      const result = merge(e1, e2);\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should merge empty and throw', () => {\n    rxTestScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' |   ');\n      const e1subs = '  (^!)';\n      const e2 = cold(' #   ');\n      const e2subs = '  (^!)';\n      const expected = '#';\n\n      const result = merge(e1, e2);\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should merge hot and throw', () => {\n    rxTestScheduler.run(({ hot, cold, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  --a--b--c--|');\n      const e1subs = '  (^!)        ';\n      const e2 = cold(' #           ');\n      const e2subs = '  (^!)        ';\n      const expected = '#           ';\n\n      const result = merge(e1, e2);\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should merge never and throw', () => {\n    rxTestScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' -   ');\n      const e1subs = '  (^!)';\n      const e2 = cold(' #   ');\n      const e2subs = '  (^!)';\n      const expected = '#   ';\n\n      const result = merge(e1, e2);\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should merge empty and eventual error', () => {\n    rxTestScheduler.run(({ hot, cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' |       ');\n      const e1subs = '  (^!)    ';\n      const e2 = hot('  -------#');\n      const e2subs = '  ^------!';\n      const expected = '-------#';\n\n      const result = merge(e1, e2);\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should merge hot and error', () => {\n    rxTestScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  --a--b--c--|');\n      const e1subs = '  ^------!    ';\n      const e2 = hot('  -------#    ');\n      const e2subs = '  ^------!    ';\n      const expected = '--a--b-#    ';\n\n      const result = merge(e1, e2);\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should merge never and error', () => {\n    rxTestScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  --------');\n      const e1subs = '  ^------!';\n      const e2 = hot('  -------#');\n      const e2subs = '  ^------!';\n      const expected = '-------#';\n\n      const result = merge(e1, e2);\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should merge single lowerCaseO into RxJS Observable', () => {\n    rxTestScheduler.run(({ expectObservable }) => {\n      const e1 = lowerCaseO('a', 'b', 'c');\n\n      const result = merge(e1);\n\n      expect(result).to.be.instanceof(Observable);\n      expectObservable(result).toBe('(abc|)');\n    });\n  });\n\n  it('should merge two lowerCaseO into RxJS Observable', () => {\n    rxTestScheduler.run(({ expectObservable }) => {\n      const e1 = lowerCaseO('a', 'b', 'c');\n      const e2 = lowerCaseO('d', 'e', 'f');\n\n      const result = merge(e1, e2);\n\n      expect(result).to.be.instanceof(Observable);\n      expectObservable(result).toBe('(abcdef|)');\n    });\n  });\n});\n\ndescribe('merge(...observables, Scheduler)', () => {\n  let rxTestScheduler: TestScheduler;\n\n  beforeEach(() => {\n    rxTestScheduler = new TestScheduler(observableMatcher);\n  });\n\n  it('should merge single lowerCaseO into RxJS Observable', () => {\n    rxTestScheduler.run(({ expectObservable }) => {\n      const e1 = lowerCaseO('a', 'b', 'c');\n\n      const result = merge(e1, rxTestScheduler);\n\n      expect(result).to.be.instanceof(Observable);\n      expectObservable(result).toBe('(abc|)');\n    });\n  });\n});\n\ndescribe('merge(...observables, Scheduler, number)', () => {\n  let rxTestScheduler: TestScheduler;\n\n  beforeEach(() => {\n    rxTestScheduler = new TestScheduler(observableMatcher);\n  });\n\n  it('should handle concurrency limits', () => {\n    rxTestScheduler.run(({ cold, expectObservable }) => {\n      const e1 = cold(' ---a---b---c---|            ');\n      const e2 = cold(' -d---e---f--|               ');\n      const e3 = cold('             ---x---y---z---|');\n      const expected = '-d-a-e-b-f-c---x---y---z---|';\n      expectObservable(merge(e1, e2, e3, 2)).toBe(expected);\n    });\n  });\n\n  it('should handle scheduler', () => {\n    rxTestScheduler.run(({ expectObservable, time }) => {\n      const delayTime = time('--|');\n      const e1 = of('a');\n      const e2 = of('b').pipe(delay(delayTime));\n      const expected = 'a-(b|)';\n\n      expectObservable(merge(e1, e2, rxTestScheduler)).toBe(expected);\n    });\n  });\n\n  it('should handle scheduler with concurrency limits', () => {\n    rxTestScheduler.run(({ cold, expectObservable }) => {\n      const e1 = cold(' ---a---b---c---|            ');\n      const e2 = cold(' -d---e---f--|               ');\n      const e3 = cold('             ---x---y---z---|');\n      const expected = '-d-a-e-b-f-c---x---y---z---|';\n      expectObservable(merge(e1, e2, e3, 2, rxTestScheduler)).toBe(expected);\n    });\n  });\n\n  it('should use the scheduler even when one Observable is merged', (done) => {\n    let e1Subscribed = false;\n    const e1 = defer(() => {\n      e1Subscribed = true;\n      return of('a');\n    });\n\n    merge(e1, asyncScheduler).subscribe({\n      error: done,\n      complete: () => {\n        expect(e1Subscribed).to.be.true;\n        done();\n      },\n    });\n\n    expect(e1Subscribed).to.be.false;\n  });\n\n  it('should deem a single array argument to be an ObservableInput', () => {\n    rxTestScheduler.run(({ expectObservable }) => {\n      const array = ['foo', 'bar'];\n      const expected = '(fb|)';\n      expectObservable(merge(array)).toBe(expected, { f: 'foo', b: 'bar' });\n    });\n  });\n});\n"
  },
  {
    "path": "packages/rxjs/spec/observables/never-spec.ts",
    "content": "/** @prettier */\nimport { NEVER } from 'rxjs';\nimport { expect } from 'chai';\nimport { TestScheduler } from 'rxjs/testing';\nimport { observableMatcher } from '../helpers/observableMatcher';\n\n/** @test {NEVER} */\ndescribe('NEVER', () => {\n  let rxTestScheduler: TestScheduler;\n\n  beforeEach(() => {\n    rxTestScheduler = new TestScheduler(observableMatcher);\n  });\n\n  it('should create a cold observable that never emits', () => {\n    rxTestScheduler.run(({ expectObservable }) => {\n      const expected = '-';\n      const e1 = NEVER;\n      expectObservable(e1).toBe(expected);\n    });\n  });\n\n  it('should return the same instance every time', () => {\n    expect(NEVER).to.equal(NEVER);\n  });\n});\n"
  },
  {
    "path": "packages/rxjs/spec/observables/of-spec.ts",
    "content": "/** @prettier */\nimport { expect } from 'chai';\nimport { of } from 'rxjs';\nimport { TestScheduler } from 'rxjs/testing';\nimport { concatMap, delay, concatAll } from 'rxjs/operators';\nimport { observableMatcher } from '../helpers/observableMatcher';\n\n/** @test {of} */\ndescribe('of', () => {\n  let rxTestScheduler: TestScheduler;\n\n  beforeEach(() => {\n    rxTestScheduler = new TestScheduler(observableMatcher);\n  });\n\n  it('should create a cold observable that emits 1, 2, 3', () => {\n    rxTestScheduler.run(({ expectObservable, time }) => {\n      const delayValue = time('--|');\n\n      const e1 = of(1, 2, 3).pipe(\n        // for the purpose of making a nice diagram, spread out the synchronous emissions\n        concatMap((x, i) => of(x).pipe(delay(i === 0 ? 0 : delayValue)))\n      );\n      const expected = 'x-y-(z|)';\n      expectObservable(e1).toBe(expected, { x: 1, y: 2, z: 3 });\n    });\n  });\n\n  it('should create an observable from the provided values', (done) => {\n    const x = { foo: 'bar' };\n    const expected = [1, 'a', x];\n    let i = 0;\n\n    of(1, 'a', x).subscribe({\n      next: (y: any) => {\n        expect(y).to.equal(expected[i++]);\n      },\n      error: (x) => {\n        done(new Error('should not be called'));\n      },\n      complete: () => {\n        done();\n      },\n    });\n  });\n\n  it('should emit one value', (done) => {\n    let calls = 0;\n\n    of(42).subscribe({\n      next: (x: number) => {\n        expect(++calls).to.equal(1);\n        expect(x).to.equal(42);\n      },\n      error: (err: any) => {\n        done(new Error('should not be called'));\n      },\n      complete: () => {\n        done();\n      },\n    });\n  });\n\n  it('should handle an Observable as the only value', () => {\n    rxTestScheduler.run(({ expectObservable }) => {\n      const source = of(of('a', 'b', 'c'));\n      const result = source.pipe(concatAll());\n      expectObservable(result).toBe('(abc|)');\n    });\n  });\n\n  it('should handle many Observable as the given values', () => {\n    rxTestScheduler.run(({ expectObservable }) => {\n      const source = of(of('a', 'b', 'c'), of('d', 'e', 'f'));\n\n      const result = source.pipe(concatAll());\n      expectObservable(result).toBe('(abcdef|)');\n    });\n  });\n});\n"
  },
  {
    "path": "packages/rxjs/spec/observables/onErrorResumeNext-spec.ts",
    "content": "/** @prettier */\nimport { onErrorResumeNext, of } from 'rxjs';\nimport { finalize } from 'rxjs/operators';\nimport { expect } from 'chai';\nimport { TestScheduler } from 'rxjs/testing';\nimport { observableMatcher } from '../helpers/observableMatcher';\n\ndescribe('onErrorResumeNext', () => {\n  let rxTestScheduler: TestScheduler;\n\n  beforeEach(() => {\n    rxTestScheduler = new TestScheduler(observableMatcher);\n  });\n\n  it('should continue with observables', () => {\n    rxTestScheduler.run(({ hot, cold, expectObservable, expectSubscriptions }) => {\n      const s1 = hot('  --a--b--#                     ');\n      const s2 = cold('         --c--d--#             ');\n      const s3 = cold('                 --e--#        ');\n      const s4 = cold('                      --f--g--|');\n      const subs1 = '   ^-------!                     ';\n      const subs2 = '   --------^-------!             ';\n      const subs3 = '   ----------------^----!        ';\n      const subs4 = '   ---------------------^-------!';\n      const expected = '--a--b----c--d----e----f--g--|';\n\n      expectObservable(onErrorResumeNext(s1, s2, s3, s4)).toBe(expected);\n      expectSubscriptions(s1.subscriptions).toBe(subs1);\n      expectSubscriptions(s2.subscriptions).toBe(subs2);\n      expectSubscriptions(s3.subscriptions).toBe(subs3);\n      expectSubscriptions(s4.subscriptions).toBe(subs4);\n    });\n  });\n\n  it('should continue array of observables', () => {\n    rxTestScheduler.run(({ hot, cold, expectObservable, expectSubscriptions }) => {\n      const s1 = hot('  --a--b--#                     ');\n      const s2 = cold('         --c--d--#             ');\n      const s3 = cold('                 --e--#        ');\n      const s4 = cold('                      --f--g--|');\n      const subs1 = '   ^-------!                     ';\n      const subs2 = '   --------^-------!             ';\n      const subs3 = '   ----------------^----!        ';\n      const subs4 = '   ---------------------^-------!';\n      const expected = '--a--b----c--d----e----f--g--|';\n\n      expectObservable(onErrorResumeNext([s1, s2, s3, s4])).toBe(expected);\n      expectSubscriptions(s1.subscriptions).toBe(subs1);\n      expectSubscriptions(s2.subscriptions).toBe(subs2);\n      expectSubscriptions(s3.subscriptions).toBe(subs3);\n      expectSubscriptions(s4.subscriptions).toBe(subs4);\n    });\n  });\n\n  it('should complete single observable throws', () => {\n    rxTestScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const source = hot('#   ');\n      const subs = '      (^!)';\n      const expected = '  |   ';\n\n      expectObservable(onErrorResumeNext(source)).toBe(expected);\n      expectSubscriptions(source.subscriptions).toBe(subs);\n    });\n  });\n\n  it('should skip invalid sources and move on', () => {\n    const results: any[] = [];\n\n    onErrorResumeNext(of(1), [2, 3, 4], { notValid: 'LOL' } as any, of(5, 6)).subscribe({\n      next: (value) => results.push(value),\n      complete: () => results.push('complete'),\n    });\n\n    expect(results).to.deep.equal([1, 2, 3, 4, 5, 6, 'complete']);\n  });\n\n  it('should call finalize after each sync observable', () => {\n    const results: any[] = [];\n\n    onErrorResumeNext(\n      of(1).pipe(finalize(() => results.push('finalize 1'))),\n      of(2).pipe(finalize(() => results.push('finalize 2'))),\n      of(3).pipe(finalize(() => results.push('finalize 3'))),\n      of(4).pipe(finalize(() => results.push('finalize 4')))\n    ).subscribe({\n      next: (value) => results.push(value),\n      complete: () => results.push('complete'),\n    });\n\n    expect(results).to.deep.equal([1, 'finalize 1', 2, 'finalize 2', 3, 'finalize 3', 4, 'finalize 4', 'complete']);\n  });\n});\n"
  },
  {
    "path": "packages/rxjs/spec/observables/partition-spec.ts",
    "content": "/** @prettier */\nimport { expect } from 'chai';\nimport type { Observable} from 'rxjs';\nimport { partition, of } from 'rxjs';\nimport { mergeMap } from 'rxjs/operators';\nimport { TestScheduler } from 'rxjs/testing';\nimport { observableMatcher } from '../helpers/observableMatcher';\n\n/** @test {partition} */\ndescribe('partition', () => {\n  let rxTestScheduler: TestScheduler;\n\n  beforeEach(() => {\n    rxTestScheduler = new TestScheduler(observableMatcher);\n  });\n\n  function expectObservableArray(result: Observable<string>[], expected: string[]) {\n    for (let idx = 0; idx < result.length; idx++) {\n      rxTestScheduler.expectObservable(result[idx]).toBe(expected[idx]);\n    }\n  }\n\n  it('should partition an observable of integers into even and odd', () => {\n    rxTestScheduler.run(({ hot, expectSubscriptions }) => {\n      const e1 = hot('   --1-2---3------4--5---6--|');\n      const e1subs = '   ^------------------------!';\n      // prettier-ignore\n      const expected = [\n        '                --1-----3---------5------|',\n        '                ----2----------4------6--|',\n      ];\n\n      const result = partition(e1, (x: any) => x % 2 === 1);\n\n      expectObservableArray(result, expected);\n      expectSubscriptions(e1.subscriptions).toBe([e1subs, e1subs]);\n    });\n  });\n\n  it('should partition an observable into two using a predicate', () => {\n    rxTestScheduler.run(({ hot, expectSubscriptions }) => {\n      const e1 = hot('   --a-b---a------d--a---c--|');\n      const e1subs = '   ^------------------------!';\n      // prettier-ignore\n      const expected = [\n        '                --a-----a---------a------|',\n        '                ----b----------d------c--|',\n      ];\n\n      function predicate(x: string) {\n        return x === 'a';\n      }\n\n      expectObservableArray(partition(e1, predicate), expected);\n      expectSubscriptions(e1.subscriptions).toBe([e1subs, e1subs]);\n    });\n  });\n\n  it('should partition an observable into two using a predicate that takes an index', () => {\n    rxTestScheduler.run(({ hot, expectSubscriptions }) => {\n      const e1 = hot('   --a-b---a------d--a---c--|');\n      const e1subs = '   ^------------------------!';\n      // prettier-ignore\n      const expected = [\n        '                --a-----a---------a------|',\n        '                ----b----------d------c--|',\n      ];\n\n      function predicate(value: string, index: number) {\n        return index % 2 === 0;\n      }\n\n      expectObservableArray(partition(e1, predicate), expected);\n      expectSubscriptions(e1.subscriptions).toBe([e1subs, e1subs]);\n    });\n  });\n\n  it('should partition an observable into two using a predicate and thisArg', () => {\n    rxTestScheduler.run(({ hot, expectSubscriptions }) => {\n      const e1 = hot('   --a-b---a------d--a---c--|');\n      const e1subs = '   ^------------------------!';\n      // prettier-ignore\n      const expected = [\n        '                --a-----a---------a------|',\n        '                ----b----------d------c--|',\n      ];\n\n      function predicate(this: any, x: string) {\n        return x === this.value;\n      }\n\n      expectObservableArray(partition(e1, predicate, { value: 'a' }), expected);\n      expectSubscriptions(e1.subscriptions).toBe([e1subs, e1subs]);\n    });\n  });\n\n  it('should pass errors to both returned observables', () => {\n    rxTestScheduler.run(({ hot, expectSubscriptions }) => {\n      const e1 = hot('   --a-b---#');\n      const e1subs = '   ^-------!';\n      // prettier-ignore\n      const expected = [\n        '                --a-----#',\n        '                ----b---#',\n      ];\n\n      function predicate(x: string) {\n        return x === 'a';\n      }\n\n      expectObservableArray(partition(e1, predicate), expected);\n      expectSubscriptions(e1.subscriptions).toBe([e1subs, e1subs]);\n    });\n  });\n\n  it('should pass errors to both returned observables if source throws', () => {\n    rxTestScheduler.run(({ cold, expectSubscriptions }) => {\n      const e1 = cold('  #   ');\n      const e1subs = '   (^!)';\n      // prettier-ignore\n      const expected = [\n        '                 #  ',\n        '                 #  ',\n      ];\n\n      function predicate(x: string) {\n        return x === 'a';\n      }\n\n      expectObservableArray(partition(e1, predicate), expected);\n      expectSubscriptions(e1.subscriptions).toBe([e1subs, e1subs]);\n    });\n  });\n\n  it('should pass errors to both returned observables if predicate throws', () => {\n    rxTestScheduler.run(({ hot, expectSubscriptions }) => {\n      const e1 = hot('   --a-b--a--|');\n      const e1subs = '   ^------!   ';\n      // prettier-ignore\n      const expected = [\n        '                --a----#   ',\n        '                ----b--#   ',\n      ];\n\n      let index = 0;\n      const error = 'error';\n      function predicate(x: string) {\n        const match = x === 'a';\n        if (match && index++ > 1) {\n          throw error;\n        }\n        return match;\n      }\n\n      expectObservableArray(partition(e1, predicate), expected);\n      expectSubscriptions(e1.subscriptions).toBe([e1subs, e1subs]);\n    });\n  });\n\n  it('should partition empty observable if source does not emits', () => {\n    rxTestScheduler.run(({ hot, expectSubscriptions }) => {\n      const e1 = hot('   ----|');\n      const e1subs = '   ^---!';\n      // prettier-ignore\n      const expected = [\n        '                ----|',\n        '                ----|',\n      ];\n\n      function predicate(x: string) {\n        return x === 'x';\n      }\n\n      expectObservableArray(partition(e1, predicate), expected);\n      expectSubscriptions(e1.subscriptions).toBe([e1subs, e1subs]);\n    });\n  });\n\n  it('should partition empty observable if source is empty', () => {\n    rxTestScheduler.run(({ cold, expectSubscriptions }) => {\n      const e1 = cold('  |   ');\n      const e1subs = '   (^!)';\n      // prettier-ignore\n      const expected = [\n        '                |   ',\n        '                |   ',\n      ];\n\n      function predicate(x: string) {\n        return x === 'x';\n      }\n\n      expectObservableArray(partition(e1, predicate), expected);\n      expectSubscriptions(e1.subscriptions).toBe([e1subs, e1subs]);\n    });\n  });\n\n  it('should partition if source emits single elements', () => {\n    rxTestScheduler.run(({ hot, expectSubscriptions }) => {\n      const e1 = hot('   --a--|');\n      const e1subs = '   ^----!';\n      // prettier-ignore\n      const expected = [\n        '                --a--|',\n        '                -----|',\n      ];\n\n      function predicate(x: string) {\n        return x === 'a';\n      }\n\n      expectObservableArray(partition(e1, predicate), expected);\n      expectSubscriptions(e1.subscriptions).toBe([e1subs, e1subs]);\n    });\n  });\n\n  it('should partition if predicate matches all of source elements', () => {\n    rxTestScheduler.run(({ hot, expectSubscriptions }) => {\n      const e1 = hot('   --a--a--a--a--a--a--a--|');\n      const e1subs = '   ^----------------------!';\n      // prettier-ignore\n      const expected = [\n        '                --a--a--a--a--a--a--a--|',\n        '                -----------------------|',\n      ];\n\n      function predicate(x: string) {\n        return x === 'a';\n      }\n\n      expectObservableArray(partition(e1, predicate), expected);\n      expectSubscriptions(e1.subscriptions).toBe([e1subs, e1subs]);\n    });\n  });\n\n  it('should partition if predicate does not match all of source elements', () => {\n    rxTestScheduler.run(({ hot, expectSubscriptions }) => {\n      const e1 = hot('   --b--b--b--b--b--b--b--|');\n      const e1subs = '   ^----------------------!';\n      // prettier-ignore\n      const expected = [\n        '                -----------------------|',\n        '                --b--b--b--b--b--b--b--|',\n      ];\n\n      function predicate(x: string) {\n        return x === 'a';\n      }\n\n      expectObservableArray(partition(e1, predicate), expected);\n      expectSubscriptions(e1.subscriptions).toBe([e1subs, e1subs]);\n    });\n  });\n\n  it('should partition to infinite observable if source does not completes', () => {\n    rxTestScheduler.run(({ hot, expectSubscriptions }) => {\n      const e1 = hot('   --a-b---a------d----');\n      const e1subs = '   ^-------------------';\n      // prettier-ignore\n      const expected = [\n        '                --a-----a-----------',\n        '                ----b----------d----',\n      ];\n\n      function predicate(x: string) {\n        return x === 'a';\n      }\n\n      expectObservableArray(partition(e1, predicate), expected);\n      expectSubscriptions(e1.subscriptions).toBe([e1subs, e1subs]);\n    });\n  });\n\n  it('should partition to infinite observable if source never completes', () => {\n    rxTestScheduler.run(({ cold, expectSubscriptions }) => {\n      const e1 = cold('  -');\n      const e1subs = '   ^';\n      // prettier-ignore\n      const expected = [\n        '                -',\n        '                -',\n      ];\n\n      function predicate(x: string) {\n        return x === 'a';\n      }\n\n      expectObservableArray(partition(e1, predicate), expected);\n      expectSubscriptions(e1.subscriptions).toBe([e1subs, e1subs]);\n    });\n  });\n\n  it('should partition into two observable with early unsubscription', () => {\n    rxTestScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('   --a-b---a------d-|');\n      const unsub = '    -------!          ';\n      const e1subs = '   ^------!          ';\n      // prettier-ignore\n      const expected = [\n        '                --a-----          ',\n        '                ----b---          ',\n      ];\n\n      function predicate(x: string) {\n        return x === 'a';\n      }\n      const result = partition(e1, predicate);\n\n      for (let idx = 0; idx < result.length; idx++) {\n        expectObservable(result[idx], unsub).toBe(expected[idx]);\n      }\n      expectSubscriptions(e1.subscriptions).toBe([e1subs, e1subs]);\n    });\n  });\n\n  it('should not break unsubscription chains when result is unsubscribed explicitly', () => {\n    rxTestScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('   --a-b---a------d-|');\n      const e1subs = '   ^------!          ';\n      // prettier-ignore\n      const expected = [\n        '                --a-----          ',\n        '                ----b---          ',\n      ];\n      const unsub = '    -------!          ';\n\n      const e1Pipe = e1.pipe(mergeMap((x: string) => of(x)));\n      const result = partition(e1Pipe, (x: string) => x === 'a');\n\n      expectObservable(result[0], unsub).toBe(expected[0]);\n      expectObservable(result[1], unsub).toBe(expected[1]);\n      expectSubscriptions(e1.subscriptions).toBe([e1subs, e1subs]);\n    });\n  });\n\n  it('should accept thisArg', () => {\n    const thisArg = {};\n\n    partition(\n      of(1),\n      function (this: any, value: number) {\n        expect(this).to.deep.equal(thisArg);\n        return true;\n      },\n      thisArg\n    ).forEach((observable: Observable<number>) => observable.subscribe());\n  });\n});\n"
  },
  {
    "path": "packages/rxjs/spec/observables/race-spec.ts",
    "content": "/** @prettier */\nimport { race, of } from 'rxjs';\nimport { mergeMap } from 'rxjs/operators';\nimport { expect } from 'chai';\nimport { TestScheduler } from 'rxjs/testing';\nimport { observableMatcher } from '../helpers/observableMatcher';\n\n/** @test {race} */\ndescribe('race', () => {\n  let rxTestScheduler: TestScheduler;\n\n  beforeEach(() => {\n    rxTestScheduler = new TestScheduler(observableMatcher);\n  });\n\n  it('should race a single observable', () => {\n    rxTestScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' ---a-----b-----c----|');\n      const e1subs = '  ^-------------------!';\n      const expected = '---a-----b-----c----|';\n\n      const result = race(e1);\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should race cold and cold', () => {\n    rxTestScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' ---a-----b-----c----|   ');\n      const e1subs = '  ^-------------------!   ';\n      const e2 = cold(' ------x-----y-----z----|');\n      const e2subs = '  ^--!                    ';\n      const expected = '---a-----b-----c----|   ';\n\n      const result = race(e1, e2);\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should race with array of observable', () => {\n    rxTestScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' ---a-----b-----c----|   ');\n      const e1subs = '  ^-------------------!   ';\n      const e2 = cold(' ------x-----y-----z----|');\n      const e2subs = '  ^--!                    ';\n      const expected = '---a-----b-----c----|   ';\n\n      const result = race([e1, e2]);\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should race hot and hot', () => {\n    rxTestScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  ---a-----b-----c----|   ');\n      const e1subs = '  ^-------------------!   ';\n      const e2 = hot('  ------x-----y-----z----|');\n      const e2subs = '  ^--!                    ';\n      const expected = '---a-----b-----c----|   ';\n\n      const result = race(e1, e2);\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should race hot and cold', () => {\n    rxTestScheduler.run(({ hot, cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' ---a-----b-----c----|   ');\n      const e1subs = '  ^-------------------!   ';\n      const e2 = hot('  ------x-----y-----z----|');\n      const e2subs = '  ^--!                    ';\n      const expected = '---a-----b-----c----|   ';\n\n      const result = race(e1, e2);\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should race 2nd and 1st', () => {\n    rxTestScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' ------x-----y-----z----|');\n      const e1subs = '  ^--!                    ';\n      const e2 = cold(' ---a-----b-----c----|   ');\n      const e2subs = '  ^-------------------!   ';\n      const expected = '---a-----b-----c----|   ';\n\n      const result = race(e1, e2);\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should race emit and complete', () => {\n    rxTestScheduler.run(({ hot, cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' -----|                  ');\n      const e1subs = '  ^----!                  ';\n      const e2 = hot('  ------x-----y-----z----|');\n      const e2subs = '  ^----!                  ';\n      const expected = '-----|                  ';\n\n      const result = race(e1, e2);\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should allow unsubscribing early and explicitly', () => {\n    rxTestScheduler.run(({ hot, cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' ---a-----b-----c----|   ');\n      const e1subs = '  ^-----------!           ';\n      const e2 = hot('  ------x-----y-----z----|');\n      const e2subs = '  ^--!                    ';\n      const expected = '---a-----b---           ';\n      const unsub = '   ------------!           ';\n\n      const result = race(e1, e2);\n\n      expectObservable(result, unsub).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should not break unsubscription chains when unsubscribed explicitly', () => {\n    rxTestScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  --a--^--b--c---d-| ');\n      const e1subs = '       ^--------!    ';\n      const e2 = hot('  ---e-^---f--g---h-|');\n      const e2subs = '       ^--!          ';\n      const expected = '     ---b--c---    ';\n      const unsub = '        ---------!    ';\n\n      const result = race(e1.pipe(mergeMap((x: string) => of(x))), e2.pipe(mergeMap((x: string) => of(x)))).pipe(\n        mergeMap((x: any) => of(x))\n      );\n\n      expectObservable(result, unsub).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should never emit when given non emitting sources', () => {\n    rxTestScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' ---|');\n      const e2 = cold(' ---|');\n      const e1subs = '  ^--!';\n      const expected = '---|';\n\n      const source = race(e1, e2);\n\n      expectObservable(source).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should throw when error occurs mid stream', () => {\n    rxTestScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' ---a-----#              ');\n      const e1subs = '  ^--------!              ';\n      const e2 = cold(' ------x-----y-----z----|');\n      const e2subs = '  ^--!                    ';\n      const expected = '---a-----#              ';\n\n      const result = race(e1, e2);\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should throw when error occurs before a winner is found', () => {\n    rxTestScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' ---#                    ');\n      const e1subs = '  ^--!                    ';\n      const e2 = cold(' ------x-----y-----z----|');\n      const e2subs = '  ^--!                    ';\n      const expected = '---#                    ';\n\n      const result = race(e1, e2);\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('handle empty', () => {\n    rxTestScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' |   ');\n      const e1subs = '  (^!)';\n      const expected = '|   ';\n\n      const source = race(e1);\n\n      expectObservable(source).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('handle never', () => {\n    rxTestScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' -');\n      const e1subs = '  ^';\n      const expected = '-';\n\n      const source = race(e1);\n\n      expectObservable(source).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('handle throw', () => {\n    rxTestScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' #   ');\n      const e1subs = '  (^!)';\n      const expected = '#   ';\n\n      const source = race(e1);\n\n      expectObservable(source).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should support a single ObservableInput argument', (done) => {\n    const source = race(Promise.resolve(42));\n    source.subscribe({\n      next: (value) => {\n        expect(value).to.equal(42);\n      },\n      error: done,\n      complete: done,\n    });\n  });\n});\n"
  },
  {
    "path": "packages/rxjs/spec/observables/range-spec.ts",
    "content": "/** @prettier */\nimport { expect } from 'chai';\nimport * as sinon from 'sinon';\nimport { asapScheduler as asap, range, of } from 'rxjs';\nimport { TestScheduler } from 'rxjs/testing';\nimport { concatMap, delay } from 'rxjs/operators';\nimport { observableMatcher } from '../helpers/observableMatcher';\n\n/** @test {range} */\ndescribe('range', () => {\n  let rxTestScheduler: TestScheduler;\n\n  beforeEach(() => {\n    rxTestScheduler = new TestScheduler(observableMatcher);\n  });\n\n  it('should create an observable with numbers 1 to 10', () => {\n    rxTestScheduler.run(({ expectObservable, time }) => {\n      const delayAmount = time('--|');\n      //                          --|\n      //                            --|\n      //                              --|\n      //                                --|\n      //                                  --|\n      //                                    --|\n      //                                      --|\n      //                                        --|\n      const expected = '        a-b-c-d-e-f-g-h-i-(j|)';\n\n      const e1 = range(1, 10)\n        // for the purpose of making a nice diagram, spread out the synchronous emissions\n        .pipe(concatMap((x, i) => of(x).pipe(delay(i === 0 ? 0 : delayAmount))));\n      const values = {\n        a: 1,\n        b: 2,\n        c: 3,\n        d: 4,\n        e: 5,\n        f: 6,\n        g: 7,\n        h: 8,\n        i: 9,\n        j: 10,\n      };\n      expectObservable(e1).toBe(expected, values);\n    });\n  });\n\n  it('should work for two subscribers', () => {\n    rxTestScheduler.run(({ expectObservable, time }) => {\n      const delayAmount = time('--|');\n      //                          --|\n      //                            --|\n      //                              --|\n      const expected = '        a-b-c-d-(e|)';\n\n      const e1 = range(1, 5).pipe(concatMap((x, i) => of(x).pipe(delay(i === 0 ? 0 : delayAmount))));\n\n      const values = {\n        a: 1,\n        b: 2,\n        c: 3,\n        d: 4,\n        e: 5,\n      };\n      expectObservable(e1).toBe(expected, values);\n      expectObservable(e1).toBe(expected, values);\n    });\n  });\n\n  it('should synchronously create a range of values by default', () => {\n    const results = [] as any[];\n    range(12, 4).subscribe(function (x) {\n      results.push(x);\n    });\n    expect(results).to.deep.equal([12, 13, 14, 15]);\n  });\n\n  it('should accept a scheduler', (done) => {\n    const expected = [12, 13, 14, 15];\n    sinon.spy(asap, 'schedule');\n\n    const source = range(12, 4, asap);\n\n    source.subscribe({\n      next: function (x) {\n        expect(asap.schedule).have.been.called;\n        const exp = expected.shift();\n        expect(x).to.equal(exp);\n      },\n      error: function (x) {\n        done(new Error('should not be called'));\n      },\n      complete: () => {\n        (<any>asap.schedule).restore();\n        done();\n      },\n    });\n  });\n\n  it('should accept only one argument where count is argument and start is zero', () => {\n    rxTestScheduler.run(({ expectObservable, time }) => {\n      const delayAmount = time('--|');\n      //                          --|\n      //                            --|\n      //                              --|\n      const expected = '        a-b-c-d-(e|)';\n\n      const e1 = range(5).pipe(concatMap((x, i) => of(x).pipe(delay(i === 0 ? 0 : delayAmount))));\n      const values = {\n        a: 0,\n        b: 1,\n        c: 2,\n        d: 3,\n        e: 4,\n      };\n      expectObservable(e1).toBe(expected, values);\n      expectObservable(e1).toBe(expected, values);\n    });\n  });\n\n  it('should return empty for range(0)', () => {\n    const results: any[] = [];\n    range(0).subscribe({\n      next: (value) => results.push(value),\n      complete: () => results.push('done'),\n    });\n    expect(results).to.deep.equal(['done']);\n  });\n\n  it('should return empty for range with a negative count', () => {\n    const results: any[] = [];\n    range(5, -5).subscribe({\n      next: (value) => results.push(value),\n      complete: () => results.push('done'),\n    });\n    expect(results).to.deep.equal(['done']);\n  });\n});\n"
  },
  {
    "path": "packages/rxjs/spec/observables/throwError-spec.ts",
    "content": "/** @prettier */\nimport { expect } from 'chai';\nimport { TestScheduler } from 'rxjs/testing';\nimport { throwError } from 'rxjs';\nimport { observableMatcher } from '../helpers/observableMatcher';\n\n/** @test {throwError} */\ndescribe('throwError', () => {\n  let rxTest: TestScheduler;\n\n  beforeEach(() => {\n    rxTest = new TestScheduler(observableMatcher);\n  });\n\n  it('should create a cold observable that just emits an error', () => {\n    rxTest.run(({ expectObservable }) => {\n      const expected = '#';\n      const e1 = throwError(() => 'error');\n      expectObservable(e1).toBe(expected);\n    });\n  });\n\n  it('should emit one value', (done) => {\n    let calls = 0;\n    throwError(() => 'bad').subscribe({\n      next: () => {\n        done(new Error('should not be called'));\n      },\n      error: (err) => {\n        expect(++calls).to.equal(1);\n        expect(err).to.equal('bad');\n        done();\n      },\n    });\n  });\n\n  it('should accept a factory function', () => {\n    let calls = 0;\n    const errors: any[] = [];\n\n    const source = throwError(() => ({\n      call: ++calls,\n      message: 'LOL',\n    }));\n\n    source.subscribe({\n      next: () => {\n        throw new Error('this should not happen');\n      },\n      error: (err) => {\n        errors.push(err);\n      },\n    });\n\n    source.subscribe({\n      next: () => {\n        throw new Error('this should not happen');\n      },\n      error: (err) => {\n        errors.push(err);\n      },\n    });\n\n    expect(errors).to.deep.equal([\n      {\n        call: 1,\n        message: 'LOL',\n      },\n      {\n        call: 2,\n        message: 'LOL',\n      },\n    ]);\n  });\n});\n"
  },
  {
    "path": "packages/rxjs/spec/observables/timer-spec.ts",
    "content": "import { timer, NEVER, merge } from 'rxjs';\nimport { TestScheduler } from 'rxjs/testing';\nimport { mergeMap, take, concatWith } from 'rxjs/operators';\nimport { observableMatcher } from '../helpers/observableMatcher';\n\n/** @test {timer} */\ndescribe('timer', () => {\n  let rxTest: TestScheduler;\n\n  beforeEach(() => {\n    rxTest = new TestScheduler(observableMatcher);\n  });\n\n  it('should create an observable emitting periodically', () => {\n    rxTest.run(({ expectObservable }) => {\n      const e1 = timer(6, 2, rxTest).pipe(\n        take(4), // make it actually finite, so it can be rendered\n        concatWith(NEVER) // but pretend it's infinite by not completing\n      );\n      const expected = '------a-b-c-d-';\n      const values = {\n        a: 0,\n        b: 1,\n        c: 2,\n        d: 3,\n      };\n      expectObservable(e1).toBe(expected, values);\n    });\n  });\n\n  it('should schedule a value of 0 then complete', () => {\n    rxTest.run(({ expectObservable }) => {\n      const dueTime = 5; // -----|\n      const expected = '    -----(x|)';\n\n      const source = timer(dueTime, undefined, rxTest);\n      expectObservable(source).toBe(expected, { x: 0 });\n    });\n  });\n\n  it('should emit a single value immediately', () => {\n    rxTest.run(({ expectObservable }) => {\n      const dueTime = 0;\n      const expected = '(x|)';\n\n      const source = timer(dueTime, rxTest);\n      expectObservable(source).toBe(expected, { x: 0 });\n    });\n  });\n\n  it('should start after delay and periodically emit values', () => {\n    rxTest.run(({ expectObservable }) => {\n      const dueTime = 4; // ----|\n      const period = 2; //       -|-|-|-|\n      const expected = '    ----a-b-c-d-(e|)';\n\n      const source = timer(dueTime, period, rxTest).pipe(take(5));\n      const values = { a: 0, b: 1, c: 2, d: 3, e: 4 };\n      expectObservable(source).toBe(expected, values);\n    });\n  });\n\n  it('should start immediately and periodically emit values', () => {\n    rxTest.run(({ expectObservable }) => {\n      const dueTime = 0; //|\n      const period = 3; //  --|--|--|--|\n      const expected = '   a--b--c--d--(e|)';\n\n      const source = timer(dueTime, period, rxTest).pipe(take(5));\n      const values = { a: 0, b: 1, c: 2, d: 3, e: 4 };\n      expectObservable(source).toBe(expected, values);\n    });\n  });\n\n  it('should stop emitting values when subscription is done', () => {\n    rxTest.run(({ expectObservable }) => {\n      const dueTime = 0; //|\n      const period = 3; //  --|--|--|--|\n      const expected = '   a--b--c--d--e';\n      const unsub = '      ^------------!';\n\n      const source = timer(dueTime, period, rxTest);\n      const values = { a: 0, b: 1, c: 2, d: 3, e: 4 };\n      expectObservable(source, unsub).toBe(expected, values);\n    });\n  });\n\n  it('should schedule a value at a specified Date', () => {\n    rxTest.run(({ expectObservable }) => {\n      const offset = 4; // ----|\n      const expected = '   ----(a|)';\n\n      const dueTime = new Date(rxTest.now() + offset);\n      const source = timer(dueTime, undefined, rxTest);\n      expectObservable(source).toBe(expected, { a: 0 });\n    });\n  });\n\n  it('should start after delay and periodically emit values', () => {\n    rxTest.run(({ expectObservable }) => {\n      const offset = 4; // ----|\n      const period = 2; //      -|-|-|-|\n      const expected = '   ----a-b-c-d-(e|)';\n\n      const dueTime = new Date(rxTest.now() + offset);\n      const source = timer(dueTime, period, rxTest).pipe(take(5));\n      const values = { a: 0, b: 1, c: 2, d: 3, e: 4 };\n      expectObservable(source).toBe(expected, values);\n    });\n  });\n\n  it('should still target the same date if a date is provided even for the ' + 'second subscription', () => {\n    rxTest.run(({ cold, time, expectObservable }) => {\n      const offset = time('----|    ');\n      const t1 = cold('    a|       ');\n      const t2 = cold('    --a|     ');\n      const expected = '   ----(aa|)';\n\n      const dueTime = new Date(rxTest.now() + offset);\n      const source = timer(dueTime, undefined, rxTest);\n\n      const testSource = merge(t1, t2).pipe(mergeMap(() => source));\n\n      expectObservable(testSource).toBe(expected, { a: 0 });\n    });\n  });\n\n  it('should accept Infinity as the first argument', () => {\n    rxTest.run(({ expectObservable }) => {\n      const source = timer(Infinity, undefined, rxTest);\n      const expected = '------';\n      expectObservable(source).toBe(expected);\n    });\n  });\n\n  it('should accept Infinity as the second argument', () => {\n    rxTest.run(({ expectObservable }) => {\n      rxTest.maxFrames = 20;\n      const source = timer(4, Infinity, rxTest);\n      const expected = '----a-';\n      expectObservable(source).toBe(expected, { a: 0 });\n    });\n  });\n\n  it('should accept negative numbers as the second argument, which should cause immediate completion', () => {\n    rxTest.run(({ expectObservable }) => {\n      const source = timer(4, -4, rxTest);\n      const expected = '----(a|)';\n      expectObservable(source).toBe(expected, { a: 0 });\n    });\n  });\n\n  it('should accept 0 as the second argument', () => {\n    rxTest.run(({ expectObservable }) => {\n      const source = timer(4, 0, rxTest).pipe(take(5));\n      const expected = '----(abcde|)';\n      expectObservable(source).toBe(expected, { a: 0, b: 1, c: 2, d: 3, e: 4 });\n    });\n  });\n\n  it('should emit after a delay of 0 for Date objects in the past', () => {\n    rxTest.run(({ expectObservable }) => {\n      const expected = '(a|)';\n      const threeSecondsInThePast = new Date(rxTest.now() - 3000);\n      const source = timer(threeSecondsInThePast, undefined, rxTest);\n      expectObservable(source).toBe(expected, { a: 0 });\n    });\n  });\n});\n"
  },
  {
    "path": "packages/rxjs/spec/observables/using-spec.ts",
    "content": "import { expect } from 'chai';\nimport { using, range, Subscription } from 'rxjs';\nimport { take } from 'rxjs/operators';\n\ndescribe('using', () => {\n  it('should dispose of the resource when the subscription is disposed', (done) => {\n    let disposed = false;\n    const source = using(\n      () => new Subscription(() => disposed = true),\n      (resource) => range(0, 3)\n    )\n    .pipe(take(2));\n\n    source.subscribe();\n\n    if (disposed) {\n      done();\n    } else {\n      done(new Error('disposed should be true but was false'));\n    }\n  });\n\n  it('should accept factory returns promise resolves', (done) => {\n    const expected = 42;\n\n    let disposed = false;\n    const e1 = using(\n      () => new Subscription(() => disposed = true),\n      (resource) => new Promise((resolve: any) => { resolve(expected); }));\n\n    e1.subscribe({ next: x => {\n      expect(x).to.equal(expected);\n    }, error: (x) => {\n      done(new Error('should not be called'));\n    }, complete: () => {\n      done();\n    } });\n  });\n\n  it('should accept factory returns promise rejects', (done) => {\n    const expected = 42;\n\n    let disposed = false;\n    const e1 = using(\n      () => new Subscription(() => disposed = true),\n      (resource) => new Promise((resolve: any, reject: any) => { reject(expected); }));\n\n    e1.subscribe({ next: x => {\n      done(new Error('should not be called'));\n    }, error: (x) => {\n      expect(x).to.equal(expected);\n      done();\n    }, complete: () => {\n      done(new Error('should not be called'));\n    } });\n  });\n\n  it('should raise error when resource factory throws', (done) => {\n    const expectedError = 'expected';\n    const error = 'error';\n\n    const source = using(\n      () => {\n        throw expectedError;\n      },\n      (resource) => {\n        throw error;\n      }\n    );\n\n    source.subscribe({ next: (x) => {\n      done(new Error('should not be called'));\n    }, error: (x) => {\n      expect(x).to.equal(expectedError);\n      done();\n    }, complete: () => {\n      done(new Error('should not be called'));\n    } });\n  });\n\n  it('should raise error when observable factory throws', (done) => {\n    const error = 'error';\n    let disposed = false;\n\n    const source = using(\n      () => new Subscription(() => disposed = true),\n      (resource) => {\n        throw error;\n      }\n    );\n\n    source.subscribe({ next: (x) => {\n      done(new Error('should not be called'));\n    }, error: (x) => {\n      expect(x).to.equal(error);\n      done();\n    }, complete: () => {\n      done(new Error('should not be called'));\n    } });\n  });\n});\n"
  },
  {
    "path": "packages/rxjs/spec/observables/zip-spec.ts",
    "content": "/** @prettier */\nimport { expect } from 'chai';\nimport { queueScheduler as rxQueueScheduler, zip, from, scheduled } from 'rxjs';\nimport { TestScheduler } from 'rxjs/testing';\nimport { observableMatcher } from '../helpers/observableMatcher';\n\nconst queueScheduler = rxQueueScheduler;\n\n/** @test {zip} */\ndescribe('zip', () => {\n  let rxTestScheduler: TestScheduler;\n\n  beforeEach(() => {\n    rxTestScheduler = new TestScheduler(observableMatcher);\n  });\n\n  it('should combine a source with a second', () => {\n    rxTestScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const a = hot('   ---1---2---3---  ');\n      const asubs = '   ^                ';\n      const b = hot('   --4--5--6--7--8--');\n      const bsubs = '   ^                ';\n      const expected = '---x---y---z     ';\n\n      expectObservable(zip(a, b)).toBe(expected, { x: ['1', '4'], y: ['2', '5'], z: ['3', '6'] });\n      expectSubscriptions(a.subscriptions).toBe(asubs);\n      expectSubscriptions(b.subscriptions).toBe(bsubs);\n    });\n  });\n\n  it('should zip the provided observables', (done) => {\n    const expected = ['a1', 'b2', 'c3'];\n    let i = 0;\n\n    zip(from(['a', 'b', 'c']), from([1, 2, 3]), (a: string, b: number) => a + b).subscribe({\n      next: (x: string) => {\n        expect(x).to.equal(expected[i++]);\n      },\n      complete: done,\n    });\n  });\n\n  it('should end once one observable completes and its buffer is empty', () => {\n    rxTestScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  ---a--b--c--|               ');\n      const e1subs = '  ^-----------!               ';\n      const e2 = hot('  ------d----e----f--------|  ');\n      const e2subs = '  ^-----------------!         ';\n      const e3 = hot('  --------h----i----j---------'); // doesn't complete\n      const e3subs = '  ^-----------------!         ';\n      const expected = '--------x----y----(z|)      '; // e1 complete and buffer empty\n      const values = {\n        x: ['a', 'd', 'h'],\n        y: ['b', 'e', 'i'],\n        z: ['c', 'f', 'j'],\n      };\n\n      expectObservable(zip(e1, e2, e3)).toBe(expected, values);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n      expectSubscriptions(e3.subscriptions).toBe(e3subs);\n    });\n  });\n\n  it('should end once one observable nexts and zips value from completed other observable whose buffer is empty', () => {\n    rxTestScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  ---a--b--c--|             ');\n      const e1subs = '  ^-----------!             ';\n      const e2 = hot('  ------d----e----f|        ');\n      const e2subs = '  ^----------------!        ';\n      const e3 = hot('  --------h----i----j-------'); // doesn't complete\n      const e3subs = '  ^-----------------!       ';\n      const expected = '--------x----y----(z|)    '; // e2 buffer empty and signaled complete\n      const values = {\n        x: ['a', 'd', 'h'],\n        y: ['b', 'e', 'i'],\n        z: ['c', 'f', 'j'],\n      };\n\n      expectObservable(zip(e1, e2, e3)).toBe(expected, values);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n      expectSubscriptions(e3.subscriptions).toBe(e3subs);\n    });\n  });\n\n  describe('with iterables', () => {\n    it('should zip them with values', () => {\n      rxTestScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n        const myIterator = (function* () {\n          for (let i = 0; i < 4; i++) {\n            yield i;\n          }\n        })();\n\n        const e1 = hot('  ---a---b---c---d---|');\n        const e1subs = '  ^--------------!    ';\n        const expected = '---w---x---y---(z|) ';\n\n        const values = {\n          w: ['a', 0],\n          x: ['b', 1],\n          y: ['c', 2],\n          z: ['d', 3],\n        };\n\n        expectObservable(zip(e1, myIterator)).toBe(expected, values);\n        expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      });\n    });\n\n    it('should work with empty observable and empty iterable', () => {\n      rxTestScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n        const a = cold('|  ');\n        const asubs = '(^!)';\n        const b: number[] = [];\n        const expected = '|';\n\n        expectObservable(zip(a, b)).toBe(expected);\n        expectSubscriptions(a.subscriptions).toBe(asubs);\n      });\n    });\n\n    it('should work with empty observable and non-empty iterable', () => {\n      rxTestScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n        const a = cold('  |   ');\n        const asubs = '   (^!)';\n        const b = [1];\n        const expected = '|   ';\n\n        expectObservable(zip(a, b)).toBe(expected);\n        expectSubscriptions(a.subscriptions).toBe(asubs);\n      });\n    });\n\n    it('should complete instantly if given an empty iterable', () => {\n      rxTestScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n        const a = hot('---^----a--|');\n        const asubs = '   (^!)     ';\n        const b: number[] = [];\n        const expected = '|        ';\n\n        expectObservable(zip(a, b)).toBe(expected);\n        expectSubscriptions(a.subscriptions).toBe(asubs);\n      });\n    });\n\n    it('should work with never observable and non-empty iterable', () => {\n      rxTestScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n        const a = cold('  -');\n        const asubs = '   ^';\n        const b = [1];\n        const expected = '-';\n\n        expectObservable(zip(a, b)).toBe(expected);\n        expectSubscriptions(a.subscriptions).toBe(asubs);\n      });\n    });\n\n    it('should work with non-empty observable and non-empty iterable', () => {\n      rxTestScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n        const a = hot('---^----1--|');\n        const asubs = '   ^----!   ';\n        const b = [2];\n        const expected = '-----(x|)';\n\n        expectObservable(zip(a, b)).toBe(expected, { x: ['1', 2] });\n        expectSubscriptions(a.subscriptions).toBe(asubs);\n      });\n    });\n\n    it('should work with observable which raises error and non-empty iterable', () => {\n      rxTestScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n        const a = hot('---^----#');\n        const asubs = '   ^----!';\n        const b = [1];\n        const expected = '-----#';\n\n        expectObservable(zip(a, b)).toBe(expected);\n        expectSubscriptions(a.subscriptions).toBe(asubs);\n      });\n    });\n\n    it('should work with non-empty many observable and non-empty many iterable', () => {\n      rxTestScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n        const a = hot('---^--1--2--3--|');\n        const asubs = '   ^--------!   ';\n        const b = [4, 5, 6];\n        const expected = '---x--y--(z|)';\n\n        expectObservable(zip(a, b)).toBe(expected, { x: ['1', 4], y: ['2', 5], z: ['3', 6] });\n        expectSubscriptions(a.subscriptions).toBe(asubs);\n      });\n    });\n\n    it('should work with non-empty observable and non-empty iterable selector that throws', () => {\n      rxTestScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n        const a = hot('---^--1--2--3--|');\n        const asubs = '   ^-----!      ';\n        const b = [4, 5, 6];\n        const expected = '---x--#      ';\n\n        const selector = (x: string, y: number) => {\n          if (y === 5) {\n            throw new Error('too bad');\n          } else {\n            return x + y;\n          }\n        };\n        expectObservable(zip(a, b, selector)).toBe(expected, { x: '14' }, new Error('too bad'));\n        expectSubscriptions(a.subscriptions).toBe(asubs);\n      });\n    });\n  });\n\n  it('should combine two observables and selector', () => {\n    rxTestScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const a = hot('   ---1---2---3---  ');\n      const asubs = '   ^                ';\n      const b = hot('   --4--5--6--7--8--');\n      const bsubs = '   ^                ';\n      const expected = '---x---y---z     ';\n\n      expectObservable(zip(a, b, (e1: string, e2: string) => e1 + e2)).toBe(expected, { x: '14', y: '25', z: '36' });\n      expectSubscriptions(a.subscriptions).toBe(asubs);\n      expectSubscriptions(b.subscriptions).toBe(bsubs);\n    });\n  });\n\n  it('should work with n-ary symmetric', () => {\n    rxTestScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const a = hot('---1-^-1----4----|');\n      const asubs = '     ^---------!  ';\n      const b = hot('---1-^--2--5----| ');\n      const bsubs = '     ^---------!  ';\n      const c = hot('---1-^---3---6-|  ');\n      const expected = '  ----x---y-|  ';\n\n      expectObservable(zip(a, b, c)).toBe(expected, { x: ['1', '2', '3'], y: ['4', '5', '6'] });\n      expectSubscriptions(a.subscriptions).toBe(asubs);\n      expectSubscriptions(b.subscriptions).toBe(bsubs);\n    });\n  });\n\n  it('should work with n-ary symmetric selector', () => {\n    rxTestScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const a = hot('---1-^-1----4----|');\n      const asubs = '     ^---------!  ';\n      const b = hot('---1-^--2--5----| ');\n      const bsubs = '     ^---------!  ';\n      const c = hot('---1-^---3---6-|  ');\n      const expected = '  ----x---y-|  ';\n\n      const observable = zip(a, b, c, (r0: string, r1: string, r2: string) => [r0, r1, r2]);\n      expectObservable(observable).toBe(expected, { x: ['1', '2', '3'], y: ['4', '5', '6'] });\n      expectSubscriptions(a.subscriptions).toBe(asubs);\n      expectSubscriptions(b.subscriptions).toBe(bsubs);\n    });\n  });\n\n  it('should work with n-ary symmetric array selector', () => {\n    rxTestScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const a = hot('---1-^-1----4----|');\n      const asubs = '     ^---------!  ';\n      const b = hot('---1-^--2--5----| ');\n      const bsubs = '     ^---------!  ';\n      const c = hot('---1-^---3---6-|  ');\n      const expected = '  ----x---y-|  ';\n\n      const observable = zip(a, b, c, (r0: string, r1: string, r2: string) => [r0, r1, r2]);\n      expectObservable(observable).toBe(expected, { x: ['1', '2', '3'], y: ['4', '5', '6'] });\n      expectSubscriptions(a.subscriptions).toBe(asubs);\n      expectSubscriptions(b.subscriptions).toBe(bsubs);\n    });\n  });\n\n  it('should work with some data asymmetric 1', () => {\n    rxTestScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const a = hot('---1-^-1-3-5-7-9-x-y-z-w-u-|');\n      const asubs = '     ^-----------------!    ';\n      const b = hot('---1-^--2--4--6--8--0--|    ');\n      const bsubs = '     ^-----------------!    ';\n      const expected = '  ---a--b--c--d--e--|    ';\n\n      expectObservable(zip(a, b, (r1: string, r2: string) => r1 + r2)).toBe(expected, { a: '12', b: '34', c: '56', d: '78', e: '90' });\n      expectSubscriptions(a.subscriptions).toBe(asubs);\n      expectSubscriptions(b.subscriptions).toBe(bsubs);\n    });\n  });\n\n  it('should work with some data asymmetric 2', () => {\n    rxTestScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const a = hot('---1-^--2--4--6--8--0--|    ');\n      const asubs = '     ^-----------------!    ';\n      const b = hot('---1-^-1-3-5-7-9-x-y-z-w-u-|');\n      const bsubs = '     ^-----------------!    ';\n      const expected = '  ---a--b--c--d--e--|    ';\n\n      expectObservable(zip(a, b, (r1: string, r2: string) => r1 + r2)).toBe(expected, { a: '21', b: '43', c: '65', d: '87', e: '09' });\n      expectSubscriptions(a.subscriptions).toBe(asubs);\n      expectSubscriptions(b.subscriptions).toBe(bsubs);\n    });\n  });\n\n  it('should work with some data symmetric', () => {\n    rxTestScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const a = hot('---1-^-1-3-5-7-9------| ');\n      const asubs = '     ^----------------! ';\n      const b = hot('---1-^--2--4--6--8--0--|');\n      const bsubs = '     ^----------------! ';\n      const expected = '  ---a--b--c--d--e-| ';\n\n      expectObservable(zip(a, b, (r1: string, r2: string) => r1 + r2)).toBe(expected, { a: '12', b: '34', c: '56', d: '78', e: '90' });\n      expectSubscriptions(a.subscriptions).toBe(asubs);\n      expectSubscriptions(b.subscriptions).toBe(bsubs);\n    });\n  });\n\n  it('should work with selector throws', () => {\n    rxTestScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const a = hot('---1-^-2---4----|  ');\n      const asubs = '     ^-------!     ';\n      const b = hot('---1-^--3----5----|');\n      const bsubs = '     ^-------!     ';\n      const expected = '  ---x----#     ';\n\n      const selector = (x: string, y: string) => {\n        if (y === '5') {\n          throw new Error('too bad');\n        } else {\n          return x + y;\n        }\n      };\n      const observable = zip(a, b, selector);\n      expectObservable(observable).toBe(expected, { x: '23' }, new Error('too bad'));\n      expectSubscriptions(a.subscriptions).toBe(asubs);\n      expectSubscriptions(b.subscriptions).toBe(bsubs);\n    });\n  });\n\n  it('should work with right completes first', () => {\n    rxTestScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const a = hot('---1-^-2-----|');\n      const asubs = '     ^-----!  ';\n      const b = hot('---1-^--3--|  ');\n      const bsubs = '     ^-----!  ';\n      const expected = '  ---x--|  ';\n\n      expectObservable(zip(a, b)).toBe(expected, { x: ['2', '3'] });\n      expectSubscriptions(a.subscriptions).toBe(asubs);\n      expectSubscriptions(b.subscriptions).toBe(bsubs);\n    });\n  });\n\n  it('should work with two nevers', () => {\n    rxTestScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const a = cold('  -');\n      const asubs = '   ^';\n      const b = cold('  -');\n      const bsubs = '   ^';\n      const expected = '-';\n\n      expectObservable(zip(a, b)).toBe(expected);\n      expectSubscriptions(a.subscriptions).toBe(asubs);\n      expectSubscriptions(b.subscriptions).toBe(bsubs);\n    });\n  });\n\n  it('should work with never and empty', () => {\n    rxTestScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const a = cold('  -   ');\n      const asubs = '   (^!)';\n      const b = cold('  |   ');\n      const bsubs = '   (^!)';\n      const expected = '|   ';\n\n      expectObservable(zip(a, b)).toBe(expected);\n      expectSubscriptions(a.subscriptions).toBe(asubs);\n      expectSubscriptions(b.subscriptions).toBe(bsubs);\n    });\n  });\n\n  it('should work with empty and never', () => {\n    rxTestScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const a = cold('  |   ');\n      const asubs = '   (^!)';\n      const b = cold('  -   ');\n      const bsubs = '   (^!)';\n      const expected = '|   ';\n\n      expectObservable(zip(a, b)).toBe(expected);\n      expectSubscriptions(a.subscriptions).toBe(asubs);\n      expectSubscriptions(b.subscriptions).toBe(bsubs);\n    });\n  });\n\n  it('should work with empty and empty', () => {\n    rxTestScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const a = cold('  |   ');\n      const asubs = '   (^!)';\n      const b = cold('  |   ');\n      const bsubs = '   (^!)';\n      const expected = '|   ';\n\n      expectObservable(zip(a, b)).toBe(expected);\n      expectSubscriptions(a.subscriptions).toBe(asubs);\n      expectSubscriptions(b.subscriptions).toBe(bsubs);\n    });\n  });\n\n  it('should work with empty and non-empty', () => {\n    rxTestScheduler.run(({ hot, cold, expectObservable, expectSubscriptions }) => {\n      const a = cold('  |      ');\n      const asubs = '   (^!)   ';\n      const b = hot('   ---1--|');\n      const bsubs = '   (^!)   ';\n      const expected = '|      ';\n\n      expectObservable(zip(a, b)).toBe(expected);\n      expectSubscriptions(a.subscriptions).toBe(asubs);\n      expectSubscriptions(b.subscriptions).toBe(bsubs);\n    });\n  });\n\n  it('should work with non-empty and empty', () => {\n    rxTestScheduler.run(({ hot, cold, expectObservable, expectSubscriptions }) => {\n      const a = hot('   ---1--|');\n      const asubs = '   (^!)   ';\n      const b = cold('  |      ');\n      const bsubs = '   (^!)   ';\n      const expected = '|      ';\n\n      expectObservable(zip(a, b)).toBe(expected);\n      expectSubscriptions(a.subscriptions).toBe(asubs);\n      expectSubscriptions(b.subscriptions).toBe(bsubs);\n    });\n  });\n\n  it('should work with never and non-empty', () => {\n    rxTestScheduler.run(({ hot, cold, expectObservable, expectSubscriptions }) => {\n      const a = cold('  -      ');\n      const asubs = '   ^      ';\n      const b = hot('   ---1--|');\n      const bsubs = '   ^-----!';\n      const expected = '-      ';\n\n      expectObservable(zip(a, b)).toBe(expected);\n      expectSubscriptions(a.subscriptions).toBe(asubs);\n      expectSubscriptions(b.subscriptions).toBe(bsubs);\n    });\n  });\n\n  it('should work with non-empty and never', () => {\n    rxTestScheduler.run(({ hot, cold, expectObservable, expectSubscriptions }) => {\n      const a = hot('   ---1--|');\n      const asubs = '   ^-----!';\n      const b = cold('  -      ');\n      const bsubs = '   ^      ';\n      const expected = '-      ';\n\n      expectObservable(zip(a, b)).toBe(expected);\n      expectSubscriptions(a.subscriptions).toBe(asubs);\n      expectSubscriptions(b.subscriptions).toBe(bsubs);\n    });\n  });\n\n  it('should work with empty and error', () => {\n    rxTestScheduler.run(({ hot, cold, expectObservable, expectSubscriptions }) => {\n      const a = cold('  |      ');\n      const asubs = '   (^!)   ';\n      const b = hot('   ------#', undefined, 'too bad');\n      const bsubs = '   (^!)   ';\n      const expected = '|      ';\n\n      expectObservable(zip(a, b)).toBe(expected);\n      expectSubscriptions(a.subscriptions).toBe(asubs);\n      expectSubscriptions(b.subscriptions).toBe(bsubs);\n    });\n  });\n\n  it('should work with error and empty', () => {\n    rxTestScheduler.run(({ hot, cold, expectObservable, expectSubscriptions }) => {\n      const a = hot('   ------#', undefined, 'too bad');\n      const asubs = '   (^!)   ';\n      const b = cold('  |      ');\n      const bsubs = '   (^!)   ';\n      const expected = '|      ';\n\n      expectObservable(zip(a, b)).toBe(expected);\n      expectSubscriptions(a.subscriptions).toBe(asubs);\n      expectSubscriptions(b.subscriptions).toBe(bsubs);\n    });\n  });\n\n  it('should work with error', () => {\n    rxTestScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const a = hot('   ----------|');\n      const asubs = '   ^-----!    ';\n      const b = hot('   ------#    ');\n      const bsubs = '   ^-----!    ';\n      const expected = '------#    ';\n\n      expectObservable(zip(a, b)).toBe(expected);\n      expectSubscriptions(a.subscriptions).toBe(asubs);\n      expectSubscriptions(b.subscriptions).toBe(bsubs);\n    });\n  });\n\n  it('should work with never and error', () => {\n    rxTestScheduler.run(({ hot, cold, expectObservable, expectSubscriptions }) => {\n      const a = cold('  -      ');\n      const asubs = '   ^-----!';\n      const b = hot('   ------#');\n      const bsubs = '   ^-----!';\n      const expected = '------#';\n\n      expectObservable(zip(a, b)).toBe(expected);\n      expectSubscriptions(a.subscriptions).toBe(asubs);\n      expectSubscriptions(b.subscriptions).toBe(bsubs);\n    });\n  });\n\n  it('should work with error and never', () => {\n    rxTestScheduler.run(({ hot, cold, expectObservable, expectSubscriptions }) => {\n      const a = hot('   ------#');\n      const asubs = '   ^-----!';\n      const b = cold('  -      ');\n      const bsubs = '   ^-----!';\n      const expected = '------#';\n\n      expectObservable(zip(a, b)).toBe(expected);\n      expectSubscriptions(a.subscriptions).toBe(asubs);\n      expectSubscriptions(b.subscriptions).toBe(bsubs);\n    });\n  });\n\n  it('should work with error and error', () => {\n    rxTestScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const a = hot('   ------#    ', undefined, 'too bad');\n      const asubs = '   ^-----!    ';\n      const b = hot('   ----------#', undefined, 'too bad 2');\n      const bsubs = '   ^-----!    ';\n      const expected = '------#    ';\n\n      expectObservable(zip(a, b)).toBe(expected, null, 'too bad');\n      expectSubscriptions(a.subscriptions).toBe(asubs);\n      expectSubscriptions(b.subscriptions).toBe(bsubs);\n    });\n  });\n\n  it('should work with two sources that eventually raise errors', () => {\n    rxTestScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const a = hot('   --w-----#----', { w: 1 }, 'too bad');\n      const asubs = '   ^-------!    ';\n      const b = hot('   -----z-----#-', { z: 2 }, 'too bad 2');\n      const bsubs = '   ^-------!    ';\n      const expected = '-----x--#    ';\n\n      expectObservable(zip(a, b)).toBe(expected, { x: [1, 2] }, 'too bad');\n      expectSubscriptions(a.subscriptions).toBe(asubs);\n      expectSubscriptions(b.subscriptions).toBe(bsubs);\n    });\n  });\n\n  it('should work with two sources that eventually raise errors (swapped)', () => {\n    rxTestScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const a = hot('   -----z-----#-', { z: 2 }, 'too bad 2');\n      const asubs = '   ^-------!    ';\n      const b = hot('   --w-----#----', { w: 1 }, 'too bad');\n      const bsubs = '   ^-------!    ';\n      const expected = '-----x--#    ';\n\n      expectObservable(zip(a, b)).toBe(expected, { x: [2, 1] }, 'too bad');\n      expectSubscriptions(a.subscriptions).toBe(asubs);\n      expectSubscriptions(b.subscriptions).toBe(bsubs);\n    });\n  });\n\n  it('should work with error and some', () => {\n    rxTestScheduler.run(({ hot, cold, expectObservable, expectSubscriptions }) => {\n      const a = cold('  #          ');\n      const asubs = '   (^!)       ';\n      const b = hot('   --1--2--3--');\n      const bsubs = '   (^!)       ';\n      const expected = '#          ';\n\n      expectObservable(zip(a, b)).toBe(expected);\n      expectSubscriptions(a.subscriptions).toBe(asubs);\n      expectSubscriptions(b.subscriptions).toBe(bsubs);\n    });\n  });\n\n  it('should combine an immediately-scheduled source with an immediately-scheduled second', (done) => {\n    const a = scheduled([1, 2, 3], queueScheduler);\n    const b = scheduled([4, 5, 6, 7, 8], queueScheduler);\n    const r = [\n      [1, 4],\n      [2, 5],\n      [3, 6],\n    ];\n    let i = 0;\n\n    zip(a, b).subscribe({\n      next: (vals: Array<number>) => {\n        expect(vals).to.deep.equal(r[i++]);\n      },\n      complete: done,\n    });\n  });\n\n  it('should be able to zip all iterables', () => {\n    const results: any[] = [];\n    zip('abc', '123', 'xyz').subscribe({\n      next: (value) => results.push(value),\n      complete: () => results.push('complete'),\n    });\n    expect(results).to.deep.equal([['a', '1', 'x'], ['b', '2', 'y'], ['c', '3', 'z'], 'complete']);\n  });\n\n  it('should return EMPTY if passed an empty array as the only argument', () => {\n    const results: string[] = [];\n    zip([]).subscribe({\n      next: () => {\n        throw new Error('should not emit');\n      },\n      complete: () => {\n        results.push('done');\n      },\n    });\n\n    expect(results).to.deep.equal(['done']);\n  });\n});\n"
  },
  {
    "path": "packages/rxjs/spec/operators/audit-spec.ts",
    "content": "import { expect } from 'chai';\nimport { TestScheduler } from 'rxjs/testing';\nimport { of, interval, EMPTY, Observable } from 'rxjs';\nimport { audit, take, mergeMap } from 'rxjs/operators';\nimport { observableMatcher } from '../helpers/observableMatcher';\n\n/** @test {audit} */\ndescribe('audit operator', () => {\n  let testScheduler: TestScheduler;\n\n  beforeEach(() => {\n    testScheduler = new TestScheduler(observableMatcher);\n  });\n\n  it('should emit the last value in each time window', () => {\n    testScheduler.run(({ hot, cold, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  -a-xy-----b--x--cxyz-|');\n      const e1subs = '  ^--------------------!';\n      const e2 = cold('  ----i                ');\n      //                          ----i\n      //                                ----i\n      const e2subs = [\n        '               -^---!                ',\n        '               ----------^---!       ',\n        '               ----------------^---! ',\n      ];\n      const expected = '-----y--------x-----z|';\n\n      const result = e1.pipe(audit(() => e2));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should delay the source if values are not emitted often enough', () => {\n    testScheduler.run(({ hot, cold, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  -a--------b-----c----|');\n      const e1subs = '  ^--------------------!';\n      const e2 = cold('  ----x                ');\n      const e2subs = [\n        '               -^---!                ',\n        '               ----------^---!       ',\n        '               ----------------^---! ',\n      ];\n      const expected = '-----a--------b-----c|';\n\n      const result = e1.pipe(audit(() => e2));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should audit with duration Observable using next to close the duration', () => {\n    testScheduler.run(({ hot, cold, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('   -a-xy-----b--x--cxxx-|');\n      const e1subs = '   ^--------------------!';\n      const e2 = cold('   ----x-y-z            ');\n      const e2subs = [\n        '                -^---!                ',\n        '                ----------^---!       ',\n        '                ----------------^---! ',\n      ];\n      const expected = ' -----y--------x-----x|';\n\n      const result = e1.pipe(audit(() => e2));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should interrupt source and duration when result is unsubscribed early', () => {\n    testScheduler.run(({ hot, cold, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  -a-x-y-z-xyz-x-y-z----b--x-x-|');\n      const unsub = '   --------------!               ';\n      const e1subs = '  ^-------------!               ';\n      const e2 = cold('  -----x------------|          ');\n      const e2subs = [\n        '               -^----!                       ',\n        '               -------^----!                 ',\n        '               -------------^!               ',\n      ];\n      const expected = '------y-----z--               ';\n\n      const result = e1.pipe(audit(() => e2));\n\n      expectObservable(result, unsub).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should not break unsubscription chains when result is unsubscribed explicitly', () => {\n    testScheduler.run(({ hot, cold, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  -a-x-y-z-xyz-x-y-z----b--x-x-|');\n      const e1subs = '  ^-------------!               ';\n      const e2 = cold('  -----x------------|          ');\n      const e2subs = [\n        '               -^----!                       ',\n        '               -------^----!                 ',\n        '               -------------^!               ',\n      ];\n      const expected = '------y-----z--               ';\n      const unsub = '   --------------!               ';\n\n      const result = e1.pipe(\n        mergeMap((x: string) => of(x)),\n        audit(() => e2),\n        mergeMap((x: string) => of(x))\n      );\n\n      expectObservable(result, unsub).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should handle a busy producer emitting a regular repeating sequence', () => {\n    testScheduler.run(({ hot, cold, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  abcdefabcdefabcdefabcdefa|    ');\n      const e1subs = '  ^------------------------!    ';\n      const e2 = cold(' -----x                        ');\n      const e2subs = [\n        '               ^----!                        ',\n        '               ------^----!                  ',\n        '               ------------^----!            ',\n        '               ------------------^----!      ',\n        '               ------------------------^----!',\n      ];\n      const expected = '-----f-----f-----f-----f-----(a|)';\n\n      const result = e1.pipe(audit(() => e2));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should mirror source if durations are immediate', () => {\n    testScheduler.run(({ hot, cold, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  abcdefabcdefabcdefabcdefa|');\n      const e1subs = '  ^------------------------!';\n      const e2 = cold(' x');\n      const expected = 'abcdefabcdefabcdefabcdefa|';\n\n      const result = e1.pipe(audit(() => e2));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should emit no values if durations are EMPTY', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  abcdefabcdefabcdefabcdefa|');\n      const e1subs = '  ^------------------------!';\n      const e2 = EMPTY;\n      const expected = '-------------------------|';\n\n      const result = e1.pipe(audit(() => e2));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should emit no values and never complete if duration is a never', () => {\n    testScheduler.run(({ hot, cold, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  ----abcdefabcdefabcdefabcdefa|');\n      const e1subs = '  ^----------------------------!';\n      const e2 = cold(' -');\n      const e2subs = '  ----^-------------------------';\n      const expected = '------------------------------';\n\n      const result = e1.pipe(audit(() => e2));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should unsubscribe duration Observable when source raise error', () => {\n    testScheduler.run(({ hot, cold, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  ----abcdefabcdefabcdefabcdefa#');\n      const e1subs = '  ^----------------------------!';\n      const e2 = cold(' -');\n      const e2subs = '  ----^------------------------!';\n      const expected = '-----------------------------#';\n\n      const result = e1.pipe(audit(() => e2));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should mirror source if durations are synchronous observables', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  abcdefabcdefabcdefabcdefa|');\n      const e1subs = '  ^------------------------!';\n      const e2 = of('one single value');\n      const expected = 'abcdefabcdefabcdefabcdefa|';\n\n      const result = e1.pipe(audit(() => e2));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should raise error as soon as just-throw duration is used', () => {\n    testScheduler.run(({ hot, cold, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  ----abcdefabcdefabcdefabcdefa|');\n      const e1subs = '  ^---!                         ';\n      const e2 = cold(' #');\n      const e2subs = '  ----(^!)                      ';\n      const expected = '----(-#)                      ';\n\n      const result = e1.pipe(audit(() => e2));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should audit using durations of varying lengths', () => {\n    testScheduler.run(({ hot, cold, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  abcdefabcdabcdefghabca|     ');\n      const e1subs = '  ^---------------------!     ';\n      const e2 = [\n        cold('          -----x                      '),\n        cold('              ---x                    '),\n        cold('                  -------x            '),\n        cold('                        --x           '),\n        cold('                           ----x      '),\n      ];\n      const e2subs = [\n        '               ^----!                      ',\n        '               ------^--!                  ',\n        '               ----------^------!          ',\n        '               ------------------^-!       ',\n        '               ---------------------^---!  ',\n      ];\n      const expected = '-----f---d-------h--c----(a|)';\n\n      let i = 0;\n      const result = e1.pipe(audit(() => e2[i++]));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      for (let j = 0; j < e2.length; j++) {\n        expectSubscriptions(e2[j].subscriptions).toBe(e2subs[j]);\n      }\n    });\n  });\n\n  it('should propagate error from duration Observable', () => {\n    testScheduler.run(({ hot, cold, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  abcdefabcdabcdefghabca|');\n      const e1subs = '  ^----------------!     ';\n      const e2 = [\n        cold('          -----x                 '),\n        cold('              ---x               '),\n        cold('                  -------#       '),\n      ];\n      const e2subs = [\n        '               ^----!                 ',\n        '               ------^--!             ',\n        '               ----------^------!     ',\n      ];\n      const expected = '-----f---d-------#     ';\n\n      let i = 0;\n      const result = e1.pipe(audit(() => e2[i++]));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      for (let j = 0; j < e2.length; j++) {\n        expectSubscriptions(e2[j].subscriptions).toBe(e2subs[j]);\n      }\n    });\n  });\n\n  it('should propagate error thrown from durationSelector function', () => {\n    testScheduler.run(({ hot, cold, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  abcdefabcdabcdefghabca|   ');\n      const e1subs = '  ^---------!               ';\n      const e2 = [\n        cold('          -----x                    '),\n        cold('              ---x                  '),\n        cold('                  -------x          '),\n      ];\n      // prettier-ignore\n      const e2subs = [\n        '               ^----!                     ',\n        '               ------^--!                 ',\n      ];\n      const expected = '-----f---d#                ';\n\n      let i = 0;\n      const result = e1.pipe(\n        audit(() => {\n          if (i === 2) {\n            throw 'error';\n          }\n          return e2[i++];\n        })\n      );\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      for (let j = 0; j < e2subs.length; j++) {\n        expectSubscriptions(e2[j].subscriptions).toBe(e2subs[j]);\n      }\n    });\n  });\n\n  it('should complete when source does not emit', () => {\n    testScheduler.run(({ hot, cold, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  -----|');\n      const subs = '    ^----!';\n      const expected = '-----|';\n      function durationSelector() {\n        return cold('-----|');\n      }\n\n      expectObservable(e1.pipe(audit(durationSelector))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(subs);\n    });\n  });\n\n  it('should raise error when source does not emit and raises error', () => {\n    testScheduler.run(({ hot, cold, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  -----#');\n      const subs = '    ^----!';\n      const expected = '-----#';\n      function durationSelector() {\n        return cold('   -----|');\n      }\n\n      expectObservable(e1.pipe(audit(durationSelector))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(subs);\n    });\n  });\n\n  it('should handle an empty source', () => {\n    testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' |');\n      const subs = '    (^!)';\n      const expected = '|';\n      function durationSelector() {\n        return cold('   -----|');\n      }\n\n      expectObservable(e1.pipe(audit(durationSelector))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(subs);\n    });\n  });\n\n  it('should handle a never source', () => {\n    testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' -');\n      const subs = '    ^';\n      const expected = '-';\n      function durationSelector() {\n        return cold('   -----|');\n      }\n\n      expectObservable(e1.pipe(audit(durationSelector))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(subs);\n    });\n  });\n\n  it('should handle a throw source', () => {\n    testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' #');\n      const subs = '    (^!)';\n      const expected = '#';\n      function durationSelector() {\n        return cold('   -----|');\n      }\n\n      expectObservable(e1.pipe(audit(durationSelector))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(subs);\n    });\n  });\n\n  it('should audit by promise resolves', (done) => {\n    const e1 = interval(1).pipe(take(5));\n    const expected = [0, 1, 2, 3, 4];\n\n    e1.pipe(audit(() => Promise.resolve(42))).subscribe({\n      next: (x: number) => {\n        expect(x).to.equal(expected.shift());\n      },\n      error: () => {\n        done(new Error('should not be called'));\n      },\n      complete: () => {\n        expect(expected.length).to.equal(0);\n        done();\n      },\n    });\n  });\n\n  it('should raise error when promise rejects', (done) => {\n    const e1 = interval(1).pipe(take(10));\n    const expected = [0, 1, 2];\n    const error = new Error('error');\n\n    e1.pipe(\n      audit((x: number) => {\n        if (x === 3) {\n          return new Promise((resolve: any, reject: any) => {\n            reject(error);\n          });\n        } else {\n          return new Promise((resolve: any) => {\n            resolve(42);\n          });\n        }\n      })\n    ).subscribe({\n      next: (x: number) => {\n        expect(x).to.equal(expected.shift());\n      },\n      error: (err: any) => {\n        expect(err).to.be.an('error', 'error');\n        expect(expected.length).to.equal(0);\n        done();\n      },\n      complete: () => {\n        done(new Error('should not be called'));\n      },\n    });\n  });\n\n  it('should stop listening to a synchronous observable when unsubscribed', () => {\n    const sideEffects: number[] = [];\n    const synchronousObservable = new Observable((subscriber) => {\n      // This will check to see if the subscriber was closed on each loop\n      // when the unsubscribe hits (from the `take`), it should be closed\n      for (let i = 0; !subscriber.closed && i < 10; i++) {\n        sideEffects.push(i);\n        subscriber.next(i);\n      }\n    });\n\n    synchronousObservable\n      .pipe(\n        audit(() => of(0)),\n        take(3)\n      )\n      .subscribe(() => {\n        /* noop */\n      });\n\n    expect(sideEffects).to.deep.equal([0, 1, 2]);\n  });\n\n  it('should emit last value after duration completes if source completes first', () => {\n    testScheduler.run(({ hot, cold, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  -a--------xy|  ');\n      const e1subs = '  ^-----------!  ';\n      const e2 = cold('  ----x         ');\n      // prettier-ignore\n      const e2subs = [\n        '               -^---!         ',\n        '               ----------^---!',\n      ];\n      const expected = '-----a--------(y|)';\n\n      const result = e1.pipe(audit(() => e2));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n});\n"
  },
  {
    "path": "packages/rxjs/spec/operators/auditTime-spec.ts",
    "content": "import { expect } from 'chai';\nimport { of } from 'rxjs';\nimport { auditTime, mergeMap } from 'rxjs/operators';\nimport { TestScheduler } from 'rxjs/testing';\nimport { observableMatcher } from '../helpers/observableMatcher';\n\n/** @test {auditTime} */\ndescribe('auditTime', () => {\n  let testScheduler: TestScheduler;\n\n  beforeEach(() => {\n    testScheduler = new TestScheduler(observableMatcher);\n  });\n\n  it('should emit the last value in each time window', () => {\n    testScheduler.run(({ hot, time, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  -a-x-y----b---x-cx---|');\n      const e1subs = '  ^--------------------!';\n      const t = time('   -----|               ');\n      //                          -----|\n      //                                -----|\n      const expected = '------y--------x-----(x|)';\n\n      const result = e1.pipe(auditTime(t));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should auditTime events by 5 time units', (done) => {\n    const expected = 3;\n    of(1, 2, 3)\n      .pipe(auditTime(5))\n      .subscribe((x: number) => {\n        expect(x).to.equal(expected);\n        done();\n      });\n  });\n\n  it('should auditTime events multiple times', () => {\n    testScheduler.run(({ hot, time, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  -012-----01234---|');\n      const e1subs = '  ^----------------!';\n      const t = time('   -----|           ');\n      //                         -----|\n      const expected = '------2-------4--|';\n\n      expectObservable(e1.pipe(auditTime(t))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should delay the source if values are not emitted often enough', () => {\n    testScheduler.run(({ hot, time, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  -a--------b-----c----|');\n      const e1subs = '  ^--------------------!';\n      const t = time('   -----|               ');\n      //                          -----|\n      //                                -----|\n      const expected = '------a--------b-----(c|)';\n\n      expectObservable(e1.pipe(auditTime(t))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should handle a busy producer emitting a regular repeating sequence', () => {\n    testScheduler.run(({ hot, time, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  abcdefabcdefabcdefabcdefa|');\n      const e1subs = '  ^------------------------!';\n      const t = time('  -----|                    ');\n      //                      -----|\n      //                            -----|\n      //                                  -----|\n      //                                        -----|\n      const expected = '-----f-----f-----f-----f-----(a|)';\n\n      expectObservable(e1.pipe(auditTime(t))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should complete when source does not emit', () => {\n    testScheduler.run(({ hot, time, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  -----|');\n      const e1subs = '  ^----!';\n      const t = time('  --|   ');\n      const expected = '-----|';\n\n      expectObservable(e1.pipe(auditTime(t))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should raise error when source does not emit and raises error', () => {\n    testScheduler.run(({ hot, time, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  -----#');\n      const e1subs = '  ^----!';\n      const t = time('  --|   ');\n      const expected = '-----#';\n\n      expectObservable(e1.pipe(auditTime(t))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should handle an empty source', () => {\n    testScheduler.run(({ cold, time, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' |   ');\n      const e1subs = '  (^!)';\n      const t = time('  ---|');\n      const expected = '|   ';\n\n      expectObservable(e1.pipe(auditTime(t))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should handle a never source', () => {\n    testScheduler.run(({ cold, time, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' -  ');\n      const e1subs = '  ^  ';\n      const t = time('  --|');\n      const expected = '-  ';\n\n      expectObservable(e1.pipe(auditTime(t))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should handle a throw source', () => {\n    testScheduler.run(({ cold, time, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' #   ');\n      const e1subs = '  (^!)';\n      const t = time('  ---|');\n      const expected = '#   ';\n\n      expectObservable(e1.pipe(auditTime(t))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should not complete when source does not complete', () => {\n    testScheduler.run(({ hot, time, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  -a--(bc)-------d----------------');\n      const e1subs = '  ^------------------------------!';\n      const t = time('   -----|                         ');\n      //                               -----|\n      const expected = '------c-------------d-----------';\n      const unsub = '   -------------------------------!';\n\n      expectObservable(e1.pipe(auditTime(t)), unsub).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should not break unsubscription chains when result is unsubscribed explicitly', () => {\n    testScheduler.run(({ hot, time, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  -a--(bc)-------d----------------');\n      const e1subs = '  ^------------------------------!';\n      const t = time('   -----|                         ');\n      //                               -----|\n      const expected = '------c-------------d-----------';\n      const unsub = '   -------------------------------!';\n\n      const result = e1.pipe(\n        mergeMap((x: string) => of(x)),\n        auditTime(t),\n        mergeMap((x: string) => of(x))\n      );\n\n      expectObservable(result, unsub).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should auditTime values until source raises error', () => {\n    testScheduler.run(({ hot, time, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  -a--(bc)-------d---------------#');\n      const e1subs = '  ^------------------------------!';\n      const t = time('   -----|                         ');\n      //                               -----|\n      const expected = '------c-------------d----------#';\n\n      expectObservable(e1.pipe(auditTime(t))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n});\n"
  },
  {
    "path": "packages/rxjs/spec/operators/buffer-spec.ts",
    "content": "import { buffer, mergeMap, take, window, toArray } from 'rxjs/operators';\nimport { EMPTY, NEVER, throwError, of, Subject, interval } from 'rxjs';\nimport { TestScheduler } from 'rxjs/testing';\nimport { observableMatcher } from '../helpers/observableMatcher';\nimport { expect } from 'chai';\n\n/** @test {buffer} */\ndescribe('Observable.prototype.buffer', () => {\n  let testScheduler: TestScheduler;\n\n  beforeEach(() => {\n    testScheduler = new TestScheduler(observableMatcher);\n  });\n\n  it('should emit buffers that close and reopen', () => {\n    testScheduler.run(({ hot, expectObservable }) => {\n      const a = hot('   -a-b-c-d-e-f-g-h-i-|');\n      const b = hot('   -----B-----B-----B-|');\n      const expected = '-----x-----y-----z-(F|)';\n      const expectedValues = {\n        x: ['a', 'b', 'c'],\n        y: ['d', 'e', 'f'],\n        z: ['g', 'h', 'i'],\n        F: [],\n      };\n      expectObservable(a.pipe(buffer(b))).toBe(expected, expectedValues);\n    });\n  });\n\n  it('should emit a final buffer if the closingNotifier is already complete', () => {\n    testScheduler.run(({ hot, expectObservable }) => {\n      const a = hot('   -a-b-c-d-e-f-g-h-i-|');\n      const b = hot('   -----B-----B--|');\n      const expected = '-----x-----y-------(F|)';\n      const expectedValues = {\n        x: ['a', 'b', 'c'],\n        y: ['d', 'e', 'f'],\n        F: ['g', 'h', 'i'],\n      };\n      expectObservable(a.pipe(buffer(b))).toBe(expected, expectedValues);\n    });\n  });\n\n  it('should emit all buffered values if the source completes before the closingNotifier does', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const source = hot('---^---a---b---c---d---e--f----|');\n      const sourceSubs = '   ^---------------------------!';\n      const closer = hot('---^-------------B----------------');\n      const closerSubs = '   ^---------------------------!';\n      const expected = '     --------------x-------------(F|)';\n\n      const result = source.pipe(buffer(closer));\n\n      const expectedValues = {\n        x: ['a', 'b', 'c'],\n        F: ['d', 'e', 'f'],\n      };\n\n      expectObservable(result).toBe(expected, expectedValues);\n      expectSubscriptions(source.subscriptions).toBe(sourceSubs);\n      expectSubscriptions(closer.subscriptions).toBe(closerSubs);\n    });\n  });\n\n  it('should work with empty and empty selector', () => {\n    testScheduler.run(({ expectObservable }) => {\n      const a = EMPTY;\n      const b = EMPTY;\n      const expected = '(F|)';\n      expectObservable(a.pipe(buffer(b))).toBe(expected, { F: [] });\n    });\n  });\n\n  it('should work with empty and non-empty selector', () => {\n    testScheduler.run(({ hot, expectObservable }) => {\n      const a = EMPTY;\n      const b = hot('-----a-----');\n      const expected = '(F|)';\n      expectObservable(a.pipe(buffer(b))).toBe(expected, { F: [] });\n    });\n  });\n\n  it('should work with non-empty and empty selector', () => {\n    testScheduler.run(({ hot, expectObservable }) => {\n      const a = hot('--1--2--^--3--4--5---6----7--8--9---0---|');\n      const b = EMPTY;\n      const expected = '     --------------------------------(F|)';\n      expectObservable(a.pipe(buffer(b))).toBe(expected, {\n        F: ['3', '4', '5', '6', '7', '8', '9', '0'],\n      });\n    });\n  });\n\n  it('should work with never and never selector', () => {\n    testScheduler.run(({ expectObservable }) => {\n      const a = NEVER;\n      const b = NEVER;\n      const expected = '-';\n      expectObservable(a.pipe(buffer(b))).toBe(expected);\n    });\n  });\n\n  it('should work with never and empty selector', () => {\n    testScheduler.run(({ expectObservable }) => {\n      const a = NEVER;\n      const b = EMPTY;\n      const expected = '-';\n      expectObservable(a.pipe(buffer(b))).toBe(expected);\n    });\n  });\n\n  it('should work with empty and never selector', () => {\n    testScheduler.run(({ expectObservable }) => {\n      const a = EMPTY;\n      const b = NEVER;\n      const expected = '(F|)';\n      expectObservable(a.pipe(buffer(b))).toBe(expected, { F: [] });\n    });\n  });\n\n  it('should work with non-empty and throw selector', () => {\n    testScheduler.run(({ hot, expectObservable }) => {\n      const a = hot('---^--a--');\n      const b = throwError(() => new Error('too bad'));\n      const expected = '#';\n      expectObservable(a.pipe(buffer(b))).toBe(expected, null, new Error('too bad'));\n    });\n  });\n\n  it('should work with throw and non-empty selector', () => {\n    testScheduler.run(({ hot, expectObservable }) => {\n      const a = throwError(() => new Error('too bad'));\n      const b = hot('---^--a--');\n      const expected = '#';\n      expectObservable(a.pipe(buffer(b))).toBe(expected, null, new Error('too bad'));\n    });\n  });\n\n  it('should work with error', () => {\n    testScheduler.run(({ hot, expectObservable }) => {\n      const a = hot('---^-------#', undefined, new Error('too bad'));\n      const b = hot('---^--------');\n      const expected = '--------#';\n      expectObservable(a.pipe(buffer(b))).toBe(expected, null, new Error('too bad'));\n    });\n  });\n\n  it('should work with error and non-empty selector', () => {\n    testScheduler.run(({ hot, expectObservable }) => {\n      const a = hot('---^-------#', undefined, new Error('too bad'));\n      const b = hot('---^---a----');\n      const expected = '----a---#';\n      expectObservable(a.pipe(buffer(b))).toBe(expected, { a: [] }, new Error('too bad'));\n    });\n  });\n\n  it('should work with selector', () => {\n    // Buffer Boundaries Simple (RxJS 4)\n    testScheduler.run(({ hot, expectObservable }) => {\n      const a = hot('--1--2--^--3--4--5---6----7--8--9---0---|');\n      const b = hot('--------^--a-------b---cd---------e---f---|');\n      const expected = '     ---a-------b---cd---------e---f-(F|)';\n      const expectedValues = {\n        a: ['3'],\n        b: ['4', '5'],\n        c: ['6'],\n        d: [] as string[],\n        e: ['7', '8', '9'],\n        f: ['0'],\n        F: [],\n      };\n      expectObservable(a.pipe(buffer(b))).toBe(expected, expectedValues);\n    });\n  });\n\n  it('should work with selector completed', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const a = hot('--1--2--^--3--4--5---6----7--8--9---0---|');\n      const subs = '         ^-------------------------------!';\n      const b = hot('--------^--a-------b---cd|               ');\n      const expected = '     ---a-------b---cd---------------(F|)';\n      const expectedValues = {\n        a: ['3'],\n        b: ['4', '5'],\n        c: ['6'],\n        d: [] as string[],\n        F: ['7', '8', '9', '0'],\n      };\n      expectObservable(a.pipe(buffer(b))).toBe(expected, expectedValues);\n      expectSubscriptions(a.subscriptions).toBe(subs);\n    });\n  });\n\n  it('should allow unsubscribing the result Observable early', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const a = hot('--1--2--^--3--4--5---6----7--8--9---0---|');\n      const unsub = '        --------------!                  ';\n      const subs = '         ^-------------!                  ';\n      const b = hot('--------^--a-------b---cd|               ');\n      const expected = '     ---a-------b---                  ';\n      const expectedValues = {\n        a: ['3'],\n        b: ['4', '5'],\n      };\n      expectObservable(a.pipe(buffer(b)), unsub).toBe(expected, expectedValues);\n      expectSubscriptions(a.subscriptions).toBe(subs);\n    });\n  });\n\n  it('should not break unsubscription chains when unsubscribed explicitly', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const a = hot('--1--2--^--3--4--5---6----7--8--9---0---|');\n      const subs = '         ^-------------!                  ';\n      const b = hot('--------^--a-------b---cd|               ');\n      const expected = '     ---a-------b---                  ';\n      const unsub = '        --------------!                  ';\n      const expectedValues = {\n        a: ['3'],\n        b: ['4', '5'],\n      };\n\n      const result = a.pipe(\n        mergeMap((x: any) => of(x)),\n        buffer(b),\n        mergeMap((x: any) => of(x))\n      );\n\n      expectObservable(result, unsub).toBe(expected, expectedValues);\n      expectSubscriptions(a.subscriptions).toBe(subs);\n    });\n  });\n\n  it('should work with non-empty and selector error', () => {\n    // Buffer Boundaries onErrorSource (RxJS 4)\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const a = hot('--1--2--^--3-----#', { '3': 3 }, new Error('too bad'));\n      const subs = '         ^--------!';\n      const b = hot('--------^--a--b---');\n      const expected = '     ---a--b--#';\n      const expectedValues = {\n        a: [3],\n        b: [] as string[],\n      };\n      expectObservable(a.pipe(buffer(b))).toBe(expected, expectedValues, new Error('too bad'));\n      expectSubscriptions(a.subscriptions).toBe(subs);\n    });\n  });\n\n  it('should work with non-empty and empty selector error', () => {\n    testScheduler.run(({ hot, expectObservable }) => {\n      const a = hot('--1--2--^--3--4--5---6----7--8--9---0---|');\n      const b = hot('--------^----------------#', undefined, new Error('too bad'));\n      const expected = '     -----------------#';\n      expectObservable(a.pipe(buffer(b))).toBe(expected, null, new Error('too bad'));\n    });\n  });\n\n  it('should work with non-empty and selector error', () => {\n    // Buffer Boundaries onErrorBoundaries (RxJS 4)\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const obj = { a: true, b: true, c: true };\n      const a = hot('--1--2--^--3--4--5---6----7--8--9---0---|');\n      const subs = '         ^----------------!';\n      const b = hot('--------^--a-------b---c-#', obj, new Error('too bad'));\n      const expected = '     ---a-------b---c-#';\n      const expectedValues = {\n        a: ['3'],\n        b: ['4', '5'],\n        c: ['6'],\n      };\n      expectObservable(a.pipe(buffer(b))).toBe(expected, expectedValues, new Error('too bad'));\n      expectSubscriptions(a.subscriptions).toBe(subs);\n    });\n  });\n\n  it('should unsubscribe notifier when source unsubscribed', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const a = hot('--1--2--^--3--4--5---6----7--8--9---0---|');\n      const unsub = '        --------------!                  ';\n      const subs = '         ^-------------!                  ';\n      const b = hot('--------^--a-------b---cd|               ');\n      const bsubs = '        ^-------------!                  ';\n      const expected = '     ---a-------b---                  ';\n      const expectedValues = {\n        a: ['3'],\n        b: ['4', '5'],\n      };\n\n      expectObservable(a.pipe(buffer(b)), unsub).toBe(expected, expectedValues);\n      expectSubscriptions(a.subscriptions).toBe(subs);\n      expectSubscriptions(b.subscriptions).toBe(bsubs);\n    });\n  });\n\n  it('should unsubscribe notifier when source unsubscribed', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const a = hot('   -a-b-c-d-e-f-g-h-i-|');\n      const b = hot('   -----1-----2-----3-|');\n      const bsubs = '   ^----!';\n      const expected = '-----(x|)';\n      const expectedValues = {\n        x: ['a', 'b', 'c'],\n      };\n\n      expectObservable(a.pipe(buffer(b), take(1))).toBe(expected, expectedValues);\n      expectSubscriptions(b.subscriptions).toBe(bsubs);\n    });\n  });\n\n  it('should emit properly with an observable using itself as a notifier', () => {\n    const results: any[] = [];\n    const subject = new Subject<number>();\n\n    subject.pipe(buffer(subject)).subscribe({\n      next: (value) => results.push(value),\n      complete: () => results.push('complete'),\n    });\n\n    subject.next(1);\n    expect(results).to.deep.equal([[]]);\n    subject.next(2);\n    expect(results).to.deep.equal([[], [1]]);\n    subject.complete();\n    expect(results).to.deep.equal([[], [1], [2], 'complete']);\n  });\n\n  it('should buffer when Promise resolves', (done) => {\n    const e1 = interval(3).pipe(take(5));\n    const expected = [\n      [0, 1],\n      [2, 3, 4],\n    ];\n\n    e1.pipe(buffer(new Promise<void>((resolve) => setTimeout(() => resolve(), 8)))).subscribe({\n      next: (x) => {\n        expect(x).to.deep.equal(expected.shift());\n      },\n      error: () => done(new Error('should not be called')),\n      complete: () => {\n        expect(expected.length).to.equal(0);\n        done();\n      },\n    });\n  });\n\n  it('should raise error when Promise rejects', (done) => {\n    const e1 = interval(1).pipe(take(5));\n    const error = new Error('err');\n\n    e1.pipe(buffer(Promise.reject(error))).subscribe({\n      next: () => {\n        done(new Error('should not be called'));\n      },\n      error: (err: any) => {\n        expect(err).to.be.an('error');\n        done();\n      },\n      complete: () => {\n        done(new Error('should not be called'));\n      },\n    });\n  });\n\n  describe('equivalence with the window operator', () => {\n    const cases = [\n      {\n        source: '   -a-b-c-d-e-f-g-h-i-|',\n        notifier: ' -----B-----B-----B-|',\n      },\n      {\n        source: '   -a-b-c-d-e-f-g-h-i-|',\n        notifier: ' -----B-----B--|     ',\n      },\n      {\n        source: '   -a-b-c-d-e---------|',\n        notifier: ' -----B-----B-----B-|',\n      },\n      {\n        source: '   -a-b-c-d-e-f-g-h-i-|',\n        notifier: ' -------------------|',\n      },\n    ];\n    cases.forEach(({ source, notifier }, index) => {\n      it(`should be equivalent for case ${index}`, () => {\n        testScheduler.run(({ hot, expectObservable }) => {\n          const a = hot(source);\n          const b = hot(notifier);\n          expectObservable(a.pipe(buffer(b))).toEqual(\n            a.pipe(\n              window(b),\n              mergeMap((w) => w.pipe(toArray()))\n            )\n          );\n        });\n      });\n    });\n  });\n});\n"
  },
  {
    "path": "packages/rxjs/spec/operators/bufferCount-spec.ts",
    "content": "import { expect } from 'chai';\nimport { Subject, of, Observable } from 'rxjs';\nimport { bufferCount, mergeMap, take } from 'rxjs/operators';\nimport { TestScheduler } from 'rxjs/testing';\nimport { observableMatcher } from '../helpers/observableMatcher';\n\n/** @test {bufferCount} */\ndescribe('bufferCount operator', () => {\n  let testScheduler: TestScheduler;\n\n  beforeEach(() => {\n    testScheduler = new TestScheduler(observableMatcher);\n  });\n\n  it('should emit buffers at intervals', () => {\n    testScheduler.run(({ hot, expectObservable }) => {\n      const values = {\n        v: ['a', 'b', 'c'],\n        w: ['c', 'd', 'e'],\n        x: ['e', 'f', 'g'],\n        y: ['g', 'h', 'i'],\n        z: ['i'],\n      };\n      const e1 = hot('  --a--b--c--d--e--f--g--h--i--|');\n      const expected = '--------v-----w-----x-----y--(z|)';\n\n      expectObservable(e1.pipe(bufferCount(3, 2))).toBe(expected, values);\n    });\n  });\n\n  it('should emit buffers at buffersize of intervals if not specified', () => {\n    testScheduler.run(({ hot, expectObservable }) => {\n      const values = {\n        x: ['a', 'b'],\n        y: ['c', 'd'],\n        z: ['e', 'f'],\n      };\n      const e1 = hot('  --a--b--c--d--e--f--|');\n      const expected = '-----x-----y-----z--|';\n\n      expectObservable(e1.pipe(bufferCount(2))).toBe(expected, values);\n    });\n  });\n\n  it('should buffer properly (issue #2062)', () => {\n    const item$ = new Subject<number>();\n    const results: any[] = [];\n    item$.pipe(bufferCount(3, 1)).subscribe((value) => {\n      results.push(value);\n\n      if (value.join() === '1,2,3') {\n        item$.next(4);\n      }\n    });\n\n    item$.next(1);\n    item$.next(2);\n    item$.next(3);\n\n    expect(results).to.deep.equal([\n      [1, 2, 3],\n      [2, 3, 4],\n    ]);\n  });\n\n  it('should emit partial buffers if source completes before reaching specified buffer count', () => {\n    testScheduler.run(({ hot, expectObservable }) => {\n      const e1 = hot('  --a--b--c--d--|');\n      const expected = '--------------(x|)';\n\n      expectObservable(e1.pipe(bufferCount(5))).toBe(expected, { x: ['a', 'b', 'c', 'd'] });\n    });\n  });\n\n  it('should emit full buffer then last partial buffer if source completes', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  --a^-b--c--d--e--|');\n      const e1subs = '     ^-------------!';\n      const expected = '   --------y-----(z|)';\n\n      expectObservable(e1.pipe(bufferCount(3))).toBe(expected, { y: ['b', 'c', 'd'], z: ['e'] });\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should emit buffers at intervals, but stop when result is unsubscribed early', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const values = {\n        v: ['a', 'b', 'c'],\n        w: ['c', 'd', 'e'],\n      };\n      const e1 = hot('  --a--b--c--d--e--f--g--h--i--|');\n      const unsub = '   ------------------!           ';\n      const subs = '    ^-----------------!           ';\n      const expected = '--------v-----w----           ';\n\n      expectObservable(e1.pipe(bufferCount(3, 2)), unsub).toBe(expected, values);\n      expectSubscriptions(e1.subscriptions).toBe(subs);\n    });\n  });\n\n  it('should not break unsubscription chains when result is unsubscribed explicitly', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const values = {\n        v: ['a', 'b', 'c'],\n        w: ['c', 'd', 'e'],\n      };\n      const e1 = hot('  --a--b--c--d--e--f--g--h--i--|');\n      const subs = '    ^-----------------!           ';\n      const expected = '--------v-----w----           ';\n      const unsub = '   ------------------!           ';\n\n      const result = e1.pipe(\n        mergeMap((x: any) => of(x)),\n        bufferCount(3, 2),\n        mergeMap((x: any) => of(x))\n      );\n\n      expectObservable(result, unsub).toBe(expected, values);\n      expectSubscriptions(e1.subscriptions).toBe(subs);\n    });\n  });\n\n  it('should raise error if source raise error before reaching specified buffer count', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  --a--b--c--d--#');\n      const e1subs = '  ^-------------!';\n      const expected = '--------------#';\n\n      expectObservable(e1.pipe(bufferCount(5))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should emit buffers with specified skip count when skip count is less than window count', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const values = {\n        v: ['a', 'b', 'c'],\n        w: ['b', 'c', 'd'],\n        x: ['c', 'd', 'e'],\n        y: ['d', 'e'],\n        z: ['e'],\n      };\n      const e1 = hot('  --a--b--c--d--e--|');\n      const e1subs = '  ^----------------!';\n      const expected = '--------v--w--x--(yz|)';\n\n      expectObservable(e1.pipe(bufferCount(3, 1))).toBe(expected, values);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should emit buffers with specified skip count when skip count is more than window count', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('--a--b--c--d--e--|');\n      const e1subs = '  ^----------------!';\n      const expected = '-----y--------z--|';\n      const values = {\n        y: ['a', 'b'],\n        z: ['d', 'e'],\n      };\n\n      expectObservable(e1.pipe(bufferCount(2, 3))).toBe(expected, values);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should stop listening to a synchronous observable when unsubscribed', () => {\n    const sideEffects: number[] = [];\n    const synchronousObservable = new Observable((subscriber) => {\n      // This will check to see if the subscriber was closed on each loop\n      // when the unsubscribe hits (from the `take`), it should be closed\n      for (let i = 0; !subscriber.closed && i < 10; i++) {\n        sideEffects.push(i);\n        subscriber.next(i);\n      }\n    });\n\n    synchronousObservable.pipe(bufferCount(1), take(3)).subscribe(() => {\n      /* noop */\n    });\n\n    expect(sideEffects).to.deep.equal([0, 1, 2]);\n  });\n});\n"
  },
  {
    "path": "packages/rxjs/spec/operators/bufferTime-spec.ts",
    "content": "import { of, throwError, interval, scheduled, asapScheduler, Subject } from 'rxjs';\nimport { bufferTime, mergeMap, take, tap } from 'rxjs/operators';\nimport { TestScheduler } from 'rxjs/testing';\nimport { observableMatcher } from '../helpers/observableMatcher';\nimport { expect } from 'chai';\n\n/** @test {bufferTime} */\ndescribe('bufferTime operator', () => {\n  let testScheduler: TestScheduler;\n\n  beforeEach(() => {\n    testScheduler = new TestScheduler(observableMatcher);\n  });\n\n  it('should emit buffers at intervals', () => {\n    testScheduler.run(({ hot, time, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  ---a---b---c---d---e---f---g-----|   ');\n      const subs = '    ^--------------------------------!   ';\n      const t = time('  ----------|                          ');\n      const expected = '----------w---------x---------y--(z|)';\n      const values = {\n        w: ['a', 'b'],\n        x: ['c', 'd', 'e'],\n        y: ['f', 'g'],\n        z: [] as string[],\n      };\n\n      const result = e1.pipe(bufferTime(t, null, Infinity, testScheduler));\n\n      expectObservable(result).toBe(expected, values);\n      expectSubscriptions(e1.subscriptions).toBe(subs);\n    });\n  });\n\n  it('should emit buffers at intervals test 2', () => {\n    testScheduler.run(({ hot, time, expectObservable }) => {\n      const e1 = hot('  ---------a---------b---------c---------d---------e---------g--------|   ');\n      const t = time('  --------------------------------|                                       ');\n      const expected = '--------------------------------x-------------------------------y---(z|)';\n      const values = {\n        x: ['a', 'b', 'c'],\n        y: ['d', 'e', 'g'],\n        z: [] as string[],\n      };\n\n      const result = e1.pipe(bufferTime(t, null, Infinity, testScheduler));\n\n      expectObservable(result).toBe(expected, values);\n    });\n  });\n\n  it('should emit buffers at intervals or when the buffer is full', () => {\n    testScheduler.run(({ hot, time, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  ---a---b---c---d---e---f---g-----|   ');\n      const subs = '    ^--------------------------------!   ';\n      const t = time('  ----------|                          ');\n      //                       ----------|\n      //                               ----------|\n      //                                       ----------|\n      const expected = '-------w-------x-------y---------(z|)';\n      const values = {\n        w: ['a', 'b'],\n        x: ['c', 'd'],\n        y: ['e', 'f'],\n        z: ['g'],\n      };\n\n      const result = e1.pipe(bufferTime(t, null, 2, testScheduler));\n\n      expectObservable(result).toBe(expected, values);\n      expectSubscriptions(e1.subscriptions).toBe(subs);\n    });\n  });\n\n  it('should handle situations with a creation interval of zero', (done) => {\n    // This is an odd scenario, and I can't imagine who is weird enough to want this, but here\n    // it is. Someone scheduling buffers to open and close on microtasks, with values emitted on microtasks\n    // NOTE: Trying this with a completely synchronous scheduler (like queueScheduler, which is\n    // async relative to what it is scheduling, but synchronous relative to its container) will\n    // cause your thread to lock up. Don't be weird. This test is just to prove behavior.\n    const source = scheduled([0, 1, 2, 3, 4], asapScheduler);\n    const results: any[] = [];\n    source.pipe(bufferTime(0, 0, asapScheduler)).subscribe({\n      next: (value) => results.push(value),\n      complete: () => {\n        expect(results).to.deep.equal([\n          // It opens one on 0 and closes it on 0\n          [],\n          // It opens one on 0, emits on 0, and closes on 0 (x 5)\n          [0],\n          [1],\n          [2],\n          [3],\n          [4],\n          // It opens one on 0, and then completes on 0, leaving us with an empty array.\n          [],\n        ]);\n        done();\n      },\n    });\n  });\n\n  it('should emit buffers at intervals or when the buffer is full test 2', () => {\n    testScheduler.run(({ hot, time, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  ---a---b---c---d---e---f---g-----|   ');\n      const subs = '    ^--------------------------------!   ';\n      const t = time('  ----------|                          ');\n      //                          ---------|---------|---------|\n      const expected = '----------w--------x---------y---(z|)';\n      const values = {\n        w: ['a', 'b'],\n        x: ['c', 'd', 'e'],\n        y: ['f', 'g'],\n        z: [] as string[],\n      };\n\n      const result = e1.pipe(bufferTime(t, null, 3, testScheduler));\n\n      expectObservable(result).toBe(expected, values);\n      expectSubscriptions(e1.subscriptions).toBe(subs);\n    });\n  });\n\n  it('should emit buffers that have been created at intervals and close after the specified delay', () => {\n    testScheduler.run(({ hot, time, expectObservable }) => {\n      const e1 = hot('       ---a---b---c----d----e----f----g----h----i----(k|)');\n      //                     --------------------*--------------------*----  start interval\n      //                     ---------------------|                          timespans\n      //                                         ---------------------|\n      //                                                              -----|\n      const t = time('       ---------------------|                            ');\n      const interval = time('--------------------|                             ');\n      const expected = '     ---------------------x-------------------y----(z|)';\n      const values = {\n        x: ['a', 'b', 'c', 'd', 'e'],\n        y: ['e', 'f', 'g', 'h', 'i'],\n        z: ['i', 'k'],\n      };\n\n      const result = e1.pipe(bufferTime(t, interval, Infinity, testScheduler));\n\n      expectObservable(result).toBe(expected, values);\n    });\n  });\n\n  it('should emit buffers that have been created at intervals and close after the specified delay or when the buffer is full', () => {\n    testScheduler.run(({ hot, time, expectObservable }) => {\n      const e1 = hot('  ---a---b---c----d----e----f----g----h----i----(k|)');\n      //                --------------------*--------------------*----  start interval\n      //                ---------------------|                          timespans\n      //                                    ---------------------|\n      //                                                         -----|\n      const t = time('  ---------------------|                            ');\n      const interval = time('                --------------------|        ');\n      const expected = '----------------x-------------------y---------(z|)';\n      const values = {\n        x: ['a', 'b', 'c', 'd'],\n        y: ['e', 'f', 'g', 'h'],\n        z: ['i', 'k'],\n      };\n\n      const result = e1.pipe(bufferTime(t, interval, 4, testScheduler));\n\n      expectObservable(result).toBe(expected, values);\n    });\n  });\n\n  it('should emit buffers with timeSpan 10 and creationInterval 7', () => {\n    testScheduler.run(({ hot, time, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('--1--^2--3---4---5--6--7---8----9------------|   ');\n      //                   -------*------*------*------*------*----- creation interval\n      //                   ----------|                               timespans\n      //                          ----------|\n      //                                 ----------|\n      //                                        ----------|\n      //                                               ----------|\n      //                                                      ----------|\n      const e1subs = '     ^---------------------------------------!   ';\n      const t = time('     ----------|');\n      const interval = time('        -------|');\n      const expected = '   ----------a------b------c------d------e-(f|)';\n      const values = {\n        a: ['2', '3', '4'],\n        b: ['4', '5', '6'],\n        c: ['6', '7', '8'],\n        d: ['8', '9'],\n        e: [] as string[],\n        f: [] as string[],\n      };\n\n      const result = e1.pipe(bufferTime(t, interval, Infinity, testScheduler));\n\n      expectObservable(result).toBe(expected, values);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should emit buffers but handle source ending with an error', () => {\n    testScheduler.run(({ hot, time, expectObservable }) => {\n      const e1 = hot('--1--^2--3---4---5--6--7---8----9------------#');\n      //                   -------*------*------*------*------*----- creation interval\n      //                   ----------|                               timespans\n      //                          ----------|\n      //                                 ----------|\n      //                                        ----------|\n      //                                               ----------|\n      //                                                      ----------|\n      const t = time('     ----------|');\n      const interval = time('        -------|');\n      const expected = '   ----------a------b------c------d------e-#';\n      const values = {\n        a: ['2', '3', '4'],\n        b: ['4', '5', '6'],\n        c: ['6', '7', '8'],\n        d: ['8', '9'],\n        e: [] as string[],\n      };\n\n      const result = e1.pipe(bufferTime(t, interval, Infinity, testScheduler));\n\n      expectObservable(result).toBe(expected, values);\n    });\n  });\n\n  it('should emit buffers and allow result to unsubscribed early', () => {\n    testScheduler.run(({ hot, time, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('--1--^2--3---4---5--6--7---8----9------------|');\n      const unsub = '      -----------------!                       ';\n      const subs = '       ^----------------!                       ';\n      //                   -------*------*------*------*------*----- creation interval\n      //                   ----------|                               timespans\n      //                          ----------|\n      //                                 ----------|\n      const t = time('     ----------|                              ');\n      const interval = time('        -------|                       ');\n      const expected = '   ----------a------                        ';\n      const values = {\n        a: ['2', '3', '4'],\n      };\n\n      const result = e1.pipe(bufferTime(t, interval, Infinity, testScheduler));\n\n      expectObservable(result, unsub).toBe(expected, values);\n      expectSubscriptions(e1.subscriptions).toBe(subs);\n    });\n  });\n\n  it('should not break unsubscription chains when result is unsubscribed explicitly', () => {\n    testScheduler.run(({ hot, time, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('--1--^2--3---4---5--6--7---8----9------------|');\n      const subs = '       ^---------------!                        ';\n      //                   -------*------*------*------*------*----- creation interval\n      //                   ----------|                               timespans\n      //                          ----------|\n      //                                 ----------|\n      const t = time('     ----------|');\n      const interval = time('        -------|');\n      const expected = '   ----------a------                        ';\n      const unsub = '      ----------------!                        ';\n      const values = {\n        a: ['2', '3', '4'],\n      };\n\n      const result = e1.pipe(\n        mergeMap((x: any) => of(x)),\n        bufferTime(t, interval, Infinity, testScheduler),\n        mergeMap((x: any) => of(x))\n      );\n\n      expectObservable(result, unsub).toBe(expected, values);\n      expectSubscriptions(e1.subscriptions).toBe(subs);\n    });\n  });\n\n  it('should handle empty', () => {\n    testScheduler.run(({ cold, time, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' |');\n      const e1subs = '  (^!)';\n      const expected = '(b|)';\n      const values = { b: [] as string[] };\n      const t = time('----------|');\n\n      const result = e1.pipe(bufferTime(t, null, Infinity, testScheduler));\n\n      expectObservable(result).toBe(expected, values);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should handle never', () => {\n    testScheduler.run(({ cold, time, expectObservable }) => {\n      const e1 = cold('-');\n      const unsub = '   --------------------------------------------!';\n      const t = time('  ----------|                                  ');\n      const expected = '----------a---------a---------a---------a----';\n\n      const result = e1.pipe(bufferTime(t, null, Infinity, testScheduler));\n\n      expectObservable(result, unsub).toBe(expected, { a: [] });\n    });\n  });\n\n  it('should handle throw', () => {\n    testScheduler.run(({ time, expectObservable }) => {\n      const e1 = throwError(() => new Error('haha'));\n      const expected = '#';\n      const t = time('----------|');\n\n      const result = e1.pipe(bufferTime(t, null, Infinity, testScheduler));\n\n      expectObservable(result).toBe(expected, undefined, new Error('haha'));\n    });\n  });\n\n  it('should handle errors', () => {\n    testScheduler.run(({ hot, time, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  ---a---b---c---#');\n      const e1subs = '  ^--------------!';\n      const t = time('  ----------|');\n      const expected = '----------w----#';\n      const values = {\n        w: ['a', 'b'],\n      };\n\n      const result = e1.pipe(bufferTime(t, null, Infinity, testScheduler));\n\n      expectObservable(result).toBe(expected, values);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should emit buffers that have been created at intervals and close after the specified delay with errors', () => {\n    testScheduler.run(({ hot, time, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('       ---a---b---c----d----e----f----g----h----i--#');\n      //                     --------------------|-------------------|-------------------| interval\n      //                     ---------------------|\n      //                                         ---------------------|\n      //                                                             ---------------------| timespan\n      const e1subs = '       ^-------------------------------------------!';\n      const t = time('       ---------------------|                       ');\n      const interval = time('                --------------------|   ');\n      const expected = '     ---------------------x-------------------y--#';\n      const values = {\n        x: ['a', 'b', 'c', 'd', 'e'],\n        y: ['e', 'f', 'g', 'h', 'i'],\n      };\n\n      const result = e1.pipe(bufferTime(t, interval, Infinity, testScheduler));\n\n      expectObservable(result).toBe(expected, values);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should not throw when subscription synchronously unsubscribed after emit', () => {\n    testScheduler.run(({ hot, time, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  ---a---b---c---d---e---f---g-----|');\n      const subs = '    ^-------------------!             ';\n      const t = time('  ----------|                       ');\n      const expected = '----------w---------(x|)          ';\n      const values = {\n        w: ['a', 'b'],\n        x: ['c', 'd', 'e'],\n      };\n\n      const result = e1.pipe(bufferTime(t, null, Infinity, testScheduler), take(2));\n\n      expectObservable(result).toBe(expected, values);\n      expectSubscriptions(e1.subscriptions).toBe(subs);\n    });\n  });\n\n  it('should not have errors when take follows and maxBufferSize is provided', () => {\n    testScheduler.run(({ expectObservable }) => {\n      const tick = 1;\n      const buffTime = 5;\n      const expected = '-----a----b----c----d----(e|)';\n      const values = {\n        a: [0, 1, 2, 3],\n        b: [4, 5, 6, 7, 8],\n        c: [9, 10, 11, 12, 13],\n        d: [14, 15, 16, 17, 18],\n        e: [19, 20, 21, 22, 23],\n      };\n\n      const source = interval(tick, testScheduler).pipe(bufferTime(buffTime, null, 10, testScheduler), take(5));\n\n      expectObservable(source).toBe(expected, values);\n    });\n  });\n\n  it('should not mutate the buffer on reentrant next', () => {\n    testScheduler.run(({ expectObservable, time }) => {\n      const subject = new Subject<number>();\n      const t1 = time(' -|');\n      const t2 = time(' --|');\n      const expected = '--(a|)';\n      const result = subject.pipe(\n        bufferTime(t2),\n        tap(() => subject.next(2)),\n        take(1)\n      );\n      testScheduler.schedule(() => subject.next(1), t1);\n      expectObservable(result).toBe(expected, { a: [1] });\n    });\n  });\n});\n"
  },
  {
    "path": "packages/rxjs/spec/operators/bufferToggle-spec.ts",
    "content": "import { expect } from 'chai';\nimport { of, concat, timer, EMPTY } from 'rxjs';\nimport { bufferToggle, mergeMap, mapTo } from 'rxjs/operators';\nimport { TestScheduler } from 'rxjs/testing';\nimport { observableMatcher } from '../helpers/observableMatcher';\n\n/** @test {bufferToggle} */\ndescribe('bufferToggle operator', () => {\n  let testScheduler: TestScheduler;\n\n  beforeEach(() => {\n    testScheduler = new TestScheduler(observableMatcher);\n  });\n\n  it('should emit buffers using hot openings and hot closings', () => {\n    testScheduler.run(({ hot, expectObservable }) => {\n      const e1 = hot('  ---a---b---c---d---e---f---g---|');\n      const e2 = hot('  --o------------------o---------|');\n      const e3 = hot('  ---------c---------------c-----|');\n      const expected = '---------x---------------y-----|';\n      const values = {\n        x: ['a', 'b'],\n        y: ['f'],\n      };\n\n      const result = e1.pipe(bufferToggle(e2, (x: any) => e3));\n\n      expectObservable(result).toBe(expected, values);\n    });\n  });\n\n  it('should emit buffers that are opened by an observable from the first argument and closed by an observable returned by the function in the second argument', () => {\n    testScheduler.run(({ hot, cold, expectObservable }) => {\n      const e1 = hot('  -----a----b----c----d----e----f----g----h----i----|');\n      const e2 = cold(' -------------x-------------y--------------z-------|');\n      const e3 = cold('              ---------------(j|)');\n      //                                           ---------------(j|)\n      //                                                          ---------------(j|)\n      const expected = '----------------------------q-------------r-------(s|)';\n\n      const values = {\n        q: ['c', 'd', 'e'],\n        r: ['f', 'g', 'h'],\n        s: ['i'],\n      };\n      const innerVals = ['x', 'y', 'z'];\n\n      expectObservable(\n        e1.pipe(\n          bufferToggle(e2, (x: string) => {\n            expect(x).to.equal(innerVals.shift());\n            return e3;\n          })\n        )\n      ).toBe(expected, values);\n    });\n  });\n\n  it('should emit buffers using varying cold closings', () => {\n    testScheduler.run(({ hot, cold, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('--a--^---b---c---d---e---f---g---h------|      ');\n      const e2 = cold('    --x-----------y--------z---|              ');\n      const subs = '       ^----------------------------------!      ';\n      const closings = [\n        cold('               ---------------s--|                     '),\n        cold('                           ----(s|)                    '),\n        cold('                                    ---------------(s|)'),\n      ];\n      const closeSubs = [\n        '                 --^--------------!                         ',\n        '                 --------------^---!                        ',\n        '                 -----------------------^-----------!       ',\n      ];\n      const expected = '  -----------------ij----------------(k|)    ';\n      const values = {\n        i: ['b', 'c', 'd', 'e'],\n        j: ['e'],\n        k: ['g', 'h'],\n      };\n\n      let i = 0;\n      const result = e1.pipe(bufferToggle(e2, () => closings[i++]));\n\n      expectObservable(result).toBe(expected, values);\n      expectSubscriptions(e1.subscriptions).toBe(subs);\n      expectSubscriptions(closings[0].subscriptions).toBe(closeSubs[0]);\n      expectSubscriptions(closings[1].subscriptions).toBe(closeSubs[1]);\n      expectSubscriptions(closings[2].subscriptions).toBe(closeSubs[2]);\n    });\n  });\n\n  it('should emit buffers using varying hot closings', () => {\n    testScheduler.run(({ hot, cold, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('--a--^---b---c---d---e---f---g---h------|   ');\n      const e2 = cold('    --x-----------y--------z---|           ');\n      const subs = '       ^----------------------------------!   ';\n      const closings = [\n        {\n          obs: hot('   -1--^----------------s-|                   '),\n          sub: '           --^--------------!                     ',\n        },\n        {\n          obs: hot('       -----3----4-------(s|)                 '),\n          sub: '           --------------^---!                    ',\n        },\n        {\n          obs: hot('       -------3----4-------5----------------s|'),\n          sub: '           -----------------------^-----------!   ',\n        },\n      ];\n\n      const expected = '   -----------------ij----------------(k|)';\n      const values = {\n        i: ['b', 'c', 'd', 'e'],\n        j: ['e'],\n        k: ['g', 'h'],\n      };\n\n      let i = 0;\n      const result = e1.pipe(bufferToggle(e2, () => closings[i++].obs));\n\n      expectObservable(result).toBe(expected, values);\n      expectSubscriptions(e1.subscriptions).toBe(subs);\n      for (let j = 0; j < closings.length; j++) {\n        expectSubscriptions(closings[j].obs.subscriptions).toBe(closings[j].sub);\n      }\n    });\n  });\n\n  it('should emit buffers using varying empty delayed closings', () => {\n    testScheduler.run(({ hot, cold, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('--a--^---b---c---d---e---f---g---h------|     ');\n      const e2 = cold('    --x-----------y--------z---|             ');\n      const subs = '       ^----------------------------------!     ';\n      const closings = [\n        cold('               ---------------|                       '),\n        cold('                           ----|                      '),\n        cold('                                    ---------------|  '),\n      ];\n      const expected = '   -----------------------------------(ijk|)';\n      const values = {\n        i: ['b', 'c', 'd', 'e', 'f', 'g', 'h'],\n        j: ['e', 'f', 'g', 'h'],\n        k: ['g', 'h'],\n      };\n\n      let i = 0;\n      const result = e1.pipe(bufferToggle(e2, () => closings[i++]));\n\n      expectObservable(result).toBe(expected, values);\n      expectSubscriptions(e1.subscriptions).toBe(subs);\n    });\n  });\n\n  it('should emit buffers using varying cold closings, outer unsubscribed early', () => {\n    testScheduler.run(({ hot, cold, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('--a--^---b---c---d---e---f---g---h------|      ');\n      const subs = '       ^---------!                               ';\n      const e2 = cold('    --x-----------y--------z---|              ');\n      const closings = [\n        cold('               ---------------s--|                     '),\n        cold('                           ----(s|)                    '),\n        cold('                                    ---------------(s|)'),\n      ];\n      const csub0 = '      --^-------!                               ';\n      const expected = '   -----------                               ';\n      const unsub = '      ----------!                               ';\n      const values = {\n        i: ['b', 'c', 'd', 'e'],\n      };\n\n      let i = 0;\n      const result = e1.pipe(bufferToggle(e2, () => closings[i++]));\n\n      expectObservable(result, unsub).toBe(expected, values);\n      expectSubscriptions(e1.subscriptions).toBe(subs);\n      expectSubscriptions(closings[0].subscriptions).toBe(csub0);\n      expectSubscriptions(closings[1].subscriptions).toBe([]);\n      expectSubscriptions(closings[2].subscriptions).toBe([]);\n    });\n  });\n\n  it('should not break unsubscription chains when result is unsubscribed explicitly', () => {\n    testScheduler.run(({ hot, cold, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('--a--^---b---c---d---e---f---g---h------|      ');\n      const subs = '       ^-----------------!                       ';\n      const e2 = cold('    --x-----------y--------z---|              ');\n      const closings = [\n        cold('               ---------------s--|                     '),\n        cold('                           ----(s|)                    '),\n        cold('                                    ---------------(s|)'),\n      ];\n      const expected = '   -----------------i-                       ';\n      const unsub = '      ------------------!                       ';\n      const values = {\n        i: ['b', 'c', 'd', 'e'],\n      };\n\n      let i = 0;\n      const result = e1.pipe(\n        mergeMap((x: any) => of(x)),\n        bufferToggle(e2, () => closings[i++]),\n        mergeMap((x: any) => of(x))\n      );\n\n      expectObservable(result, unsub).toBe(expected, values);\n      expectSubscriptions(e1.subscriptions).toBe(subs);\n    });\n  });\n\n  it('should propagate error thrown from closingSelector', () => {\n    testScheduler.run(({ hot, cold, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('--a--^---b---c---d---e---f---g---h------|      ');\n      const e2 = cold('    --x-----------y--------z---|              ');\n      const subs = '       ^-------------!                           ';\n      const closings = [\n        cold('               ---------------s--|                     '),\n        cold('                           ----(s|)                    '),\n        cold('                                    ---------------(s|)'),\n      ];\n      const closeSubs0 = ' --^-----------!                           ';\n      const expected = '   --------------#                           ';\n\n      let i = 0;\n      const result = e1.pipe(\n        bufferToggle(e2, () => {\n          if (i === 1) {\n            throw 'error';\n          }\n          return closings[i++];\n        })\n      );\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(subs);\n      expectSubscriptions(closings[0].subscriptions).toBe(closeSubs0);\n      expectSubscriptions(closings[1].subscriptions).toBe([]);\n      expectSubscriptions(closings[2].subscriptions).toBe([]);\n    });\n  });\n\n  it('should propagate error emitted from a closing', () => {\n    testScheduler.run(({ hot, cold, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('--a--^---b---c---d---e---f---g---h------|');\n      const e2 = cold('    --x-----------y--------z---|        ');\n      const subs = '       ^-------------!                     ';\n      const closings = [\n        cold('               ---------------s--|               '),\n        cold('                           #                     '),\n      ];\n      const closeSubs = [\n        '                  --^-----------!                     ',\n        '                  --------------(^!)                  ',\n      ];\n      const expected = '   --------------#                     ';\n\n      let i = 0;\n      const result = e1.pipe(bufferToggle(e2, () => closings[i++]));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(subs);\n      expectSubscriptions(closings[0].subscriptions).toBe(closeSubs[0]);\n      expectSubscriptions(closings[1].subscriptions).toBe(closeSubs[1]);\n    });\n  });\n\n  it('should propagate error emitted late from a closing', () => {\n    testScheduler.run(({ hot, cold, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('--a--^---b---c---d---e---f---g---h------|');\n      const e2 = cold('    --x-----------y--------z---|        ');\n      const subs = '       ^------------------!                ';\n      const closings = [\n        cold('               ---------------s--|               '),\n        cold('                           -----#                '),\n      ];\n      const closeSubs = [\n        '                  --^--------------!                  ',\n        '                  --------------^----!                ',\n      ];\n      const expected = '   -----------------i-#                ';\n      const values = {\n        i: ['b', 'c', 'd', 'e'],\n      };\n\n      let i = 0;\n      const result = e1.pipe(bufferToggle(e2, () => closings[i++]));\n\n      expectObservable(result).toBe(expected, values);\n      expectSubscriptions(e1.subscriptions).toBe(subs);\n      expectSubscriptions(closings[0].subscriptions).toBe(closeSubs[0]);\n      expectSubscriptions(closings[1].subscriptions).toBe(closeSubs[1]);\n    });\n  });\n\n  it('should handle errors', () => {\n    testScheduler.run(({ hot, cold, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('--a--^---b---c---d---e--#        ');\n      const e2 = cold('    --x-----------y--------z---|');\n      const subs = '       ^------------------!        ';\n      // prettier-ignore\n      const closings = [\n        cold('               ---------------s--|       '),\n        cold('                           -------s|     '),\n      ];\n      // prettier-ignore\n      const closeSubs = [\n        '                  --^--------------!          ',\n        '                  --------------^----!        ',\n      ];\n      const expected = '   -----------------i-#        ';\n      const values = {\n        i: ['b', 'c', 'd', 'e'],\n      };\n\n      let i = 0;\n      const result = e1.pipe(bufferToggle(e2, () => closings[i++]));\n\n      expectObservable(result).toBe(expected, values);\n      expectSubscriptions(e1.subscriptions).toBe(subs);\n      expectSubscriptions(closings[0].subscriptions).toBe(closeSubs[0]);\n      expectSubscriptions(closings[1].subscriptions).toBe(closeSubs[1]);\n    });\n  });\n\n  it('should handle empty source', () => {\n    testScheduler.run(({ cold, expectObservable }) => {\n      const e1 = cold(' |');\n      const e2 = cold(' --o-----|');\n      const e3 = cold('   -----c--|');\n      const expected = '|';\n      const values = { x: [] as string[] };\n\n      const result = e1.pipe(bufferToggle(e2, () => e3));\n\n      expectObservable(result).toBe(expected, values);\n    });\n  });\n\n  it('should handle throw', () => {\n    testScheduler.run(({ cold, expectObservable }) => {\n      const e1 = cold(' #');\n      const e2 = cold(' --o-----|');\n      const e3 = cold('   -----c--|');\n      const expected = '#';\n      const values = { x: [] as string[] };\n\n      const result = e1.pipe(bufferToggle(e2, () => e3));\n\n      expectObservable(result).toBe(expected, values);\n    });\n  });\n\n  it('should handle never', () => {\n    testScheduler.run(({ hot, cold, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  -');\n      const e2 = cold(' --o-----o------o-----o---o-----|');\n      const e3 = cold('   --c-|');\n      //                        --c-|\n      //                               --c-|\n      //                                     --c-|\n      //                                         --c-|\n      const unsub = '   --------------------------------------------!';\n      const subs = '    ^-------------------------------------------!';\n      const expected = '----x-----x------x-----x---x-----------------';\n      const values = { x: [] as string[] };\n\n      const result = e1.pipe(bufferToggle(e2, () => e3));\n\n      expectObservable(result, unsub).toBe(expected, values);\n      expectSubscriptions(e1.subscriptions).toBe(subs);\n    });\n  });\n\n  it('should handle a never opening Observable', () => {\n    testScheduler.run(({ hot, cold, expectObservable }) => {\n      const e1 = hot('--a--^---b---c---d---e---f---g---h------|');\n      const e2 = cold('    -');\n      const e3 = cold('    --c-|');\n      const expected = '   -----------------------------------|';\n\n      const result = e1.pipe(bufferToggle(e2, () => e3));\n\n      expectObservable(result).toBe(expected);\n    });\n  });\n\n  it('should handle a never closing Observable', () => {\n    testScheduler.run(({ hot, cold, expectObservable }) => {\n      const e1 = hot('--a--^---b---c---d---e---f---g---h------|    ');\n      const e2 = cold('    ---o---------------o-----------|        ');\n      const e3 = cold('    -');\n      const expected = '   -----------------------------------(xy|)';\n      const values = {\n        x: ['b', 'c', 'd', 'e', 'f', 'g', 'h'],\n        y: ['f', 'g', 'h'],\n      };\n\n      const result = e1.pipe(bufferToggle(e2, () => e3));\n\n      expectObservable(result).toBe(expected, values);\n    });\n  });\n\n  it('should handle opening Observable that just throws', () => {\n    testScheduler.run(({ hot, cold, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('--a--^---b---c---d---e---f---g---h------|');\n      const e1subs = '     (^!)';\n      const e2 = cold('    #');\n      const e2subs = '     (^!)';\n      const e3 = cold('    --c-|');\n      const expected = '   #';\n\n      const result = e1.pipe(bufferToggle(e2, () => e3));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should accept openings resolved promise', (done) => {\n    const e1 = concat(timer(10).pipe(mapTo(1)), timer(100).pipe(mapTo(2)), timer(150).pipe(mapTo(3)), timer(200).pipe(mapTo(4)));\n\n    const expected = [[1]];\n\n    e1.pipe(\n      bufferToggle(\n        new Promise((resolve: any) => {\n          resolve(42);\n        }),\n        () => {\n          return timer(50);\n        }\n      )\n    ).subscribe({\n      next: (x) => {\n        expect(x).to.deep.equal(expected.shift());\n      },\n      error: (x) => {\n        done(new Error('should not be called'));\n      },\n      complete: () => {\n        expect(expected.length).to.be.equal(0);\n        done();\n      },\n    });\n  });\n\n  it('should accept openings rejected promise', (done) => {\n    const e1 = concat(of(1), timer(10).pipe(mapTo(2)), timer(10).pipe(mapTo(3)), timer(100).pipe(mapTo(4)));\n\n    const expected = 42;\n\n    e1.pipe(\n      bufferToggle(\n        new Promise((resolve: any, reject: any) => {\n          reject(expected);\n        }),\n        () => {\n          return timer(50);\n        }\n      )\n    ).subscribe({\n      next: (x) => {\n        done(new Error('should not be called'));\n      },\n      error: (x) => {\n        expect(x).to.equal(expected);\n        done();\n      },\n      complete: () => {\n        done(new Error('should not be called'));\n      },\n    });\n  });\n\n  it('should accept closing selector that returns a resolved promise', (done) => {\n    const e1 = concat(of(1), timer(10).pipe(mapTo(2)), timer(10).pipe(mapTo(3)), timer(100).pipe(mapTo(4)));\n    const expected = [[1]];\n\n    e1.pipe(\n      bufferToggle(\n        of(10),\n        () =>\n          new Promise((resolve: any) => {\n            resolve(42);\n          })\n      )\n    ).subscribe({\n      next: (x) => {\n        expect(x).to.deep.equal(expected.shift());\n      },\n      error: () => {\n        done(new Error('should not be called'));\n      },\n      complete: () => {\n        expect(expected.length).to.be.equal(0);\n        done();\n      },\n    });\n  });\n\n  it('should accept closing selector that returns a rejected promise', (done) => {\n    const e1 = concat(of(1), timer(10).pipe(mapTo(2)), timer(10).pipe(mapTo(3)), timer(100).pipe(mapTo(4)));\n\n    const expected = 42;\n\n    e1.pipe(\n      bufferToggle(\n        of(10),\n        () =>\n          new Promise((resolve: any, reject: any) => {\n            reject(expected);\n          })\n      )\n    ).subscribe({\n      next: (x) => {\n        done(new Error('should not be called'));\n      },\n      error: (x) => {\n        expect(x).to.equal(expected);\n        done();\n      },\n      complete: () => {\n        done(new Error('should not be called'));\n      },\n    });\n  });\n\n  it('should handle empty closing observable', () => {\n    testScheduler.run(({ hot, cold, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('--a--^---b---c---d---e---f---g---h------|     ');\n      const subs = '       ^----------------------------------!     ';\n      const e2 = cold('    --x-----------y--------z---|             ');\n      const expected = '   -----------------------------------(ijk|)';\n      const values = {\n        i: ['b', 'c', 'd', 'e', 'f', 'g', 'h'],\n        j: ['e', 'f', 'g', 'h'],\n        k: ['g', 'h'],\n      };\n\n      const result = e1.pipe(bufferToggle(e2, () => EMPTY));\n\n      expectObservable(result).toBe(expected, values);\n      expectSubscriptions(e1.subscriptions).toBe(subs);\n    });\n  });\n});\n"
  },
  {
    "path": "packages/rxjs/spec/operators/bufferWhen-spec.ts",
    "content": "import { expect } from 'chai';\nimport { of } from 'rxjs';\nimport { bufferWhen, mergeMap, takeWhile } from 'rxjs/operators';\nimport { TestScheduler } from 'rxjs/testing';\nimport { observableMatcher } from '../helpers/observableMatcher';\n\n/** @test {bufferWhen} */\ndescribe('bufferWhen operator', () => {\n  let testScheduler: TestScheduler;\n\n  beforeEach(() => {\n    testScheduler = new TestScheduler(observableMatcher);\n  });\n\n  it('should emit buffers that close and reopen', () => {\n    testScheduler.run(({ hot, cold, expectObservable }) => {\n      const e1 = hot('--a--^---b---c---d---e---f---g---------|   ');\n      const e2 = cold('    --------------(s|)                    ');\n      //                                 --------------(s|)\n      const expected = '   --------------x-------------y-----(z|)';\n      const values = {\n        x: ['b', 'c', 'd'],\n        y: ['e', 'f', 'g'],\n        z: [] as string[],\n      };\n\n      expectObservable(e1.pipe(bufferWhen(() => e2))).toBe(expected, values);\n    });\n  });\n\n  it('should emit buffers using varying cold closings', () => {\n    testScheduler.run(({ hot, cold, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('--a--^---b---c---d---e---f---g---h------|      ');\n      const subs = '       ^----------------------------------!      ';\n      const closings = [\n        cold('             ---------------s--|                       '),\n        cold('                            ----------(s|)             '),\n        cold('                                      -------------(s|)'),\n      ];\n      const expected = '   ---------------x---------y---------(z|)   ';\n      const values = {\n        x: ['b', 'c', 'd'],\n        y: ['e', 'f', 'g'],\n        z: ['h'],\n      };\n\n      let i = 0;\n      const result = e1.pipe(bufferWhen(() => closings[i++]));\n\n      expectObservable(result).toBe(expected, values);\n      expectSubscriptions(e1.subscriptions).toBe(subs);\n    });\n  });\n\n  it('should emit buffers using varying hot closings', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('--a--^---b---c---d---e---f---g---h------|   ');\n      const subs = '       ^----------------------------------!   ';\n      const closings = [\n        {\n          obs: hot('   -1--^--------------s---|                   '),\n          sub: '           ^--------------!                       ',\n        },\n        {\n          obs: hot('   --1-^----3--------4----------s-|           '),\n          sub: '           ---------------^---------!             ',\n        },\n        {\n          obs: hot('   1-2-^------3----4-------5--6-----------s--|'),\n          sub: '           -------------------------^---------!   ',\n        },\n      ];\n      const expected = '   ---------------x---------y---------(z|)';\n      const values = {\n        x: ['b', 'c', 'd'],\n        y: ['e', 'f', 'g'],\n        z: ['h'],\n      };\n\n      let i = 0;\n      const result = e1.pipe(bufferWhen(() => closings[i++].obs));\n\n      expectObservable(result).toBe(expected, values);\n      expectSubscriptions(e1.subscriptions).toBe(subs);\n      for (let j = 0; j < closings.length; j++) {\n        expectSubscriptions(closings[j].obs.subscriptions).toBe(closings[j].sub);\n      }\n    });\n  });\n\n  it('should not emit buffers using varying empty delayed closings', () => {\n    testScheduler.run(({ hot, cold, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('--a--^---b---c---d---e---f---g---h------|   ');\n      const subs = '       ^----------------------------------!   ';\n      const closings = [\n        cold('             ---------------|                       '),\n        cold('                            ----------|             '),\n        cold('                                      -------------|'),\n      ];\n      const closeSubs = [\n        '                  ^--------------!                       ',\n        '                                                         ',\n        '                                                         ',\n      ];\n      const expected = '   -----------------------------------(x|)';\n      const values = {\n        x: ['b', 'c', 'd', 'e', 'f', 'g', 'h'],\n      };\n\n      let i = 0;\n      const result = e1.pipe(bufferWhen(() => closings[i++]));\n\n      expectObservable(result).toBe(expected, values);\n      expectSubscriptions(e1.subscriptions).toBe(subs);\n      expectSubscriptions(closings[0].subscriptions).toBe(closeSubs[0]);\n      expectSubscriptions(closings[1].subscriptions).toBe(closeSubs[1]);\n      expectSubscriptions(closings[2].subscriptions).toBe(closeSubs[2]);\n    });\n  });\n\n  it('should emit buffers using varying cold closings, outer unsubscribed early', () => {\n    testScheduler.run(({ hot, cold, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('--a--^---b---c---d---e---f---g---h------|      ');\n      const unsub = '      ------------------!                       ';\n      const subs = '       ^-----------------!                       ';\n      const closings = [\n        cold('             ---------------(s|)                       '),\n        cold('                            ----------(s|)             '),\n        cold('                                      -------------(s|)'),\n      ];\n      const closeSubs = [\n        '                  ^--------------!                          ',\n        '                  ---------------^--!                       ',\n      ];\n      const expected = '   ---------------x---                       ';\n      const values = {\n        x: ['b', 'c', 'd'],\n      };\n\n      let i = 0;\n      const result = e1.pipe(bufferWhen(() => closings[i++]));\n\n      expectObservable(result, unsub).toBe(expected, values);\n      expectSubscriptions(e1.subscriptions).toBe(subs);\n      expectSubscriptions(closings[0].subscriptions).toBe(closeSubs[0]);\n      expectSubscriptions(closings[1].subscriptions).toBe(closeSubs[1]);\n      expectSubscriptions(closings[2].subscriptions).toBe([]);\n    });\n  });\n\n  it('should not break unsubscription chains when result is unsubscribed explicitly', () => {\n    testScheduler.run(({ hot, cold, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('--a--^---b---c---d---e---f---g---h------|      ');\n      const subs = '       ^-----------------!                       ';\n      const closings = [\n        cold('             ---------------(s|)                       '),\n        cold('                            ----------(s|)             '),\n        cold('                                      -------------(s|)'),\n      ];\n      const closeSubs = [\n        '                  ^--------------!                          ',\n        '                  ---------------^--!                       ',\n      ];\n      const expected = '   ---------------x---                       ';\n      const unsub = '      ------------------!                       ';\n      const values = {\n        x: ['b', 'c', 'd'],\n      };\n\n      let i = 0;\n      const result = e1.pipe(\n        mergeMap((x: any) => of(x)),\n        bufferWhen(() => closings[i++]),\n        mergeMap((x: any) => of(x))\n      );\n\n      expectObservable(result, unsub).toBe(expected, values);\n      expectSubscriptions(e1.subscriptions).toBe(subs);\n      expectSubscriptions(closings[0].subscriptions).toBe(closeSubs[0]);\n      expectSubscriptions(closings[1].subscriptions).toBe(closeSubs[1]);\n      expectSubscriptions(closings[2].subscriptions).toBe([]);\n    });\n  });\n\n  it('should propagate error thrown from closingSelector', () => {\n    testScheduler.run(({ hot, cold, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('--a--^---b---c---d---e---f---g---h------|      ');\n      const subs = '       ^--------------!                          ';\n      const closings = [\n        cold('             ---------------s--|                       '),\n        cold('                            ----------(s|)             '),\n        cold('                                      -------------(s|)'),\n      ];\n      const closeSubs0 = ' ^--------------!                          ';\n      const expected = '   ---------------(x#)                       ';\n      const values = { x: ['b', 'c', 'd'] };\n\n      let i = 0;\n      const result = e1.pipe(\n        bufferWhen(() => {\n          if (i === 1) {\n            throw 'error';\n          }\n          return closings[i++];\n        })\n      );\n\n      expectObservable(result).toBe(expected, values);\n      expectSubscriptions(e1.subscriptions).toBe(subs);\n      expectSubscriptions(closings[0].subscriptions).toBe(closeSubs0);\n    });\n  });\n\n  it('should propagate error emitted from a closing', () => {\n    testScheduler.run(({ hot, cold, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('--a--^---b---c---d---e---f---g---h------|');\n      const subs = '       ^--------------!                    ';\n      const closings = [\n        cold('             ---------------s--|                 '),\n        cold('                            #                    '),\n      ];\n      const closeSubs = [\n        '                  ^--------------!                    ',\n        '                  ---------------(^!)                 ',\n      ];\n      const expected = '   ---------------(x#)                 ';\n      const values = {\n        x: ['b', 'c', 'd'],\n      };\n\n      let i = 0;\n      const result = e1.pipe(bufferWhen(() => closings[i++]));\n\n      expectObservable(result).toBe(expected, values);\n      expectSubscriptions(e1.subscriptions).toBe(subs);\n      expectSubscriptions(closings[0].subscriptions).toBe(closeSubs[0]);\n      expectSubscriptions(closings[1].subscriptions).toBe(closeSubs[1]);\n    });\n  });\n\n  it('should propagate error emitted late from a closing', () => {\n    testScheduler.run(({ hot, cold, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('--a--^---b---c---d---e---f---g---h------|');\n      const subs = '       ^--------------------!              ';\n      const closings = [\n        cold('             ---------------s--|                 '),\n        cold('                            ------#              '),\n      ];\n      const closeSubs = [\n        '                  ^--------------!                    ',\n        '                  ---------------^-----!              ',\n      ];\n      const expected = '   ---------------x-----#              ';\n      const values = { x: ['b', 'c', 'd'] };\n\n      let i = 0;\n      const result = e1.pipe(bufferWhen(() => closings[i++]));\n\n      expectObservable(result).toBe(expected, values);\n      expectSubscriptions(e1.subscriptions).toBe(subs);\n      expectSubscriptions(closings[0].subscriptions).toBe(closeSubs[0]);\n      expectSubscriptions(closings[1].subscriptions).toBe(closeSubs[1]);\n    });\n  });\n\n  it('should handle errors', () => {\n    testScheduler.run(({ hot, cold, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('--a--^---b---c---d---e---f---#');\n      const e2 = cold('    ---------------(s|)      ');\n      //                                ---------------(s|)\n      // prettier-ignore\n      const e2subs = [\n        '                  ^--------------!         ',\n        '                  ---------------^--------!',\n      ];\n      const expected = '   ---------------x--------#';\n      const values = {\n        x: ['b', 'c', 'd'],\n      };\n\n      const result = e1.pipe(bufferWhen(() => e2));\n\n      expectObservable(result).toBe(expected, values);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should handle empty', () => {\n    testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' |');\n      const e2 = cold(' --------(s|)');\n      const e1subs = '  (^!)';\n      const expected = '(x|)';\n      const values = {\n        x: [] as string[],\n      };\n\n      const result = e1.pipe(bufferWhen(() => e2));\n\n      expectObservable(result).toBe(expected, values);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should handle throw', () => {\n    testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' #');\n      const e2 = cold(' --------(s|)');\n      const e1subs = '  (^!)';\n      const expected = '#';\n      const values = {\n        x: [] as string[],\n      };\n\n      const result = e1.pipe(bufferWhen(() => e2));\n\n      expectObservable(result).toBe(expected, values);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should handle never', () => {\n    testScheduler.run(({ hot, cold, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  -');\n      const unsub = '   --------------------------------------------!';\n      const e1subs = '  ^-------------------------------------------!';\n      const e2 = cold(' --------(s|)                                 ');\n      const e2subs = [\n        '               ^-------!                                    ',\n        '               --------^-------!                            ',\n        '               ----------------^-------!                    ',\n        '               ------------------------^-------!            ',\n        '               --------------------------------^-------!    ',\n        '               ----------------------------------------^---!',\n      ];\n      const expected = '--------x-------x-------x-------x-------x----';\n      const values = {\n        x: [] as string[],\n      };\n\n      const source = e1.pipe(bufferWhen(() => e2));\n\n      expectObservable(source, unsub).toBe(expected, values);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should handle an inner never', () => {\n    testScheduler.run(({ hot, cold, expectObservable }) => {\n      const e1 = hot('--a--^---b---c---d---e---f---g---h------|');\n      const e2 = cold('-');\n      const expected = '   -----------------------------------(x|)';\n      const values = {\n        x: ['b', 'c', 'd', 'e', 'f', 'g', 'h'],\n      };\n\n      expectObservable(e1.pipe(bufferWhen(() => e2))).toBe(expected, values);\n    });\n  });\n\n  // bufferWhen is not supposed to handle a factory that returns always sync\n  // closing Observables, because doing such would constantly recreate a new\n  // buffer in a synchronous infinite loop until the stack overflows. This also\n  // happens with buffer in RxJS 4.\n  it('should NOT handle synchronous inner', (done) => {\n    const source = of(1, 2, 3, 4, 5, 6, 7, 8, 9);\n    const closing = of(1);\n    const TOO_MANY_INVOCATIONS = 30;\n\n    source\n      .pipe(\n        bufferWhen(() => closing),\n        takeWhile((val: any, index: number) => index < TOO_MANY_INVOCATIONS)\n      )\n      .subscribe({\n        next: (val: any) => {\n          expect(Array.isArray(val)).to.be.true;\n          expect(val.length).to.equal(0);\n        },\n        error: (err: any) => {\n          done(new Error('should not be called'));\n        },\n        complete: () => {\n          done();\n        },\n      });\n  });\n\n  it('should handle inner throw', () => {\n    testScheduler.run(({ hot, cold, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('--a--^---b---c---d---e---f---g---h------|');\n      const e1subs = '     (^!)';\n      const e2 = cold('    #');\n      const e2subs = '     (^!)';\n      const expected = '   #';\n      const values = {\n        x: ['b', 'c', 'd', 'e', 'f', 'g', 'h'],\n      };\n\n      const result = e1.pipe(bufferWhen(() => e2));\n\n      expectObservable(result).toBe(expected, values);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should handle disposing of source', () => {\n    testScheduler.run(({ hot, cold, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('--a--^---b---c---d---e---f---g---h------|');\n      const subs = '       ^-------------------!';\n      const unsub = '      --------------------!';\n      const e2 = cold('    ---------------(s|)');\n      //                                  ---------------(s|)\n      const expected = '   ---------------x-----';\n      const values = {\n        x: ['b', 'c', 'd'],\n        y: ['e', 'f', 'g', 'h'],\n        z: [] as string[],\n      };\n\n      const source = e1.pipe(bufferWhen(() => e2));\n\n      expectObservable(source, unsub).toBe(expected, values);\n      expectSubscriptions(e1.subscriptions).toBe(subs);\n    });\n  });\n});\n"
  },
  {
    "path": "packages/rxjs/spec/operators/catchError-spec.ts",
    "content": "import { expect } from 'chai';\nimport { concat, defer, Observable, of, throwError, EMPTY, from } from 'rxjs';\nimport { catchError, map, mergeMap, takeWhile, delay, take } from 'rxjs/operators';\nimport * as sinon from 'sinon';\nimport { createObservableInputs } from '../helpers/test-helper';\nimport { TestScheduler } from 'rxjs/testing';\nimport { observableMatcher } from '../helpers/observableMatcher';\nimport { asInteropObservable } from '../helpers/interop-helper';\n\n/** @test {catch} */\ndescribe('catchError operator', () => {\n  let testScheduler: TestScheduler;\n\n  beforeEach(() => {\n    testScheduler = new TestScheduler(observableMatcher);\n  });\n\n  it('should catch error and replace with a cold Observable', () => {\n    testScheduler.run(({ hot, cold, expectObservable }) => {\n      const e1 = hot('  --a--b--#       ');\n      const e2 = cold('         -1-2-3-|');\n      const expected = '--a--b---1-2-3-|';\n\n      const result = e1.pipe(catchError((err: any) => e2));\n\n      expectObservable(result).toBe(expected);\n    });\n  });\n\n  it('should catch error and replace it with Observable.of()', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  --a--b--c--------|');\n      const subs = '    ^-------!';\n      const expected = '--a--b--(XYZ|)';\n\n      const result = e1.pipe(\n        map((n: string) => {\n          if (n === 'c') {\n            throw 'bad';\n          }\n          return n;\n        }),\n        catchError((err: any) => {\n          return of('X', 'Y', 'Z');\n        })\n      );\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(subs);\n    });\n  });\n\n  it('should catch error and replace it with a cold Observable', () => {\n    testScheduler.run(({ hot, cold, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  --a--b--#          ');\n      const e1subs = '  ^-------!          ';\n      const e2 = cold('         1-2-3-4-5-|');\n      const e2subs = '  --------^---------!';\n      const expected = '--a--b--1-2-3-4-5-|';\n\n      const result = e1.pipe(catchError((err: any) => e2));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should allow unsubscribing explicitly and early', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  --1-2-3-4-5-6---#');\n      const e1subs = '  ^------!         ';\n      const expected = '--1-2-3-         ';\n      const unsub = '   -------!         ';\n\n      const result = e1.pipe(\n        catchError(() => {\n          return of('X', 'Y', 'Z');\n        })\n      );\n\n      expectObservable(result, unsub).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should not break unsubscription chain when unsubscribed explicitly', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  --1-2-3-4-5-6---#');\n      const e1subs = '  ^------!         ';\n      const expected = '--1-2-3-         ';\n      const unsub = '   -------!         ';\n\n      const result = e1.pipe(\n        mergeMap((x: any) => of(x)),\n        catchError(() => {\n          return of('X', 'Y', 'Z');\n        }),\n        mergeMap((x: any) => of(x))\n      );\n\n      expectObservable(result, unsub).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should unsubscribe from a caught hot caught observable when unsubscribed explicitly', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  -1-2-3-#          ');\n      const e1subs = '  ^------!          ';\n      const e2 = hot('  ---3-4-5-6-7-8-9-|');\n      const e2subs = '  -------^----!     ';\n      const expected = '-1-2-3-5-6-7-     ';\n      const unsub = '   ------------!     ';\n\n      const result = e1.pipe(catchError(() => e2));\n\n      expectObservable(result, unsub).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should unsubscribe from a caught cold caught observable when unsubscribed explicitly', () => {\n    testScheduler.run(({ hot, cold, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  -1-2-3-#          ');\n      const e1subs = '  ^------!          ';\n      const e2 = cold('        5-6-7-8-9-|');\n      const e2subs = '  -------^----!     ';\n      const expected = '-1-2-3-5-6-7-     ';\n      const unsub = '   ------------!     ';\n\n      const result = e1.pipe(catchError(() => e2));\n\n      expectObservable(result, unsub).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should unsubscribe from a caught cold caught interop observable when unsubscribed explicitly', () => {\n    testScheduler.run(({ hot, cold, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  -1-2-3-#          ');\n      const e1subs = '  ^------!          ';\n      const e2 = cold('        5-6-7-8-9-|');\n      const e2subs = '  -------^----!     ';\n      const expected = '-1-2-3-5-6-7-     ';\n      const unsub = '   ------------!     ';\n\n      // This test is the same as the previous test, but the observable is\n      // manipulated to make it look like an interop observable - an observable\n      // from a foreign library. Interop subscribers are treated differently:\n      // they are wrapped in a safe subscriber. This test ensures that\n      // unsubscriptions are chained all the way to the interop subscriber.\n\n      const result = e1.pipe(catchError(() => asInteropObservable(e2)));\n\n      expectObservable(result, unsub).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should stop listening to a synchronous observable when unsubscribed', () => {\n    const sideEffects: number[] = [];\n    const synchronousObservable = concat(\n      defer(() => {\n        sideEffects.push(1);\n        return of(1);\n      }),\n      defer(() => {\n        sideEffects.push(2);\n        return of(2);\n      }),\n      defer(() => {\n        sideEffects.push(3);\n        return of(3);\n      })\n    );\n\n    throwError(() => new Error('Some error'))\n      .pipe(\n        catchError(() => synchronousObservable),\n        takeWhile((x) => x != 2) // unsubscribe at the second side-effect\n      )\n      .subscribe(() => {\n        /* noop */\n      });\n\n    expect(sideEffects).to.deep.equal([1, 2]);\n  });\n\n  it('should catch error and replace it with a hot Observable', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  --a--b--#          ');\n      const e1subs = '  ^-------!          ';\n      const e2 = hot('  1-2-3-4-5-6-7-8-9-|');\n      const e2subs = '  --------^---------!';\n      const expected = '--a--b--5-6-7-8-9-|';\n\n      const result = e1.pipe(catchError((err: any) => e2));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should catch and allow the cold observable to be repeated with the third (caught) argument', () => {\n    testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold('--a--b--c--------|       ');\n      const subs = [\n        '               ^-------!                ',\n        '              --------^-------!         ',\n        '              ----------------^-------! ',\n      ];\n      const expected = '--a--b----a--b----a--b--#';\n\n      let retries = 0;\n      const result = e1.pipe(\n        map((n: any) => {\n          if (n === 'c') {\n            throw 'bad';\n          }\n          return n;\n        }),\n        catchError((err: any, caught: any) => {\n          if (retries++ === 2) {\n            throw 'done';\n          }\n          return caught;\n        })\n      );\n\n      expectObservable(result).toBe(expected, undefined, 'done');\n      expectSubscriptions(e1.subscriptions).toBe(subs);\n    });\n  });\n\n  it('should catch and allow the hot observable to proceed with the third (caught) argument', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  --a--b--c----d---|');\n      // prettier-ignore\n      const subs = [\n        '               ^-------!         ',\n        '              --------^--------! ',\n      ];\n      const expected = '--a--b-------d---|';\n\n      let retries = 0;\n      const result = e1.pipe(\n        map((n: any) => {\n          if (n === 'c') {\n            throw 'bad';\n          }\n          return n;\n        }),\n        catchError((err: any, caught: any) => {\n          if (retries++ === 2) {\n            throw 'done';\n          }\n          return caught;\n        })\n      );\n\n      expectObservable(result).toBe(expected, undefined, 'done');\n      expectSubscriptions(e1.subscriptions).toBe(subs);\n    });\n  });\n\n  it('should catch and replace a Observable.throw() as the source', () => {\n    testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' #');\n      const subs = '    (^!)';\n      const expected = '(abc|)';\n\n      const result = e1.pipe(catchError((err: any) => of('a', 'b', 'c')));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(subs);\n    });\n  });\n\n  it('should mirror the source if it does not raise errors', () => {\n    testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' --a--b--c--|');\n      const subs = '    ^----------!';\n      const expected = '--a--b--c--|';\n\n      const result = e1.pipe(catchError((err: any) => of('x', 'y', 'z')));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(subs);\n    });\n  });\n\n  it('should complete if you return Observable.empty()', () => {\n    testScheduler.run(({ hot, cold, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  --a--b--#');\n      const e1subs = '  ^-------!';\n      const e2 = cold('         |');\n      const e2subs = '  --------(^!)';\n      const expected = '--a--b--|';\n\n      const result = e1.pipe(catchError(() => e2));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should raise error if you return Observable.throw()', () => {\n    testScheduler.run(({ hot, cold, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  --a--b--#');\n      const e1subs = '  ^-------!';\n      const e2 = cold('         #');\n      const e2subs = '  --------(^!)';\n      const expected = '--a--b--#';\n\n      const result = e1.pipe(catchError(() => e2));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should never terminate if you return NEVER', () => {\n    testScheduler.run(({ hot, cold, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  --a--b--#');\n      const e1subs = '  ^-------!';\n      const e2 = cold('         -');\n      const e2subs = '  --------^';\n      const expected = '--a--b---';\n\n      const result = e1.pipe(catchError(() => e2));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should pass the error as the first argument', (done) => {\n    throwError(() => 'bad')\n      .pipe(\n        catchError((err: any) => {\n          expect(err).to.equal('bad');\n          return EMPTY;\n        })\n      )\n      .subscribe({\n        next: () => {\n          //noop\n        },\n        error: (err: any) => {\n          done(new Error('should not be called'));\n        },\n        complete: () => {\n          done();\n        },\n      });\n  });\n\n  it('should accept selector returns any ObservableInput', (done) => {\n    const input$ = createObservableInputs(42);\n\n    input$.pipe(mergeMap((input) => throwError(() => 'bad').pipe(catchError((err) => input)))).subscribe({\n      next: (x) => {\n        expect(x).to.be.equal(42);\n      },\n      error: (err: any) => {\n        done(new Error('should not be called'));\n      },\n      complete: () => {\n        done();\n      },\n    });\n  });\n\n  it('should catch errors throw from within the constructor', () => {\n    // See https://github.com/ReactiveX/rxjs/issues/3740\n    testScheduler.run(({ expectObservable }) => {\n      const source = concat(\n        new Observable<string>((o) => {\n          o.next('a');\n          throw 'kaboom';\n        }).pipe(catchError((_) => of('b'))),\n        of('c')\n      );\n      const expected = '(abc|)';\n      expectObservable(source).toBe(expected);\n    });\n  });\n\n  context('fromPromise', () => {\n    type SetTimeout = (callback: (...args: any[]) => void, ms: number, ...args: any[]) => NodeJS.Timer;\n\n    let trueSetTimeout: SetTimeout;\n    let sandbox: sinon.SinonSandbox;\n    let timers: sinon.SinonFakeTimers;\n\n    beforeEach(() => {\n      trueSetTimeout = global.setTimeout;\n      sandbox = sinon.createSandbox();\n      timers = sandbox.useFakeTimers();\n    });\n\n    afterEach(() => {\n      sandbox.restore();\n    });\n\n    it('should chain a throw from a promise using Observable.throw', (done) => {\n      const subscribeSpy = sinon.spy();\n      const errorSpy = sinon.spy();\n      const thrownError = new Error('BROKEN THROW');\n      const testError = new Error('BROKEN PROMISE');\n      from(Promise.reject(testError))\n        .pipe(catchError((err) => throwError(() => thrownError)))\n        .subscribe({ next: subscribeSpy, error: errorSpy });\n\n      trueSetTimeout(() => {\n        try {\n          timers.tick(1);\n        } catch (e) {\n          return done(new Error('This should not have thrown an error'));\n        }\n        expect(subscribeSpy).not.to.be.called;\n        expect(errorSpy).to.have.been.called;\n        expect(errorSpy).to.have.been.calledWith(thrownError);\n        done();\n      }, 0);\n    });\n  });\n\n  // TODO(v8): see https://github.com/ReactiveX/rxjs/issues/5115\n  // The re-implementation in version 8 should fix the problem in the\n  // referenced issue. Closed subscribers should remain closed.\n\n  it('Properly handle async handled result if source is synchronous', (done) => {\n    const source = new Observable<string>((observer) => {\n      observer.error(new Error('kaboom!'));\n      observer.complete();\n    });\n\n    const sourceWithDelay = new Observable<string>((observer) => {\n      observer.next('delayed');\n      observer.complete();\n    }).pipe(delay(0));\n\n    const values: string[] = [];\n    source.pipe(catchError((err) => sourceWithDelay)).subscribe({\n      next: (value) => values.push(value),\n      error: (err) => done(err),\n      complete: () => {\n        expect(values).to.deep.equal(['delayed']);\n        done();\n      },\n    });\n  });\n\n  it('should stop listening to a synchronous observable when unsubscribed', () => {\n    const sideEffects: number[] = [];\n    const synchronousObservable = new Observable((subscriber) => {\n      // This will check to see if the subscriber was closed on each loop\n      // when the unsubscribe hits (from the `take`), it should be closed\n      for (let i = 0; !subscriber.closed && i < 10; i++) {\n        sideEffects.push(i);\n        subscriber.next(i);\n      }\n    });\n\n    synchronousObservable\n      .pipe(\n        catchError(() => EMPTY),\n        take(3)\n      )\n      .subscribe(() => {\n        /* noop */\n      });\n\n    expect(sideEffects).to.deep.equal([0, 1, 2]);\n  });\n});\n"
  },
  {
    "path": "packages/rxjs/spec/operators/combineLatestAll-spec.ts",
    "content": "import { expect } from 'chai';\nimport { queueScheduler, of, scheduled } from 'rxjs';\nimport { combineLatestAll, mergeMap } from 'rxjs/operators';\nimport { TestScheduler } from 'rxjs/testing';\nimport { observableMatcher } from '../helpers/observableMatcher';\n\n/** @test {combineLatestAll} */\ndescribe('combineLatestAll operator', () => {\n  let testScheduler: TestScheduler;\n\n  beforeEach(() => {\n    testScheduler = new TestScheduler(observableMatcher);\n  });\n\n  it('should combine events from two observables', () => {\n    testScheduler.run(({ hot, cold, expectObservable }) => {\n      const x = cold('                  -a-----b---|');\n      const y = cold('                  --1-2-|     ');\n      const outer = hot('-x----y--------|           ', { x: x, y: y });\n      const expected = ' -----------------A-B--C---|';\n\n      const result = outer.pipe(combineLatestAll((a, b) => String(a) + String(b)));\n\n      expectObservable(result).toBe(expected, { A: 'a1', B: 'a2', C: 'b2' });\n    });\n  });\n\n  it('should work with two nevers', () => {\n    testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' -');\n      const e1subs = '  ^';\n      const e2 = cold(' -');\n      const e2subs = '  ^';\n      const expected = '-';\n\n      const result = of(e1, e2).pipe(combineLatestAll((x, y) => x + y));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should work with never and empty', () => {\n    testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' -');\n      const e1subs = '  ^';\n      const e2 = cold(' |');\n      const e2subs = '  (^!)';\n      const expected = '-';\n\n      const result = of(e1, e2).pipe(combineLatestAll((x, y) => x + y));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should work with empty and never', () => {\n    testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' |');\n      const e1subs = '  (^!)';\n      const e2 = cold(' -');\n      const e2subs = '  ^';\n      const expected = '-';\n\n      const result = of(e1, e2).pipe(combineLatestAll((x, y) => x + y));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should work with empty and empty', () => {\n    testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' |');\n      const e1subs = '  (^!)';\n      const e2 = cold(' |');\n      const e2subs = '  (^!)';\n      const expected = '|';\n\n      const result = of(e1, e2).pipe(combineLatestAll((x, y) => x + y));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should work with hot-empty and hot-single', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('-a-^-|');\n      const e1subs = '   ^-!';\n      const e2 = hot('-b-^-c-|');\n      const e2subs = '   ^---!';\n      const expected = ' ----|';\n\n      const result = of(e1, e2).pipe(combineLatestAll((x, y) => x + y));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should work with hot-single and hot-empty', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('-a-^-|');\n      const e1subs = '   ^-!';\n      const e2 = hot('-b-^-c-|');\n      const e2subs = '   ^---!';\n      const expected = ' ----|';\n\n      const result = of(e2, e1).pipe(combineLatestAll((x, y) => x + y));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should work with hot-single and never', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('-a-^-|');\n      const e1subs = '   ^-!';\n      const e2 = hot('------'); //never\n      const e2subs = '   ^--';\n      const expected = ' ---'; //never\n\n      const result = of(e1, e2).pipe(combineLatestAll((x, y) => x + y));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should work with never and hot-single', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('--------'); //never\n      const e1subs = '   ^----';\n      const e2 = hot('-a-^-b-|');\n      const e2subs = '   ^---!';\n      const expected = ' -----'; //never\n\n      const result = of(e1, e2).pipe(combineLatestAll((x, y) => x + y));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should work with hot and hot', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('--a--^--b--c--|');\n      const e1subs = '     ^--------!';\n      const e2 = hot('---e-^---f--g--|');\n      const e2subs = '     ^---------!';\n      const expected = '   ----x-yz--|';\n\n      const result = of(e1, e2).pipe(combineLatestAll((x, y) => x + y));\n\n      expectObservable(result).toBe(expected, { x: 'bf', y: 'cf', z: 'cg' });\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should allow unsubscribing early and explicitly', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('--a--^--b--c---d-| ');\n      const e1subs = '     ^--------!    ';\n      const e2 = hot('---e-^---f--g---h-|');\n      const e2subs = '     ^--------!    ';\n      const expected = '   ----x-yz--    ';\n      const unsub = '      ---------!    ';\n      const values = { x: 'bf', y: 'cf', z: 'cg' };\n\n      const result = of(e1, e2).pipe(combineLatestAll((x, y) => x + y));\n\n      expectObservable(result, unsub).toBe(expected, values);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should not break unsubscription chains when unsubscribed explicitly', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  --a--^--b--c---d-| ');\n      const e1subs = '       ^--------!    ';\n      const e2 = hot('  ---e-^---f--g---h-|');\n      const e2subs = '       ^--------!    ';\n      const expected = '     ----x-yz--    ';\n      const unsub = '        ---------!    ';\n      const values = { x: 'bf', y: 'cf', z: 'cg' };\n\n      const result = of(e1, e2).pipe(\n        mergeMap((x) => of(x)),\n        combineLatestAll((x, y) => x + y),\n        mergeMap((x) => of(x))\n      );\n\n      expectObservable(result, unsub).toBe(expected, values);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should combine 3 observables', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('--a--^--b--c--|');\n      const e1subs = '     ^--------!';\n      const e2 = hot('---e-^---f--g--|');\n      const e2subs = '     ^---------!';\n      const e3 = hot('---h-^----i--j-|');\n      const e3subs = '     ^---------!';\n      const expected = '   -----wxyz-|';\n\n      const result = of(e1, e2, e3).pipe(combineLatestAll((x, y, z) => x + y + z));\n\n      expectObservable(result).toBe(expected, { w: 'bfi', x: 'cfi', y: 'cgi', z: 'cgj' });\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n      expectSubscriptions(e3.subscriptions).toBe(e3subs);\n    });\n  });\n\n  it('should work with empty and error', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  ----------|'); //empty\n      const e1subs = '  ^-----!';\n      const e2 = hot('  ------#', undefined, 'shazbot!'); //error\n      const e2subs = '  ^-----!';\n      const expected = '------#';\n\n      const result = of(e1, e2).pipe(combineLatestAll((x, y) => x + y));\n\n      expectObservable(result).toBe(expected, null, 'shazbot!');\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should work with error and empty', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('--^---#', undefined, 'too bad, honk'); //error\n      const e1subs = '  ^---!';\n      const e2 = hot('--^--------|'); //empty\n      const e2subs = '  ^---!';\n      const expected = '----#';\n\n      const result = of(e1, e2).pipe(combineLatestAll((x, y) => x + y));\n\n      expectObservable(result).toBe(expected, null, 'too bad, honk');\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should work with hot and throw', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('-a-^--b--c--|');\n      const e1subs = '   ^-!';\n      const e2 = hot('---^-#', undefined, 'bazinga');\n      const e2subs = '   ^-!';\n      const expected = ' --#';\n\n      const result = of(e1, e2).pipe(combineLatestAll((x, y) => x + y));\n\n      expectObservable(result).toBe(expected, null, 'bazinga');\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should work with throw and hot', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('---^-#', undefined, 'bazinga');\n      const e1subs = '   ^-!';\n      const e2 = hot('-a-^--b--c--|');\n      const e2subs = '   ^-!';\n      const expected = ' --#';\n\n      const result = of(e1, e2).pipe(combineLatestAll((x, y) => x + y));\n\n      expectObservable(result).toBe(expected, null, 'bazinga');\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should work with throw and throw', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('---^----#', undefined, 'jenga');\n      const e1subs = '   ^-!';\n      const e2 = hot('---^-#', undefined, 'bazinga');\n      const e2subs = '   ^-!';\n      const expected = ' --#';\n\n      const result = of(e1, e2).pipe(combineLatestAll((x, y) => x + y));\n\n      expectObservable(result).toBe(expected, null, 'bazinga');\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should work with error and throw', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('-a-^--b--#', undefined, 'wokka wokka');\n      const e1subs = '   ^-!';\n      const e2 = hot('---^-#', undefined, 'flurp');\n      const e2subs = '   ^-!';\n      const expected = ' --#';\n\n      const result = of(e1, e2).pipe(combineLatestAll((x, y) => x + y));\n\n      expectObservable(result).toBe(expected, null, 'flurp');\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should work with throw and error', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('---^-#', undefined, 'flurp');\n      const e1subs = '   ^-!';\n      const e2 = hot('-a-^--b--#', undefined, 'wokka wokka');\n      const e2subs = '   ^-!';\n      const expected = ' --#';\n\n      const result = of(e1, e2).pipe(combineLatestAll((x, y) => x + y));\n\n      expectObservable(result).toBe(expected, null, 'flurp');\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should work with never and throw', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('---^-----------');\n      const e1subs = '   ^-----!';\n      const e2 = hot('---^-----#', undefined, 'wokka wokka');\n      const e2subs = '   ^-----!';\n      const expected = ' ------#';\n\n      const result = of(e1, e2).pipe(combineLatestAll((x, y) => x + y));\n\n      expectObservable(result).toBe(expected, null, 'wokka wokka');\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should work with throw and never', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('   ---^----#', undefined, 'wokka wokka');\n      const e1subs = '      ^----!';\n      const e2 = hot('   ---^-----------');\n      const e2subs = '      ^----!';\n      const expected = '    -----#';\n\n      const result = of(e1, e2).pipe(combineLatestAll((x, y) => x + y));\n\n      expectObservable(result).toBe(expected, null, 'wokka wokka');\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should work with some and throw', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('---^----a---b--|');\n      const e1subs = '   ^--!';\n      const e2 = hot('---^--#', undefined, 'wokka wokka');\n      const e2subs = '   ^--!';\n      const expected = ' ---#';\n\n      const result = of(e1, e2).pipe(combineLatestAll((x, y) => x + y));\n\n      expectObservable(result).toBe(expected, { a: 1, b: 2 }, 'wokka wokka');\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should work with throw and some', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('---^--#', undefined, 'wokka wokka');\n      const e1subs = '   ^--!';\n      const e2 = hot('---^----a---b--|');\n      const e2subs = '   ^--!';\n      const expected = ' ---#';\n\n      const result = of(e1, e2).pipe(combineLatestAll((x, y) => x + y));\n\n      expectObservable(result).toBe(expected, null, 'wokka wokka');\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should handle throw after complete left', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const left = hot(' --a--^--b---|');\n      const leftSubs = '      ^------!';\n      const right = hot('-----^--------#', undefined, 'bad things');\n      const rightSubs = '     ^--------!';\n      const expected = '      ---------#';\n\n      const result = of(left, right).pipe(combineLatestAll((x, y) => x + y));\n\n      expectObservable(result).toBe(expected, null, 'bad things');\n      expectSubscriptions(left.subscriptions).toBe(leftSubs);\n      expectSubscriptions(right.subscriptions).toBe(rightSubs);\n    });\n  });\n\n  it('should handle throw after complete right', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const left = hot(' -----^--------#', undefined, 'bad things');\n      const leftSubs = '      ^--------!';\n      const right = hot('--a--^--b---|');\n      const rightSubs = '     ^------!';\n      const expected = '      ---------#';\n\n      const result = of(left, right).pipe(combineLatestAll((x, y) => x + y));\n\n      expectObservable(result).toBe(expected, null, 'bad things');\n      expectSubscriptions(left.subscriptions).toBe(leftSubs);\n      expectSubscriptions(right.subscriptions).toBe(rightSubs);\n    });\n  });\n\n  it('should handle interleaved with tail', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('-a--^--b---c---|');\n      const e1subs = '    ^----------!';\n      const e2 = hot('--d-^----e---f--|');\n      const e2subs = '    ^-----------!';\n      const expected = '  -----x-y-z--|';\n\n      const result = of(e1, e2).pipe(combineLatestAll((x, y) => x + y));\n\n      expectObservable(result).toBe(expected, { x: 'be', y: 'ce', z: 'cf' });\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should handle two consecutive hot observables', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('--a--^--b--c--|');\n      const e1subs = '     ^--------!';\n      const e2 = hot('-----^----------d--e--f--|');\n      const e2subs = '     ^-------------------!';\n      const expected = '   -----------x--y--z--|';\n\n      const result = of(e1, e2).pipe(combineLatestAll((x, y) => x + y));\n\n      expectObservable(result).toBe(expected, { x: 'cd', y: 'ce', z: 'cf' });\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should handle two consecutive hot observables with error left', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const left = hot(' --a--^--b--c--#', undefined, 'jenga');\n      const leftSubs = '      ^--------!';\n      const right = hot('-----^----------d--e--f--|');\n      const rightSubs = '     ^--------!';\n      const expected = '      ---------#';\n\n      const result = of(left, right).pipe(combineLatestAll((x, y) => x + y));\n\n      expectObservable(result).toBe(expected, null, 'jenga');\n      expectSubscriptions(left.subscriptions).toBe(leftSubs);\n      expectSubscriptions(right.subscriptions).toBe(rightSubs);\n    });\n  });\n\n  it('should handle two consecutive hot observables with error right', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const left = hot(' --a--^--b--c--|');\n      const leftSubs = '      ^--------!';\n      const right = hot('-----^----------d--e--f--#', undefined, 'dun dun dun');\n      const rightSubs = '     ^-------------------!';\n      const expected = '      -----------x--y--z--#';\n\n      const result = of(left, right).pipe(combineLatestAll((x, y) => x + y));\n\n      expectObservable(result).toBe(expected, { x: 'cd', y: 'ce', z: 'cf' }, 'dun dun dun');\n      expectSubscriptions(left.subscriptions).toBe(leftSubs);\n      expectSubscriptions(right.subscriptions).toBe(rightSubs);\n    });\n  });\n\n  it('should handle selector throwing', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('--a--^--b--|');\n      const e1subs = '     ^--!';\n      const e2 = hot('--c--^--d--|');\n      const e2subs = '     ^--!';\n      const expected = '   ---#';\n\n      const result = of(e1, e2).pipe(\n        combineLatestAll((x, y) => {\n          throw 'ha ha ' + x + ', ' + y;\n        })\n      );\n\n      expectObservable(result).toBe(expected, null, 'ha ha b, d');\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should combine two observables', (done) => {\n    const a = of(1, 2, 3);\n    const b = of(4, 5, 6, 7, 8);\n    const expected = [\n      [3, 4],\n      [3, 5],\n      [3, 6],\n      [3, 7],\n      [3, 8],\n    ];\n    of(a, b)\n      .pipe(combineLatestAll())\n      .subscribe({\n        next: (vals) => {\n          expect(vals).to.deep.equal(expected.shift());\n        },\n        complete: () => {\n          expect(expected.length).to.equal(0);\n          done();\n        },\n      });\n  });\n\n  it('should combine two immediately-scheduled observables', (done) => {\n    const a = scheduled([1, 2, 3], queueScheduler);\n    const b = scheduled([4, 5, 6, 7, 8], queueScheduler);\n    const r = [\n      [1, 4],\n      [2, 4],\n      [2, 5],\n      [3, 5],\n      [3, 6],\n      [3, 7],\n      [3, 8],\n    ];\n\n    scheduled([a, b], queueScheduler)\n      .pipe(combineLatestAll())\n      .subscribe({\n        next: (vals) => {\n          expect(vals).to.deep.equal(r.shift());\n        },\n        complete: () => {\n          expect(r.length).to.equal(0);\n          done();\n        },\n      });\n  });\n});\n"
  },
  {
    "path": "packages/rxjs/spec/operators/combineLatestWith-spec.ts",
    "content": "import { of } from 'rxjs';\nimport { combineLatestWith, mergeMap, distinct, count, map } from 'rxjs/operators';\nimport { TestScheduler } from 'rxjs/testing';\nimport { observableMatcher } from '../helpers/observableMatcher';\n\n/** @test {combineLatestWith} */\ndescribe('combineLatestWith', () => {\n  let testScheduler: TestScheduler;\n\n  beforeEach(() => {\n    testScheduler = new TestScheduler(observableMatcher);\n  });\n\n  it('should combine events from two cold observables', () => {\n    testScheduler.run(({ cold, expectObservable }) => {\n      const e1 = cold(' -a--b-----c-d-e-|');\n      const e2 = cold(' --1--2-3-4---|   ');\n      const expected = '--A-BC-D-EF-G-H-|';\n\n      const result = e1.pipe(\n        combineLatestWith(e2),\n        map(([a, b]) => a + b)\n      );\n\n      expectObservable(result).toBe(expected, {\n        A: 'a1',\n        B: 'b1',\n        C: 'b2',\n        D: 'b3',\n        E: 'b4',\n        F: 'c4',\n        G: 'd4',\n        H: 'e4',\n      });\n    });\n  });\n\n  it('should work with two nevers', () => {\n    testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' -');\n      const e1subs = '  ^';\n      const e2 = cold(' -');\n      const e2subs = '  ^';\n      const expected = '-';\n\n      const result = e1.pipe(\n        combineLatestWith(e2),\n        map(([x, y]) => x + y)\n      );\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should work with never and empty', () => {\n    testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' -');\n      const e1subs = '  ^';\n      const e2 = cold(' |');\n      const e2subs = '  (^!)';\n      const expected = '-';\n\n      const result = e1.pipe(\n        combineLatestWith(e2),\n        map(([x, y]) => x + y)\n      );\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should work with empty and never', () => {\n    testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' |');\n      const e1subs = '  (^!)';\n      const e2 = cold(' -');\n      const e2subs = '  ^';\n      const expected = '-';\n\n      const result = e1.pipe(\n        combineLatestWith(e2),\n        map(([x, y]) => x + y)\n      );\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should work with empty and empty', () => {\n    testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' |');\n      const e1subs = '  (^!)';\n      const e2 = cold(' |');\n      const e2subs = '  (^!)';\n      const expected = '|';\n\n      const result = e1.pipe(\n        combineLatestWith(e2),\n        map(([x, y]) => x + y)\n      );\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should work with hot-empty and hot-single', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const values = {\n        a: 1,\n        b: 2,\n        c: 3,\n        r: 1 + 3, //a + c\n      };\n      const e1 = hot('-a-^-|', values);\n      const e1subs = '   ^-!';\n      const e2 = hot('-b-^-c-|', values);\n      const e2subs = '   ^---!';\n      const expected = ' ----|';\n\n      const result = e1.pipe(\n        combineLatestWith(e2),\n        map(([x, y]) => x + y)\n      );\n\n      expectObservable(result).toBe(expected, values);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should work with hot-single and hot-empty', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const values = {\n        a: 1,\n        b: 2,\n        c: 3,\n      };\n      const e1 = hot('-a-^-|', values);\n      const e1subs = '   ^-!';\n      const e2 = hot('-b-^-c-|', values);\n      const e2subs = '   ^---!';\n      const expected = ' ----|';\n\n      const result = e2.pipe(\n        combineLatestWith(e1),\n        map(([x, y]) => x + y)\n      );\n\n      expectObservable(result).toBe(expected, values);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should work with hot-single and never', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const values = {\n        a: 1,\n      };\n      const e1 = hot('-a-^-|', values);\n      const e1subs = '   ^-!';\n      const e2 = hot('------', values); //never\n      const e2subs = '   ^--';\n      const expected = ' ---'; //never\n\n      const result = e1.pipe(\n        combineLatestWith(e2),\n        map(([x, y]) => x + y)\n      );\n\n      expectObservable(result).toBe(expected, values);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should work with never and hot-single', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const values = {\n        a: 1,\n        b: 2,\n      };\n      const e1 = hot('--------', values); //never\n      const e1subs = '   ^    ';\n      const e2 = hot('-a-^-b-|', values);\n      const e2subs = '   ^---!';\n      const expected = ' -----'; //never\n\n      const result = e1.pipe(\n        combineLatestWith(e2),\n        map(([x, y]) => x + y)\n      );\n\n      expectObservable(result).toBe(expected, values);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should work with hot and hot', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('--a--^--b--c--|', { a: 'a', b: 'b', c: 'c' });\n      const e1subs = '     ^--------!';\n      const e2 = hot('---e-^---f--g--|', { e: 'e', f: 'f', g: 'g' });\n      const e2subs = '     ^---------!';\n      const expected = '   ----x-yz--|';\n\n      const result = e1.pipe(\n        combineLatestWith(e2),\n        map(([x, y]) => x + y)\n      );\n\n      expectObservable(result).toBe(expected, { x: 'bf', y: 'cf', z: 'cg' });\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should work with empty and error', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  ----------|'); //empty\n      const e1subs = '  ^-----!';\n      const e2 = hot('  ------#', undefined, 'shazbot!'); //error\n      const e2subs = '  ^-----!';\n      const expected = '------#';\n\n      const result = e1.pipe(\n        combineLatestWith(e2),\n        map(([x, y]) => x + y)\n      );\n\n      expectObservable(result).toBe(expected, null, 'shazbot!');\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should work with error and empty', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('--^---#', undefined, 'too bad, honk'); //error\n      const e1subs = '  ^---!';\n      const e2 = hot('--^--------|'); //empty\n      const e2subs = '  ^---!';\n      const expected = '----#';\n\n      const result = e1.pipe(\n        combineLatestWith(e2),\n        map(([x, y]) => x + y)\n      );\n\n      expectObservable(result).toBe(expected, null, 'too bad, honk');\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should work with hot and throw', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('-a-^--b--c--|', { a: 1, b: 2, c: 3 });\n      const e1subs = '   ^-!';\n      const e2 = hot('---^-#', undefined, 'bazinga');\n      const e2subs = '   ^-!';\n      const expected = ' --#';\n\n      const result = e1.pipe(\n        combineLatestWith(e2),\n        map(([x, y]) => x + y)\n      );\n\n      expectObservable(result).toBe(expected, null, 'bazinga');\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should work with throw and hot', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('---^-#', undefined, 'bazinga');\n      const e1subs = '   ^-!';\n      const e2 = hot('-a-^--b--c--|', { a: 1, b: 2, c: 3 });\n      const e2subs = '   ^-!';\n      const expected = ' --#';\n\n      const result = e1.pipe(\n        combineLatestWith(e2),\n        map(([x, y]) => x + y)\n      );\n\n      expectObservable(result).toBe(expected, null, 'bazinga');\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should work with throw and throw', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('---^----#', undefined, 'jenga');\n      const e1subs = '   ^-!';\n      const e2 = hot('---^-#', undefined, 'bazinga');\n      const e2subs = '   ^-!';\n      const expected = ' --#';\n\n      const result = e1.pipe(\n        combineLatestWith(e2),\n        map(([x, y]) => x + y)\n      );\n\n      expectObservable(result).toBe(expected, null, 'bazinga');\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should work with error and throw', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('-a-^--b--#', { a: 1, b: 2 }, 'wokka wokka');\n      const e1subs = '   ^-!';\n      const e2 = hot('---^-#', undefined, 'flurp');\n      const e2subs = '   ^-!';\n      const expected = ' --#';\n\n      const result = e1.pipe(\n        combineLatestWith(e2),\n        map(([x, y]) => x + y)\n      );\n\n      expectObservable(result).toBe(expected, null, 'flurp');\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should work with throw and error', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('---^-#', undefined, 'flurp');\n      const e1subs = '   ^-!';\n      const e2 = hot('-a-^--b--#', { a: 1, b: 2 }, 'wokka wokka');\n      const e2subs = '   ^-!';\n      const expected = ' --#';\n\n      const result = e1.pipe(\n        combineLatestWith(e2),\n        map(([x, y]) => x + y)\n      );\n\n      expectObservable(result).toBe(expected, null, 'flurp');\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should work with never and throw', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('---^-----------');\n      const e1subs = '   ^-----!';\n      const e2 = hot('---^-----#', undefined, 'wokka wokka');\n      const e2subs = '   ^-----!';\n      const expected = ' ------#';\n\n      const result = e1.pipe(\n        combineLatestWith(e2),\n        map(([x, y]) => x + y)\n      );\n\n      expectObservable(result).toBe(expected, null, 'wokka wokka');\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should work with throw and never', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('---^----#', undefined, 'wokka wokka');\n      const e1subs = '   ^----!';\n      const e2 = hot('---^-----------');\n      const e2subs = '   ^----!';\n      const expected = ' -----#';\n\n      const result = e1.pipe(\n        combineLatestWith(e2),\n        map(([x, y]) => x + y)\n      );\n\n      expectObservable(result).toBe(expected, null, 'wokka wokka');\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should work with some and throw', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('   ---^----a---b--|', { a: 1, b: 2 });\n      const e1subs = '      ^--!';\n      const e2 = hot('   ---^--#', undefined, 'wokka wokka');\n      const e2subs = '      ^--!';\n      const expected = '    ---#';\n\n      const result = e1.pipe(\n        combineLatestWith(e2),\n        map(([x, y]) => x + y)\n      );\n\n      expectObservable(result).toBe(expected, { a: 1, b: 2 }, 'wokka wokka');\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should work with throw and some', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('---^--#', undefined, 'wokka wokka');\n      const e1subs = '   ^--!';\n      const e2 = hot('---^----a---b--|', { a: 1, b: 2 });\n      const e2subs = '   ^--!';\n      const expected = ' ---#';\n\n      const result = e1.pipe(\n        combineLatestWith(e2),\n        map(([x, y]) => x + y)\n      );\n\n      expectObservable(result).toBe(expected, { a: 1, b: 2 }, 'wokka wokka');\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should handle throw after complete left', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const left = hot(' --a--^--b---|', { a: 1, b: 2 });\n      const leftSubs = '      ^------!';\n      const right = hot('-----^--------#', undefined, 'bad things');\n      const rightSubs = '     ^--------!';\n      const expected = '      ---------#';\n\n      const result = left.pipe(\n        combineLatestWith(right),\n        map(([x, y]) => x + y)\n      );\n\n      expectObservable(result).toBe(expected, null, 'bad things');\n      expectSubscriptions(left.subscriptions).toBe(leftSubs);\n      expectSubscriptions(right.subscriptions).toBe(rightSubs);\n    });\n  });\n\n  it('should handle throw after complete right', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const left = hot('  -----^--------#', undefined, 'bad things');\n      const leftSubs = '       ^--------!';\n      const right = hot(' --a--^--b---|', { a: 1, b: 2 });\n      const rightSubs = '      ^------!';\n      const expected = '       ---------#';\n\n      const result = left.pipe(\n        combineLatestWith(right),\n        map(([x, y]) => x + y)\n      );\n\n      expectObservable(result).toBe(expected, null, 'bad things');\n      expectSubscriptions(left.subscriptions).toBe(leftSubs);\n      expectSubscriptions(right.subscriptions).toBe(rightSubs);\n    });\n  });\n\n  it('should handle interleaved with tail', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('-a--^--b---c---|', { a: 'a', b: 'b', c: 'c' });\n      const e1subs = '    ^----------!';\n      const e2 = hot('--d-^----e---f--|', { d: 'd', e: 'e', f: 'f' });\n      const e2subs = '    ^-----------!';\n      const expected = '  -----x-y-z--|';\n\n      const result = e1.pipe(\n        combineLatestWith(e2),\n        map(([x, y]) => x + y)\n      );\n\n      expectObservable(result).toBe(expected, { x: 'be', y: 'ce', z: 'cf' });\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should handle two consecutive hot observables', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('--a--^--b--c--|', { a: 'a', b: 'b', c: 'c' });\n      const e1subs = '     ^--------!';\n      const e2 = hot('-----^----------d--e--f--|', { d: 'd', e: 'e', f: 'f' });\n      const e2subs = '     ^-------------------!';\n      const expected = '   -----------x--y--z--|';\n\n      const result = e1.pipe(\n        combineLatestWith(e2),\n        map(([x, y]) => x + y)\n      );\n\n      expectObservable(result).toBe(expected, { x: 'cd', y: 'ce', z: 'cf' });\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should handle two consecutive hot observables with error left', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const left = hot(' --a--^--b--c--#', { a: 'a', b: 'b', c: 'c' }, 'jenga');\n      const leftSubs = '      ^--------!';\n      const right = hot('-----^----------d--e--f--|', { d: 'd', e: 'e', f: 'f' });\n      const rightSubs = '     ^--------!';\n      const expected = '      ---------#';\n\n      const result = left.pipe(\n        combineLatestWith(right),\n        map(([x, y]) => x + y)\n      );\n\n      expectObservable(result).toBe(expected, null, 'jenga');\n      expectSubscriptions(left.subscriptions).toBe(leftSubs);\n      expectSubscriptions(right.subscriptions).toBe(rightSubs);\n    });\n  });\n\n  it('should handle two consecutive hot observables with error right', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const left = hot(' --a--^--b--c--|', { a: 'a', b: 'b', c: 'c' });\n      const leftSubs = '      ^--------!';\n      const right = hot('-----^----------d--e--f--#', { d: 'd', e: 'e', f: 'f' }, 'dun dun dun');\n      const rightSubs = '     ^-------------------!';\n      const expected = '      -----------x--y--z--#';\n\n      const result = left.pipe(\n        combineLatestWith(right),\n        map(([x, y]) => x + y)\n      );\n\n      expectObservable(result).toBe(expected, { x: 'cd', y: 'ce', z: 'cf' }, 'dun dun dun');\n      expectSubscriptions(left.subscriptions).toBe(leftSubs);\n      expectSubscriptions(right.subscriptions).toBe(rightSubs);\n    });\n  });\n\n  it('should allow unsubscribing early and explicitly', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('--a--^--b--c---d-| ');\n      const e1subs = '     ^--------!    ';\n      const e2 = hot('---e-^---f--g---h-|');\n      const e2subs = '     ^--------!    ';\n      const expected = '   ----x-yz--    ';\n      const unsub = '      ---------!    ';\n      const values = { x: 'bf', y: 'cf', z: 'cg' };\n\n      const result = e1.pipe(\n        combineLatestWith(e2),\n        map(([x, y]) => x + y)\n      );\n\n      expectObservable(result, unsub).toBe(expected, values);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should not break unsubscription chains when unsubscribed explicitly', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('--a--^--b--c---d-| ');\n      const e1subs = '     ^--------!    ';\n      const e2 = hot('---e-^---f--g---h-|');\n      const e2subs = '     ^--------!    ';\n      const expected = '   ----x-yz--    ';\n      const unsub = '      ---------!    ';\n      const values = { x: 'bf', y: 'cf', z: 'cg' };\n\n      const result = e1.pipe(\n        mergeMap((x) => of(x)),\n        combineLatestWith(e2),\n        map(([x, y]) => x + y),\n        mergeMap((x) => of(x))\n      );\n\n      expectObservable(result, unsub).toBe(expected, values);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should emit unique array instances with the default projection', () => {\n    testScheduler.run(({ hot, expectObservable }) => {\n      const e1 = hot('  -a--b--|');\n      const e2 = hot('  --1--2-|');\n      const expected = '-------(c|)';\n\n      const result = e1.pipe(combineLatestWith(e2), distinct(), count());\n\n      expectObservable(result).toBe(expected, { c: 3 });\n    });\n  });\n});\n"
  },
  {
    "path": "packages/rxjs/spec/operators/concatAll-spec.ts",
    "content": "import { expect } from 'chai';\nimport { from, throwError, of, scheduled, Observable, defer } from 'rxjs';\nimport { concatAll, take, mergeMap, finalize, delay } from 'rxjs/operators';\nimport { TestScheduler } from 'rxjs/testing';\nimport { observableMatcher } from '../helpers/observableMatcher';\n\n/** @test {concatAll} */\ndescribe('concatAll operator', () => {\n  let testScheduler: TestScheduler;\n\n  beforeEach(() => {\n    testScheduler = new TestScheduler(observableMatcher);\n  });\n\n  it('should concat an observable of observables', () => {\n    testScheduler.run(({ cold, hot, expectObservable }) => {\n      const x = cold('    ----a------b------|                 ');\n      const y = cold('                      ---c-d---|        ');\n      const z = cold('                               ---e--f-|');\n      const outer = hot('-x---y----z------|', { x: x, y: y, z: z });\n      const expected = ' -----a------b---------c-d------e--f-|';\n\n      const result = outer.pipe(concatAll());\n\n      expectObservable(result).toBe(expected);\n    });\n  });\n\n  it('should concat sources from promise', function (done) {\n    this.timeout(2000);\n    const sources = from([\n      new Promise<number>((res) => {\n        res(0);\n      }),\n      new Promise<number>((res) => {\n        res(1);\n      }),\n      new Promise<number>((res) => {\n        res(2);\n      }),\n      new Promise<number>((res) => {\n        res(3);\n      }),\n    ]).pipe(take(10));\n\n    const res: number[] = [];\n    sources.pipe(concatAll()).subscribe({\n      next: (x) => {\n        res.push(x);\n      },\n      error: (err) => {\n        done(new Error('should not be called'));\n      },\n      complete: () => {\n        expect(res).to.deep.equal([0, 1, 2, 3]);\n        done();\n      },\n    });\n  });\n\n  it('should finalize before moving to the next observable', () => {\n    const results: any[] = [];\n\n    const create = (n: number) =>\n      defer(() => {\n        results.push(`init ${n}`);\n        return of(`next ${n}`).pipe(\n          delay(100, testScheduler),\n          finalize(() => {\n            results.push(`finalized ${n}`);\n          })\n        );\n      });\n\n    of(create(1), create(2), create(3))\n      .pipe(concatAll())\n      .subscribe({\n        next: (value) => results.push(value),\n      });\n\n    testScheduler.flush();\n\n    expect(results).to.deep.equal([\n      'init 1',\n      'next 1',\n      'finalized 1',\n      'init 2',\n      'next 2',\n      'finalized 2',\n      'init 3',\n      'next 3',\n      'finalized 3',\n    ]);\n  });\n\n  it('should concat and raise error from promise', function (done) {\n    this.timeout(2000);\n\n    const sources = from([\n      new Promise<number>((res) => {\n        res(0);\n      }),\n      new Promise<number>((res, rej) => {\n        rej(1);\n      }),\n      new Promise<number>((res) => {\n        res(2);\n      }),\n      new Promise<number>((res) => {\n        res(3);\n      }),\n    ]).pipe(take(10));\n\n    const res: number[] = [];\n    sources.pipe(concatAll()).subscribe({\n      next: (x) => {\n        res.push(x);\n      },\n      error: (err) => {\n        expect(res.length).to.equal(1);\n        expect(err).to.equal(1);\n        done();\n      },\n      complete: () => {\n        done(new Error('should not be called'));\n      },\n    });\n  });\n\n  it('should concat all observables in an observable', () => {\n    testScheduler.run(({ expectObservable }) => {\n      const e1 = from([of('a'), of('b'), of('c')]).pipe(take(10));\n      const expected = '(abc|)';\n\n      expectObservable(e1.pipe(concatAll())).toBe(expected);\n    });\n  });\n\n  it('should throw if any child observable throws', () => {\n    testScheduler.run(({ expectObservable }) => {\n      const e1 = from([of('a'), throwError(() => 'error'), of('c')]).pipe(take(10));\n      const expected = '(a#)';\n\n      expectObservable(e1.pipe(concatAll())).toBe(expected);\n    });\n  });\n\n  it('should concat merging a hot observable of non-overlapped observables', () => {\n    testScheduler.run(({ cold, hot, expectObservable }) => {\n      const values = {\n        x: cold('       a-b---------|'),\n        y: cold('                 c-d-e-f-|'),\n        z: cold('                          g-h-i-j-k-|'),\n      };\n\n      const e1 = hot('  --x---------y--------z--------|', values);\n      const expected = '--a-b---------c-d-e-f-g-h-i-j-k-|';\n\n      expectObservable(e1.pipe(concatAll())).toBe(expected);\n    });\n  });\n\n  it('should raise error if inner observable raises error', () => {\n    testScheduler.run(({ cold, hot, expectObservable }) => {\n      const values = {\n        x: cold('       a-b---------|'),\n        y: cold('                 c-d-e-f-#'),\n        z: cold('                         g-h-i-j-k-|'),\n      };\n      const e1 = hot('  --x---------y--------z--------|', values);\n      const expected = '--a-b---------c-d-e-f-#';\n\n      expectObservable(e1.pipe(concatAll())).toBe(expected);\n    });\n  });\n\n  it('should raise error if outer observable raises error', () => {\n    testScheduler.run(({ cold, hot, expectObservable }) => {\n      const values = {\n        y: cold('       a-b---------|'),\n        z: cold('                 c-d-e-f-|'),\n      };\n      const e1 = hot('  --y---------z---#    ', values);\n      const expected = '--a-b---------c-#';\n\n      expectObservable(e1.pipe(concatAll())).toBe(expected);\n    });\n  });\n\n  it('should complete without emit if both sources are empty', () => {\n    testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold('  --|');\n      const e1subs = '   ^-!';\n      const e2 = cold('    ----|');\n      const e2subs = '   --^---!';\n      const expected = ' ------|';\n\n      const result = of(e1, e2).pipe(concatAll());\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should not complete if first source does not completes', () => {\n    testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold('  -');\n      const e1subs = '   ^';\n      const e2 = cold('  --|');\n      const e2subs: string[] = [];\n      const expected = ' -';\n\n      const result = of(e1, e2).pipe(concatAll());\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should not complete if second source does not completes', () => {\n    testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold('  --|');\n      const e1subs = '   ^-!';\n      const e2 = cold('  ---');\n      const e2subs = '   --^';\n      const expected = ' ---';\n\n      const result = of(e1, e2).pipe(concatAll());\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should not complete if both sources do not complete', () => {\n    testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold('  -');\n      const e1subs = '   ^';\n      const e2 = cold('  -');\n      const e2subs: string[] = [];\n      const expected = ' -';\n\n      const result = of(e1, e2).pipe(concatAll());\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should raise error when first source is empty, second source raises error', () => {\n    testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold('  --|');\n      const e1subs = '   ^-!';\n      const e2 = cold('    ----#');\n      const e2subs = '   --^---!';\n      const expected = ' ------#';\n\n      const result = of(e1, e2).pipe(concatAll());\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should raise error when first source raises error, second source is empty', () => {\n    testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold('  ---#');\n      const e1subs = '   ^--!';\n      const e2 = cold('  ----|');\n      const e2subs: string[] = [];\n      const expected = ' ---#';\n\n      const result = of(e1, e2).pipe(concatAll());\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should raise first error when both source raise error', () => {\n    testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold('  ---#');\n      const e1subs = '   ^--!';\n      const e2 = cold('  ------#');\n      const e2subs: string[] = [];\n      const expected = ' ---#';\n\n      const result = of(e1, e2).pipe(concatAll());\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should concat if first source emits once, second source is empty', () => {\n    testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold('  --a--|');\n      const e1subs = '   ^----!';\n      const e2 = cold('       --------|');\n      const e2subs = '   -----^-------!';\n      const expected = ' --a----------|';\n\n      const result = of(e1, e2).pipe(concatAll());\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should concat if first source is empty, second source emits once', () => {\n    testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold('  --|');\n      const e1subs = '   ^-!';\n      const e2 = cold('    --a--|');\n      const e2subs = '   --^----!';\n      const expected = ' ----a--|';\n\n      const result = of(e1, e2).pipe(concatAll());\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should emit element from first source, and should not complete if second source does not completes', () => {\n    testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold('  --a--|');\n      const e1subs = '   ^----!';\n      const e2 = cold('       -');\n      const e2subs = '   -----^';\n      const expected = ' --a---';\n\n      const result = of(e1, e2).pipe(concatAll());\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should not complete if first source does not complete', () => {\n    testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold('  -');\n      const e1subs = '   ^';\n      const e2 = cold('  --a--|');\n      const e2subs: string[] = [];\n      const expected = ' -';\n\n      const result = of(e1, e2).pipe(concatAll());\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should emit elements from each source when source emit once', () => {\n    testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold('  ---a|');\n      const e1subs = '   ^---!';\n      const e2 = cold('      -----b--|');\n      const e2subs = '   ----^-------!';\n      const expected = ' ---a-----b--|';\n\n      const result = of(e1, e2).pipe(concatAll());\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should unsubscribe to inner source if outer is unsubscribed early', () => {\n    testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold('  ---a-a--a|            ');\n      const e1subs = '   ^--------!            ';\n      const e2 = cold('           -----b-b--b-|');\n      const e2subs = '   ---------^-------!    ';\n      const unsub = '    -----------------!    ';\n      const expected = ' ---a-a--a-----b-b     ';\n\n      const result = of(e1, e2).pipe(concatAll());\n\n      expectObservable(result, unsub).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should not break unsubscription chains when result is unsubscribed explicitly', () => {\n    testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold('  ---a-a--a|            ');\n      const e1subs = '   ^--------!            ';\n      const e2 = cold('           -----b-b--b-|');\n      const e2subs = '   ---------^-------!    ';\n      const expected = ' ---a-a--a-----b-b-    ';\n      const unsub = '    -----------------!    ';\n\n      const result = of(e1, e2).pipe(\n        mergeMap((x) => of(x)),\n        concatAll(),\n        mergeMap((x) => of(x))\n      );\n\n      expectObservable(result, unsub).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should raise error from first source and does not emit from second source', () => {\n    testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold('  --#');\n      const e1subs = '   ^-!';\n      const e2 = cold('  ----a--|');\n      const e2subs: string[] = [];\n      const expected = ' --#';\n\n      const result = of(e1, e2).pipe(concatAll());\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should emit element from first source then raise error from second source', () => {\n    testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold('  --a--|');\n      const e1subs = '   ^----!';\n      const e2 = cold('       -------#');\n      const e2subs = '   -----^------!';\n      const expected = ' --a---------#';\n\n      const result = of(e1, e2).pipe(concatAll());\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should emit all elements from both hot observable sources if first source completes before second source starts emit', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  --a--b-|');\n      const e1subs = '  ^------!';\n      const e2 = hot('  --------x--y--|');\n      const e2subs = '  -------^------!';\n      const expected = '--a--b--x--y--|';\n\n      const result = of(e1, e2).pipe(concatAll());\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should emit elements from second source regardless of completion time when second source is cold observable', () => {\n    testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  --a--b--c---|');\n      const e1subs = '  ^-----------!';\n      const e2 = cold(' -x-y-z-|');\n      const e2subs = '  ------------^------!';\n      const expected = '--a--b--c----x-y-z-|';\n\n      const result = of(e1, e2).pipe(concatAll());\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should not emit collapsing element from second source', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  --a--b--c--|');\n      const e1subs = '  ^----------!';\n      const e2 = hot('  --------x--y--z--|');\n      const e2subs = '  -----------^-----!';\n      const expected = '--a--b--c--y--z--|';\n\n      const result = of(e1, e2).pipe(concatAll());\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should be able to work on a different scheduler', () => {\n    testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold('  ---a|');\n      const e1subs = '   ^---!';\n      const e2 = cold('      ---b--|');\n      const e2subs = '   ----^-----!';\n      const e3 = cold('            ---c--|');\n      const e3subs = '   ----------^-----!';\n      const expected = ' ---a---b-----c--|';\n\n      const result = scheduled([e1, e2, e3], testScheduler).pipe(concatAll());\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n      expectSubscriptions(e3.subscriptions).toBe(e3subs);\n    });\n  });\n\n  it('should concatAll a nested observable with a single inner observable', () => {\n    testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold('  ---a-|');\n      const e1subs = '   ^----!';\n      const expected = ' ---a-|';\n\n      const result = of(e1).pipe(concatAll());\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should concatAll a nested observable with a single inner observable, and a scheduler', () => {\n    testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold('  ---a-|');\n      const e1subs = '   ^----!';\n      const expected = ' ---a-|';\n\n      const result = scheduled([e1], testScheduler).pipe(concatAll());\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should stop listening to a synchronous observable when unsubscribed', () => {\n    const sideEffects: number[] = [];\n    const synchronousObservable = new Observable((subscriber) => {\n      // This will check to see if the subscriber was closed on each loop\n      // when the unsubscribe hits (from the `take`), it should be closed\n      for (let i = 0; !subscriber.closed && i < 10; i++) {\n        sideEffects.push(i);\n        subscriber.next(i);\n      }\n    });\n\n    of(synchronousObservable)\n      .pipe(concatAll(), take(3))\n      .subscribe(() => {\n        /* noop */\n      });\n\n    expect(sideEffects).to.deep.equal([0, 1, 2]);\n  });\n});\n"
  },
  {
    "path": "packages/rxjs/spec/operators/concatMap-spec.ts",
    "content": "import { expect } from 'chai';\nimport { of, from, Observable, defer } from 'rxjs';\nimport { concatMap, mergeMap, map, take, finalize, delay } from 'rxjs/operators';\nimport { TestScheduler } from 'rxjs/testing';\nimport { observableMatcher } from '../helpers/observableMatcher';\n\n/** @test {concatMap} */\ndescribe('Observable.prototype.concatMap', () => {\n  let testScheduler: TestScheduler;\n\n  beforeEach(() => {\n    testScheduler = new TestScheduler(observableMatcher);\n  });\n\n  it('should map-and-flatten each item to an Observable', () => {\n    testScheduler.run(({ hot, cold, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('   --1-----3--5-------|');\n      const e1subs = '   ^------------------!';\n      const e2 = cold('  x-x-x|              ', { x: 10 });\n      const expected = ' --x-x-x-y-y-yz-z-z-|';\n      const values = { x: 10, y: 30, z: 50 };\n\n      const result = e1.pipe(concatMap((x) => e2.pipe(map((i) => i * parseInt(x)))));\n\n      expectObservable(result).toBe(expected, values);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should concatenate many regular interval inners', () => {\n    testScheduler.run(({ hot, cold, expectObservable, expectSubscriptions }) => {\n      const a = cold('  --a-a-a-(a|)                            ');\n      const asubs = '   ^-------!                               ';\n      const b = cold('          ----b--b--(b|)                  ');\n      const bsubs = '   --------^---------!                     ';\n      const c = cold('                           -c-c-(c|)      ');\n      const csubs = '   -------------------------^----!         ';\n      const d = cold('                                ------(d|)');\n      const dsubs = '   ------------------------------^-----!   ';\n      const e1 = hot('  a---b--------------------c-d----|       ');\n      const e1subs = '  ^-------------------------------!       ';\n      const expected = '--a-a-a-a---b--b--b-------c-c-c-----(d|)';\n\n      const observableLookup = { a: a, b: b, c: c, d: d };\n      const source = e1.pipe(concatMap((value) => observableLookup[value as keyof typeof observableLookup]));\n\n      expectObservable(source).toBe(expected);\n      expectSubscriptions(a.subscriptions).toBe(asubs);\n      expectSubscriptions(b.subscriptions).toBe(bsubs);\n      expectSubscriptions(c.subscriptions).toBe(csubs);\n      expectSubscriptions(d.subscriptions).toBe(dsubs);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should concatMap many outer values to many inner values', () => {\n    testScheduler.run(({ hot, cold, expectObservable, expectSubscriptions }) => {\n      const values = { i: 'foo', j: 'bar', k: 'baz', l: 'qux' };\n      const e1 = hot('    -a---b---c---d---|                        ');\n      const e1subs = '    ^----------------!                        ';\n      const inner = cold(' --i-j-k-l-|                              ', values);\n      const innersubs = [\n        '                 -^---------!                              ',\n        '                 -----------^---------!                    ',\n        '                 ---------------------^---------!          ',\n        '                 -------------------------------^---------!',\n      ];\n      const expected = '  ---i-j-k-l---i-j-k-l---i-j-k-l---i-j-k-l-|';\n\n      const result = e1.pipe(concatMap((value) => inner));\n\n      expectObservable(result).toBe(expected, values);\n      expectSubscriptions(inner.subscriptions).toBe(innersubs);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should handle an empty source', () => {\n    testScheduler.run(({ hot, cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold('   |');\n      const e1subs = '    (^!)';\n      const inner = cold('-1-2-3|');\n      const innersubs: string[] = [];\n      const expected = '  |';\n\n      const result = e1.pipe(concatMap(() => inner));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(inner.subscriptions).toBe(innersubs);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should handle a never source', () => {\n    testScheduler.run(({ hot, cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold('   -');\n      const e1subs = '    ^';\n      const inner = cold('-1-2-3|');\n      const innersubs: string[] = [];\n      const expected = '  -';\n\n      const result = e1.pipe(\n        concatMap(() => {\n          return inner;\n        })\n      );\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(inner.subscriptions).toBe(innersubs);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should error immediately if given a just-throw source', () => {\n    testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold('   #');\n      const e1subs = '    (^!)';\n      const inner = cold('-1-2-3|');\n      const innersubs: string[] = [];\n      const expected = '  #';\n\n      const result = e1.pipe(\n        concatMap(() => {\n          return inner;\n        })\n      );\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(inner.subscriptions).toBe(innersubs);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should return a silenced version of the source if the mapped inner is empty', () => {\n    testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold('   --a-b--c-| ');\n      const e1subs = '    ^--------! ';\n      const inner = cold('  |');\n      // prettier-ignore\n      const innersubs = [\n        '                 --(^!)     ',\n        '                 ----(^!)   ',\n        '                 -------(^!)',\n      ];\n      const expected = '  ---------| ';\n\n      const result = e1.pipe(\n        concatMap(() => {\n          return inner;\n        })\n      );\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(inner.subscriptions).toBe(innersubs);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should return a never if the mapped inner is never', () => {\n    testScheduler.run(({ hot, cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold('  --a-b--c-|');\n      const e1subs = '   ^--------!';\n      const inner = cold(' -');\n      const innersubs = '--^-------';\n      const expected = ' ----------';\n\n      const result = e1.pipe(\n        concatMap(() => {\n          return inner;\n        })\n      );\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(inner.subscriptions).toBe(innersubs);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should propagate errors if the mapped inner is a just-throw Observable', () => {\n    testScheduler.run(({ hot, cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold('  --a-b--c-|');\n      const e1subs = '   ^-!       ';\n      const inner = cold(' #');\n      const innersubs = '--(^!)    ';\n      const expected = ' --#       ';\n\n      const result = e1.pipe(\n        concatMap(() => {\n          return inner;\n        })\n      );\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(inner.subscriptions).toBe(innersubs);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should concatMap many outer to many inner, complete late', () => {\n    testScheduler.run(({ hot, cold, expectObservable, expectSubscriptions }) => {\n      const values = { i: 'foo', j: 'bar', k: 'baz', l: 'qux' };\n      const e1 = hot('    -a---b---c---d----------------------------------|');\n      const e1subs = '    ^-----------------------------------------------!';\n      const inner = cold(' --i-j-k-l-|                                     ', values);\n      const innersubs = [\n        '                 -^---------!                                     ',\n        '                 -----------^---------!                           ',\n        '                 ---------------------^---------!                 ',\n        '                 -------------------------------^---------!       ',\n      ];\n      const expected = '  ---i-j-k-l---i-j-k-l---i-j-k-l---i-j-k-l--------|';\n\n      const result = e1.pipe(concatMap((value) => inner));\n\n      expectObservable(result).toBe(expected, values);\n      expectSubscriptions(inner.subscriptions).toBe(innersubs);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should concatMap many outer to many inner, outer never completes', () => {\n    testScheduler.run(({ hot, cold, expectObservable, expectSubscriptions }) => {\n      const values = { i: 'foo', j: 'bar', k: 'baz', l: 'qux' };\n      const e1 = hot('    -a---b---c---d-----------------------------------');\n      const e1subs = '    ^------------------------------------------------';\n      const inner = cold(' --i-j-k-l-|                                     ', values);\n      const innersubs = [\n        '                 -^---------!                                     ',\n        '                 -----------^---------!                           ',\n        '                 ---------------------^---------!                 ',\n        '                 -------------------------------^---------!       ',\n      ];\n      const expected = '  ---i-j-k-l---i-j-k-l---i-j-k-l---i-j-k-l---------';\n\n      const result = e1.pipe(concatMap((value) => inner));\n\n      expectObservable(result).toBe(expected, values);\n      expectSubscriptions(inner.subscriptions).toBe(innersubs);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should concatMap many outer to many inner, inner never completes', () => {\n    testScheduler.run(({ hot, cold, expectObservable, expectSubscriptions }) => {\n      const values = { i: 'foo', j: 'bar', k: 'baz', l: 'qux' };\n      const e1 = hot('    -a---b---c---d---|');\n      const e1subs = '    ^----------------!';\n      const inner = cold(' --i-j-k-l-       ', values);\n      const innersubs = ' -^----------------';\n      const expected = '  ---i-j-k-l--------';\n\n      const result = e1.pipe(concatMap((value) => inner));\n\n      expectObservable(result).toBe(expected, values);\n      expectSubscriptions(inner.subscriptions).toBe(innersubs);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should concatMap many outer to many inner, and inner throws', () => {\n    testScheduler.run(({ hot, cold, expectObservable, expectSubscriptions }) => {\n      const values = { i: 'foo', j: 'bar', k: 'baz', l: 'qux' };\n      const e1 = hot('    -a---b---c---d---|');\n      const e1subs = '    ^----------!      ';\n      const inner = cold(' --i-j-k-l-#      ', values);\n      const innersubs = ' -^---------!      ';\n      const expected = '  ---i-j-k-l-#      ';\n\n      const result = e1.pipe(concatMap(() => inner));\n\n      expectObservable(result).toBe(expected, values);\n      expectSubscriptions(inner.subscriptions).toBe(innersubs);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should concatMap many outer to many inner, and outer throws', () => {\n    testScheduler.run(({ hot, cold, expectObservable, expectSubscriptions }) => {\n      const values = { i: 'foo', j: 'bar', k: 'baz', l: 'qux' };\n      const e1 = hot('    -a---b---c---d---#');\n      const e1subs = '    ^----------------!';\n      const inner = cold(' --i-j-k-l-|      ', values);\n      // prettier-ignore\n      const innersubs = [\n        '                 -^---------!      ',\n        '                 -----------^-----!',\n      ];\n      const expected = '  ---i-j-k-l---i-j-#';\n\n      const result = e1.pipe(concatMap((value) => inner));\n\n      expectObservable(result).toBe(expected, values);\n      expectSubscriptions(inner.subscriptions).toBe(innersubs);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should concatMap many outer to many inner, both inner and outer throw', () => {\n    testScheduler.run(({ hot, cold, expectObservable, expectSubscriptions }) => {\n      const values = { i: 'foo', j: 'bar', k: 'baz', l: 'qux' };\n      const e1 = hot('    -a---b---c---d---#');\n      const e1subs = '    ^----------!      ';\n      const inner = cold(' --i-j-k-l-#      ', values);\n      const innersubs = ' -^---------!      ';\n      const expected = '  ---i-j-k-l-#      ';\n\n      const result = e1.pipe(concatMap((value) => inner));\n\n      expectObservable(result).toBe(expected, values);\n      expectSubscriptions(inner.subscriptions).toBe(innersubs);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should concatMap many complex, where all inners are finite', () => {\n    testScheduler.run(({ hot, cold, expectObservable, expectSubscriptions }) => {\n      const a = cold('   -#                                                          ');\n      const asubs: string[] = [];\n      const b = cold('     -#                                                        ');\n      const bsubs: string[] = [];\n      const c = cold('          -2--3--4--5----6-|                                   ');\n      const csubs = '         --^----------------!                                   ';\n      const d = cold('                           ----2--3|                           ');\n      const dsubs = '         -------------------^-------!                           ';\n      const e = cold('                                   -1------2--3-4-5---|        ');\n      const esubs = '         ---------------------------^------------------!        ';\n      const f = cold('                                                      --|      ');\n      const fsubs = '         ----------------------------------------------^-!      ';\n      const g = cold('                                                        ---1-2|');\n      const gsubs = '         ------------------------------------------------^-----!';\n      const e1 = hot('  -a-b--^-c-----d------e----------------f-----g|               ');\n      const e1subs = '        ^--------------------------------------!               ';\n      const expected = '      ---2--3--4--5----6-----2--3-1------2--3-4-5--------1-2|';\n      const observableLookup = { a: a, b: b, c: c, d: d, e: e, f: f, g: g };\n\n      const result = e1.pipe(concatMap((value) => observableLookup[value as keyof typeof observableLookup]));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(a.subscriptions).toBe(asubs);\n      expectSubscriptions(b.subscriptions).toBe(bsubs);\n      expectSubscriptions(c.subscriptions).toBe(csubs);\n      expectSubscriptions(d.subscriptions).toBe(dsubs);\n      expectSubscriptions(e.subscriptions).toBe(esubs);\n      expectSubscriptions(f.subscriptions).toBe(fsubs);\n      expectSubscriptions(g.subscriptions).toBe(gsubs);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should concatMap many complex, all inners finite except one', () => {\n    testScheduler.run(({ hot, cold, expectObservable, expectSubscriptions }) => {\n      const a = cold('   -#                                                          ');\n      const asubs: string[] = [];\n      const b = cold('     -#                                                        ');\n      const bsubs: string[] = [];\n      const c = cold('          -2--3--4--5----6-|                                   ');\n      const csubs = '         --^----------------!                                   ';\n      const d = cold('                           ----2--3-                           ');\n      const dsubs = '         -------------------^-----------------------------------';\n      const e = cold('                                   -1------2--3-4-5---|        ');\n      const esubs: string[] = [];\n      const f = cold('                                                      --|      ');\n      const fsubs: string[] = [];\n      const g = cold('                                                        ---1-2|');\n      const gsubs: string[] = [];\n      const e1 = hot('  -a-b--^-c-----d------e----------------f-----g|               ');\n      const e1subs = '        ^--------------------------------------!               ';\n      const expected = '      ---2--3--4--5----6-----2--3----------------------------';\n      const observableLookup = { a: a, b: b, c: c, d: d, e: e, f: f, g: g };\n\n      const result = e1.pipe(concatMap((value) => observableLookup[value as keyof typeof observableLookup]));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(a.subscriptions).toBe(asubs);\n      expectSubscriptions(b.subscriptions).toBe(bsubs);\n      expectSubscriptions(c.subscriptions).toBe(csubs);\n      expectSubscriptions(d.subscriptions).toBe(dsubs);\n      expectSubscriptions(e.subscriptions).toBe(esubs);\n      expectSubscriptions(f.subscriptions).toBe(fsubs);\n      expectSubscriptions(g.subscriptions).toBe(gsubs);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should concatMap many complex, inners finite, outer does not complete', () => {\n    testScheduler.run(({ hot, cold, expectObservable, expectSubscriptions }) => {\n      const a = cold('   -#                                                          ');\n      const asubs: string[] = [];\n      const b = cold('     -#                                                        ');\n      const bsubs: string[] = [];\n      const c = cold('          -2--3--4--5----6-|                                   ');\n      const csubs = '         --^----------------!                                   ';\n      const d = cold('                           ----2--3|                           ');\n      const dsubs = '         -------------------^-------!                           ';\n      const e = cold('                                   -1------2--3-4-5---|        ');\n      const esubs = '         ---------------------------^------------------!        ';\n      const f = cold('                                                      --|      ');\n      const fsubs = '         ----------------------------------------------^-!      ';\n      const g = cold('                                                        ---1-2|');\n      const gsubs = '         ------------------------------------------------^-----!';\n      const e1 = hot('  -a-b--^-c-----d------e----------------f-----g---             ');\n      const e1subs = '        ^                                                      ';\n      const expected = '      ---2--3--4--5----6-----2--3-1------2--3-4-5--------1-2-';\n      const observableLookup = { a: a, b: b, c: c, d: d, e: e, f: f, g: g };\n\n      const result = e1.pipe(concatMap((value) => observableLookup[value as keyof typeof observableLookup]));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(a.subscriptions).toBe(asubs);\n      expectSubscriptions(b.subscriptions).toBe(bsubs);\n      expectSubscriptions(c.subscriptions).toBe(csubs);\n      expectSubscriptions(d.subscriptions).toBe(dsubs);\n      expectSubscriptions(e.subscriptions).toBe(esubs);\n      expectSubscriptions(f.subscriptions).toBe(fsubs);\n      expectSubscriptions(g.subscriptions).toBe(gsubs);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should concatMap many complex, all inners finite, and outer throws', () => {\n    testScheduler.run(({ hot, cold, expectObservable, expectSubscriptions }) => {\n      const a = cold('   -#                                                          ');\n      const asubs: string[] = [];\n      const b = cold('     -#                                                        ');\n      const bsubs: string[] = [];\n      const c = cold('          -2--3--4--5----6-|                                   ');\n      const csubs = '         --^----------------!                                   ';\n      const d = cold('                           ----2--3|                           ');\n      const dsubs = '         -------------------^-------!                           ';\n      const e = cold('                                   -1------2--3-4-5---|        ');\n      const esubs = '         ---------------------------^-----------!               ';\n      const f = cold('                                                      --|      ');\n      const fsubs: string[] = [];\n      const g = cold('                                                        ---1-2|');\n      const gsubs: string[] = [];\n      const e1 = hot('  -a-b--^-c-----d------e----------------f-----g#               ');\n      const e1subs = '        ^--------------------------------------!               ';\n      const expected = '      ---2--3--4--5----6-----2--3-1------2--3#               ';\n      const observableLookup = { a: a, b: b, c: c, d: d, e: e, f: f, g: g };\n\n      const result = e1.pipe(concatMap((value) => observableLookup[value as keyof typeof observableLookup]));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(a.subscriptions).toBe(asubs);\n      expectSubscriptions(b.subscriptions).toBe(bsubs);\n      expectSubscriptions(c.subscriptions).toBe(csubs);\n      expectSubscriptions(d.subscriptions).toBe(dsubs);\n      expectSubscriptions(e.subscriptions).toBe(esubs);\n      expectSubscriptions(f.subscriptions).toBe(fsubs);\n      expectSubscriptions(g.subscriptions).toBe(gsubs);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should concatMap many complex, all inners complete except one throws', () => {\n    testScheduler.run(({ hot, cold, expectObservable, expectSubscriptions }) => {\n      const a = cold('   -#                                                          ');\n      const asubs: string[] = [];\n      const b = cold('     -#                                                        ');\n      const bsubs: string[] = [];\n      const c = cold('          -2--3--4--5----6-#                                   ');\n      const csubs = '         --^----------------!                                   ';\n      const d = cold('                           ----2--3|                           ');\n      const dsubs: string[] = [];\n      const e = cold('                                   -1------2--3-4-5---|        ');\n      const esubs: string[] = [];\n      const f = cold('                                                      --|      ');\n      const fsubs: string[] = [];\n      const g = cold('                                                        ---1-2|');\n      const gsubs: string[] = [];\n      const e1 = hot('  -a-b--^-c-----d------e----------------f-----g|               ');\n      const e1subs = '        ^------------------!                                   ';\n      const expected = '      ---2--3--4--5----6-#                                   ';\n      const observableLookup = { a: a, b: b, c: c, d: d, e: e, f: f, g: g };\n\n      const result = e1.pipe(concatMap((value) => observableLookup[value as keyof typeof observableLookup]));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(a.subscriptions).toBe(asubs);\n      expectSubscriptions(b.subscriptions).toBe(bsubs);\n      expectSubscriptions(c.subscriptions).toBe(csubs);\n      expectSubscriptions(d.subscriptions).toBe(dsubs);\n      expectSubscriptions(e.subscriptions).toBe(esubs);\n      expectSubscriptions(f.subscriptions).toBe(fsubs);\n      expectSubscriptions(g.subscriptions).toBe(gsubs);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should concatMap many complex, all inners finite, outer is unsubscribed early', () => {\n    testScheduler.run(({ hot, cold, expectObservable, expectSubscriptions }) => {\n      const a = cold('   -#                                                          ');\n      const asubs: string[] = [];\n      const b = cold('     -#                                                        ');\n      const bsubs: string[] = [];\n      const c = cold('          -2--3--4--5----6-|                                   ');\n      const csubs = '         --^----------------!                                   ';\n      const d = cold('                           ----2--3|                           ');\n      const dsubs = '         -------------------^-------!                           ';\n      const e = cold('                                   -1------2--3-4-5---|        ');\n      const esubs = '         ---------------------------^--!                        ';\n      const f = cold('                                                      --|      ');\n      const fsubs: string[] = [];\n      const g = cold('                                                        ---1-2|');\n      const gsubs: string[] = [];\n      const e1 = hot('  -a-b--^-c-----d------e----------------f-----g|               ');\n      const e1subs = '        ^-----------------------------!                        ';\n      const unsub = '         ^-----------------------------!                        ';\n      const expected = '      ---2--3--4--5----6-----2--3-1--                        ';\n      const observableLookup: Record<string, Observable<string>> = {\n        a: a,\n        b: b,\n        c: c,\n        d: d,\n        e: e,\n        f: f,\n        g: g,\n      };\n\n      const result = e1.pipe(concatMap((value) => observableLookup[value]));\n\n      expectObservable(result, unsub).toBe(expected);\n      expectSubscriptions(a.subscriptions).toBe(asubs);\n      expectSubscriptions(b.subscriptions).toBe(bsubs);\n      expectSubscriptions(c.subscriptions).toBe(csubs);\n      expectSubscriptions(d.subscriptions).toBe(dsubs);\n      expectSubscriptions(e.subscriptions).toBe(esubs);\n      expectSubscriptions(f.subscriptions).toBe(fsubs);\n      expectSubscriptions(g.subscriptions).toBe(gsubs);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should not break unsubscription chains when result is unsubscribed explicitly', () => {\n    testScheduler.run(({ hot, cold, expectObservable, expectSubscriptions }) => {\n      const a = cold('   -#                                                          ');\n      const asubs: string[] = [];\n      const b = cold('   -#                                                          ');\n      const bsubs: string[] = [];\n      const c = cold('          -2--3--4--5----6-|                                   ');\n      const csubs = '         --^----------------!                                   ';\n      const d = cold('                           ----2--3|                           ');\n      const dsubs = '         -------------------^-------!                           ';\n      const e = cold('                                   -1------2--3-4-5---|        ');\n      const esubs = '         ---------------------------^--!                        ';\n      const f = cold('                                                      --|      ');\n      const fsubs: string[] = [];\n      const g = cold('                                                        ---1-2|');\n      const gsubs: string[] = [];\n      const e1 = hot('  -a-b--^-c-----d------e----------------f-----g|               ');\n      const e1subs = '        ^-----------------------------!                        ';\n      const unsub = '         ^-----------------------------!                        ';\n      const expected = '      ---2--3--4--5----6-----2--3-1--                        ';\n      const observableLookup: Record<string, Observable<string>> = {\n        a: a,\n        b: b,\n        c: c,\n        d: d,\n        e: e,\n        f: f,\n        g: g,\n      };\n\n      const result = e1.pipe(\n        mergeMap((x) => of(x)),\n        concatMap((value) => observableLookup[value]),\n        mergeMap((x) => of(x))\n      );\n\n      expectObservable(result, unsub).toBe(expected);\n      expectSubscriptions(a.subscriptions).toBe(asubs);\n      expectSubscriptions(b.subscriptions).toBe(bsubs);\n      expectSubscriptions(c.subscriptions).toBe(csubs);\n      expectSubscriptions(d.subscriptions).toBe(dsubs);\n      expectSubscriptions(e.subscriptions).toBe(esubs);\n      expectSubscriptions(f.subscriptions).toBe(fsubs);\n      expectSubscriptions(g.subscriptions).toBe(gsubs);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should concatMap many complex, all inners finite, project throws', () => {\n    testScheduler.run(({ hot, cold, expectObservable, expectSubscriptions }) => {\n      const a = cold('   -#                                                          ');\n      const asubs: string[] = [];\n      const b = cold('     -#                                                        ');\n      const bsubs: string[] = [];\n      const c = cold('          -2--3--4--5----6-|                                   ');\n      const csubs = '         --^----------------!                                   ';\n      const d = cold('                           ----2--3|                           ');\n      const dsubs = '         -------------------^-------!                           ';\n      const e = cold('                                   -1------2--3-4-5---|        ');\n      const esubs: string[] = [];\n      const f = cold('                                                      --|      ');\n      const fsubs: string[] = [];\n      const g = cold('                                                        ---1-2|');\n      const gsubs: string[] = [];\n      const e1 = hot('  -a-b--^-c-----d------e----------------f-----g|               ');\n      const e1subs = '        ^--------------------------!                           ';\n      const expected = '      ---2--3--4--5----6-----2--3#                           ';\n      const observableLookup: Record<string, Observable<string>> = {\n        a: a,\n        b: b,\n        c: c,\n        d: d,\n        e: e,\n        f: f,\n        g: g,\n      };\n\n      const result = e1.pipe(\n        concatMap((value) => {\n          if (value === 'e') {\n            throw 'error';\n          }\n          return observableLookup[value];\n        })\n      );\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(a.subscriptions).toBe(asubs);\n      expectSubscriptions(b.subscriptions).toBe(bsubs);\n      expectSubscriptions(c.subscriptions).toBe(csubs);\n      expectSubscriptions(d.subscriptions).toBe(dsubs);\n      expectSubscriptions(e.subscriptions).toBe(esubs);\n      expectSubscriptions(f.subscriptions).toBe(fsubs);\n      expectSubscriptions(g.subscriptions).toBe(gsubs);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should finalize before moving to the next observable', () => {\n    const results: any[] = [];\n\n    const create = (n: number) =>\n      defer(() => {\n        results.push(`init ${n}`);\n        return of(`next ${n}`).pipe(\n          delay(100, testScheduler),\n          finalize(() => {\n            results.push(`finalized ${n}`);\n          })\n        );\n      });\n\n    of(1, 2, 3)\n      .pipe(concatMap((n) => create(n)))\n      .subscribe({\n        next: (value) => results.push(value),\n      });\n\n    testScheduler.flush();\n\n    expect(results).to.deep.equal([\n      'init 1',\n      'next 1',\n      'finalized 1',\n      'init 2',\n      'next 2',\n      'finalized 2',\n      'init 3',\n      'next 3',\n      'finalized 3',\n    ]);\n  });\n\n  function arrayRepeat(value: string, times: number) {\n    const results = [];\n    for (let i = 0; i < times; i++) {\n      results.push(value);\n    }\n    return results;\n  }\n\n  it('should concatMap many outer to an array for each value', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  2-----4--------3--------2-------|');\n      const e1subs = '  ^-------------------------------!';\n      const expected = '(22)--(4444)---(333)----(22)----|';\n\n      const result = e1.pipe(concatMap((value) => arrayRepeat(value, +value)));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should concatMap many outer to inner arrays, outer unsubscribed early', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  2-----4--------3--------2-------|');\n      const e1subs = '  ^------------!                   ';\n      const unsub = '   ^------------!                   ';\n      const expected = '(22)--(4444)--                   ';\n\n      const result = e1.pipe(concatMap((value) => arrayRepeat(value, +value)));\n\n      expectObservable(result, unsub).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should concatMap many outer to inner arrays, project throws', () => {\n    testScheduler.run(({ hot, cold, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  2-----4--------3--------2-------|');\n      const e1subs = '  ^--------------!                 ';\n      const expected = '(22)--(4444)---#                 ';\n\n      let invoked = 0;\n      const result = e1.pipe(\n        concatMap((value) => {\n          invoked++;\n          if (invoked === 3) {\n            throw 'error';\n          }\n          return arrayRepeat(value, +value);\n        })\n      );\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should map values to constant resolved promises and concatenate', (done) => {\n    const source = from([4, 3, 2, 1]);\n    const project = (value: number) => from(Promise.resolve(42));\n\n    const results: number[] = [];\n    source.pipe(concatMap(project)).subscribe({\n      next: (x) => {\n        results.push(x);\n      },\n      error: (err) => {\n        done(new Error('Subscriber error handler not supposed to be called.'));\n      },\n      complete: () => {\n        expect(results).to.deep.equal([42, 42, 42, 42]);\n        done();\n      },\n    });\n  });\n\n  it('should map values to constant rejected promises and concatenate', (done) => {\n    const source = from([4, 3, 2, 1]);\n    const project = (value: any) => from(Promise.reject(42));\n\n    source.pipe(concatMap(project)).subscribe({\n      next: (x) => {\n        done(new Error('Subscriber next handler not supposed to be called.'));\n      },\n      error: (err) => {\n        expect(err).to.deep.equal(42);\n        done();\n      },\n      complete: () => {\n        done(new Error('Subscriber complete handler not supposed to be called.'));\n      },\n    });\n  });\n\n  it('should map values to resolved promises and concatenate', (done) => {\n    const source = from([4, 3, 2, 1]);\n    const project = (value: number, index: number) => from(Promise.resolve(value + index));\n\n    const results: number[] = [];\n    source.pipe(concatMap(project)).subscribe({\n      next: (x) => {\n        results.push(x);\n      },\n      error: (err) => {\n        done(new Error('Subscriber error handler not supposed to be called.'));\n      },\n      complete: () => {\n        expect(results).to.deep.equal([4, 4, 4, 4]);\n        done();\n      },\n    });\n  });\n\n  it('should map values to rejected promises and concatenate', (done) => {\n    const source = from([4, 3, 2, 1]);\n    const project = (value: number, index: number) => from(Promise.reject('' + value + '-' + index));\n\n    source.pipe(concatMap(project)).subscribe({\n      next: (x) => {\n        done(new Error('Subscriber next handler not supposed to be called.'));\n      },\n      error: (err) => {\n        expect(err).to.deep.equal('4-0');\n        done();\n      },\n      complete: () => {\n        done(new Error('Subscriber complete handler not supposed to be called.'));\n      },\n    });\n  });\n\n  it('should stop listening to a synchronous observable when unsubscribed', () => {\n    const sideEffects: number[] = [];\n    const synchronousObservable = new Observable((subscriber) => {\n      // This will check to see if the subscriber was closed on each loop\n      // when the unsubscribe hits (from the `take`), it should be closed\n      for (let i = 0; !subscriber.closed && i < 10; i++) {\n        sideEffects.push(i);\n        subscriber.next(i);\n      }\n    });\n\n    synchronousObservable\n      .pipe(\n        concatMap((value) => of(value)),\n        take(3)\n      )\n      .subscribe(() => {\n        /* noop */\n      });\n\n    expect(sideEffects).to.deep.equal([0, 1, 2]);\n  });\n});\n"
  },
  {
    "path": "packages/rxjs/spec/operators/concatMapTo-spec.ts",
    "content": "import { expect } from 'chai';\nimport { of, from, Observable } from 'rxjs';\nimport { concatMapTo, mergeMap, take } from 'rxjs/operators';\nimport { TestScheduler } from 'rxjs/testing';\nimport { observableMatcher } from '../helpers/observableMatcher';\n\n/** @test {concatMapTo} */\ndescribe('concatMapTo', () => {\n  let testScheduler: TestScheduler;\n\n  beforeEach(() => {\n    testScheduler = new TestScheduler(observableMatcher);\n  });\n\n  it('should map-and-flatten each item to an Observable', () => {\n    testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  --1-----3--5-------|');\n      const e1subs = '  ^------------------!';\n      const e2 = cold(' x-x-x|              ', { x: 10 });\n      const expected = '--x-x-x-x-x-xx-x-x-|';\n      const values = { x: 10 };\n\n      const result = e1.pipe(concatMapTo(e2));\n\n      expectObservable(result).toBe(expected, values);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should concatMapTo many outer values to many inner values', () => {\n    testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => {\n      const values = { i: 'foo', j: 'bar', k: 'baz', l: 'qux' };\n      const e1 = hot('    -a---b---c---d---|                        ');\n      const e1subs = '    ^----------------!                        ';\n      const inner = cold('--i-j-k-l-|                               ', values);\n      const innerSubs = [\n        '                 -^---------!                              ',\n        '                 -----------^---------!                    ',\n        '                 ---------------------^---------!          ',\n        '                 -------------------------------^---------!',\n      ];\n      const expected = '  ---i-j-k-l---i-j-k-l---i-j-k-l---i-j-k-l-|';\n\n      const result = e1.pipe(concatMapTo(inner));\n\n      expectObservable(result).toBe(expected, values);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(inner.subscriptions).toBe(innerSubs);\n    });\n  });\n\n  it('should handle an empty source', () => {\n    testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' |');\n      const e1subs = '  (^!)';\n      const inner = cold('-1-2-3|');\n      const innerSubs: string[] = [];\n      const expected = '|';\n\n      const result = e1.pipe(concatMapTo(inner));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(inner.subscriptions).toBe(innerSubs);\n    });\n  });\n\n  it('should handle a never source', () => {\n    testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' -');\n      const e1subs = '  ^';\n      const inner = cold('-1-2-3|');\n      const innerSubs: string[] = [];\n      const expected = '-';\n\n      const result = e1.pipe(concatMapTo(inner));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(inner.subscriptions).toBe(innerSubs);\n    });\n  });\n\n  it('should error immediately if given a just-throw source', () => {\n    testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' #');\n      const e1subs = '  (^!)';\n      const inner = cold('-1-2-3|');\n      const innerSubs: string[] = [];\n      const expected = '#';\n\n      const result = e1.pipe(concatMapTo(inner));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(inner.subscriptions).toBe(innerSubs);\n    });\n  });\n\n  it('should return a silenced version of the source if the mapped inner is empty', () => {\n    testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold('   --a-b--c-|');\n      const e1subs = '    ^--------!';\n      const inner = cold('|');\n      // prettier-ignore\n      const innerSubs = [\n        '                 --(^!)     ',\n        '                 ----(^!)   ',\n        '                 -------(^!)',\n      ];\n      const expected = '  ---------|';\n\n      const result = e1.pipe(concatMapTo(inner));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(inner.subscriptions).toBe(innerSubs);\n    });\n  });\n\n  it('should return a never if the mapped inner is never', () => {\n    testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold('   --a-b--c-|');\n      const e1subs = '    ^--------!';\n      const inner = cold('-');\n      const innerSubs = ' --^       ';\n      const expected = '  ----------';\n\n      const result = e1.pipe(concatMapTo(inner));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(inner.subscriptions).toBe(innerSubs);\n    });\n  });\n\n  it('should propagate errors if the mapped inner is a just-throw Observable', () => {\n    testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold('   --a-b--c-|');\n      const e1subs = '    ^-!       ';\n      const inner = cold('#');\n      const innerSubs = ' --(^!)    ';\n      const expected = '  --#';\n\n      const result = e1.pipe(concatMapTo(inner));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(inner.subscriptions).toBe(innerSubs);\n    });\n  });\n\n  it('should concatMapTo many outer to many inner, complete late', () => {\n    testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => {\n      const values = { i: 'foo', j: 'bar', k: 'baz', l: 'qux' };\n      const e1 = hot('    -a---b---c---d----------------------------------|');\n      const e1subs = '    ^-----------------------------------------------!';\n      const inner = cold('--i-j-k-l-|                                      ', values);\n      const innerSubs = [\n        '                 -^---------!                                     ',\n        '                 -----------^---------!                           ',\n        '                 ---------------------^---------!                 ',\n        '                 -------------------------------^---------!       ',\n      ];\n      const expected = '  ---i-j-k-l---i-j-k-l---i-j-k-l---i-j-k-l--------|';\n\n      const result = e1.pipe(concatMapTo(inner));\n\n      expectObservable(result).toBe(expected, values);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(inner.subscriptions).toBe(innerSubs);\n    });\n  });\n\n  it('should concatMapTo many outer to many inner, outer never completes', () => {\n    testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => {\n      const values = { i: 'foo', j: 'bar', k: 'baz', l: 'qux' };\n      const e1 = hot('    -a---b---c---d-----------------------------------');\n      const e1subs = '    ^------------------------------------------------';\n      const inner = cold('--i-j-k-l-|                                      ', values);\n      const innerSubs = [\n        '                 -^---------!                                     ',\n        '                 -----------^---------!                           ',\n        '                 ---------------------^---------!                 ',\n        '                 -------------------------------^---------!       ',\n      ];\n      const expected = '  ---i-j-k-l---i-j-k-l---i-j-k-l---i-j-k-l---------';\n\n      const result = e1.pipe(concatMapTo(inner));\n\n      expectObservable(result).toBe(expected, values);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(inner.subscriptions).toBe(innerSubs);\n    });\n  });\n\n  it('should not break unsubscription chains when result is unsubscribed explicitly', () => {\n    testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => {\n      const values = { i: 'foo', j: 'bar', k: 'baz', l: 'qux' };\n      const e1 = hot('    -a---b---c---d---| ');\n      const e1subs = '    ^----------------! ';\n      const inner = cold('--i-j-k-l-|        ', values);\n      // prettier-ignore\n      const innerSubs = [\n        '                 -^---------!       ',\n        '                 -----------^------!',\n      ];\n      const expected = '  ---i-j-k-l---i-j-k-';\n      const unsub = '     ------------------!';\n\n      const result = e1.pipe(\n        mergeMap((x) => of(x)),\n        concatMapTo(inner),\n        mergeMap((x) => of(x))\n      );\n\n      expectObservable(result, unsub).toBe(expected, values);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(inner.subscriptions).toBe(innerSubs);\n    });\n  });\n\n  it('should concatMapTo many outer to many inner, inner never completes', () => {\n    testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => {\n      const values = { i: 'foo', j: 'bar', k: 'baz', l: 'qux' };\n      const e1 = hot('    -a---b---c---d---|');\n      const e1subs = '    ^----------------!';\n      const inner = cold('--i-j-k-l-        ', values);\n      const innerSubs = ' -^                ';\n      const expected = '  ---i-j-k-l--------';\n\n      const result = e1.pipe(concatMapTo(inner));\n\n      expectObservable(result).toBe(expected, values);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(inner.subscriptions).toBe(innerSubs);\n    });\n  });\n\n  it('should concatMapTo many outer to many inner, and inner throws', () => {\n    testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => {\n      const values = { i: 'foo', j: 'bar', k: 'baz', l: 'qux' };\n      const e1 = hot('    -a---b---c---d---|');\n      const e1subs = '    ^----------!      ';\n      const inner = cold('--i-j-k-l-#       ', values);\n      const innerSubs = ' -^---------!      ';\n      const expected = '  ---i-j-k-l-#      ';\n\n      const result = e1.pipe(concatMapTo(inner));\n\n      expectObservable(result).toBe(expected, values);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(inner.subscriptions).toBe(innerSubs);\n    });\n  });\n\n  it('should concatMapTo many outer to many inner, and outer throws', () => {\n    testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => {\n      const values = { i: 'foo', j: 'bar', k: 'baz', l: 'qux' };\n      const e1 = hot('    -a---b---c---d---#');\n      const e1subs = '    ^----------------!';\n      const inner = cold('--i-j-k-l-|       ', values);\n      // prettier-ignore\n      const innerSubs = [\n        '                 -^---------!      ',\n        '                 -----------^-----!',\n      ];\n      const expected = '  ---i-j-k-l---i-j-#';\n\n      const result = e1.pipe(concatMapTo(inner));\n\n      expectObservable(result).toBe(expected, values);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(inner.subscriptions).toBe(innerSubs);\n    });\n  });\n\n  it('should concatMapTo many outer to many inner, both inner and outer throw', () => {\n    testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => {\n      const values = { i: 'foo', j: 'bar', k: 'baz', l: 'qux' };\n      const e1 = hot('    -a---b---c---d---#');\n      const e1subs = '    ^----------!      ';\n      const inner = cold('--i-j-k-l-#       ', values);\n      const innerSubs = ' -^---------!      ';\n      const expected = '  ---i-j-k-l-#      ';\n\n      const result = e1.pipe(concatMapTo(inner));\n\n      expectObservable(result).toBe(expected, values);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(inner.subscriptions).toBe(innerSubs);\n    });\n  });\n\n  it('should concatMapTo many outer to an array', () => {\n    testScheduler.run(({ hot, expectObservable }) => {\n      const e1 = hot('  2-----4--------3--------2-------|');\n      const expected = '(0123)(0123)---(0123)---(0123)--|';\n\n      const result = e1.pipe(concatMapTo(['0', '1', '2', '3']));\n\n      expectObservable(result).toBe(expected);\n    });\n  });\n\n  it('should concatMapTo many outer to inner arrays, and outer throws', () => {\n    testScheduler.run(({ hot, expectObservable }) => {\n      const e1 = hot('  2-----4--------3--------2-------#');\n      const expected = '(0123)(0123)---(0123)---(0123)--#';\n\n      const result = e1.pipe(concatMapTo(['0', '1', '2', '3']));\n\n      expectObservable(result).toBe(expected);\n    });\n  });\n\n  it('should concatMapTo many outer to inner arrays, outer unsubscribed early', () => {\n    testScheduler.run(({ hot, expectObservable }) => {\n      const e1 = hot('  2-----4--------3--------2-------|');\n      const unsub = '   -------------!';\n      const expected = '(0123)(0123)--';\n\n      const result = e1.pipe(concatMapTo(['0', '1', '2', '3']));\n\n      expectObservable(result, unsub).toBe(expected);\n    });\n  });\n\n  it('should map values to constant resolved promises and concatenate', (done) => {\n    const source = from([4, 3, 2, 1]);\n\n    const results: number[] = [];\n    source.pipe(concatMapTo(from(Promise.resolve(42)))).subscribe({\n      next: (x) => {\n        results.push(x);\n      },\n      error: (err) => {\n        done(new Error('Subscriber error handler not supposed to be called.'));\n      },\n      complete: () => {\n        expect(results).to.deep.equal([42, 42, 42, 42]);\n        done();\n      },\n    });\n  });\n\n  it('should map values to constant rejected promises and concatenate', (done) => {\n    const source = from([4, 3, 2, 1]);\n\n    source.pipe(concatMapTo(from(Promise.reject(42)))).subscribe({\n      next: (x) => {\n        done(new Error('Subscriber next handler not supposed to be called.'));\n      },\n      error: (err) => {\n        expect(err).to.equal(42);\n        done();\n      },\n      complete: () => {\n        done(new Error('Subscriber complete handler not supposed to be called.'));\n      },\n    });\n  });\n\n  it('should stop listening to a synchronous observable when unsubscribed', () => {\n    const sideEffects: number[] = [];\n    const synchronousObservable = new Observable((subscriber) => {\n      // This will check to see if the subscriber was closed on each loop\n      // when the unsubscribe hits (from the `take`), it should be closed\n      for (let i = 0; !subscriber.closed && i < 10; i++) {\n        sideEffects.push(i);\n        subscriber.next(i);\n      }\n    });\n\n    synchronousObservable.pipe(concatMapTo(of(0)), take(3)).subscribe(() => {\n      /* noop */\n    });\n\n    expect(sideEffects).to.deep.equal([0, 1, 2]);\n  });\n});\n"
  },
  {
    "path": "packages/rxjs/spec/operators/concatWith-spec.ts",
    "content": "import { expect } from 'chai';\nimport { of, Observable } from 'rxjs';\nimport { concatWith, mergeMap, take } from 'rxjs/operators';\nimport { TestScheduler } from 'rxjs/testing';\nimport { NO_SUBS } from '../helpers/test-helper';\nimport { observableMatcher } from '../helpers/observableMatcher';\n\n/** @test {concat} */\ndescribe('concat operator', () => {\n  let rxTest: TestScheduler;\n\n  beforeEach(() => {\n    rxTest = new TestScheduler(observableMatcher);\n  });\n\n  it('should concatenate two cold observables', () => {\n    rxTest.run(({ cold, expectObservable }) => {\n      const e1 = cold(' --a--b-|');\n      const e2 = cold('        --x---y--|');\n      const expected = '--a--b---x---y--|';\n\n      expectObservable(e1.pipe(concatWith(e2))).toBe(expected);\n    });\n  });\n\n  it('should work properly with scalar observables', (done) => {\n    const results: string[] = [];\n\n    const s1 = new Observable<number>((observer) => {\n      setTimeout(() => {\n        observer.next(1);\n        observer.complete();\n      });\n    }).pipe(concatWith(of(2)));\n\n    s1.subscribe({\n      next: (x) => {\n        results.push('Next: ' + x);\n      },\n      error: (x) => {\n        done(new Error('should not be called'));\n      },\n      complete: () => {\n        results.push('Completed');\n        expect(results).to.deep.equal(['Next: 1', 'Next: 2', 'Completed']);\n        done();\n      },\n    });\n  });\n\n  it('should complete without emit if both sources are empty', () => {\n    rxTest.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' --|');\n      const e1subs = '  ^-!';\n      const e2 = cold('   ----|');\n      const e2subs = '  --^---!';\n      const expected = '------|';\n\n      expectObservable(e1.pipe(concatWith(e2))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should not complete if first source does not completes', () => {\n    rxTest.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' ---');\n      const e1subs = '  ^--';\n      const e2 = cold('    --|');\n      const e2subs = NO_SUBS;\n      const expected = '---';\n\n      expectObservable(e1.pipe(concatWith(e2))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should not complete if second source does not completes', () => {\n    rxTest.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' --|');\n      const e1subs = '  ^-!';\n      const e2 = cold('   ---');\n      const e2subs = '  --^--';\n      const expected = '-----';\n\n      expectObservable(e1.pipe(concatWith(e2))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should not complete if both sources do not complete', () => {\n    rxTest.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' ---');\n      const e1subs = '  ^--';\n      const e2 = cold('    ---');\n      const e2subs = NO_SUBS;\n      const expected = '---';\n\n      expectObservable(e1.pipe(concatWith(e2))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should raise error when first source is empty, second source raises error', () => {\n    rxTest.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' --|');\n      const e1subs = '  ^-!';\n      const e2 = cold('   ----#');\n      const e2subs = '  --^---!';\n      const expected = '------#';\n\n      expectObservable(e1.pipe(concatWith(e2))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should raise error when first source raises error, second source is empty', () => {\n    rxTest.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' ---#');\n      const e1subs = '  ^--!';\n      const e2 = cold('    ----|');\n      const expected = '---#';\n      const e2subs = NO_SUBS;\n\n      expectObservable(e1.pipe(concatWith(e2))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should raise first error when both source raise error', () => {\n    rxTest.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' ---#');\n      const e1subs = '  ^--!';\n      const e2 = cold('    ------#');\n      const expected = '---#';\n      const e2subs = NO_SUBS;\n\n      expectObservable(e1.pipe(concatWith(e2))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should concat if first source emits once, second source is empty', () => {\n    rxTest.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' --a--|');\n      const e1subs = '  ^----!';\n      const e2 = cold('      --------|');\n      const e2subs = '  -----^-------!';\n      const expected = '--a----------|';\n\n      expectObservable(e1.pipe(concatWith(e2))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should concat if first source is empty, second source emits once', () => {\n    rxTest.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' --|');\n      const e1subs = '  ^-!';\n      const e2 = cold('   --a--|');\n      const e2subs = '  --^----!';\n      const expected = '----a--|';\n\n      expectObservable(e1.pipe(concatWith(e2))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should emit element from first source, and should not complete if second source does not completes', () => {\n    rxTest.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' --a--|');\n      const e1subs = '  ^----!';\n      const e2 = cold('      ---');\n      const e2subs = '  -----^--';\n      const expected = '--a-----';\n\n      expectObservable(e1.pipe(concatWith(e2))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should not complete if first source does not complete', () => {\n    rxTest.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' ---');\n      const e1subs = '  ^--';\n      const e2 = cold('    --a--|');\n      const e2subs = NO_SUBS;\n      const expected = '---';\n\n      expectObservable(e1.pipe(concatWith(e2))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should emit elements from each source when source emit once', () => {\n    rxTest.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' ---a|');\n      const e1subs = '  ^---!';\n      const e2 = cold('     -----b--|');\n      const e2subs = '  ----^-------!';\n      const expected = '---a-----b--|';\n\n      expectObservable(e1.pipe(concatWith(e2))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should unsubscribe to inner source if outer is unsubscribed early', () => {\n    rxTest.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold('  ---a-a--a|            ');\n      const e1subs = '   ^--------!            ';\n      const e2 = cold('           -----b-b--b-|');\n      const e2subs = '   ---------^-------!';\n      const unsub = '    -----------------!  ';\n      const expected = ' ---a-a--a-----b-b     ';\n\n      expectObservable(e1.pipe(concatWith(e2)), unsub).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should not break unsubscription chains when result is unsubscribed explicitly', () => {\n    rxTest.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' ---a-a--a|            ');\n      const e1subs = '  ^--------!            ';\n      const e2 = cold('          -----b-b--b-|');\n      const e2subs = '  ---------^--------!    ';\n      const expected = '---a-a--a-----b-b-    ';\n      const unsub = '   ------------------!    ';\n\n      const result = e1.pipe(\n        mergeMap((x) => of(x)),\n        concatWith(e2),\n        mergeMap((x) => of(x))\n      );\n\n      expectObservable(result, unsub).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should raise error from first source and does not emit from second source', () => {\n    rxTest.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' --#');\n      const e1subs = '  ^-!';\n      const e2 = cold('   ----a--|');\n      const e2subs = NO_SUBS;\n      const expected = '--#';\n\n      expectObservable(e1.pipe(concatWith(e2))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should emit element from first source then raise error from second source', () => {\n    rxTest.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' --a--|');\n      const e1subs = '  ^----!';\n      const e2 = cold('      -------#');\n      const e2subs = '  -----^------!';\n      const expected = '--a---------#';\n\n      expectObservable(e1.pipe(concatWith(e2))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should emit all elements from both hot observable sources if first source completes before second source starts emit', () => {\n    rxTest.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  --a--b-|');\n      const e1subs = '  ^------!';\n      const e2 = hot('  --------x--y--|');\n      const e2subs = '  -------^------!';\n      const expected = '--a--b--x--y--|';\n\n      expectObservable(e1.pipe(concatWith(e2))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should emit elements from second source regardless of completion time when second source is cold observable', () => {\n    rxTest.run(({ hot, cold, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  --a--b--c---|');\n      const e1subs = '  ^-----------!';\n      const e2 = cold('           -x-y-z-|');\n      const e2subs = '  ------------^------!';\n      const expected = '--a--b--c----x-y-z-|';\n\n      expectObservable(e1.pipe(concatWith(e2))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should not emit collapsing element from second source', () => {\n    rxTest.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  --a--b--c--|');\n      const e1subs = '  ^----------!';\n      const e2 = hot('  --------x--y--z--|');\n      const e2subs = '  -----------^-----!';\n      const expected = '--a--b--c--y--z--|';\n\n      expectObservable(e1.pipe(concatWith(e2))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should emit self without parameters', () => {\n    rxTest.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' ---a-|');\n      const e1subs = '  ^----!';\n      const expected = '---a-|';\n\n      expectObservable(e1.pipe(concatWith())).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should stop listening to a synchronous observable when unsubscribed', () => {\n    const sideEffects: number[] = [];\n    const synchronousObservable = new Observable((subscriber) => {\n      // This will check to see if the subscriber was closed on each loop\n      // when the unsubscribe hits (from the `take`), it should be closed\n      for (let i = 0; !subscriber.closed && i < 10; i++) {\n        sideEffects.push(i);\n        subscriber.next(i);\n      }\n    });\n\n    synchronousObservable.pipe(concatWith(of(0)), take(3)).subscribe(() => {\n      /* noop */\n    });\n\n    expect(sideEffects).to.deep.equal([0, 1, 2]);\n  });\n});\n"
  },
  {
    "path": "packages/rxjs/spec/operators/connect-spec.ts",
    "content": "import { BehaviorSubject, merge } from 'rxjs';\nimport { connect, delay } from 'rxjs/operators';\nimport { TestScheduler } from 'rxjs/testing';\nimport { observableMatcher } from '../helpers/observableMatcher';\n\ndescribe('connect', () => {\n  let rxTest: TestScheduler;\n\n  beforeEach(() => {\n    rxTest = new TestScheduler(observableMatcher);\n  });\n\n  it('should connect a source through a selector function', () => {\n    rxTest.run(({ cold, time, expectObservable }) => {\n      const source = cold('---a----b-----c---|');\n      const d = time('        ---|');\n      const expected = '   ---a--a-b--b--c--c|';\n\n      const result = source.pipe(connect((shared) => merge(shared.pipe(delay(d)), shared)));\n\n      expectObservable(result).toBe(expected);\n    });\n  });\n\n  it('should connect a source through a selector function and use the provided connector', () => {\n    rxTest.run(({ cold, time, expectObservable }) => {\n      const source = cold('--------a---------b---------c-----|');\n      const d = time('             ---|');\n      const expected = '   S--S----a--a------b--b------c--c--|';\n\n      const result = source.pipe(\n        connect(\n          (shared) => {\n            return merge(shared.pipe(delay(d)), shared);\n          },\n          {\n            connector: () => new BehaviorSubject('S'),\n          }\n        )\n      );\n\n      expectObservable(result).toBe(expected);\n    });\n  });\n});\n"
  },
  {
    "path": "packages/rxjs/spec/operators/count-spec.ts",
    "content": "import { expect } from 'chai';\nimport { of, range } from 'rxjs';\nimport { count, skip, take, mergeMap } from 'rxjs/operators';\nimport { TestScheduler } from 'rxjs/testing';\nimport { observableMatcher } from '../helpers/observableMatcher';\n\n/** @test {count} */\ndescribe('count', () => {\n  let testScheduler: TestScheduler;\n\n  beforeEach(() => {\n    testScheduler = new TestScheduler(observableMatcher);\n  });\n\n  it('should count the values of an observable', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const source = hot('--a--b--c--|');\n      const subs = '      ^----------!';\n      const expected = '  -----------(x|)';\n\n      expectObservable(source.pipe(count())).toBe(expected, { x: 3 });\n      expectSubscriptions(source.subscriptions).toBe(subs);\n    });\n  });\n\n  it('should be never when source is never', () => {\n    testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' -');\n      const e1subs = '  ^';\n      const expected = '-';\n\n      expectObservable(e1.pipe(count())).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should be zero when source is empty', () => {\n    testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' |');\n      const e1subs = '  (^!)';\n      const expected = '(w|)';\n\n      expectObservable(e1.pipe(count())).toBe(expected, { w: 0 });\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it(\"should be never when source doesn't complete\", () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('--x--^--y--');\n      const e1subs = '     ^     ';\n      const expected = '   ------';\n\n      expectObservable(e1.pipe(count())).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it(\"should be zero when source doesn't have values\", () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('-x-^---|');\n      const e1subs = '   ^---!';\n      const expected = ' ----(w|)';\n\n      expectObservable(e1.pipe(count())).toBe(expected, { w: 0 });\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should count the unique value of an observable', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('-x-^--y--|');\n      const e1subs = '   ^-----!';\n      const expected = ' ------(w|)';\n\n      expectObservable(e1.pipe(count())).toBe(expected, { w: 1 });\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should count the values of an ongoing hot observable', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const source = hot('--a-^-b--c--d--|');\n      const subs = '          ^----------!';\n      const expected = '      -----------(x|)';\n\n      expectObservable(source.pipe(count())).toBe(expected, { x: 3 });\n      expectSubscriptions(source.subscriptions).toBe(subs);\n    });\n  });\n\n  it('should count a range() source observable', (done) => {\n    range(1, 10)\n      .pipe(count())\n      .subscribe({\n        next: (value: number) => {\n          expect(value).to.equal(10);\n        },\n        error: (x) => {\n          done(new Error('should not be called'));\n        },\n        complete: () => {\n          done();\n        },\n      });\n  });\n\n  it('should count a range().skip(1) source observable', (done) => {\n    range(1, 10)\n      .pipe(skip(1), count())\n      .subscribe({\n        next: (value: number) => {\n          expect(value).to.equal(9);\n        },\n        error: (x) => {\n          done(new Error('should not be called'));\n        },\n        complete: () => {\n          done();\n        },\n      });\n  });\n\n  it('should count a range().take(1) source observable', (done) => {\n    range(1, 10)\n      .pipe(take(1), count())\n      .subscribe({\n        next: (value: number) => {\n          expect(value).to.equal(1);\n        },\n        error: (x) => {\n          done(new Error('should not be called'));\n        },\n        complete: () => {\n          done();\n        },\n      });\n  });\n\n  it('should work with error', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('-x-^--y--z--#', { x: 1, y: 2, z: 3 }, 'too bad');\n      const e1subs = '   ^--------!';\n      const expected = ' ---------#';\n\n      expectObservable(e1.pipe(count())).toBe(expected, null, 'too bad');\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should work with throw', () => {\n    testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' #');\n      const e1subs = '  (^!)';\n      const expected = '#';\n\n      expectObservable(e1.pipe(count())).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should handle an always-true predicate on an empty hot observable', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('-x-^---|');\n      const e1subs = '   ^---!';\n      const expected = ' ----(w|)';\n      const predicate = () => {\n        return true;\n      };\n\n      expectObservable(e1.pipe(count(predicate))).toBe(expected, { w: 0 });\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should handle an always-false predicate on an empty hot observable', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('-x-^---|');\n      const e1subs = '   ^---!';\n      const expected = ' ----(w|)';\n      const predicate = () => {\n        return false;\n      };\n\n      expectObservable(e1.pipe(count(predicate))).toBe(expected, { w: 0 });\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should handle an always-true predicate on a simple hot observable', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('-x-^-a-|');\n      const e1subs = '   ^---!';\n      const expected = ' ----(w|)';\n      const predicate = () => {\n        return true;\n      };\n\n      expectObservable(e1.pipe(count(predicate))).toBe(expected, { w: 1 });\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should handle an always-false predicate on a simple hot observable', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('-x-^-a-|');\n      const e1subs = '   ^---!';\n      const expected = ' ----(w|)';\n      const predicate = () => {\n        return false;\n      };\n\n      expectObservable(e1.pipe(count(predicate))).toBe(expected, { w: 0 });\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should allow unsubscribing early and explicitly', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('-1-^-2--3--4-|');\n      const e1subs = '   ^-----!    ';\n      const expected = ' -------    ';\n      const unsub = '    ------!    ';\n\n      const result = e1.pipe(count((value: string) => parseInt(value) < 10));\n\n      expectObservable(result, unsub).toBe(expected, { w: 3 });\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should not break unsubscription chains when result is unsubscribed explicitly', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('-1-^-2--3--4-|');\n      const e1subs = '   ^-----!    ';\n      const expected = ' -------    ';\n      const unsub = '    ------!    ';\n\n      const result = e1.pipe(\n        mergeMap((x: string) => of(x)),\n        count((value: string) => parseInt(value) < 10),\n        mergeMap((x: number) => of(x))\n      );\n\n      expectObservable(result, unsub).toBe(expected, { w: 3 });\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should handle a match-all predicate on observable with many values', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('-1-^-2--3--4-|');\n      const e1subs = '   ^---------!';\n      const expected = ' ----------(w|)';\n      const predicate = (value: string) => parseInt(value) < 10;\n\n      expectObservable(e1.pipe(count(predicate))).toBe(expected, { w: 3 });\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should handle a match-none predicate on observable with many values', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('-1-^-2--3--4-|');\n      const e1subs = '   ^---------!';\n      const expected = ' ----------(w|)';\n      const predicate = (value: string) => parseInt(value) > 10;\n\n      expectObservable(e1.pipe(count(predicate))).toBe(expected, { w: 0 });\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should handle an always-true predicate on observable that throws', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('-1-^---#');\n      const e1subs = '   ^---!';\n      const expected = ' ----#';\n      const predicate = () => true;\n\n      expectObservable(e1.pipe(count(predicate))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should handle an always-false predicate on observable that throws', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('-1-^---#');\n      const e1subs = '   ^---!';\n      const expected = ' ----#';\n      const predicate = () => false;\n\n      expectObservable(e1.pipe(count(predicate))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should handle an always-true predicate on a hot never-observable', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('-x-^----');\n      const e1subs = '   ^    ';\n      const expected = ' -----';\n      const predicate = () => true;\n\n      expectObservable(e1.pipe(count(predicate))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should handle a predicate that throws, on observable with many values', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('-1-^-2--3--|');\n      const e1subs = '   ^----!   ';\n      const expected = ' -----#   ';\n      const predicate = (value: string) => {\n        if (value === '3') {\n          throw 'error';\n        }\n        return true;\n      };\n\n      expectObservable(e1.pipe(count(predicate))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n});\n"
  },
  {
    "path": "packages/rxjs/spec/operators/debounce-spec.ts",
    "content": "import { expect } from 'chai';\nimport { NEVER, timer, of, EMPTY, concat, Subject, Observable } from 'rxjs';\nimport { debounce, mergeMap, mapTo, take } from 'rxjs/operators';\nimport { TestScheduler } from 'rxjs/testing';\nimport { observableMatcher } from '../helpers/observableMatcher';\n\n/** @test {debounce} */\ndescribe('debounce', () => {\n  let testScheduler: TestScheduler;\n\n  beforeEach(() => {\n    testScheduler = new TestScheduler(observableMatcher);\n  });\n\n  function getTimerSelector(x: number) {\n    return () => timer(x, testScheduler);\n  }\n\n  it('should debounce values by a specified cold Observable', () => {\n    testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  -a----bc----d-ef----|');\n      const e1subs = '  ^-------------------!';\n      const e2 = cold('  ---x                ');\n      //                       ---x\n      //                               ---x\n      const e2subs = [\n        '               -^--!                ',\n        '               ------^!             ',\n        '               -------^--!          ',\n        '               ------------^-!      ',\n        '               --------------^!     ',\n        '               ---------------^--!  ',\n      ];\n      const expected = '----a-----c-------f-|';\n\n      const result = e1.pipe(debounce(() => e2));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should delay all element by selector observable', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  --a--b--c--d---------|');\n      const e1subs = '  ^--------------------!';\n      const expected = '----a--b--c--d-------|';\n\n      expectObservable(e1.pipe(debounce(getTimerSelector(2)))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should debounce by selector observable', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  --a--bc--d----|');\n      const e1subs = '  ^-------------!';\n      const expected = '----a---c--d--|';\n\n      expectObservable(e1.pipe(debounce(getTimerSelector(2)))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should support a scalar selector observable', () => {\n    // If the selector returns a scalar observable, the debounce operator\n    // should emit the value immediately.\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  --a--bc--d----|');\n      const e1subs = '  ^-------------!';\n      const expected = '--a--bc--d----|';\n\n      expectObservable(e1.pipe(debounce(() => of(0)))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should complete when source does not emit', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  -----|');\n      const e1subs = '  ^----!';\n      const expected = '-----|';\n\n      expectObservable(e1.pipe(debounce(getTimerSelector(2)))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should complete when source is empty', () => {\n    testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' |');\n      const e1subs = '  (^!)';\n      const expected = '|';\n\n      expectObservable(e1.pipe(debounce(getTimerSelector(2)))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should raise error when source does not emit and raises error', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  -----#');\n      const e1subs = '  ^----!';\n      const expected = '-----#';\n\n      expectObservable(e1.pipe(debounce(getTimerSelector(2)))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should raise error when source throws', () => {\n    testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' #');\n      const e1subs = '  (^!)';\n      const expected = '#';\n\n      expectObservable(e1.pipe(debounce(getTimerSelector(2)))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should allow unsubscribing early and explicitly', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  --a--bc--d----|');\n      const e1subs = '  ^------!       ';\n      const expected = '----a---       ';\n      const unsub = '   -------!       ';\n\n      const result = e1.pipe(debounce(getTimerSelector(2)));\n\n      expectObservable(result, unsub).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should not break unsubscription chains when unsubscribed explicitly', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  --a--bc--d----|');\n      const e1subs = '  ^------!       ';\n      const expected = '----a---       ';\n      const unsub = '   -------!       ';\n\n      const result = e1.pipe(\n        mergeMap((x: any) => of(x)),\n        debounce(getTimerSelector(2)),\n        mergeMap((x: any) => of(x))\n      );\n\n      expectObservable(result, unsub).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should debounce and does not complete when source does not completes', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  --a--bc--d---');\n      const e1subs = '  ^            ';\n      const expected = '----a---c--d-';\n\n      expectObservable(e1.pipe(debounce(getTimerSelector(2)))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should not complete when source does not complete', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  -');\n      const e1subs = '  ^';\n      const expected = '-';\n\n      expectObservable(e1.pipe(debounce(getTimerSelector(2)))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should not completes when source never completes', () => {\n    testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' -');\n      const e1subs = '  ^';\n      const expected = '-';\n\n      expectObservable(e1.pipe(debounce(getTimerSelector(2)))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should delay all element until source raises error', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  --a--b--c--d---------#');\n      const e1subs = '  ^--------------------!';\n      const expected = '----a--b--c--d-------#';\n\n      expectObservable(e1.pipe(debounce(getTimerSelector(2)))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should debounce all elements while source emits by selector observable', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  ---a---b---c---d---e|');\n      const e1subs = '  ^-------------------!';\n      const expected = '--------------------(e|)';\n\n      expectObservable(e1.pipe(debounce(getTimerSelector(4)))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should debounce all element while source emits by selector observable until raises error', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  --a--b--c--d-#');\n      const e1subs = '  ^------------!';\n      const expected = '-------------#';\n\n      expectObservable(e1.pipe(debounce(getTimerSelector(5)))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should delay element by same selector observable emits multiple', () => {\n    testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('       ----a--b--c----d-----e-------|');\n      const e1subs = '       ^----------------------------!';\n      const expected = '     ------a--b--c----d-----e-----|';\n      const selector = cold('--x-y-');\n      const selectorSubs = [\n        '                    ----^-!                      ',\n        '                    -------^-!                   ',\n        '                    ----------^-!                ',\n        '                    ---------------^-!           ',\n        '                    ---------------------^-!     ',\n      ];\n\n      expectObservable(e1.pipe(debounce(() => selector))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(selector.subscriptions).toBe(selectorSubs);\n    });\n  });\n\n  it('should debounce by selector observable emits multiple', () => {\n    testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  ----a--b--c----d-----e-------|');\n      const e1subs = '  ^----------------------------!';\n      const expected = '------a-----c----------e-----|';\n      const selector = [\n        cold('              --x-y-                    '),\n        cold('                 ----x-y-               '),\n        cold('                    --x-y-              '),\n        cold('                         ------x-y-     '),\n        cold('                               --x-y-   '),\n      ];\n      const selectorSubs = [\n        '               ----^-!                       ',\n        '               -------^--!                   ',\n        '               ----------^-!                 ',\n        '               ---------------^-----!        ',\n        '               ---------------------^-!      ',\n      ];\n\n      expectObservable(e1.pipe(debounce(() => selector.shift()!))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      for (let i = 0; i < selectorSubs.length; i++) {\n        expectSubscriptions(selector[i].subscriptions).toBe(selectorSubs[i]);\n      }\n    });\n  });\n\n  it('should debounce by selector observable until source completes', () => {\n    testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  ----a--b--c----d----e|    ');\n      const e1subs = '  ^--------------------!    ';\n      const expected = '------a-----c--------(e|) ';\n      const selector = [\n        cold('              --x-y-                '),\n        cold('                 ----x-y-           '),\n        cold('                    --x-y-          '),\n        cold('                         ------x-y- '),\n        cold('                              --x-y-'),\n      ];\n      const selectorSubs = [\n        '               ----^-!                   ',\n        '               -------^--!               ',\n        '               ----------^-!             ',\n        '               ---------------^----!     ',\n        '               --------------------^!    ',\n      ];\n\n      expectObservable(e1.pipe(debounce(() => selector.shift()!))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      for (let i = 0; i < selectorSubs.length; i++) {\n        expectSubscriptions(selector[i].subscriptions).toBe(selectorSubs[i]);\n      }\n    });\n  });\n\n  it('should raise error when selector observable raises error', () => {\n    testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  --------a--------b--------c---------|');\n      const e1subs = '  ^----------------------------!       ';\n      const expected = '---------a---------b---------#       ';\n      const selector = [\n        cold('                  -x-y-                        '),\n        cold('                           --x-y-              '),\n        cold('                                    ---#       '),\n      ];\n      const selectorSubs = [\n        '               --------^!                           ',\n        '               -----------------^-!                 ',\n        '               --------------------------^--!       ',\n      ];\n\n      expectObservable(e1.pipe(debounce(() => selector.shift()!))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      for (let i = 0; i < selectorSubs.length; i++) {\n        expectSubscriptions(selector[i].subscriptions).toBe(selectorSubs[i]);\n      }\n    });\n  });\n\n  it('should raise error when source raises error with selector observable', () => {\n    testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  --------a--------b--------c---------d#      ');\n      const e1subs = '  ^------------------------------------!      ';\n      const expected = '---------a---------b---------c-------#      ';\n      const selector = [\n        cold('                  -x-y-                               '),\n        cold('                           --x-y-                     '),\n        cold('                                    ---x-y-           '),\n        cold('                                              ----x-y-'),\n      ];\n      const selectorSubs = [\n        '               --------^!                                  ',\n        '               -----------------^-!                        ',\n        '               --------------------------^--!              ',\n        '               ------------------------------------^!      ',\n      ];\n\n      expectObservable(e1.pipe(debounce(() => selector.shift()!))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      for (let i = 0; i < selectorSubs.length; i++) {\n        expectSubscriptions(selector[i].subscriptions).toBe(selectorSubs[i]);\n      }\n    });\n  });\n\n  it('should raise error when selector function throws', () => {\n    testScheduler.run(({ hot, cold, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  --------a--------b--------c---------|');\n      const e1subs = '  ^-------------------------!          ';\n      const expected = '---------a---------b------#          ';\n      // prettier-ignore\n      const selector = [\n        cold('                  -x-y-                        '),\n        cold('                           --x-y-              '),\n      ];\n      // prettier-ignore\n      const selectorSubs = [\n        '               --------^!                           ',\n        '               -----------------^-!                 ',\n      ];\n\n      function selectorFunction(x: string) {\n        if (x !== 'c') {\n          return selector.shift();\n        } else {\n          throw 'error';\n        }\n      }\n\n      expectObservable(e1.pipe(debounce(selectorFunction as any))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      for (let i = 0; i < selectorSubs.length; i++) {\n        expectSubscriptions(selector[i].subscriptions).toBe(selectorSubs[i]);\n      }\n    });\n  });\n\n  it('should ignore all values except last, when given an empty selector Observable', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  --------a-x-yz---bxy---z--c--x--y--z|   ');\n      const e1subs = '  ^-----------------------------------!   ';\n      const expected = '------------------------------------(z|)';\n\n      function selectorFunction(x: string) {\n        return EMPTY;\n      }\n\n      expectObservable(e1.pipe(debounce(selectorFunction))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should ignore all values except last, when given a never selector Observable', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  --------a-x-yz---bxy---z--c--x--y--z|  ');\n      const e1subs = '  ^-----------------------------------!  ';\n      const expected = '------------------------------------(z|)';\n\n      function selectorFunction() {\n        return NEVER;\n      }\n\n      expectObservable(e1.pipe(debounce(selectorFunction))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should not delay by selector observable completes when it does not emits', () => {\n    testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  --------a--------b--------c---------|   ');\n      const e1subs = '  ^-----------------------------------!   ';\n      const expected = '------------------------------------(c|)';\n      const selector = [\n        cold('                  -|                              '),\n        cold('                           --|                    '),\n        cold('                                    ---|          '),\n      ];\n      const selectorSubs = [\n        '               --------^!                              ',\n        '               -----------------^-!                    ',\n        '               --------------------------^--!          ',\n      ];\n\n      expectObservable(e1.pipe(debounce(() => selector.shift()!))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      for (let i = 0; i < selectorSubs.length; i++) {\n        expectSubscriptions(selector[i].subscriptions).toBe(selectorSubs[i]);\n      }\n    });\n  });\n\n  it('should not debounce by selector observable completes when it does not emits', () => {\n    testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  ----a--b-c---------de-------------|   ');\n      const e1subs = '  ^---------------------------------!   ';\n      const expected = '----------------------------------(e|)';\n      const selector = [\n        cold('              -|                                '),\n        cold('                 --|                            '),\n        cold('                   ---|                         '),\n        cold('                             ----|              '),\n        cold('                              -----|            '),\n      ];\n      const selectorSubs = [\n        '               ----^!                                ',\n        '               -------^-!                            ',\n        '               ---------^--!                         ',\n        '               -------------------^!                 ',\n        '               --------------------^----!            ',\n      ];\n\n      expectObservable(e1.pipe(debounce(() => selector.shift()!))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      for (let i = 0; i < selectorSubs.length; i++) {\n        expectSubscriptions(selector[i].subscriptions).toBe(selectorSubs[i]);\n      }\n    });\n  });\n\n  it('should delay by promise resolves', (done) => {\n    const e1 = concat(of(1), timer(10).pipe(mapTo(2)), timer(10).pipe(mapTo(3)), timer(100).pipe(mapTo(4)));\n    const expected = [1, 2, 3, 4];\n\n    e1.pipe(\n      debounce(() => {\n        return new Promise((resolve: any) => {\n          resolve(42);\n        });\n      })\n    ).subscribe({\n      next: (x: number) => {\n        expect(x).to.equal(expected.shift());\n      },\n      error: (x) => {\n        done(new Error('should not be called'));\n      },\n      complete: () => {\n        expect(expected.length).to.equal(0);\n        done();\n      },\n    });\n  });\n\n  it('should raises error when promise rejects', (done) => {\n    const e1 = concat(of(1), timer(10).pipe(mapTo(2)), timer(10).pipe(mapTo(3)), timer(100).pipe(mapTo(4)));\n    const expected = [1, 2];\n    const error = new Error('error');\n\n    e1.pipe(\n      debounce((x: number) => {\n        if (x === 3) {\n          return new Promise((resolve: any, reject: any) => {\n            reject(error);\n          });\n        } else {\n          return new Promise((resolve: any) => {\n            resolve(42);\n          });\n        }\n      })\n    ).subscribe({\n      next: (x: number) => {\n        expect(x).to.equal(expected.shift());\n      },\n      error: (err: any) => {\n        expect(err).to.be.an('error', 'error');\n        expect(expected.length).to.equal(0);\n        done();\n      },\n      complete: () => {\n        done(new Error('should not be called'));\n      },\n    });\n  });\n\n  it('should debounce correctly when synchronously reentered', () => {\n    const results: number[] = [];\n    const source = new Subject<number>();\n\n    source.pipe(debounce(() => of(null))).subscribe((value) => {\n      results.push(value);\n\n      if (value === 1) {\n        source.next(2);\n      }\n    });\n    source.next(1);\n\n    expect(results).to.deep.equal([1, 2]);\n  });\n\n  it('should stop listening to a synchronous observable when unsubscribed', () => {\n    const sideEffects: number[] = [];\n    const synchronousObservable = new Observable((subscriber) => {\n      // This will check to see if the subscriber was closed on each loop\n      // when the unsubscribe hits (from the `take`), it should be closed\n      for (let i = 0; !subscriber.closed && i < 10; i++) {\n        sideEffects.push(i);\n        subscriber.next(i);\n      }\n    });\n\n    synchronousObservable\n      .pipe(\n        debounce(() => of(0)),\n        take(3)\n      )\n      .subscribe(() => {\n        /* noop */\n      });\n\n    expect(sideEffects).to.deep.equal([0, 1, 2]);\n  });\n});\n"
  },
  {
    "path": "packages/rxjs/spec/operators/debounceTime-spec.ts",
    "content": "import { expect } from 'chai';\nimport { NEVER, of, Subject, queueScheduler } from 'rxjs';\nimport { AnimationFrameAction } from 'rxjs/internal/scheduler/AnimationFrameAction';\nimport { AnimationFrameScheduler } from 'rxjs/internal/scheduler/AnimationFrameScheduler';\nimport { debounceTime, mergeMap, startWith } from 'rxjs/operators';\nimport { TestScheduler } from 'rxjs/testing';\nimport { VirtualTimeScheduler } from 'rxjs/internal/scheduler/VirtualTimeScheduler';\nimport { observableMatcher } from '../helpers/observableMatcher';\n\n/** @test {debounceTime} */\ndescribe('debounceTime', () => {\n  let testScheduler: TestScheduler;\n\n  beforeEach(() => {\n    testScheduler = new TestScheduler(observableMatcher);\n  });\n\n  it('should debounce values by 2 time units', () => {\n    testScheduler.run(({ hot, time, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  -a--bc--d---|');\n      const e1subs = '  ^-----------!';\n      const expected = '---a---c--d-|';\n      const t = time('  --|');\n\n      expectObservable(e1.pipe(debounceTime(t))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should delay all elements by the specified time', () => {\n    testScheduler.run(({ hot, time, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  -a--------b------c----|');\n      const e1subs = '  ^---------------------!';\n      const expected = '------a--------b------(c|)';\n      const t = time('  -----|');\n\n      expectObservable(e1.pipe(debounceTime(t))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should debounce and delay element by the specified time', () => {\n    testScheduler.run(({ hot, time, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  -a--(bc)-----------d-------|');\n      const e1subs = '  ^--------------------------!';\n      const expected = '---------c--------------d--|';\n      const t = time('  -----|');\n\n      expectObservable(e1.pipe(debounceTime(t))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should complete when source does not emit', () => {\n    testScheduler.run(({ hot, time, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  -----|');\n      const e1subs = '  ^----!';\n      const expected = '-----|';\n      const t = time('  -|');\n\n      expectObservable(e1.pipe(debounceTime(t))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should complete when source is empty', () => {\n    testScheduler.run(({ cold, time, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' |');\n      const e1subs = '  (^!)';\n      const expected = '|';\n      const t = time('  -|');\n\n      expectObservable(e1.pipe(debounceTime(t))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should raise error when source does not emit and raises error', () => {\n    testScheduler.run(({ hot, time, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  -----#');\n      const e1subs = '  ^----!';\n      const expected = '-----#';\n      const t = time('  -|');\n\n      expectObservable(e1.pipe(debounceTime(t))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should raise error when source throws', () => {\n    testScheduler.run(({ cold, time, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' #');\n      const e1subs = '  (^!)';\n      const expected = '#';\n      const t = time('  -|');\n\n      expectObservable(e1.pipe(debounceTime(t))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should allow unsubscribing early and explicitly', () => {\n    testScheduler.run(({ hot, time, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  --a--bc--d----|');\n      const e1subs = '  ^------!       ';\n      const expected = '----a---       ';\n      const unsub = '   -------!       ';\n      const t = time('  --|');\n\n      const result = e1.pipe(debounceTime(t));\n\n      expectObservable(result, unsub).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should not break unsubscription chains when unsubscribed explicitly', () => {\n    testScheduler.run(({ hot, time, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  --a--bc--d----|');\n      const e1subs = '  ^------!       ';\n      const expected = '----a---       ';\n      const unsub = '   -------!       ';\n      const t = time('  --|');\n\n      const result = e1.pipe(\n        mergeMap((x: any) => of(x)),\n        debounceTime(t),\n        mergeMap((x: any) => of(x))\n      );\n\n      expectObservable(result, unsub).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should debounce and does not complete when source does not completes', () => {\n    testScheduler.run(({ hot, time, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  -a--(bc)-----------d-------');\n      const e1subs = '  ^--------------------------';\n      const expected = '---------c--------------d--';\n      const t = time('  -----|');\n\n      expectObservable(e1.pipe(debounceTime(t))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should not completes when source does not completes', () => {\n    testScheduler.run(({ hot, time, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  -');\n      const e1subs = '  ^';\n      const expected = '-';\n      const t = time('  -|');\n\n      expectObservable(e1.pipe(debounceTime(t))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should not completes when source never completes', () => {\n    testScheduler.run(({ cold, time, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' -');\n      const e1subs = '  ^';\n      const expected = '-';\n      const t = time('  -|');\n\n      expectObservable(e1.pipe(debounceTime(t))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should delay all elements until source raises error', () => {\n    testScheduler.run(({ hot, time, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  -a--------b------c----#');\n      const e1subs = '  ^---------------------!';\n      const expected = '------a--------b------#';\n      const t = time('  -----|');\n\n      expectObservable(e1.pipe(debounceTime(t))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should debounce all elements while source emits within given time', () => {\n    testScheduler.run(({ hot, time, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  --a--b--c--d--e--f--g--h-|');\n      const e1subs = '  ^------------------------!';\n      const expected = '-------------------------(h|)';\n      const t = time('  ----|');\n\n      expectObservable(e1.pipe(debounceTime(t))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should debounce all element while source emits within given time until raises error', () => {\n    testScheduler.run(({ hot, time, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  --a--b--c--d--e--f--g--h-#');\n      const e1subs = '  ^------------------------!';\n      const expected = '-------------------------#';\n      const t = time('  ----|');\n\n      expectObservable(e1.pipe(debounceTime(t))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should debounce correctly when synchronously reentered', () => {\n    const results: number[] = [];\n    const source = new Subject<number>();\n    const scheduler = new VirtualTimeScheduler();\n\n    source.pipe(debounceTime(0, scheduler)).subscribe((value) => {\n      results.push(value);\n\n      if (value === 1) {\n        source.next(2);\n      }\n    });\n    source.next(1);\n    scheduler.flush();\n\n    expect(results).to.deep.equal([1, 2]);\n  });\n\n  it('should unsubscribe from the scheduled debounce action when downstream unsubscribes', () => {\n    const scheduler = new AnimationFrameScheduler(AnimationFrameAction);\n\n    expect(scheduler._scheduled).to.not.exist;\n    expect(scheduler.actions).to.be.empty;\n\n    const subscription = NEVER.pipe(startWith(1), debounceTime(0, scheduler)).subscribe();\n\n    expect(scheduler._scheduled).to.exist;\n    expect(scheduler.actions.length).to.equal(1);\n\n    subscription.unsubscribe();\n\n    expect(scheduler._scheduled).to.not.exist;\n    expect(scheduler.actions).to.be.empty;\n  });\n\n  it('should work synchronously with queueScheduler', () => {\n    testScheduler.run(({ cold, expectObservable }) => {\n      const a = cold('a');\n      const expected = 'a';\n\n      const result = a.pipe(debounceTime(0, queueScheduler));\n      expectObservable(result).toBe(expected);\n    });\n  });\n});\n"
  },
  {
    "path": "packages/rxjs/spec/operators/defaultIfEmpty-spec.ts",
    "content": "import { expect } from 'chai';\nimport { observableMatcher } from '../helpers/observableMatcher';\nimport { of, Observable } from 'rxjs';\nimport { defaultIfEmpty, mergeMap, take } from 'rxjs/operators';\nimport { TestScheduler } from 'rxjs/testing';\n\n/** @test {defaultIfEmpty} */\ndescribe('defaultIfEmpty', () => {\n  let testScheduler: TestScheduler;\n\n  beforeEach(() => {\n    testScheduler = new TestScheduler(observableMatcher);\n  });\n\n  it('should return the Observable if not empty with a default value', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  --------|');\n      const e1subs = '  ^-------!';\n      const expected = '--------(x|)';\n\n      expectObservable(e1.pipe(defaultIfEmpty(42))).toBe(expected, { x: 42 });\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should return the argument if Observable is empty', () => {\n    testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' |');\n      const e1subs = '  (^!)';\n      const expected = '(x|)';\n\n      expectObservable(e1.pipe(defaultIfEmpty('x'))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should return the Observable if not empty with a default value', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  --a--b--|');\n      const e1subs = '  ^-------!';\n      const expected = '--a--b--|';\n\n      expectObservable(e1.pipe(defaultIfEmpty('x'))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should allow undefined as a default value', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  --------|');\n      const e1subs = '  ^-------!';\n      const expected = '--------(U|)';\n\n      expectObservable(e1.pipe(defaultIfEmpty(undefined))).toBe(expected, { U: undefined });\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should allow unsubscribing early and explicitly', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  --a--b--|');\n      const e1subs = '  ^---!    ';\n      const expected = '--a--    ';\n      const unsub = '   ----!    ';\n\n      const result = e1.pipe(defaultIfEmpty('x'));\n\n      expectObservable(result, unsub).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should not break unsubscription chains when unsubscribed explicitly', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  --a--b--|');\n      const e1subs = '  ^---!    ';\n      const expected = '--a--    ';\n      const unsub = '   ----!    ';\n\n      const result = e1.pipe(\n        mergeMap((x) => of(x)),\n        defaultIfEmpty('x'),\n        mergeMap((x) => of(x))\n      );\n\n      expectObservable(result, unsub).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should error if the Observable errors', () => {\n    testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' #');\n      const e1subs = '  (^!)';\n      const expected = '#';\n\n      expectObservable(e1.pipe(defaultIfEmpty('x'))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should stop listening to a synchronous observable when unsubscribed', () => {\n    const sideEffects: number[] = [];\n    const synchronousObservable = new Observable((subscriber) => {\n      // This will check to see if the subscriber was closed on each loop\n      // when the unsubscribe hits (from the `take`), it should be closed\n      for (let i = 0; !subscriber.closed && i < 10; i++) {\n        sideEffects.push(i);\n        subscriber.next(i);\n      }\n    });\n\n    synchronousObservable.pipe(defaultIfEmpty(0), take(3)).subscribe(() => {\n      /* noop */\n    });\n\n    expect(sideEffects).to.deep.equal([0, 1, 2]);\n  });\n});\n"
  },
  {
    "path": "packages/rxjs/spec/operators/delay-spec.ts",
    "content": "import { of, concat } from 'rxjs';\nimport { delay, repeatWhen, skip, take, tap, mergeMap, ignoreElements } from 'rxjs/operators';\nimport { TestScheduler } from 'rxjs/testing';\nimport * as sinon from 'sinon';\nimport { expect } from 'chai';\nimport { observableMatcher } from '../helpers/observableMatcher';\n\n/** @test {delay} */\ndescribe('delay', () => {\n  let testScheduler: TestScheduler;\n\n  beforeEach(() => {\n    testScheduler = new TestScheduler(observableMatcher);\n  });\n\n  it('should delay by specified timeframe', () => {\n    testScheduler.run(({ hot, time, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  ---a--b--|');\n      const e1subs = '  ^--------!';\n      const t = time('     --|    ');\n      //                      --|\n      const expected = '-----a--b|';\n\n      const result = e1.pipe(delay(t));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should not delay at all if the delay number is negative', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  ---a--b--|');\n      const e1subs = '  ^--------!';\n      const t = -1;\n      const expected = '---a--b--|';\n\n      const result = e1.pipe(delay(t));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should delay by absolute time period', () => {\n    testScheduler.run(({ hot, time, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  --a--a---a----a----a------------b---b---b---b--|');\n      const e1subs = '  ^----------------------------------------------!';\n      const t = time('  --------------------|                           ');\n      const expected = '--------------------(aaaaa)-----b---b---b---b--|';\n\n      const absoluteDelay = new Date(testScheduler.now() + t);\n      const result = e1.pipe(delay(absoluteDelay));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should not delay at all if the absolute time is in the past', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  --a--a---a----a----a------------b---b---b---b--|');\n      const e1subs = '  ^----------------------------------------------!';\n      const t = -10000;\n      const expected = '--a--a---a----a----a------------b---b---b---b--|';\n\n      const absoluteDelay = new Date(testScheduler.now() + t);\n      const result = e1.pipe(delay(absoluteDelay));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should delay by absolute time period after source ends', () => {\n    testScheduler.run(({ hot, time, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('---^--a-----a---a-----a---|             ');\n      const e1subs = '   ^----------------------!             ';\n      const t = time('   ------------------------------|      ');\n      const expected = ' ------------------------------(aaaa|)';\n\n      const absoluteDelay = new Date(testScheduler.now() + t);\n      const result = e1.pipe(delay(absoluteDelay));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should raise error when source raises error', () => {\n    testScheduler.run(({ hot, time, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  ---a---b---#');\n      const e1subs = '  ^----------!';\n      const t = time('     ---|     ');\n      //                       ---|\n      const expected = '------a---b#';\n\n      const result = e1.pipe(delay(t));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should raise error when source raises error before absolute delay fires', () => {\n    testScheduler.run(({ hot, time, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  --a--a---a-----#     ');\n      const e1subs = '  ^--------------!     ';\n      const t = time('  --------------------|');\n      const expected = '---------------#     ';\n\n      const absoluteDelay = new Date(testScheduler.now() + t);\n      const result = e1.pipe(delay(absoluteDelay));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should raise error when source raises error after absolute delay fires', () => {\n    testScheduler.run(({ hot, time, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('---^---a--a---a---a--------b---b---b--#');\n      const e1subs = '   ^----------------------------------!';\n      const t = time('   -----------------|                  ');\n      const expected = ' -----------------(aaaa)-b---b---b--#';\n\n      const absoluteDelay = new Date(testScheduler.now() + t);\n      const result = e1.pipe(delay(absoluteDelay));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should delay when source does not emit', () => {\n    testScheduler.run(({ hot, time, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  ----|');\n      const e1subs = '  ^---!';\n      const t = time('  ---| ');\n      const expected = '----|';\n\n      const result = e1.pipe(delay(t));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should not delay when source is empty', () => {\n    testScheduler.run(({ cold, time, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' |   ');\n      const e1subs = '  (^!)';\n      const t = time('  ---|');\n      const expected = '|   ';\n\n      const result = e1.pipe(delay(t));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should delay complete when a value is scheduled', () => {\n    testScheduler.run(({ cold, time, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' -a-|    ');\n      const e1subs = '  ^--!    ';\n      const t = time('   ---|   ');\n      const expected = '----(a|)';\n\n      const result = e1.pipe(delay(t));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should not complete when source does not complete', () => {\n    testScheduler.run(({ hot, time, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  ---a---b---------');\n      const e1subs = '  ^---------------!';\n      const t = time('     ---|          ');\n      //                       ---|\n      const expected = '------a---b------';\n      const unsub = '   ----------------!';\n\n      const result = e1.pipe(delay(t));\n\n      expectObservable(result, unsub).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should not break unsubscription chains when result is unsubscribed explicitly', () => {\n    testScheduler.run(({ hot, time, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  ---a---b----');\n      const e1subs = '  ^-------!   ';\n      const t = time('     ---|     ');\n      //                       ---|\n      const expected = '------a--   ';\n      const unsub = '   --------!   ';\n\n      const result = e1.pipe(\n        mergeMap((x: any) => of(x)),\n        delay(t),\n        mergeMap((x: any) => of(x))\n      );\n\n      expectObservable(result, unsub).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should not complete when source never completes', () => {\n    testScheduler.run(({ cold, time, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' -   ');\n      const e1subs = '  ^   ';\n      const t = time('  ---|');\n      const expected = '-   ';\n\n      const result = e1.pipe(delay(t));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  // TODO: We could use a more straightforward way to test this.\n  it('should unsubscribe scheduled actions after execution', () => {\n    testScheduler.run(({ cold, time, expectObservable, expectSubscriptions }) => {\n      let subscribeSpy: any = null;\n      const counts: number[] = [];\n\n      const e1 = cold(' a|      ');\n      const t = time('  -|      ');\n      const expected = '--a-(a|)';\n\n      const result = e1.pipe(\n        repeatWhen((notifications) => {\n          const delayed = notifications.pipe(delay(t));\n          subscribeSpy = sinon.spy(notifications as any, 'subscribe');\n          return delayed;\n        }),\n        skip(1),\n        tap({\n          next() {\n            const [[subscriber]] = subscribeSpy.args;\n            counts.push(subscriber._finalizers.size);\n          },\n          complete() {\n            // This is checking the number of finalizers on the subscribers for\n            // each delayed observable from our 2 repetitions above.\n            // We expect 2 finalizers for each repetition:\n            // 1. The finalizer for the timer subscription that the delay operator uses,\n            // 2. The finalizer that inner subscription uses to remove itself from the\n            // outer subscription's finalizers.\n            expect(counts).to.deep.equal([2, 2]);\n          },\n        }),\n        take(2)\n      );\n\n      expectObservable(result).toBe(expected);\n    });\n  });\n\n  it('should be possible to delay complete by composition', () => {\n    testScheduler.run(({ hot, time, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  ---a--b---|  ');\n      const e1subs = '  ^---------!  ';\n      const t = time('     --|       ');\n      //                      --|\n      //                          --|\n      const expected = '-----a--b---|';\n\n      const result = concat(e1.pipe(delay(t)), of(undefined).pipe(delay(t), ignoreElements()));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n});\n"
  },
  {
    "path": "packages/rxjs/spec/operators/delayWhen-spec.ts",
    "content": "import { of, EMPTY, interval, take } from 'rxjs';\nimport { delayWhen, tap } from 'rxjs/operators';\nimport { TestScheduler } from 'rxjs/testing';\nimport { observableMatcher } from '../helpers/observableMatcher';\nimport { expect } from 'chai';\n\n/** @test {delayWhen} */\ndescribe('delayWhen', () => {\n  let testScheduler: TestScheduler;\n\n  beforeEach(() => {\n    testScheduler = new TestScheduler(observableMatcher);\n  });\n\n  it('should delay by duration selector', () => {\n    testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  ---a---b---c--|      ');\n      const expected = '-----a------c----(b|)';\n      const subs = '    ^-------------!      ';\n      const selector = [\n        cold('             --x--|            '),\n        cold('                 ----------(x|)'),\n        cold('                     -x--|     '),\n      ];\n      const selectorSubs = [\n        '               ---^-!               ',\n        '               -------^---------!   ',\n        '               -----------^!        ',\n      ];\n\n      let idx = 0;\n      function durationSelector(x: any) {\n        return selector[idx++];\n      }\n\n      const result = e1.pipe(delayWhen(durationSelector));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(subs);\n      expectSubscriptions(selector[0].subscriptions).toBe(selectorSubs[0]);\n      expectSubscriptions(selector[1].subscriptions).toBe(selectorSubs[1]);\n      expectSubscriptions(selector[2].subscriptions).toBe(selectorSubs[2]);\n    });\n  });\n\n  it('should delay by selector', () => {\n    testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('     --a--b--| ');\n      const expected = '   ---a--b-| ';\n      const subs = '       ^-------! ';\n      const selector = cold('-x--|   ');\n      //                        -x--|\n      // prettier-ignore\n      const selectorSubs = [\n        '                  --^!      ',\n        '                  -----^!   ',\n      ];\n\n      const result = e1.pipe(delayWhen((x: any) => selector));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(subs);\n      expectSubscriptions(selector.subscriptions).toBe(selectorSubs);\n    });\n  });\n\n  it('should raise error if source raises error', () => {\n    testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('      --a--# ');\n      const expected = '    ---a-# ';\n      const subs = '        ^----! ';\n      const selector = cold(' -x--|');\n      const selectorSubs = '--^!   ';\n\n      const result = e1.pipe(delayWhen((x: any) => selector));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(subs);\n      expectSubscriptions(selector.subscriptions).toBe(selectorSubs);\n    });\n  });\n\n  it('should raise error if selector raises error', () => {\n    testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('      --a--b--|');\n      const expected = '    ---#     ';\n      const subs = '        ^--!     ';\n      const selector = cold(' -#     ');\n      const selectorSubs = '--^!     ';\n\n      const result = e1.pipe(delayWhen((x: any) => selector));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(subs);\n      expectSubscriptions(selector.subscriptions).toBe(selectorSubs);\n    });\n  });\n\n  it('should delay by selector and completes after value emits', () => {\n    testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('     --a--b--|       ');\n      const expected = '   ---------a--(b|)';\n      const subs = '       ^-------!       ';\n      const selector = cold('-------x--|   ');\n      //                        -------x--|\n      // prettier-ignore\n      const selectorSubs = [\n        '                  --^------!      ',\n        '                  -----^------!   '\n      ];\n\n      const result = e1.pipe(delayWhen((x: any) => selector));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(subs);\n      expectSubscriptions(selector.subscriptions).toBe(selectorSubs);\n    });\n  });\n\n  it('should delay, but not emit if the selector never emits a notification', () => {\n    testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('     --a--b--|   ');\n      const expected = '   -----------|';\n      const subs = '       ^-------!   ';\n      const selector = cold('------|   ');\n      //                        ------|\n      // prettier-ignore\n      const selectorSubs = [\n        '                  --^-----!   ',\n        '                  -----^-----!'\n      ];\n\n      const result = e1.pipe(delayWhen((x: any) => selector));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(subs);\n      expectSubscriptions(selector.subscriptions).toBe(selectorSubs);\n    });\n  });\n\n  it('should not emit for async source and sync empty selector', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  a--|');\n      const expected = '---|';\n      const subs = '    ^--!';\n\n      const result = e1.pipe(delayWhen((x: any) => EMPTY));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(subs);\n    });\n  });\n\n  it('should not emit if selector never emits', () => {\n    testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('     --a--b--|');\n      const expected = '   -        ';\n      const subs = '       ^-------!';\n      const selector = cold('-      ');\n      //                        -\n      // prettier-ignore\n      const selectorSubs = [\n        '                  --^      ',\n        '                  -----^   ',\n      ];\n\n      const result = e1.pipe(delayWhen((x: any) => selector));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(subs);\n      expectSubscriptions(selector.subscriptions).toBe(selectorSubs);\n    });\n  });\n\n  it('should delay by first value from selector', () => {\n    testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('     --a--b--|       ');\n      const expected = '   ------a--(b|)   ';\n      const subs = '       ^-------!       ';\n      const selector = cold('----x--y--|   ');\n      //                        ----x--y--|\n      // prettier-ignore\n      const selectorSubs = [\n        '                  --^---!         ',\n        '                  -----^---!      ',\n      ];\n\n      const result = e1.pipe(delayWhen((x: any) => selector));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(subs);\n      expectSubscriptions(selector.subscriptions).toBe(selectorSubs);\n    });\n  });\n\n  it('should delay by selector that does not completes', () => {\n    testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('     --a--b--|          ');\n      const expected = '   ------a--(b|)      ';\n      const subs = '       ^-------!          ';\n      const selector = cold('----x-----y---   ');\n      //                        ----x-----y---\n      // prettier-ignore\n      const selectorSubs = [\n        '                  --^---!            ',\n        '                  -----^---!         '\n      ];\n\n      const result = e1.pipe(delayWhen((x: any) => selector));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(subs);\n      expectSubscriptions(selector.subscriptions).toBe(selectorSubs);\n    });\n  });\n\n  it('should raise error if selector throws', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  --a--b--|');\n      const e1subs = '  ^-!      ';\n      const expected = '--#      ';\n\n      const err = new Error('error');\n      const result = e1.pipe(\n        delayWhen(<any>((x: any) => {\n          throw err;\n        }))\n      );\n\n      expectObservable(result).toBe(expected, null, err);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should start subscription when subscription delay emits', () => {\n    testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('       -----a---b---| ');\n      const expected = '     -------a---b-| ';\n      const subs = '         ---^---------! ';\n      const selector = cold('     --x--|    ');\n      //                              --x--|\n      // prettier-ignore\n      const selectorSubs = [\n        '                      -----^-!     ',\n        '                      ---------^-! '\n      ];\n      const subDelay = cold('---x--|        ');\n      const subDelaySub = '  ^--!           ';\n\n      const result = e1.pipe(delayWhen((x: any) => selector, subDelay));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(subs);\n      expectSubscriptions(selector.subscriptions).toBe(selectorSubs);\n      expectSubscriptions(subDelay.subscriptions).toBe(subDelaySub);\n    });\n  });\n\n  it('should start subscription when subscription delay completes without emit value', () => {\n    testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('       -----a---b---| ');\n      const expected = '     -------a---b-| ';\n      const subs = '         ---^---------! ';\n      const selector = cold('     --x--|    ');\n      //                              --x--|\n      // prettier-ignore\n      const selectorSubs = [\n        '                    -----^-!       ',\n        '                    ---------^-!   '\n      ];\n      const subDelay = cold('---|           ');\n      const subDelaySub = '  ^--!           ';\n\n      const result = e1.pipe(delayWhen((x: any) => selector, subDelay));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(subs);\n      expectSubscriptions(selector.subscriptions).toBe(selectorSubs);\n      expectSubscriptions(subDelay.subscriptions).toBe(subDelaySub);\n    });\n  });\n\n  it('should raise error when subscription delay raises error', () => {\n    testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('       -----a---b---|');\n      const expected = '     ---#          ';\n      const selector = cold('     --x--|   ');\n      const subDelay = cold('---#          ');\n      const subDelaySub = '  ^--!          ';\n\n      const result = e1.pipe(delayWhen((x: any) => selector, subDelay));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe([]);\n      expectSubscriptions(selector.subscriptions).toBe([]);\n      expectSubscriptions(subDelay.subscriptions).toBe(subDelaySub);\n    });\n  });\n\n  it('should complete when duration selector returns synchronous observable', () => {\n    let next: boolean = false;\n    let complete: boolean = false;\n\n    of(1)\n      .pipe(delayWhen(() => of(2)))\n      .subscribe({ next: () => (next = true), complete: () => (complete = true) });\n\n    expect(next).to.be.true;\n    expect(complete).to.be.true;\n  });\n\n  it('should call predicate with indices starting at 0', () => {\n    testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('       --a--b--c--|');\n      const e1subs = '       ^----------!';\n      const expected = '     --a--b--c--|';\n      const selector = cold('  (x|)');\n      //                          (x|)\n      //                             (x|)\n\n      const indices: number[] = [];\n      const predicate = (value: string, index: number) => {\n        indices.push(index);\n        return selector;\n      };\n\n      const result = e1.pipe(delayWhen(predicate));\n\n      expectObservable(\n        result.pipe(\n          tap({\n            complete: () => {\n              expect(indices).to.deep.equal([0, 1, 2]);\n            },\n          })\n        )\n      ).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should delayWhen Promise resolves', (done) => {\n    const e1 = interval(1).pipe(take(5));\n    const expected = [0, 1, 2, 3, 4];\n\n    e1.pipe(delayWhen(() => Promise.resolve(42))).subscribe({\n      next: (x: number) => {\n        expect(x).to.equal(expected.shift());\n      },\n      error: () => {\n        done(new Error('should not be called'));\n      },\n      complete: () => {\n        expect(expected.length).to.equal(0);\n        done();\n      },\n    });\n  });\n\n  it('should raise error when Promise rejects', (done) => {\n    const e1 = interval(1).pipe(take(10));\n    const expected = [0, 1, 2];\n    const error = new Error('err');\n\n    e1.pipe(delayWhen((x) => (x === 3 ? Promise.reject(error) : Promise.resolve(42)))).subscribe({\n      next: (x: number) => {\n        expect(x).to.equal(expected.shift());\n      },\n      error: (err: any) => {\n        expect(err).to.be.an('error');\n        expect(expected.length).to.equal(0);\n        done();\n      },\n      complete: () => {\n        done(new Error('should not be called'));\n      },\n    });\n  });\n});\n"
  },
  {
    "path": "packages/rxjs/spec/operators/dematerialize-spec.ts",
    "content": "import { expect } from 'chai';\nimport type { ObservableNotification} from 'rxjs';\nimport { of, Observable } from 'rxjs';\nimport { COMPLETE_NOTIFICATION, errorNotification, nextNotification } from '@rxjs/observable';\nimport { dematerialize, map, mergeMap, materialize, take } from 'rxjs/operators';\nimport { TestScheduler } from 'rxjs/testing';\nimport { observableMatcher } from '../helpers/observableMatcher';\n\n/** @test {dematerialize} */\ndescribe('dematerialize', () => {\n  let testScheduler: TestScheduler;\n\n  beforeEach(() => {\n    testScheduler = new TestScheduler(observableMatcher);\n  });\n\n  it('should dematerialize an Observable', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const values = {\n        a: '{x}',\n        b: '{y}',\n        c: '{z}',\n        d: '|',\n      };\n\n      const e1 = hot('  --a--b--c--d-|', values);\n      const e1subs = '  ^----------!  ';\n      const expected = '--x--y--z--|  ';\n\n      const result = e1.pipe(\n        map((x: string) => {\n          if (x === '|') {\n            return COMPLETE_NOTIFICATION;\n          } else {\n            return nextNotification(x.replace('{', '').replace('}', ''));\n          }\n        }),\n        dematerialize()\n      );\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should dematerialize a happy stream', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const values = {\n        a: nextNotification('w'),\n        b: nextNotification('x'),\n        c: nextNotification('y'),\n        d: COMPLETE_NOTIFICATION,\n      };\n\n      const e1 = hot('  --a--b--c--d--|', values);\n      const e1subs = '  ^----------!   ';\n      const expected = '--w--x--y--|   ';\n\n      expectObservable(e1.pipe(dematerialize())).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should dematerialize a sad stream', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const values = {\n        a: nextNotification('w'),\n        b: nextNotification('x'),\n        c: nextNotification('y'),\n        d: errorNotification('error'),\n      };\n\n      const e1 = hot('  --a--b--c--d--|', values);\n      const e1subs = '  ^----------!   ';\n      const expected = '--w--x--y--#   ';\n\n      expectObservable(e1.pipe(dematerialize())).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should dematerialize stream does not completes', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot<ObservableNotification<any>>('------');\n      const e1subs = '                             ^';\n      const expected = '                           -';\n\n      expectObservable(e1.pipe(dematerialize())).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should dematerialize stream never completes', () => {\n    testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold<ObservableNotification<any>>('-');\n      const e1subs = '                              ^';\n      const expected = '                            -';\n\n      expectObservable(e1.pipe(dematerialize())).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should dematerialize stream does not emit', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot<ObservableNotification<any>>('----|');\n      const e1subs = '                             ^---!';\n      const expected = '                           ----|';\n\n      expectObservable(e1.pipe(dematerialize())).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should dematerialize empty stream', () => {\n    testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold<ObservableNotification<any>>('|   ');\n      const e1subs = '                              (^!)';\n      const expected = '                            |   ';\n\n      expectObservable(e1.pipe(dematerialize())).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should dematerialize stream throws', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const error = 'error';\n      const e1 = hot('  (x|)', { x: errorNotification(error) });\n      const e1subs = '  (^!)';\n      const expected = '#   ';\n\n      expectObservable(e1.pipe(dematerialize())).toBe(expected, null, error);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should allow unsubscribing early and explicitly', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const values = {\n        a: nextNotification('w'),\n        b: nextNotification('x'),\n      };\n\n      const e1 = hot('  --a--b--c--d--|', values);\n      const e1subs = '  ^------!       ';\n      const expected = '--w--x--       ';\n      const unsub = '   -------!       ';\n\n      const result = e1.pipe(dematerialize());\n\n      expectObservable(result, unsub).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should not break unsubscription chains when unsubscribed explicitly', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const values = {\n        a: nextNotification('w'),\n        b: nextNotification('x'),\n      };\n\n      const e1 = hot('  --a--b--c--d--|', values);\n      const e1subs = '  ^------!       ';\n      const expected = '--w--x--       ';\n      const unsub = '   -------!       ';\n\n      const result = e1.pipe(\n        mergeMap((x: any) => of(x)),\n        dematerialize(),\n        mergeMap((x: any) => of(x))\n      );\n\n      expectObservable(result, unsub).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should dematerialize and completes when stream completes with complete notification', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  ----(a|)', { a: COMPLETE_NOTIFICATION });\n      const e1subs = '  ^---!   ';\n      const expected = '----|   ';\n\n      expectObservable(e1.pipe(dematerialize())).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should dematerialize and completes when stream emits complete notification', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  ----a--|', { a: COMPLETE_NOTIFICATION });\n      const e1subs = '  ^---!   ';\n      const expected = '----|   ';\n\n      expectObservable(e1.pipe(dematerialize())).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should work with materialize', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  ----a--b---c---d---e----f--|');\n      const e1subs = '  ^--------------------------!';\n      const expected = '----a--b---c---d---e----f--|';\n\n      const result = e1.pipe(materialize(), dematerialize());\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should stop listening to a synchronous observable when unsubscribed', () => {\n    const sideEffects: number[] = [];\n    const synchronousObservable = new Observable<number>((subscriber) => {\n      // This will check to see if the subscriber was closed on each loop\n      // when the unsubscribe hits (from the `take`), it should be closed\n      for (let i = 0; !subscriber.closed && i < 10; i++) {\n        sideEffects.push(i);\n        subscriber.next(i);\n      }\n    });\n\n    synchronousObservable.pipe(materialize(), dematerialize(), take(3)).subscribe(() => {\n      /* noop */\n    });\n\n    expect(sideEffects).to.deep.equal([0, 1, 2]);\n  });\n});\n"
  },
  {
    "path": "packages/rxjs/spec/operators/distinct-spec.ts",
    "content": "import { expect } from 'chai';\nimport { distinct, mergeMap, take } from 'rxjs/operators';\nimport { TestScheduler } from 'rxjs/testing';\nimport { of, Observable } from 'rxjs';\nimport { observableMatcher } from '../helpers/observableMatcher';\n\n/** @test {distinct} */\ndescribe('distinct', () => {\n  let testScheduler: TestScheduler;\n\n  beforeEach(() => {\n    testScheduler = new TestScheduler(observableMatcher);\n  });\n\n  it('should distinguish between values', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  --a--a--a--b--b--a--|');\n      const e1subs = '  ^-------------------!';\n      const expected = '--a--------b--------|';\n\n      expectObservable(e1.pipe(distinct())).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should distinguish between values and does not complete', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  --a--a--a--b--b--a-');\n      const e1subs = '  ^------------------';\n      const expected = '--a--------b-------';\n\n      expectObservable(e1.pipe(distinct())).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should not complete if source never completes', () => {\n    testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' -');\n      const e1subs = '  ^';\n      const expected = '-';\n\n      expectObservable(e1.pipe(distinct())).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should not complete if source does not complete', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  -');\n      const e1subs = '  ^';\n      const expected = '-';\n\n      expectObservable(e1.pipe(distinct())).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should complete if source is empty', () => {\n    testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' |');\n      const e1subs = '  (^!)';\n      const expected = '|';\n\n      expectObservable(e1.pipe(distinct())).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should complete if source does not emit', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  ------|');\n      const e1subs = '  ^-----!';\n      const expected = '------|';\n\n      expectObservable(e1.pipe(distinct())).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should emit if source emits single element only', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  --a--|');\n      const e1subs = '  ^----!';\n      const expected = '--a--|';\n\n      expectObservable(e1.pipe(distinct())).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should emit if source is scalar', () => {\n    testScheduler.run(({ expectObservable }) => {\n      const e1 = of('a');\n      const expected = '(a|)';\n\n      expectObservable(e1.pipe(distinct())).toBe(expected);\n    });\n  });\n\n  it('should raises error if source raises error', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  --a--a--#');\n      const e1subs = '  ^-------!';\n      const expected = '--a-----#';\n\n      expectObservable(e1.pipe(distinct())).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should raises error if source throws', () => {\n    testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' #   ');\n      const e1subs = '  (^!)';\n      const expected = '#   ';\n\n      expectObservable(e1.pipe(distinct())).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should not omit if source elements are all different', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  --a--b--c--d--e--f--|');\n      const e1subs = '  ^-------------------!';\n      const expected = '--a--b--c--d--e--f--|';\n\n      expectObservable(e1.pipe(distinct())).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should allow unsubscribing early and explicitly', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  --a--b--b--d--a--f--|');\n      const e1subs = '  ^---------!          ';\n      const expected = '--a--b-----          ';\n      const unsub = '   ----------!          ';\n\n      const result = e1.pipe(distinct());\n\n      expectObservable(result, unsub).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should not break unsubscription chains when unsubscribed explicitly', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  --a--b--b--d--a--f--|');\n      const e1subs = '  ^---------!          ';\n      const expected = '--a--b-----          ';\n      const unsub = '   ----------!          ';\n\n      const result = e1.pipe(\n        mergeMap((x: any) => of(x)),\n        distinct(),\n        mergeMap((x: any) => of(x))\n      );\n\n      expectObservable(result, unsub).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should emit once if source elements are all same', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  --a--a--a--a--a--a--|');\n      const e1subs = '  ^-------------------!';\n      const expected = '--a-----------------|';\n\n      expectObservable(e1.pipe(distinct())).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should distinguish values by key', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const values = { a: 1, b: 2, c: 3, d: 4, e: 5, f: 6 };\n      const e1 = hot('  --a--b--c--d--e--f--|', values);\n      const e1subs = '  ^-------------------!';\n      const expected = '--a--b--c-----------|';\n      const selector = (value: number) => value % 3;\n\n      expectObservable(e1.pipe(distinct(selector))).toBe(expected, values);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should raises error when selector throws', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  --a--b--c--d--e--f--|');\n      const e1subs = '  ^----------!         ';\n      const expected = '--a--b--c--#         ';\n      const selector = (value: string) => {\n        if (value === 'd') {\n          throw new Error('d is for dumb');\n        }\n        return value;\n      };\n\n      expectObservable(e1.pipe(distinct(selector))).toBe(expected, undefined, new Error('d is for dumb'));\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should support a flushing stream', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  --a--b--a--b--a--b--|');\n      const e1subs = '  ^-------------------!';\n      const e2 = hot('  -----------x--------|');\n      const e2subs = '  ^-------------------!';\n      const expected = '--a--b--------a--b--|';\n\n      expectObservable(e1.pipe(distinct(undefined, e2))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should raise error if flush raises error', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  --a--b--a--b--a--b--|');\n      const e1subs = '  ^------------!       ';\n      const e2 = hot('  -----------x-#       ');\n      const e2subs = '  ^------------!       ';\n      const expected = '--a--b-------#       ';\n\n      expectObservable(e1.pipe(distinct(undefined, e2))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should unsubscribe from the flushing stream when the main stream is unsubbed', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  --a--b--a--b--a--b--|');\n      const e1subs = '  ^----------!         ';\n      const e2 = hot('  -----------x--------|');\n      const e2subs = '  ^----------!         ';\n      const unsub = '   -----------!         ';\n      const expected = '--a--b------         ';\n\n      expectObservable(e1.pipe(distinct(undefined, e2)), unsub).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should allow opting in to default comparator with flush', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  --a--b--a--b--a--b--|');\n      const e1subs = '  ^-------------------!';\n      const e2 = hot('  -----------x--------|');\n      const e2subs = '  ^-------------------!';\n      const expected = '--a--b--------a--b--|';\n\n      expectObservable(e1.pipe(distinct(undefined, e2))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should stop listening to a synchronous observable when unsubscribed', () => {\n    const sideEffects: number[] = [];\n    const synchronousObservable = new Observable<number>((subscriber) => {\n      // This will check to see if the subscriber was closed on each loop\n      // when the unsubscribe hits (from the `take`), it should be closed\n      for (let i = 0; !subscriber.closed && i < 10; i++) {\n        sideEffects.push(i);\n        subscriber.next(i);\n      }\n    });\n\n    synchronousObservable.pipe(distinct(), take(3)).subscribe(() => {\n      /* noop */\n    });\n\n    expect(sideEffects).to.deep.equal([0, 1, 2]);\n  });\n});\n"
  },
  {
    "path": "packages/rxjs/spec/operators/distinctUntilChanged-spec.ts",
    "content": "import { expect } from 'chai';\nimport { distinctUntilChanged, mergeMap, take } from 'rxjs/operators';\nimport { of, Observable, Subject } from 'rxjs';\nimport { TestScheduler } from 'rxjs/testing';\nimport { observableMatcher } from '../helpers/observableMatcher';\n\n/** @test {distinctUntilChanged} */\ndescribe('distinctUntilChanged', () => {\n  let testScheduler: TestScheduler;\n\n  beforeEach(() => {\n    testScheduler = new TestScheduler(observableMatcher);\n  });\n\n  it('should distinguish between values', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  -1--2-2----1-3-|');\n      const e1subs = '  ^--------------!';\n      const expected = '-1--2------1-3-|';\n\n      expectObservable(e1.pipe(distinctUntilChanged())).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should distinguish between values', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  --a--a--a--b--b--a--|');\n      const e1subs = '  ^-------------------!';\n      const expected = '--a--------b-----a--|';\n\n      expectObservable(e1.pipe(distinctUntilChanged())).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should distinguish between values and does not complete', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  --a--a--a--b--b--a-');\n      const e1subs = '  ^------------------';\n      const expected = '--a--------b-----a-';\n\n      expectObservable(e1.pipe(distinctUntilChanged())).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should not complete if source never completes', () => {\n    testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' -');\n      const e1subs = '  ^';\n      const expected = '-';\n\n      expectObservable(e1.pipe(distinctUntilChanged())).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should not complete if source does not complete', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  -');\n      const e1subs = '  ^';\n      const expected = '-';\n\n      expectObservable(e1.pipe(distinctUntilChanged())).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should complete if source is empty', () => {\n    testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' |   ');\n      const e1subs = '  (^!)';\n      const expected = '|   ';\n\n      expectObservable(e1.pipe(distinctUntilChanged())).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should complete if source does not emit', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  ------|');\n      const e1subs = '  ^-----!';\n      const expected = '------|';\n\n      expectObservable(e1.pipe(distinctUntilChanged())).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should emit if source emits single element only', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  --a--|');\n      const e1subs = '  ^----!';\n      const expected = '--a--|';\n\n      expectObservable(e1.pipe(distinctUntilChanged())).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should emit if source is scalar', () => {\n    testScheduler.run(({ expectObservable }) => {\n      const e1 = of('a');\n      const expected = '(a|)';\n\n      expectObservable(e1.pipe(distinctUntilChanged())).toBe(expected);\n    });\n  });\n\n  it('should raise error if source raises error', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  --a--a--#');\n      const e1subs = '  ^-------!';\n      const expected = '--a-----#';\n\n      expectObservable(e1.pipe(distinctUntilChanged())).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should raise error if source throws', () => {\n    testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' #   ');\n      const e1subs = '  (^!)';\n      const expected = '#   ';\n\n      expectObservable(e1.pipe(distinctUntilChanged())).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should not omit if source elements are all different', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  --a--b--c--d--e--f--|');\n      const e1subs = '  ^-------------------!';\n      const expected = '--a--b--c--d--e--f--|';\n\n      expectObservable(e1.pipe(distinctUntilChanged())).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should allow unsubscribing early and explicitly', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  --a--b--b--d--a--f--|');\n      const e1subs = '  ^---------!          ';\n      const expected = '--a--b-----          ';\n      const unsub = '   ----------!          ';\n\n      const result = e1.pipe(distinctUntilChanged());\n\n      expectObservable(result, unsub).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should not break unsubscription chains when unsubscribed explicitly', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  --a--b--b--d--a--f--|');\n      const e1subs = '  ^---------!          ';\n      const expected = '--a--b-----          ';\n      const unsub = '   ----------!          ';\n\n      const result = e1.pipe(\n        mergeMap((x: any) => of(x)),\n        distinctUntilChanged(),\n        mergeMap((x: any) => of(x))\n      );\n\n      expectObservable(result, unsub).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should emit once if source elements are all same', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  --a--a--a--a--a--a--|');\n      const e1subs = '  ^-------------------!';\n      const expected = '--a-----------------|';\n\n      expectObservable(e1.pipe(distinctUntilChanged())).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should emit once if comparator returns true always regardless of source emits', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  --a--b--c--d--e--f--|');\n      const e1subs = '  ^-------------------!';\n      const expected = '--a-----------------|';\n      const comparator = () => true;\n\n      expectObservable(e1.pipe(distinctUntilChanged(comparator))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should emit all if comparator returns false always regardless of source emits', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  --a--a--a--a--a--a--|');\n      const e1subs = '  ^-------------------!';\n      const expected = '--a--a--a--a--a--a--|';\n      const comparator = () => false;\n\n      expectObservable(e1.pipe(distinctUntilChanged(comparator))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should distinguish values by comparator', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  --a--b--c--d--e--f--|', { a: 1, b: 2, c: 3, d: 4, e: 5, f: 6 });\n      const e1subs = '  ^-------------------!';\n      const expected = '--a-----c-----e-----|';\n      const comparator = (x: number, y: number) => y % 2 === 0;\n\n      expectObservable(e1.pipe(distinctUntilChanged(comparator))).toBe(expected, { a: 1, c: 3, e: 5 });\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should raise error when comparator throws', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  --a--b--c--d--e--f--|');\n      const e1subs = '  ^----------!         ';\n      const expected = '--a--b--c--#         ';\n      const comparator = (x: string, y: string) => {\n        if (y === 'd') {\n          throw 'error';\n        }\n        return x === y;\n      };\n\n      expectObservable(e1.pipe(distinctUntilChanged(comparator))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should use the keySelector to pick comparator values', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  --a--b--c--d--e--f--|', { a: 1, b: 2, c: 3, d: 4, e: 5, f: 6 });\n      const e1subs = '  ^-------------------!';\n      const expected = '--a--b-----d-----f--|';\n      const comparator = (x: number, y: number) => y % 2 === 1;\n      const keySelector = (x: number) => x % 2;\n\n      expectObservable(e1.pipe(distinctUntilChanged(comparator, keySelector))).toBe(expected, { a: 1, b: 2, d: 4, f: 6 });\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should use the keySelector even for the first emit', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  --a--b--|', { a: 2, b: 4 });\n      const e1subs = '  ^-------!';\n      const expected = '--a-----|';\n      const keySelector = (x: number) => x % 2;\n\n      expectObservable(e1.pipe(distinctUntilChanged(null!, keySelector))).toBe(expected, { a: 2 });\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should raise error when keySelector throws', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  --a--b--c--d--e--f--|');\n      const e1subs = '  ^----------!         ';\n      const expected = '--a--b--c--#         ';\n      const keySelector = (x: string) => {\n        if (x === 'd') {\n          throw 'error';\n        }\n        return x;\n      };\n\n      expectObservable(e1.pipe(distinctUntilChanged(null as any, keySelector))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should stop listening to a synchronous observable when unsubscribed', () => {\n    const sideEffects: number[] = [];\n    const synchronousObservable = new Observable<number>((subscriber) => {\n      // This will check to see if the subscriber was closed on each loop\n      // when the unsubscribe hits (from the `take`), it should be closed\n      for (let i = 0; !subscriber.closed && i < 10; i++) {\n        sideEffects.push(i);\n        subscriber.next(i);\n      }\n    });\n\n    synchronousObservable.pipe(distinctUntilChanged(), take(3)).subscribe(() => {\n      /* noop */\n    });\n\n    expect(sideEffects).to.deep.equal([0, 1, 2]);\n  });\n\n  // This test is to cover a corner case where someone might write\n  // synchronous, reentrant code. At the time this test was authored,\n  // the operator was written in such a way that it would allow\n  // the duplicate non-distinct values to be emitted repeatedly.\n  it('should work properly with reentrant streams', () => {\n    const subject = new Subject<number | undefined>();\n    const results: any[] = [];\n    let count = 0;\n\n    subject.pipe(distinctUntilChanged()).subscribe((n) => {\n      results.push(n);\n\n      // Protect against an infinite loop in this test.\n      // That shouldn't happen.\n      if (++count > 2) {\n        throw new Error('this should have only been hit once');\n      }\n\n      // If we reenter with the same value, it should not\n      // emit again.\n      subject.next(1);\n    });\n\n    // Start with 1.\n    subject.next(1);\n\n    // It should only have emitted one value.\n    expect(results).to.deep.equal([1]);\n  });\n});\n"
  },
  {
    "path": "packages/rxjs/spec/operators/distinctUntilKeyChanged-spec.ts",
    "content": "import { expect } from 'chai';\nimport { distinctUntilKeyChanged, mergeMap, map, take } from 'rxjs/operators';\nimport { TestScheduler } from 'rxjs/testing';\nimport { of, Observable } from 'rxjs';\nimport { observableMatcher } from '../helpers/observableMatcher';\n\n/** @test {distinctUntilKeyChanged} */\ndescribe('distinctUntilKeyChanged', () => {\n  let testScheduler: TestScheduler;\n\n  beforeEach(() => {\n    testScheduler = new TestScheduler(observableMatcher);\n  });\n\n  it('should distinguish between values', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const values = { a: { k: 1 }, b: { k: 2 }, c: { k: 3 } };\n      const e1 = hot('  -a--b-b----a-c-|', values);\n      const e1Subs = '  ^--------------!';\n      const expected = '-a--b------a-c-|';\n\n      const result = e1.pipe(distinctUntilKeyChanged('k'));\n\n      expectObservable(result).toBe(expected, values);\n      expectSubscriptions(e1.subscriptions).toBe(e1Subs);\n    });\n  });\n\n  it('should distinguish between values', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const values = { a: { val: 1 }, b: { val: 2 } };\n      const e1 = hot('  --a--a--a--b--b--a--|', values);\n      const e1subs = '  ^-------------------!';\n      const expected = '--a--------b-----a--|';\n\n      expectObservable(e1.pipe(distinctUntilKeyChanged('val'))).toBe(expected, values);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should distinguish between values and does not complete', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const values = { a: { val: 1 }, b: { val: 2 } };\n      const e1 = hot('  --a--a--a--b--b--a-', values);\n      const e1subs = '  ^                  ';\n      const expected = '--a--------b-----a-';\n\n      expectObservable(e1.pipe(distinctUntilKeyChanged('val'))).toBe(expected, values);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should distinguish between values with key', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const values = { a: { val: 1 }, b: { valOther: 1 }, c: { valOther: 3 }, d: { val: 1 }, e: { val: 5 } };\n      const e1 = hot<any>('--a--b--c--d--e--|', values);\n      const e1subs = '     ^----------------!';\n      const expected = '   --a--b-----d--e--|';\n\n      expectObservable(e1.pipe(distinctUntilKeyChanged('val'))).toBe(expected, values);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should not compare if source does not have element with key', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const values = { a: { valOther: 1 }, b: { valOther: 1 }, c: { valOther: 3 }, d: { valOther: 1 }, e: { valOther: 5 } };\n      const e1 = hot<any>('--a--b--c--d--e--|', values);\n      const e1subs = '     ^----------------!';\n      const expected = '   --a--------------|';\n\n      expectObservable(e1.pipe(distinctUntilKeyChanged('val'))).toBe(expected, values);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should not complete if source never completes', () => {\n    testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold<any>('-');\n      const e1subs = '      ^';\n      const expected = '    -';\n\n      expectObservable(e1.pipe(distinctUntilKeyChanged('val'))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should not complete if source does not complete', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot<any>('-');\n      const e1subs = '     ^';\n      const expected = '   -';\n\n      expectObservable(e1.pipe(distinctUntilKeyChanged('val'))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should complete if source is empty', () => {\n    testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold<any>('|');\n      const e1subs = '      (^!)';\n      const expected = '    |';\n\n      expectObservable(e1.pipe(distinctUntilKeyChanged('val'))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should complete if source does not emit', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot<any>('------|');\n      const e1subs = '     ^-----!';\n      const expected = '   ------|';\n\n      expectObservable(e1.pipe(distinctUntilKeyChanged('val'))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should emit if source emits single element only', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const values = { a: { val: 1 } };\n      const e1 = hot('  --a--|', values);\n      const e1subs = '  ^----!';\n      const expected = '--a--|';\n\n      expectObservable(e1.pipe(distinctUntilKeyChanged('val'))).toBe(expected, values);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should emit if source is scalar', () => {\n    testScheduler.run(({ expectObservable }) => {\n      const values = { a: { val: 1 } };\n      const e1 = of(values.a);\n      const expected = '(a|)';\n\n      expectObservable(e1.pipe(distinctUntilKeyChanged('val'))).toBe(expected, values);\n    });\n  });\n\n  it('should raise error if source raises error', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const values = { a: { val: 1 } };\n      const e1 = hot('  --a--a--#', values);\n      const e1subs = '  ^-------!';\n      const expected = '--a-----#';\n\n      expectObservable(e1.pipe(distinctUntilKeyChanged('val'))).toBe(expected, values);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should raise error if source throws', () => {\n    testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold<any>('#   ');\n      const e1subs = '      (^!)';\n      const expected = '    #   ';\n\n      expectObservable(e1.pipe(distinctUntilKeyChanged('val'))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should not omit if source elements are all different', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const values = { a: { val: 1 }, b: { val: 2 }, c: { val: 3 }, d: { val: 4 }, e: { val: 5 } };\n      const e1 = hot('  --a--b--c--d--e--|', values);\n      const e1subs = '  ^----------------!';\n      const expected = '--a--b--c--d--e--|';\n\n      expectObservable(e1.pipe(distinctUntilKeyChanged('val'))).toBe(expected, values);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should allow unsubscribing early and explicitly', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const values = { a: { val: 1 }, b: { val: 2 }, c: { val: 3 }, d: { val: 4 }, e: { val: 5 } };\n      const e1 = hot('  --a--b--b--d--a--e--|', values);\n      const e1subs = '  ^---------!          ';\n      const expected = '--a--b-----          ';\n      const unsub = '   ----------!          ';\n\n      const result = e1.pipe(distinctUntilKeyChanged('val'));\n\n      expectObservable(result, unsub).toBe(expected, values);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should not break unsubscription chains when unsubscribed explicitly', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const values = { a: { val: 1 }, b: { val: 2 }, c: { val: 3 }, d: { val: 4 }, e: { val: 5 } };\n      const e1 = hot('  --a--b--b--d--a--e--|', values);\n      const e1subs = '  ^---------!          ';\n      const expected = '--a--b-----          ';\n      const unsub = '   ----------!          ';\n\n      const result = e1.pipe(\n        mergeMap((x: any) => of(x)),\n        distinctUntilKeyChanged('val'),\n        mergeMap((x: any) => of(x))\n      );\n\n      expectObservable(result, unsub).toBe(expected, values);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should emit once if source elements are all same', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const values = { a: { val: 1 } };\n      const e1 = hot('  --a--a--a--a--a--a--|', values);\n      const e1subs = '  ^-------------------!';\n      const expected = '--a-----------------|';\n\n      expectObservable(e1.pipe(distinctUntilKeyChanged('val'))).toBe(expected, values);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should emit once if comparer returns true always regardless of source emits', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const values = { a: { val: 1 }, b: { val: 2 }, c: { val: 3 }, d: { val: 4 }, e: { val: 5 } };\n      const e1 = hot('  --a--b--c--d--e--|', values);\n      const e1subs = '  ^----------------!';\n      const expected = '--a--------------|';\n\n      expectObservable(e1.pipe(distinctUntilKeyChanged('val', () => true))).toBe(expected, values);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should emit all if comparer returns false always regardless of source emits', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const values = { a: { val: 1 } };\n      const e1 = hot('  --a--a--a--a--a--a--|', values);\n      const e1subs = '  ^-------------------!';\n      const expected = '--a--a--a--a--a--a--|';\n\n      expectObservable(e1.pipe(distinctUntilKeyChanged('val', () => false))).toBe(expected, values);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should distinguish values by selector', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const values = { a: { val: 1 }, b: { val: 2 }, c: { val: 3 }, d: { val: 4 }, e: { val: 5 } };\n      const e1 = hot('  --a--b--c--d--e--|', values);\n      const e1subs = '  ^----------------!';\n      const expected = '--a-----c-----e--|';\n      const selector = (x: number, y: number) => y % 2 === 0;\n\n      expectObservable(e1.pipe(distinctUntilKeyChanged('val', selector))).toBe(expected, values);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should raise error when comparer throws', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const values = { a: { val: 1 }, b: { val: 2 }, c: { val: 3 }, d: { val: 4 }, e: { val: 5 } };\n      const e1 = hot('  --a--b--c--d--e--|', values);\n      const e1subs = '  ^----------!      ';\n      const expected = '--a--b--c--#      ';\n      const selector = (x: number, y: number) => {\n        if (y === 4) {\n          throw 'error';\n        }\n        return x === y;\n      };\n\n      expectObservable(e1.pipe(distinctUntilKeyChanged('val', selector))).toBe(expected, values);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should stop listening to a synchronous observable when unsubscribed', () => {\n    const sideEffects: number[] = [];\n    const synchronousObservable = new Observable<number>((subscriber) => {\n      // This will check to see if the subscriber was closed on each loop\n      // when the unsubscribe hits (from the `take`), it should be closed\n      for (let i = 0; !subscriber.closed && i < 10; i++) {\n        sideEffects.push(i);\n        subscriber.next(i);\n      }\n    });\n\n    synchronousObservable\n      .pipe(\n        map((value) => ({ value })),\n        distinctUntilKeyChanged('value'),\n        take(3)\n      )\n      .subscribe(() => {\n        /* noop */\n      });\n\n    expect(sideEffects).to.deep.equal([0, 1, 2]);\n  });\n});\n"
  },
  {
    "path": "packages/rxjs/spec/operators/elementAt-spec.ts",
    "content": "import { expect } from 'chai';\nimport { elementAt, mergeMap, tap } from 'rxjs/operators';\nimport { TestScheduler } from 'rxjs/testing';\nimport { ArgumentOutOfRangeError, of, range, Observable, Subject, merge } from 'rxjs';\nimport { observableMatcher } from '../helpers/observableMatcher';\n\n/** @test {elementAt} */\ndescribe('elementAt', () => {\n  let testScheduler: TestScheduler;\n\n  beforeEach(() => {\n    testScheduler = new TestScheduler(observableMatcher);\n  });\n\n  it('should return next to last element by zero-based index', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  --a--b--c-d---|');\n      const e1subs = '  ^-------!      ';\n      const expected = '--------(c|)   ';\n\n      expectObservable(e1.pipe(elementAt(2))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should return first element by zero-based index', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  --a--b--c--|');\n      const e1subs = '  ^-!';\n      const expected = '--(a|)';\n\n      expectObservable(e1.pipe(elementAt(0))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should allow undefined as a default value', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  -----a--a---a-|   ');\n      const e1subs = '  ^-------------!   ';\n      const expected = '--------------(U|)';\n\n      expectObservable(e1.pipe(elementAt(100, undefined))).toBe(expected, { U: undefined });\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should return non-first element by zero-based index', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  --a--b--c--d--e--f--|');\n      const e1subs = '  ^----------!         ';\n      const expected = '-----------(d|)      ';\n\n      expectObservable(e1.pipe(elementAt(3))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should return last element by zero-based index', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  --a--b--c--|');\n      const e1subs = '  ^-------!   ';\n      const expected = '--------(c|)';\n\n      expectObservable(e1.pipe(elementAt(2))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should raise error if e1 is Empty Observable', () => {\n    testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' |   ');\n      const e1subs = '  (^!)';\n      const expected = '#   ';\n\n      expectObservable(e1.pipe(elementAt(0))).toBe(expected, undefined, new ArgumentOutOfRangeError());\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should raise error if source throws', () => {\n    testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' #   ');\n      const e1subs = '  (^!)';\n      const expected = '#   ';\n\n      expectObservable(e1.pipe(elementAt(0))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should not complete if source never completes', () => {\n    testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' -');\n      const expected = '-';\n      const e1subs = '  ^';\n\n      expectObservable(e1.pipe(elementAt(0))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should allow unsubscribing early and explicitly', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  --a--b--c--|');\n      const e1subs = '  ^-----!     ';\n      const expected = '-------     ';\n      const unsub = '   ------!     ';\n\n      const result = e1.pipe(elementAt(2));\n\n      expectObservable(result, unsub).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should not break unsubscription chains when result Observable is unsubscribed', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  --a--b--c--|');\n      const e1subs = '  ^-----!     ';\n      const expected = '-------     ';\n      const unsub = '   ------!     ';\n\n      const result = e1.pipe(\n        mergeMap((x: any) => of(x)),\n        elementAt(2),\n        mergeMap((x: any) => of(x))\n      );\n\n      expectObservable(result, unsub).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should throw if index is smaller than zero', () => {\n    expect(() => {\n      range(0, 10).pipe(elementAt(-1));\n    }).to.throw(ArgumentOutOfRangeError);\n  });\n\n  it('should raise error if index is out of range but does not have default value', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  --a--|');\n      const e1subs = '  ^----!';\n      const expected = '-----#';\n\n      expectObservable(e1.pipe(elementAt(3))).toBe(expected, null, new ArgumentOutOfRangeError());\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should return default value if index is out of range', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  --a--|   ');\n      const e1subs = '  ^----!   ';\n      const expected = '-----(x|)';\n      const defaultValue = '42';\n\n      expectObservable(e1.pipe(elementAt(3, defaultValue))).toBe(expected, { x: defaultValue });\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should stop listening to a synchronous observable when unsubscribed', () => {\n    const sideEffects: number[] = [];\n    const synchronousObservable = new Observable<number>((subscriber) => {\n      // This will check to see if the subscriber was closed on each loop\n      // when the unsubscribe hits, it should be closed\n      for (let i = 0; !subscriber.closed && i < 10; i++) {\n        sideEffects.push(i);\n        subscriber.next(i);\n      }\n    });\n\n    synchronousObservable.pipe(elementAt(2)).subscribe(() => {\n      /* noop */\n    });\n\n    expect(sideEffects).to.deep.equal([0, 1, 2]);\n  });\n\n  it('should not emit errors sent from the source *after* it found the first value in reentrant scenarios', () => {\n    testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const subject = new Subject();\n      const source = cold('-------a----b----c---|');\n      const expected = '   ------------(b|)';\n      const subs = '       ^-----------!';\n\n      const result = merge(source, subject).pipe(\n        elementAt(1),\n        tap(() => {\n          subject.error(new Error('reentrant shennanigans'));\n        })\n      );\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(source.subscriptions).toBe(subs);\n    });\n  });\n});\n"
  },
  {
    "path": "packages/rxjs/spec/operators/endWith-spec.ts",
    "content": "import { expect } from 'chai';\nimport { of, Observable } from 'rxjs';\nimport { endWith, mergeMap, take } from 'rxjs/operators';\nimport { TestScheduler } from 'rxjs/testing';\nimport { observableMatcher } from '../helpers/observableMatcher';\n\n/** @test {endWith} */\ndescribe('endWith', () => {\n  const defaultEndValue = 'x';\n  let testScheduler: TestScheduler;\n\n  beforeEach(() => {\n    testScheduler = new TestScheduler(observableMatcher);\n  });\n\n  it('should append to a cold Observable', () => {\n    testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' ---a--b--c--|   ');\n      const e1subs = '  ^-----------!   ';\n      const expected = '---a--b--c--(s|)';\n\n      expectObservable(e1.pipe(endWith('s'))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should append numbers to a cold Observable', () => {\n    testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const values = { a: 1, b: 2, c: 3, s: 4 };\n      const e1 = cold(' ---a--b--c--|   ', values);\n      const e1subs = '  ^-----------!   ';\n      const expected = '---a--b--c--(s|)';\n\n      expectObservable(e1.pipe(endWith(values.s))).toBe(expected, values);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should end an observable with given value', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  --a--|   ');\n      const e1subs = '  ^----!   ';\n      const expected = '--a--(x|)';\n\n      expectObservable(e1.pipe(endWith(defaultEndValue))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should not end with given value if source does not complete', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  ----a-');\n      const e1subs = '  ^     ';\n      const expected = '----a-';\n\n      expectObservable(e1.pipe(endWith(defaultEndValue))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should not end with given value if source never emits and does not completes', () => {\n    testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' -');\n      const e1subs = '  ^';\n      const expected = '-';\n\n      expectObservable(e1.pipe(endWith(defaultEndValue))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should end with given value if source does not emit but does complete', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  ---|   ');\n      const e1subs = '  ^--!   ';\n      const expected = '---(x|)';\n\n      expectObservable(e1.pipe(endWith(defaultEndValue))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should emit given value and complete immediately if source is empty', () => {\n    testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' |   ');\n      const e1subs = '  (^!)';\n      const expected = '(x|)';\n\n      expectObservable(e1.pipe(endWith(defaultEndValue))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should end with given value and source both if source emits single value', () => {\n    testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' (a|) ');\n      const e1subs = '  (^!) ';\n      const expected = '(ax|)';\n\n      expectObservable(e1.pipe(endWith(defaultEndValue))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should end with given values when given more than one value', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  -----a--|    ');\n      const e1subs = '  ^-------!    ';\n      const expected = '-----a--(yz|)';\n\n      expectObservable(e1.pipe(endWith('y', 'z'))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should raise error and not end with given value if source raises error', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  --#');\n      const e1subs = '  ^-!';\n      const expected = '--#';\n\n      expectObservable(e1.pipe(endWith(defaultEndValue))).toBe(expected, defaultEndValue);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should raise error immediately and not end with given value if source throws error immediately', () => {\n    testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' #   ');\n      const e1subs = '  (^!)';\n      const expected = '#   ';\n\n      expectObservable(e1.pipe(endWith(defaultEndValue))).toBe(expected, defaultEndValue);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should allow unsubscribing explicitly and early', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  ---a--b----c--d--|');\n      const e1subs = '  ^--------!        ';\n      const expected = '---a--b---        ';\n      const unsub = '   ---------!        ';\n\n      const result = e1.pipe(endWith('s'));\n\n      expectObservable(result, unsub).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should not break unsubscription chains when result is unsubscribed explicitly', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  ---a--b----c--d--|');\n      const e1subs = '  ^--------!        ';\n      const expected = '---a--b---        ';\n      const unsub = '   ---------!        ';\n\n      const result = e1.pipe(\n        mergeMap((x: string) => of(x)),\n        endWith('s'),\n        mergeMap((x: string) => of(x))\n      );\n\n      expectObservable(result, unsub).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should end with empty if given value is not specified', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  -a-|');\n      const e1subs = '  ^--!';\n      const expected = '-a-|';\n\n      expectObservable(e1.pipe(endWith())).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should stop listening to a synchronous observable when unsubscribed', () => {\n    const sideEffects: number[] = [];\n    const synchronousObservable = new Observable<number>((subscriber) => {\n      // This will check to see if the subscriber was closed on each loop\n      // when the unsubscribe hits (from the `take`), it should be closed\n      for (let i = 0; !subscriber.closed && i < 10; i++) {\n        sideEffects.push(i);\n        subscriber.next(i);\n      }\n    });\n\n    synchronousObservable.pipe(endWith(0), take(3)).subscribe(() => {\n      /* noop */\n    });\n\n    expect(sideEffects).to.deep.equal([0, 1, 2]);\n  });\n});\n"
  },
  {
    "path": "packages/rxjs/spec/operators/every-spec.ts",
    "content": "import { expect } from 'chai';\nimport { every, mergeMap } from 'rxjs/operators';\nimport { TestScheduler } from 'rxjs/testing';\nimport type { Observer } from 'rxjs';\nimport { of, Observable, Subject } from 'rxjs';\nimport { observableMatcher } from '../helpers/observableMatcher';\n\n/** @test {every} */\ndescribe('every', () => {\n  let testScheduler: TestScheduler;\n\n  beforeEach(() => {\n    testScheduler = new TestScheduler(observableMatcher);\n  });\n\n  function truePredicate(x: number | string) {\n    return true;\n  }\n\n  function predicate(x: number | string) {\n    return +x % 5 === 0;\n  }\n\n  it('should return false if only one of elements does not match with predicate', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const values = { a: 5, b: 10, c: 15, d: 18, e: 20 };\n      const e1 = hot('  --a--b--c--d--e--|', values);\n      const e1subs = '  ^----------!      ';\n      const expected = '-----------(x|)   ';\n\n      expectObservable(e1.pipe(every(predicate))).toBe(expected, { x: false });\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should increment index on each call to the predicate', () => {\n    const indices: number[] = [];\n    of(1, 2, 3, 4)\n      .pipe(\n        every((_, i) => {\n          indices.push(i);\n          return true;\n        })\n      )\n      .subscribe();\n\n    expect(indices).to.deep.equal([0, 1, 2, 3]);\n  });\n\n  it('should emit true if source is empty', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  -----|   ');\n      const e1subs = '  ^----!   ';\n      const expected = '-----(x|)';\n\n      expectObservable(e1.pipe(every(predicate))).toBe(expected, { x: true });\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should emit false if single source element does not match with predicate', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  --a--|');\n      const e1subs = '  ^-!   ';\n      const expected = '--(x|)';\n\n      expectObservable(e1.pipe(every(predicate))).toBe(expected, { x: false });\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should emit false if none of elements match with predicate', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  --a--b--c--d--e--|');\n      const e1subs = '  ^-!               ';\n      const expected = '--(x|)            ';\n\n      expectObservable(e1.pipe(every(predicate))).toBe(expected, { x: false });\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should return false if only some of elements matches with predicate', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const values = { a: 5, b: 10, c: 15 };\n      const e1 = hot('  --a--b--c--d--e--|', values);\n      const e1subs = '  ^----------!      ';\n      const expected = '-----------(x|)   ';\n\n      expectObservable(e1.pipe(every(predicate))).toBe(expected, { x: false });\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should allow unsubscribing early and explicitly', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const values = { a: 5, b: 10, c: 15 };\n      const e1 = hot('  --a--b--c--d--e--|', values);\n      const e1subs = '  ^------!          ';\n      const expected = '--------          ';\n      const unsub = '   -------!          ';\n\n      const result = e1.pipe(every(predicate));\n\n      expectObservable(result, unsub).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should not break unsubscription chains when result observable is unsubscribed', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const values = { a: 5, b: 10, c: 15 };\n      const e1 = hot('  --a--b--c--d--e--|', values);\n      const e1subs = '  ^------!          ';\n      const expected = '--------          ';\n      const unsub = '   -------!          ';\n\n      const result = e1.pipe(\n        mergeMap((x: any) => of(x)),\n        every(predicate),\n        mergeMap((x: any) => of(x))\n      );\n\n      expectObservable(result, unsub).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should propagate error if predicate eventually throws', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  --a--b--c--d--e--|');\n      const e1subs = '  ^-------!';\n      const expected = '--------#';\n\n      function faultyPredicate(x: string) {\n        if (x === 'c') {\n          throw 'error';\n        } else {\n          return true;\n        }\n      }\n\n      expectObservable(e1.pipe(every(faultyPredicate))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should emit true if single source element matches with predicate', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const values = { a: 5 };\n      const e1 = hot('  --a--|   ', values);\n      const e1subs = '  ^----!   ';\n      const expected = '-----(x|)';\n\n      expectObservable(e1.pipe(every(predicate))).toBe(expected, { x: true });\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should emit true if scalar source matches with predicate', () => {\n    testScheduler.run(({ expectObservable }) => {\n      const e1 = of(5);\n      const expected = '(x|)';\n\n      expectObservable(e1.pipe(every(predicate))).toBe(expected, { x: true });\n    });\n  });\n\n  it('should emit false if scalar source does not match with predicate', () => {\n    testScheduler.run(({ expectObservable }) => {\n      const e1 = of(3);\n      const expected = '(x|)';\n\n      expectObservable(e1.pipe(every(predicate))).toBe(expected, { x: false });\n    });\n  });\n\n  it('should propagate error if predicate throws on scalar source', () => {\n    testScheduler.run(({ expectObservable }) => {\n      const e1 = of(3);\n      const expected = '#';\n\n      function faultyPredicate(x: number): boolean {\n        throw 'error';\n      }\n\n      expectObservable(e1.pipe(every(faultyPredicate))).toBe(expected);\n    });\n  });\n\n  it('should emit true if scalar array source matches with predicate', () => {\n    testScheduler.run(({ expectObservable }) => {\n      const e1 = of(5, 10, 15, 20);\n      const expected = '(x|)';\n\n      expectObservable(e1.pipe(every(predicate))).toBe(expected, { x: true });\n    });\n  });\n\n  it('should emit false if scalar array source does not match with predicate', () => {\n    testScheduler.run(({ expectObservable }) => {\n      const e1 = of(5, 9, 15, 20);\n      const expected = '(x|)';\n\n      expectObservable(e1.pipe(every(predicate))).toBe(expected, { x: false });\n    });\n  });\n\n  it('should propagate error if predicate eventually throws on scalar array source', () => {\n    testScheduler.run(({ expectObservable }) => {\n      const e1 = of(5, 10, 15, 20);\n      const expected = '#';\n\n      function faultyPredicate(x: number) {\n        if (x === 15) {\n          throw 'error';\n        }\n        return true;\n      }\n\n      expectObservable(e1.pipe(every(faultyPredicate))).toBe(expected);\n    });\n  });\n\n  it('should emit true if all source elements match with predicate', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const values = { a: 5, b: 10, c: 15, d: 20, e: 25 };\n      const e1 = hot('  --a--b--c--d--e--|   ', values);\n      const e1subs = '  ^----------------!   ';\n      const expected = '-----------------(x|)';\n\n      expectObservable(e1.pipe(every(predicate))).toBe(expected, { x: true });\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should raise error if source raises error', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  --#');\n      const e1subs = '  ^-!';\n      const expected = '--#';\n\n      expectObservable(e1.pipe(every(truePredicate))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should not complete if source never emits', () => {\n    testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' -');\n      const e1subs = '  ^';\n      const expected = '-';\n\n      expectObservable(e1.pipe(every(truePredicate))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should emit true if source element matches with predicate after subscription', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const values = { a: 5, b: 10, c: 15, d: 20, e: 25 };\n      const e1 = hot('--z--^--a--b--c--d--e--|   ', values);\n      const e1subs = '     ^-----------------!   ';\n      const expected = '   ------------------(x|)';\n\n      expectObservable(e1.pipe(every(predicate))).toBe(expected, { x: true });\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should emit false if source element does not match with predicate after subscription', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const values = { a: 5, b: 10, c: 15, d: 20 };\n      const e1 = hot('--z--^--b--c--z--d--|', values);\n      const e1subs = '     ^--------!      ';\n      const expected = '   ---------(x|)   ';\n\n      expectObservable(e1.pipe(every(predicate))).toBe(expected, { x: false });\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should raise error if source raises error after subscription', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('--z--^--#');\n      const e1subs = '     ^--!';\n      const expected = '   ---#';\n\n      expectObservable(e1.pipe(every(truePredicate))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should emit true if source does not emit after subscription', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('--z--^-----|   ');\n      const e1subs = '     ^-----!   ';\n      const expected = '   ------(x|)';\n\n      expectObservable(e1.pipe(every(predicate))).toBe(expected, { x: true });\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should handle reentrancy properly', () => {\n    const subject = new Subject<number>();\n    const results: any[] = [];\n    let n = 0;\n\n    subject.pipe(every(() => false)).subscribe({\n      next: (result) => {\n        results.push(result);\n        if (n < 3) {\n          subject.next(n++);\n        }\n      },\n      complete: () => results.push('done'),\n    });\n\n    subject.next(n);\n\n    expect(results).to.deep.equal([false, 'done']);\n  });\n});\n"
  },
  {
    "path": "packages/rxjs/spec/operators/exhaustAll-spec.ts",
    "content": "import { expect } from 'chai';\nimport { exhaustAll, mergeMap, take } from 'rxjs/operators';\nimport { TestScheduler } from 'rxjs/testing';\nimport { of, Observable } from 'rxjs';\nimport { observableMatcher } from '../helpers/observableMatcher';\n\n/** @test {exhaustAll} */\ndescribe('exhaustAll', () => {\n  let testScheduler: TestScheduler;\n\n  beforeEach(() => {\n    testScheduler = new TestScheduler(observableMatcher);\n  });\n\n  it('should handle a hot observable of hot observables', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const x = hot('   -----a---b---c--|                  ');\n      const xsubs = '   ------^---------!                  ';\n      const y = hot('   -------d--e---f---|                ');\n      const ysubs: string[] = [];\n      const z = hot('   --------------g--h---i---|         ');\n      const zsubs = '   --------------------^----!         ';\n      const e1 = hot('  ------x-------y-----z-------------|', { x: x, y: y, z: z });\n      const e1subs = '  ^---------------------------------!';\n      const expected = '---------b---c-------i------------|';\n\n      expectObservable(e1.pipe(exhaustAll())).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(x.subscriptions).toBe(xsubs);\n      expectSubscriptions(y.subscriptions).toBe(ysubs);\n      expectSubscriptions(z.subscriptions).toBe(zsubs);\n    });\n  });\n\n  it('should switch to first immediately-scheduled inner Observable', () => {\n    testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' (ab|)');\n      const e1subs = '  (^!) ';\n      const e2 = cold(' (cd|)');\n      const e2subs: string[] = [];\n      const expected = '(ab|)';\n\n      expectObservable(of(e1, e2).pipe(exhaustAll())).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should handle throw', () => {\n    testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' #   ');\n      const e1subs = '  (^!)';\n      const expected = '#   ';\n\n      expectObservable(e1.pipe(exhaustAll())).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should handle empty', () => {\n    testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' |   ');\n      const e1subs = '  (^!)';\n      const expected = '|   ';\n\n      expectObservable(e1.pipe(exhaustAll())).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should handle never', () => {\n    testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' -');\n      const e1subs = '  ^';\n      const expected = '-';\n\n      expectObservable(e1.pipe(exhaustAll())).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should handle a hot observable of observables', () => {\n    testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => {\n      const x = cold('        --a---b---c--|               ');\n      const xsubs = '   ------^------------!               ';\n      const y = cold('                ---d--e---f---|      ');\n      const ysubs: string[] = [];\n      const z = cold('                      ---g--h---i---|');\n      const zsubs = '   --------------------^-------------!';\n      const e1 = hot('  ------x-------y-----z-------------|', { x: x, y: y, z: z });\n      const e1subs = '  ^---------------------------------!';\n      const expected = '--------a---b---c------g--h---i---|';\n\n      expectObservable(e1.pipe(exhaustAll())).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(x.subscriptions).toBe(xsubs);\n      expectSubscriptions(y.subscriptions).toBe(ysubs);\n      expectSubscriptions(z.subscriptions).toBe(zsubs);\n    });\n  });\n\n  it('should handle a hot observable of observables, outer is unsubscribed early', () => {\n    testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => {\n      const x = cold('        --a---b---c--|         ');\n      const xsubs = '   ------^---------!            ';\n      const y = cold('                ---d--e---f---|');\n      const ysubs: string[] = [];\n      const e1 = hot('  ------x-------y------|       ', { x: x, y: y });\n      const unsub = '   ----------------!            ';\n      const expected = '--------a---b----            ';\n\n      expectObservable(e1.pipe(exhaustAll()), unsub).toBe(expected);\n      expectSubscriptions(x.subscriptions).toBe(xsubs);\n      expectSubscriptions(y.subscriptions).toBe(ysubs);\n    });\n  });\n\n  it('should not break unsubscription chains when result is unsubscribed explicitly', () => {\n    testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => {\n      const x = cold('        --a---b---c--|         ');\n      const xsubs = '   ------^---------!            ';\n      const y = cold('                ---d--e---f---|');\n      const ysubs: string[] = [];\n      const e1 = hot('  ------x-------y------|       ', { x: x, y: y });\n      const unsub = '   ----------------!            ';\n      const expected = '--------a---b----            ';\n\n      const result = e1.pipe(\n        mergeMap((x) => of(x)),\n        exhaustAll(),\n        mergeMap((x) => of(x))\n      );\n\n      expectObservable(result, unsub).toBe(expected);\n      expectSubscriptions(x.subscriptions).toBe(xsubs);\n      expectSubscriptions(y.subscriptions).toBe(ysubs);\n    });\n  });\n\n  it('should handle a hot observable of observables, inner never completes', () => {\n    testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => {\n      const x = cold('     --a---b--|              ');\n      const xsubs = '   ---^--------!              ';\n      const y = cold('         -d---e-             ');\n      const ysubs: string[] = [];\n      const z = cold('                ---f--g---h--');\n      const zsubs = '   --------------^------------';\n      const e1 = hot('  ---x---y------z----------| ', { x: x, y: y, z: z });\n      const expected = '-----a---b-------f--g---h--';\n\n      expectObservable(e1.pipe(exhaustAll())).toBe(expected);\n      expectSubscriptions(x.subscriptions).toBe(xsubs);\n      expectSubscriptions(y.subscriptions).toBe(ysubs);\n      expectSubscriptions(z.subscriptions).toBe(zsubs);\n    });\n  });\n\n  it('should handle a synchronous switch and stay on the first inner observable', () => {\n    testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => {\n      const x = cold('        --a---b---c--|   ');\n      const xsubs = '   ------^------------!   ';\n      const y = cold('        ---d--e---f---|  ');\n      const ysubs: string[] = [];\n      const e1 = hot('  ------(xy)------------|', { x: x, y: y });\n      const expected = '--------a---b---c-----|';\n\n      expectObservable(e1.pipe(exhaustAll())).toBe(expected);\n      expectSubscriptions(x.subscriptions).toBe(xsubs);\n      expectSubscriptions(y.subscriptions).toBe(ysubs);\n    });\n  });\n\n  it('should handle a hot observable of observables, one inner throws', () => {\n    testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => {\n      const x = cold('        --a---#                ');\n      const xsubs = '   ------^-----!                ';\n      const y = cold('                ---d--e---f---|');\n      const ysubs: string[] = [];\n      const e1 = hot('  ------x-------y------|       ', { x: x, y: y });\n      const expected = '--------a---#                ';\n\n      expectObservable(e1.pipe(exhaustAll())).toBe(expected);\n      expectSubscriptions(x.subscriptions).toBe(xsubs);\n      expectSubscriptions(y.subscriptions).toBe(ysubs);\n    });\n  });\n\n  it('should handle a hot observable of observables, outer throws', () => {\n    testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => {\n      const x = cold('        --a---b---c--|         ');\n      const xsubs = '   ------^------------!         ';\n      const y = cold('                ---d--e---f---|');\n      const ysubs: string[] = [];\n      const e1 = hot('  ------x-------y-------#      ', { x: x, y: y });\n      const expected = '--------a---b---c-----#      ';\n\n      expectObservable(e1.pipe(exhaustAll())).toBe(expected);\n      expectSubscriptions(x.subscriptions).toBe(xsubs);\n      expectSubscriptions(y.subscriptions).toBe(ysubs);\n    });\n  });\n\n  it('should handle an empty hot observable', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  ------|');\n      const e1subs = '  ^-----!';\n      const expected = '------|';\n\n      expectObservable(e1.pipe(exhaustAll())).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should handle a never hot observable', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  -');\n      const e1subs = '  ^';\n      const expected = '-';\n\n      expectObservable(e1.pipe(exhaustAll())).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should complete not before the outer completes', () => {\n    testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => {\n      const x = cold('        --a---b---c--|   ');\n      const xsubs = '   ------^------------!   ';\n      const e1 = hot('  ------x---------------|', { x: x });\n      const expected = '--------a---b---c-----|';\n\n      expectObservable(e1.pipe(exhaustAll())).toBe(expected);\n      expectSubscriptions(x.subscriptions).toBe(xsubs);\n    });\n  });\n\n  it('should handle an observable of promises', (done) => {\n    const expected = [1];\n\n    of(Promise.resolve(1), Promise.resolve(2), Promise.resolve(3))\n      .pipe(exhaustAll())\n      .subscribe({\n        next: (x) => {\n          expect(x).to.equal(expected.shift());\n        },\n        complete: () => {\n          expect(expected.length).to.equal(0);\n          done();\n        },\n      });\n  });\n\n  it('should handle an observable of promises, where one rejects', (done) => {\n    of(Promise.reject(2), Promise.resolve(1))\n      .pipe(exhaustAll())\n      .subscribe({\n        next: (x) => {\n          done(new Error('should not be called'));\n        },\n        error: (err) => {\n          expect(err).to.equal(2);\n          done();\n        },\n        complete: () => {\n          done(new Error('should not be called'));\n        },\n      });\n  });\n\n  it('should stop listening to a synchronous observable when unsubscribed', () => {\n    const sideEffects: number[] = [];\n    const synchronousObservable = new Observable<number>((subscriber) => {\n      // This will check to see if the subscriber was closed on each loop\n      // when the unsubscribe hits (from the `take`), it should be closed\n      for (let i = 0; !subscriber.closed && i < 10; i++) {\n        sideEffects.push(i);\n        subscriber.next(i);\n      }\n    });\n\n    of(synchronousObservable)\n      .pipe(exhaustAll(), take(3))\n      .subscribe(() => {\n        /* noop */\n      });\n\n    expect(sideEffects).to.deep.equal([0, 1, 2]);\n  });\n\n  it('should handle synchronously completing inner observables', (done) => {\n    let i = 1;\n    of(of(1), of(2))\n      .pipe(exhaustAll())\n      .subscribe({\n        next: (v) => expect(v).to.equal(i++),\n        complete: () => {\n          expect(i).to.equal(3);\n          done();\n        },\n      });\n  });\n});\n"
  },
  {
    "path": "packages/rxjs/spec/operators/exhaustMap-spec.ts",
    "content": "import { TestScheduler } from 'rxjs/testing';\nimport { concat, defer, Observable, of, BehaviorSubject } from 'rxjs';\nimport { exhaustMap, mergeMap, takeWhile, map, take } from 'rxjs/operators';\nimport { expect } from 'chai';\nimport { asInteropObservable } from '../helpers/interop-helper';\nimport { observableMatcher } from '../helpers/observableMatcher';\n\n/** @test {exhaustMap} */\ndescribe('exhaustMap', () => {\n  let testScheduler: TestScheduler;\n\n  beforeEach(() => {\n    testScheduler = new TestScheduler(observableMatcher);\n  });\n\n  it('should map-and-flatten each item to an Observable', () => {\n    testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => {\n      const values = { x: 10, y: 30, z: 50 };\n      const e1 = hot('   --1-----3--5-------|');\n      const e1subs = '   ^------------------!';\n      const e2 = cold('    x-x-x|            ', values);\n      //                         x-x-x|\n      //                            x-x-x|\n      const expected = ' --x-x-x-y-y-y------|';\n\n      const result = e1.pipe(exhaustMap((x) => e2.pipe(map((i) => i * +x))));\n\n      expectObservable(result).toBe(expected, values);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should handle outer throw', () => {\n    testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const x = cold('  --a--b--c--|');\n      const xsubs: string[] = [];\n      const e1 = cold(' #   ');\n      const e1subs = '  (^!)';\n      const expected = '#   ';\n\n      const result = e1.pipe(exhaustMap(() => x));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(x.subscriptions).toBe(xsubs);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should handle outer empty', () => {\n    testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const x = cold('  --a--b--c--|');\n      const xsubs: string[] = [];\n      const e1 = cold(' |   ');\n      const e1subs = '  (^!)';\n      const expected = '|   ';\n\n      const result = e1.pipe(exhaustMap(() => x));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(x.subscriptions).toBe(xsubs);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should handle outer never', () => {\n    testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const x = cold('  --a--b--c--|');\n      const xsubs: string[] = [];\n      const e1 = cold(' -');\n      const e1subs = '  ^';\n      const expected = '-';\n\n      const result = e1.pipe(exhaustMap(() => x));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(x.subscriptions).toBe(xsubs);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should raise error if project throws', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  ---x---------y-----------------z-------------|');\n      const e1subs = '  ^--!';\n      const expected = '---#';\n\n      const result = e1.pipe(\n        exhaustMap(() => {\n          throw 'error';\n        })\n      );\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should switch with a selector function', () => {\n    testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => {\n      const x = cold('     --a--b--c--|                               ');\n      const xsubs = '   ---^----------!                               ';\n      const y = cold('               --d--e--f--|                     ');\n      const ysubs: string[] = [];\n      const z = cold('                                 --g--h--i--|   ');\n      const zsubs = '   -------------------------------^----------!   ';\n      const e1 = hot('  ---x---------y-----------------z-------------|');\n      const e1subs = '  ^--------------------------------------------!';\n      const expected = '-----a--b--c---------------------g--h--i-----|';\n\n      const observableLookup: Record<string, Observable<string>> = { x: x, y: y, z: z };\n\n      const result = e1.pipe(exhaustMap((value) => observableLookup[value]));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(x.subscriptions).toBe(xsubs);\n      expectSubscriptions(y.subscriptions).toBe(ysubs);\n      expectSubscriptions(z.subscriptions).toBe(zsubs);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should switch inner cold observables, outer is unsubscribed early', () => {\n    testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => {\n      const x = cold('     --a--b--c--|                               ');\n      const xsubs = '   ---^----------!                               ';\n      const y = cold('               --d--e--f--|                     ');\n      const ysubs: string[] = [];\n      const z = cold('                                 --g--h--i--|   ');\n      const zsubs = '   -------------------------------^--!           ';\n      const e1 = hot('  ---x---------y-----------------z-------------|');\n      const unsub = '   ----------------------------------!           ';\n      const e1subs = '  ^---------------------------------!           ';\n      const expected = '-----a--b--c---------------------g-           ';\n\n      const observableLookup: Record<string, Observable<string>> = { x: x, y: y, z: z };\n\n      const result = e1.pipe(exhaustMap((value) => observableLookup[value]));\n\n      expectObservable(result, unsub).toBe(expected);\n      expectSubscriptions(x.subscriptions).toBe(xsubs);\n      expectSubscriptions(y.subscriptions).toBe(ysubs);\n      expectSubscriptions(z.subscriptions).toBe(zsubs);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should not break unsubscription chains when result is unsubscribed explicitly', () => {\n    testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => {\n      const x = cold('     --a--b--c--|                               ');\n      const xsubs = '   ---^----------!                               ';\n      const y = cold('               --d--e--f--|                     ');\n      const ysubs: string[] = [];\n      const z = cold('                                 --g--h--i--|   ');\n      const zsubs = '   -------------------------------^--!           ';\n      const e1 = hot('  ---x---------y-----------------z-------------|');\n      const e1subs = '  ^---------------------------------!           ';\n      const expected = '-----a--b--c---------------------g-           ';\n      const unsub = '   ----------------------------------!           ';\n\n      const observableLookup: Record<string, Observable<string>> = { x: x, y: y, z: z };\n\n      const result = e1.pipe(\n        mergeMap((x) => of(x)),\n        exhaustMap((value) => observableLookup[value]),\n        mergeMap((x) => of(x))\n      );\n\n      expectObservable(result, unsub).toBe(expected);\n      expectSubscriptions(x.subscriptions).toBe(xsubs);\n      expectSubscriptions(y.subscriptions).toBe(ysubs);\n      expectSubscriptions(z.subscriptions).toBe(zsubs);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should not break unsubscription chains with interop inners when result is unsubscribed explicitly', () => {\n    testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => {\n      const x = cold('     --a--b--c--|                               ');\n      const xsubs = '   ---^----------!                               ';\n      const y = cold('               --d--e--f--|                     ');\n      const ysubs: string[] = [];\n      const z = cold('                                 --g--h--i--|   ');\n      const zsubs = '   -------------------------------^--!           ';\n      const e1 = hot('  ---x---------y-----------------z-------------|');\n      const e1subs = '  ^---------------------------------!           ';\n      const expected = '-----a--b--c---------------------g-           ';\n      const unsub = '   ----------------------------------!           ';\n\n      const observableLookup: Record<string, Observable<string>> = { x: x, y: y, z: z };\n\n      // This test is the same as the previous test, but the observable is\n      // manipulated to make it look like an interop observable - an observable\n      // from a foreign library. Interop subscribers are treated differently:\n      // they are wrapped in a safe subscriber. This test ensures that\n      // unsubscriptions are chained all the way to the interop subscriber.\n\n      const result = e1.pipe(\n        mergeMap((x) => of(x)),\n        exhaustMap((value) => asInteropObservable(observableLookup[value])),\n        mergeMap((x) => of(x))\n      );\n\n      expectObservable(result, unsub).toBe(expected);\n      expectSubscriptions(x.subscriptions).toBe(xsubs);\n      expectSubscriptions(y.subscriptions).toBe(ysubs);\n      expectSubscriptions(z.subscriptions).toBe(zsubs);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should stop listening to a synchronous observable when unsubscribed', () => {\n    const sideEffects: number[] = [];\n    const synchronousObservable = concat(\n      defer(() => {\n        sideEffects.push(1);\n        return of(1);\n      }),\n      defer(() => {\n        sideEffects.push(2);\n        return of(2);\n      }),\n      defer(() => {\n        sideEffects.push(3);\n        return of(3);\n      })\n    );\n\n    of(null)\n      .pipe(\n        exhaustMap(() => synchronousObservable),\n        takeWhile((x) => x != 2) // unsubscribe at the second side-effect\n      )\n      .subscribe(() => {\n        /* noop */\n      });\n\n    expect(sideEffects).to.deep.equal([1, 2]);\n  });\n\n  it('should switch inner cold observables, inner never completes', () => {\n    testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => {\n      const x = cold('     --a--b--c--|                              ');\n      const xsubs = '   ---^----------!                              ';\n      const y = cold('               --d--e--f--|                    ');\n      const ysubs: string[] = [];\n      const z = cold('                                 --g--h--i-----');\n      const zsubs = '   -------------------------------^-------------';\n      const e1 = hot('  ---x---------y-----------------z---------|   ');\n      const e1subs = '  ^----------------------------------------!   ';\n      const expected = '-----a--b--c---------------------g--h--i-----';\n\n      const observableLookup: Record<string, Observable<string>> = { x: x, y: y, z: z };\n\n      const result = e1.pipe(exhaustMap((value) => observableLookup[value]));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(x.subscriptions).toBe(xsubs);\n      expectSubscriptions(y.subscriptions).toBe(ysubs);\n      expectSubscriptions(z.subscriptions).toBe(zsubs);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should handle a synchronous switch and stay on the first inner observable', () => {\n    testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => {\n      const x = cold('           --a--b--c--d--e--|   ');\n      const xsubs = '   ---------^----------------!   ';\n      const y = cold('           ---f---g---h---i--|  ');\n      const ysubs: string[] = [];\n      const e1 = hot('  ---------(xy)----------------|');\n      const e1subs = '  ^----------------------------!';\n      const expected = '-----------a--b--c--d--e-----|';\n\n      const observableLookup: Record<string, Observable<string>> = { x: x, y: y };\n\n      const result = e1.pipe(exhaustMap((value) => observableLookup[value]));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(x.subscriptions).toBe(xsubs);\n      expectSubscriptions(y.subscriptions).toBe(ysubs);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should switch inner cold observables, one inner throws', () => {\n    testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => {\n      const x = cold('           --a--b--c--d--#             ');\n      const xsubs = '   ---------^-------------!             ';\n      const y = cold('                     ---f---g---h---i--');\n      const ysubs: string[] = [];\n      const e1 = hot('  ---------x---------y---------|       ');\n      const e1subs = '  ^----------------------!             ';\n      const expected = '-----------a--b--c--d--#             ';\n\n      const observableLookup: Record<string, Observable<string>> = { x: x, y: y };\n\n      const result = e1.pipe(exhaustMap((value) => observableLookup[value]));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(x.subscriptions).toBe(xsubs);\n      expectSubscriptions(y.subscriptions).toBe(ysubs);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should switch inner hot observables', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const x = hot('   -----a--b--c--d--e--|                  ');\n      const xsubs = '   ---------^----------!                  ';\n      const y = hot('   --p-o-o-p-------f---g---h---i--|       ');\n      const ysubs: string[] = [];\n      const z = hot('   ---z-o-o-m-------------j---k---l---m--|');\n      const zsubs = '   --------------------^-----------------!';\n      const e1 = hot('  ---------x----y-----z--------|         ');\n      const e1subs = '  ^----------------------------!         ';\n      const expected = '-----------c--d--e-----j---k---l---m--|';\n\n      const observableLookup: Record<string, Observable<string>> = { x: x, y: y, z: z };\n\n      const result = e1.pipe(exhaustMap((value) => observableLookup[value]));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(x.subscriptions).toBe(xsubs);\n      expectSubscriptions(y.subscriptions).toBe(ysubs);\n      expectSubscriptions(z.subscriptions).toBe(zsubs);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should switch inner empty and empty', () => {\n    testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => {\n      const x = cold('           |                    ');\n      const y = cold('                     |          ');\n      const xsubs = '   ---------(^!)                 ';\n      const ysubs = '   -------------------(^!)       ';\n      const e1 = hot('  ---------x---------y---------|');\n      const e1subs = '  ^----------------------------!';\n      const expected = '-----------------------------|';\n\n      const observableLookup: Record<string, Observable<string>> = { x: x, y: y };\n\n      const result = e1.pipe(exhaustMap((value) => observableLookup[value]));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(x.subscriptions).toBe(xsubs);\n      expectSubscriptions(y.subscriptions).toBe(ysubs);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should switch inner empty and never', () => {\n    testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => {\n      const x = cold('           |                    ');\n      const xsubs = '   ---------(^!)                 ';\n      const y = cold('                     -          ');\n      const ysubs = '   -------------------^          ';\n      const e1 = hot('  ---------x---------y---------|');\n      const e1subs = '  ^----------------------------!';\n      const expected = '------------------------------';\n\n      const observableLookup: Record<string, Observable<string>> = { x: x, y: y };\n\n      const result = e1.pipe(exhaustMap((value) => observableLookup[value]));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(x.subscriptions).toBe(xsubs);\n      expectSubscriptions(y.subscriptions).toBe(ysubs);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should never switch inner never', () => {\n    testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => {\n      const x = cold('           -                     ');\n      const xsubs = '   ---------^                     ';\n      const y = cold('                     #           ');\n      const ysubs: string[] = [];\n      const e1 = hot('  ---------x---------y----------|');\n      const e1subs = '  ^-----------------------------!';\n      const expected = '-------------------------------';\n\n      const observableLookup: Record<string, Observable<string>> = { x: x, y: y };\n\n      const result = e1.pipe(exhaustMap((value) => observableLookup[value]));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(x.subscriptions).toBe(xsubs);\n      expectSubscriptions(y.subscriptions).toBe(ysubs);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should switch inner empty and throw', () => {\n    testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => {\n      const x = cold('           |                    ');\n      const xsubs = '   ---------(^!)                 ';\n      const y = cold('                     #          ');\n      const ysubs = '   -------------------(^!)       ';\n      const e1 = hot('  ---------x---------y---------|');\n      const e1subs = '  ^------------------!          ';\n      const expected = '-------------------#          ';\n\n      const observableLookup: Record<string, Observable<string>> = { x: x, y: y };\n\n      const result = e1.pipe(exhaustMap((value) => observableLookup[value]));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(x.subscriptions).toBe(xsubs);\n      expectSubscriptions(y.subscriptions).toBe(ysubs);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should handle outer error', () => {\n    testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => {\n      const x = cold('           --a--b--c--d--e--|');\n      const xsubs = '   ---------^---------!       ';\n      const e1 = hot('  ---------x---------#       ');\n      const e1subs = '  ^------------------!       ';\n      const expected = '-----------a--b--c-#       ';\n\n      const observableLookup: Record<string, Observable<string>> = { x: x };\n\n      const result = e1.pipe(exhaustMap((value) => observableLookup[value]));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(x.subscriptions).toBe(xsubs);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should stop listening to a synchronous observable when unsubscribed', () => {\n    const sideEffects: number[] = [];\n    const synchronousObservable = new Observable<number>((subscriber) => {\n      // This will check to see if the subscriber was closed on each loop\n      // when the unsubscribe hits (from the `take`), it should be closed\n      for (let i = 0; !subscriber.closed && i < 10; i++) {\n        sideEffects.push(i);\n        subscriber.next(i);\n      }\n    });\n\n    synchronousObservable\n      .pipe(\n        exhaustMap((value) => of(value)),\n        take(3)\n      )\n      .subscribe(() => {\n        /* noop */\n      });\n\n    expect(sideEffects).to.deep.equal([0, 1, 2]);\n  });\n\n  it('should ignore subsequent synchronous reentrances during subscribing the inner sub', () => {\n    const e = new BehaviorSubject(1);\n    const results: Array<number> = [];\n\n    e.pipe(\n      take(3),\n      exhaustMap(\n        (value) =>\n          new Observable<number>((subscriber) => {\n            e.next(value + 1);\n            subscriber.next(value);\n          })\n      )\n    ).subscribe((value) => results.push(value));\n\n    expect(results).to.deep.equal([1]);\n  });\n});\n"
  },
  {
    "path": "packages/rxjs/spec/operators/expand-spec.ts",
    "content": "import { expect } from 'chai';\nimport { expand, mergeMap, map, take, toArray } from 'rxjs/operators';\nimport { TestScheduler } from 'rxjs/testing';\nimport type { Observer, InteropObservable } from 'rxjs';\nimport { EMPTY, Observable, of, asapScheduler, asyncScheduler } from 'rxjs';\nimport { observableMatcher } from '../helpers/observableMatcher';\n\n/** @test {expand} */\ndescribe('expand', () => {\n  let testScheduler: TestScheduler;\n\n  beforeEach(() => {\n    testScheduler = new TestScheduler(observableMatcher);\n  });\n\n  it('should recursively map-and-flatten each item to an Observable', () => {\n    testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  --x----|  ', { x: 1 });\n      const e1subs = '  ^------!  ';\n      const e2 = cold('   --c|    ', { c: 2 });\n      //                    --c|\n      //                      --c|\n      const expected = '--a-b-c-d|';\n      const values = { a: 1, b: 2, c: 4, d: 8 };\n\n      const result = e1.pipe(expand((x) => (x === 8 ? EMPTY : e2.pipe(map((c) => c * x)))));\n\n      expectObservable(result).toBe(expected, values);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should map and recursively flatten', () => {\n    testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => {\n      const values = {\n        a: 1,\n        b: 1 + 1, // a + a,\n        c: 2 + 2, // b + b,\n        d: 4 + 4, // c + c,\n        e: 8 + 8, // d + d\n      };\n      const e1 = hot('  (a|)            ', values);\n      const e1subs = '  (^!)            ';\n      const e2shape = ' ---(z|)         ';\n      const expected = 'a--b--c--d--(e|)';\n      /*\n        expectation explanation: (conjunction junction?) ...\n\n        since `cold('---(z|)')` emits `x + x` and completes on frame 30\n        but the next \"expanded\" return value is synchronously subscribed to in\n        that same frame, it stacks like so:\n\n        a\n        ---(b|)\n           ---(c|)\n              ---(d|)\n                 ---(e|)      (...which flattens into:)\n        a--b--c--d--(e|)\n      */\n\n      const result = e1.pipe(\n        expand((x, index): Observable<any> => {\n          if (x === 16) {\n            return EMPTY;\n          } else {\n            return cold(e2shape, { z: x + x });\n          }\n        })\n      );\n\n      expectObservable(result).toBe(expected, values);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should map and recursively flatten, and handle event raised error', () => {\n    testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => {\n      const values = {\n        a: 1,\n        b: 1 + 1, // a + a,\n        c: 2 + 2, // b + b,\n        d: 4 + 4, // c + c,\n        e: 8 + 8, // d + d\n      };\n      const e1 = hot('  (a|)         ', values);\n      const e1subs = '  (^!)         ';\n      const e2shape = ' ---(z|)      ';\n      const expected = 'a--b--c--(d#)';\n\n      const result = e1.pipe(\n        expand((x) => {\n          if (x === 8) {\n            return cold<number>('#');\n          }\n          return cold(e2shape, { z: x + x });\n        })\n      );\n\n      expectObservable(result).toBe(expected, values);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should map and recursively flatten, and propagate error thrown from projection', () => {\n    testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => {\n      const values = {\n        a: 1,\n        b: 1 + 1, // a + a,\n        c: 2 + 2, // b + b,\n        d: 4 + 4, // c + c,\n        e: 8 + 8, // d + d\n      };\n      const e1 = hot('  (a|)         ', values);\n      const e1subs = '  (^!)         ';\n      const e2shape = ' ---(z|)      ';\n      const expected = 'a--b--c--(d#)';\n\n      const result = e1.pipe(\n        expand((x) => {\n          if (x === 8) {\n            throw 'error';\n          }\n          return cold(e2shape, { z: x + x });\n        })\n      );\n\n      expectObservable(result).toBe(expected, values);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should allow unsubscribing early', () => {\n    testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => {\n      const values = {\n        a: 1,\n        b: 1 + 1, // a + a,\n        c: 2 + 2, // b + b,\n        d: 4 + 4, // c + c,\n        e: 8 + 8, // d + d\n      };\n      const e1 = hot('  (a|)    ', values);\n      const unsub = '   -------!';\n      const e1subs = '  (^!)    ';\n      const e2shape = ' ---(z|) ';\n      const expected = 'a--b--c-';\n\n      const result = e1.pipe(\n        expand((x): Observable<any> => {\n          if (x === 16) {\n            return EMPTY;\n          }\n          return cold(e2shape, { z: x + x });\n        })\n      );\n\n      expectObservable(result, unsub).toBe(expected, values);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should not break unsubscription chains when result is unsubscribed explicitly', () => {\n    testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => {\n      const values = {\n        a: 1,\n        b: 1 + 1, // a + a,\n        c: 2 + 2, // b + b,\n        d: 4 + 4, // c + c,\n        e: 8 + 8, // d + d\n      };\n      const e1 = hot('  (a|)    ', values);\n      const e1subs = '  (^!)    ';\n      const e2shape = ' ---(z|) ';\n      const expected = 'a--b--c-';\n      const unsub = '   -------!';\n\n      const result = e1.pipe(\n        mergeMap((x) => of(x)),\n        expand((x): Observable<any> => {\n          if (x === 16) {\n            return EMPTY;\n          }\n          return cold(e2shape, { z: x + x });\n        }),\n        mergeMap((x) => of(x))\n      );\n\n      expectObservable(result, unsub).toBe(expected, values);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should allow concurrent expansions', () => {\n    testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => {\n      const values = {\n        a: 1,\n        b: 1 + 1, // a + a,\n        c: 2 + 2, // b + b,\n        d: 4 + 4, // c + c,\n        e: 8 + 8, // d + d\n      };\n      const e1 = hot('  a-a|              ', values);\n      const e1subs = '  ^--!              ';\n      const e2shape = ' ---(z|)           ';\n      const expected = 'a-ab-bc-cd-de-(e|)';\n\n      const result = e1.pipe(\n        expand((x): Observable<any> => {\n          if (x === 16) {\n            return EMPTY;\n          }\n          return cold(e2shape, { z: x + x });\n        })\n      );\n\n      expectObservable(result).toBe(expected, values);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should allow configuring the concurrency limit parameter to 1', () => {\n    testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => {\n      const values = {\n        a: 1,\n        b: 1 + 1, // a + a,\n        c: 2 + 2, // b + b,\n        d: 4 + 4, // c + c,\n        e: 8 + 8, // d + d\n        u: 10,\n        v: 20, // u + u\n        x: 40, // v + v\n        y: 80, // x + x\n        z: 160, // y + y\n      };\n      const e1 = hot('  a-u|                         ', values);\n      const e1subs = '  ^--!                         ';\n      const e2shape = ' ---(z|)                      ';\n      //                 ---(z|)\n      //                    ---(z|)\n      //                       ---(z|)\n      //                          ---(z|)\n      //                             ---(z|)\n      //                                ---(z|)\n      //                                   ---(z|)\n      // Notice how for each column, there is at most 1 `-` character.\n      const expected = 'a--u--b--v--c--x--d--y--(ez|)';\n      const concurrencyLimit = 1;\n\n      const result = e1.pipe(\n        expand((x): Observable<any> => {\n          if (x === 16 || x === 160) {\n            return EMPTY;\n          }\n          return cold(e2shape, { z: x + x });\n        }, concurrencyLimit)\n      );\n\n      expectObservable(result).toBe(expected, values);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should allow configuring the concurrency limit parameter to 2', () => {\n    testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => {\n      const values = {\n        a: 1,\n        b: 1 + 1, // a + a,\n        c: 2 + 2, // b + b,\n        u: 10,\n        v: 20, // u + u\n        x: 40, // v + v\n      };\n      const e1 = hot('  a---au|                   ', values);\n      const e1subs = '  ^-----!                   ';\n      const e2shape = ' ------(z|)                ';\n      //                  ------(z|)\n      //                    ------(z|)\n      //                        ------(z|)\n      //                          ------(z|)\n      //                              ------(z|)\n      //                                ------(z|)\n      // Notice how for each column, there is at most 2 `-` characters.\n      const expected = 'a---a-u---b-b---v-(cc)(x|)';\n      const concurrencyLimit = 2;\n\n      const result = e1.pipe(\n        expand((x): Observable<any> => {\n          if (x === 4 || x === 40) {\n            return EMPTY;\n          }\n          return cold(e2shape, { z: x + x });\n        }, concurrencyLimit)\n      );\n\n      expectObservable(result).toBe(expected, values);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should ignore concurrency limit if it is not passed', () => {\n    testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => {\n      const values = {\n        a: 1,\n        b: 1 + 1, // a + a,\n        c: 2 + 2, // b + b,\n        d: 4 + 4, // c + c,\n        e: 8 + 8, // d + d\n        u: 10,\n        v: 20, // u + u\n        x: 40, // v + v\n        y: 80, // x + x\n        z: 160, // y + y\n      };\n      const e1 = hot('  a-u|              ', values);\n      const e1subs = '  ^--!              ';\n      const e2shape = ' ---(z|)           ';\n      const expected = 'a-ub-vc-xd-ye-(z|)';\n      const concurrencyLimit = 100;\n\n      const result = e1.pipe(\n        expand((x): Observable<any> => {\n          if (x === 16 || x === 160) {\n            return EMPTY;\n          }\n          return cold(e2shape, { z: x + x });\n        }, concurrencyLimit)\n      );\n\n      expectObservable(result).toBe(expected, values);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should map and recursively flatten with scalars', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const values = {\n        a: 1,\n        b: 1 + 1, // a + a,\n        c: 2 + 2, // b + b,\n        d: 4 + 4, // c + c,\n        e: 8 + 8, // d + d\n      };\n      const e1 = hot('  (a|)    ', values);\n      const e1subs = '  (^!)    ';\n      const expected = '(abcde|)';\n\n      const result = e1.pipe(\n        expand((x) => {\n          if (x === 16) {\n            return EMPTY;\n          }\n          return of(x + x); // scalar\n        })\n      );\n\n      expectObservable(result).toBe(expected, values);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should recursively flatten promises', (done) => {\n    const expected = [1, 2, 4, 8, 16];\n    of(1)\n      .pipe(\n        expand((x): any => {\n          if (x === 16) {\n            return EMPTY;\n          }\n          return Promise.resolve(x + x);\n        })\n      )\n      .subscribe({\n        next: (x) => {\n          expect(x).to.equal(expected.shift());\n        },\n        complete: () => {\n          expect(expected.length).to.equal(0);\n          done();\n        },\n      });\n  });\n\n  it('should recursively flatten Arrays', (done) => {\n    const expected = [1, 2, 4, 8, 16];\n    of(1)\n      .pipe(\n        expand((x): any => {\n          if (x === 16) {\n            return EMPTY;\n          }\n          return [x + x];\n        })\n      )\n      .subscribe({\n        next: (x) => {\n          expect(x).to.equal(expected.shift());\n        },\n        complete: () => {\n          expect(expected.length).to.equal(0);\n          done();\n        },\n      });\n  });\n\n  it('should recursively flatten lowercase-o observables', (done) => {\n    const expected = [1, 2, 4, 8, 16];\n    const project = (x: number): InteropObservable<number> => {\n      if (x === 16) {\n        return EMPTY as any;\n      }\n\n      return {\n        subscribe(observer: Observer<number>) {\n          observer.next(x + x);\n          observer.complete();\n        },\n        [Symbol.observable]() {\n          return this;\n        },\n      } as any;\n    };\n\n    of(1)\n      .pipe(expand(project))\n      .subscribe({\n        next: (x) => {\n          expect(x).to.equal(expected.shift());\n        },\n        complete: () => {\n          expect(expected.length).to.equal(0);\n          done();\n        },\n      });\n  });\n\n  it('should work when passing undefined for the optional arguments', () => {\n    testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => {\n      const values = {\n        a: 1,\n        b: 1 + 1, // a + a,\n        c: 2 + 2, // b + b,\n        d: 4 + 4, // c + c,\n        e: 8 + 8, // d + d\n      };\n      const e1 = hot('  (a|)            ', values);\n      const e1subs = '  (^!)            ';\n      const e2shape = ' ---(z|)         ';\n      const expected = 'a--b--c--d--(e|)';\n\n      const project = (x: any, index: number): Observable<any> => {\n        if (x === 16) {\n          return EMPTY;\n        }\n        return cold(e2shape, { z: x + x });\n      };\n\n      const result = e1.pipe(expand(project, undefined));\n\n      expectObservable(result).toBe(expected, values);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should stop listening to a synchronous observable when unsubscribed', () => {\n    const sideEffects: number[] = [];\n    const synchronousObservable = new Observable<number>((subscriber) => {\n      // This will check to see if the subscriber was closed on each loop\n      // when the unsubscribe hits (from the `take`), it should be closed\n      for (let i = 0; !subscriber.closed && i < 10; i++) {\n        sideEffects.push(i);\n        subscriber.next(i);\n      }\n    });\n\n    synchronousObservable\n      .pipe(\n        expand(() => EMPTY),\n        take(3)\n      )\n      .subscribe(() => {\n        /* noop */\n      });\n\n    expect(sideEffects).to.deep.equal([0, 1, 2]);\n  });\n});\n"
  },
  {
    "path": "packages/rxjs/spec/operators/filter-spec.ts",
    "content": "import { expect } from 'chai';\nimport { filter, tap, map, mergeMap, take } from 'rxjs/operators';\nimport { TestScheduler } from 'rxjs/testing';\nimport { of, Observable, from } from 'rxjs';\nimport { observableMatcher } from '../helpers/observableMatcher';\n\n/** @test {filter} */\ndescribe('filter', () => {\n  let testScheduler: TestScheduler;\n\n  beforeEach(() => {\n    testScheduler = new TestScheduler(observableMatcher);\n  });\n\n  function oddFilter(x: number | string) {\n    return +x % 2 === 1;\n  }\n\n  function isPrime(i: number | string) {\n    if (+i <= 1) {\n      return false;\n    }\n    const max = Math.floor(Math.sqrt(+i));\n    for (let j = 2; j <= max; ++j) {\n      if (+i % j === 0) {\n        return false;\n      }\n    }\n    return true;\n  }\n\n  it('should filter out even values', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  --0--1--2--3--4--|');\n      const e1subs = '  ^----------------!';\n      const expected = '-----1-----3-----|';\n\n      expectObservable(e1.pipe(filter(oddFilter))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should filter in only prime numbers', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('-1--2--^-3-4-5-6--7-8--9--|');\n      const e1subs = '       ^------------------!';\n      const expected = '     --3---5----7-------|';\n\n      expectObservable(e1.pipe(filter(isPrime))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should filter with an always-true predicate', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('-1--2--^-3-4-5-6--7-8--9--|');\n      const e1subs = '       ^------------------!';\n      const expected = '     --3-4-5-6--7-8--9--|';\n\n      const predicate = () => {\n        return true;\n      };\n\n      expectObservable(e1.pipe(filter(predicate))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should filter with an always-false predicate', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('-1--2--^-3-4-5-6--7-8--9--|');\n      const e1subs = '       ^------------------!';\n      const expected = '     -------------------|';\n\n      const predicate = () => {\n        return false;\n      };\n\n      expectObservable(e1.pipe(filter(predicate))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should filter in only prime numbers, source unsubscribes early', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('-1--2--^-3-4-5-6--7-8--9--|');\n      const e1subs = '       ^-----------!       ';\n      const expected = '     --3---5----7-       ';\n      const unsub = '        ------------!       ';\n\n      expectObservable(e1.pipe(filter(isPrime)), unsub).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should filter in only prime numbers, source throws', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('-1--2--^-3-4-5-6--7-8--9--#');\n      const e1subs = '       ^------------------!';\n      const expected = '     --3---5----7-------#';\n\n      expectObservable(e1.pipe(filter(isPrime))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should filter in only prime numbers, but predicate throws', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('-1--2--^-3-4-5-6--7-8--9--|');\n      const e1subs = '       ^-------!           ';\n      const expected = '     --3---5-#           ';\n\n      let invoked = 0;\n      function predicate(x: any) {\n        invoked++;\n        if (invoked === 4) {\n          throw 'error';\n        }\n        return isPrime(x);\n      }\n\n      expectObservable(e1.pipe(filter(predicate))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should filter in only prime numbers, predicate with index', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('-1--2--^-3-4-5-6--7-8--9--|');\n      const e1subs = '       ^------------------!';\n      const expected = '     --3--------7-------|';\n\n      function predicate(x: any, i: number) {\n        return isPrime(+x + i * 10);\n      }\n\n      expectObservable(e1.pipe(filter(predicate))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should invoke predicate once for each checked value', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('-1--2--^-3-4-5-6--7-8--9--|');\n      const e1subs = '       ^------------------!';\n      const expected = '     --3---5----7-------|';\n\n      let invoked = 0;\n      const predicate = (x: any) => {\n        invoked++;\n        return isPrime(x);\n      };\n\n      const result = e1.pipe(\n        filter(predicate),\n        tap({\n          complete: () => {\n            expect(invoked).to.equal(7);\n          },\n        })\n      );\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should filter in only prime numbers, predicate with index, source unsubscribes early', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('-1--2--^-3-4-5-6--7-8--9--|');\n      const e1subs = '       ^-----------!       ';\n      const expected = '     --3--------7-       ';\n      const unsub = '        ------------!       ';\n\n      function predicate(x: any, i: number) {\n        return isPrime(+x + i * 10);\n      }\n\n      expectObservable(e1.pipe(filter(predicate)), unsub).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should filter in only prime numbers, predicate with index, source throws', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('-1--2--^-3-4-5-6--7-8--9--#');\n      const e1subs = '       ^------------------!';\n      const expected = '     --3--------7-------#';\n\n      function predicate(x: any, i: number) {\n        return isPrime(+x + i * 10);\n      }\n\n      expectObservable(e1.pipe(filter(predicate))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should filter in only prime numbers, predicate with index and throws', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('-1--2--^-3-4-5-6--7-8--9--|');\n      const e1subs = '       ^-------!           ';\n      const expected = '     --3-----#           ';\n\n      let invoked = 0;\n      function predicate(x: any, i: number) {\n        invoked++;\n        if (invoked === 4) {\n          throw 'error';\n        }\n        return isPrime(+x + i * 10);\n      }\n\n      expectObservable(e1.pipe(filter(predicate))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should compose with another filter to allow multiples of six', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('-1--2--^-3-4-5-6--7-8--9--|');\n      const e1subs = '       ^------------------!';\n      const expected = '     --------6----------|';\n\n      const result = e1.pipe(\n        filter((x: string) => +x % 2 === 0),\n        filter((x: string) => +x % 3 === 0)\n      );\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should be able to accept and use a thisArg', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('-1--2--^-3-4-5-6--7-8--9--|');\n      const e1subs = '       ^------------------!';\n      const expected = '     --------6----------|';\n\n      class Filterer {\n        filter1 = (x: string) => +x % 2 === 0;\n        filter2 = (x: string) => +x % 3 === 0;\n      }\n\n      const filterer = new Filterer();\n\n      const result = e1.pipe(\n        filter(function (this: any, x) {\n          return this.filter1(x);\n        }, filterer),\n        filter(function (this: any, x) {\n          return this.filter2(x);\n        }, filterer),\n        filter(function (this: any, x) {\n          return this.filter1(x);\n        }, filterer)\n      );\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should be able to use filter and map composed', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('-1--2--^-3-4-5-6--7-8--9--|');\n      const e1subs = '       ^------------------!';\n      const expected = '     ----a---b----c-----|';\n      const values = { a: 16, b: 36, c: 64 };\n\n      const result = e1.pipe(\n        filter((x: string) => +x % 2 === 0),\n        map((x: string) => +x * +x)\n      );\n\n      expectObservable(result).toBe(expected, values);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should propagate errors from the source', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  --0--1--2--3--4--#');\n      const e1subs = '  ^----------------!';\n      const expected = '-----1-----3-----#';\n\n      expectObservable(e1.pipe(filter(oddFilter))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should handle empty', () => {\n    testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' |   ');\n      const e1subs = '  (^!)';\n      const expected = '|   ';\n\n      expectObservable(e1.pipe(filter(oddFilter))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should handle never', () => {\n    testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' -');\n      const e1subs = '  ^';\n      const expected = '-';\n\n      expectObservable(e1.pipe(filter(oddFilter))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should handle throw', () => {\n    testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' #   ');\n      const e1subs = '  (^!)';\n      const expected = '#   ';\n\n      expectObservable(e1.pipe(filter(oddFilter))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should send errors down the error path', (done) => {\n    of(42)\n      .pipe(\n        filter((x: number, index: number): boolean => {\n          throw 'bad';\n        })\n      )\n      .subscribe({\n        next: (x: number) => {\n          done(new Error('should not be called'));\n        },\n        error: (err: any) => {\n          expect(err).to.equal('bad');\n          done();\n        },\n        complete: () => {\n          done(new Error('should not be called'));\n        },\n      });\n  });\n\n  it('should not break unsubscription chain when unsubscribed explicitly', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('-1--2--^-3-4-5-6--7-8--9--|');\n      const e1subs = '       ^-----------!       ';\n      const expected = '     --3---5----7-       ';\n      const unsub = '        ------------!       ';\n\n      const result = e1.pipe(\n        mergeMap((x: any) => of(x)),\n        filter(isPrime),\n        mergeMap((x: any) => of(x))\n      );\n\n      expectObservable(result, unsub).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should support type guards without breaking previous behavior', () => {\n    // type guards with interfaces and classes\n    {\n      interface Bar {\n        bar?: string;\n      }\n      interface Baz {\n        baz?: number;\n      }\n      class Foo implements Bar, Baz {\n        constructor(public bar: string = 'name', public baz: number = 42) {}\n      }\n\n      const isBar = (x: any): x is Bar => x && (<Bar>x).bar !== undefined;\n      const isBaz = (x: any): x is Baz => x && (<Baz>x).baz !== undefined;\n\n      const foo: Foo = new Foo();\n      of(foo)\n        .pipe(filter((foo) => foo.baz === 42))\n        .subscribe((x) => x.baz); // x is still Foo\n      of(foo)\n        .pipe(filter(isBar))\n        .subscribe((x) => x.bar); // x is Bar!\n\n      const foobar: Bar = new Foo(); // type is interface, not the class\n      of(foobar)\n        .pipe(filter((foobar) => foobar.bar === 'name'))\n        .subscribe((x) => x.bar); // <-- x is still Bar\n      of(foobar)\n        .pipe(filter(isBar))\n        .subscribe((x) => x.bar); // <--- x is Bar!\n\n      const barish = { bar: 'quack', baz: 42 }; // type can quack like a Bar\n      of(barish)\n        .pipe(filter((x) => x.bar === 'quack'))\n        .subscribe((x) => x.bar); // x is still { bar: string; baz: number; }\n      of(barish)\n        .pipe(filter(isBar))\n        .subscribe((bar) => bar.bar); // x is Bar!\n    }\n\n    // type guards with primitive types\n    {\n      const xs: Observable<string | number> = from([1, 'aaa', 3, 'bb']);\n\n      // This type guard will narrow a `string | number` to a string in the examples below\n      const isString = (x: string | number): x is string => typeof x === 'string';\n\n      xs.pipe(filter(isString)).subscribe((s) => s.length); // s is string\n\n      // In contrast, this type of regular boolean predicate still maintains the original type\n      xs.pipe(filter((x) => typeof x === 'number')).subscribe((x) => x); // x is still string | number\n      xs.pipe(filter((x, i) => typeof x === 'number' && x > i)).subscribe((x) => x); // x is still string | number\n    }\n  });\n\n  it('should support Boolean as a predicate', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const values = { t: 1, f: 0 };\n      const e1 = hot('-t--f--^-t-f-t-f--t-f--f--|', values);\n      const e1subs = '       ^------------------!';\n      const expected = '     --t---t----t-------|';\n\n      expectObservable(e1.pipe(filter(Boolean))).toBe(expected, values);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should stop listening to a synchronous observable when unsubscribed', () => {\n    const sideEffects: number[] = [];\n    const synchronousObservable = new Observable<number>((subscriber) => {\n      // This will check to see if the subscriber was closed on each loop\n      // when the unsubscribe hits (from the `take`), it should be closed\n      for (let i = 0; !subscriber.closed && i < 10; i++) {\n        sideEffects.push(i);\n        subscriber.next(i);\n      }\n    });\n\n    synchronousObservable\n      .pipe(\n        filter(() => true),\n        take(3)\n      )\n      .subscribe(() => {\n        /* noop */\n      });\n\n    expect(sideEffects).to.deep.equal([0, 1, 2]);\n  });\n});\n"
  },
  {
    "path": "packages/rxjs/spec/operators/finalize-spec.ts",
    "content": "import { expect } from 'chai';\nimport { finalize, map, share, take } from 'rxjs/operators';\nimport { TestScheduler } from 'rxjs/testing';\nimport { observableMatcher } from '../helpers/observableMatcher';\nimport { of, timer, interval, NEVER, Observable, noop } from 'rxjs';\nimport { asInteropObservable } from '../helpers/interop-helper';\n\n/** @test {finalize} */\ndescribe('finalize', () => {\n  it('should call finalize after complete', (done) => {\n    let completed = false;\n    of(1, 2, 3)\n      .pipe(\n        finalize(() => {\n          expect(completed).to.be.true;\n          done();\n        })\n      )\n      .subscribe({\n        complete: () => {\n          completed = true;\n        },\n      });\n  });\n\n  it('should call finalize after error', (done) => {\n    let thrown = false;\n    of(1, 2, 3)\n      .pipe(\n        map(function (x) {\n          if (x === 3) {\n            throw x;\n          }\n          return x;\n        }),\n        finalize(() => {\n          expect(thrown).to.be.true;\n          done();\n        })\n      )\n      .subscribe({\n        error: () => {\n          thrown = true;\n        },\n      });\n  });\n\n  it('should call finalize upon disposal', (done) => {\n    let disposed = false;\n    const subscription = timer(100)\n      .pipe(\n        finalize(() => {\n          expect(disposed).to.be.true;\n          done();\n        })\n      )\n      .subscribe();\n    disposed = true;\n    subscription.unsubscribe();\n  });\n\n  it('should call finalize when synchronously subscribing to and unsubscribing from a shared Observable', (done) => {\n    interval(50).pipe(finalize(done), share()).subscribe().unsubscribe();\n  });\n\n  it('should call two finalize instances in succession on a shared Observable', (done) => {\n    let invoked = 0;\n    function checkFinally() {\n      invoked += 1;\n      if (invoked === 2) {\n        done();\n      }\n    }\n\n    of(1, 2, 3).pipe(finalize(checkFinally), finalize(checkFinally), share()).subscribe();\n  });\n\n  it('should handle empty', () => {\n    const testScheduler = new TestScheduler(observableMatcher);\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      let executed = false;\n      const e1 = hot('  |   ');\n      const e1subs = '  (^!)';\n      const expected = '|   ';\n\n      const result = e1.pipe(finalize(() => (executed = true)));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n\n      // manually flush so `finalize()` has chance to execute before the test is over.\n      testScheduler.flush();\n      expect(executed).to.be.true;\n    });\n  });\n\n  it('should handle never', () => {\n    const testScheduler = new TestScheduler(observableMatcher);\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      let executed = false;\n      const e1 = hot('  -');\n      const e1subs = '  ^';\n      const expected = '-';\n\n      const result = e1.pipe(finalize(() => (executed = true)));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n\n      // manually flush so `finalize()` has chance to execute before the test is over.\n      testScheduler.flush();\n      expect(executed).to.be.false;\n    });\n  });\n\n  it('should handle throw', () => {\n    const testScheduler = new TestScheduler(observableMatcher);\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      let executed = false;\n      const e1 = hot('  #   ');\n      const e1subs = '  (^!)';\n      const expected = '#   ';\n\n      const result = e1.pipe(finalize(() => (executed = true)));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n\n      // manually flush so `finalize()` has chance to execute before the test is over.\n      testScheduler.flush();\n      expect(executed).to.be.true;\n    });\n  });\n\n  it('should handle basic hot observable', () => {\n    const testScheduler = new TestScheduler(observableMatcher);\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      let executed = false;\n      const e1 = hot('  --a--b--c--|');\n      const e1subs = '  ^----------!';\n      const expected = '--a--b--c--|';\n\n      const result = e1.pipe(finalize(() => (executed = true)));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n\n      // manually flush so `finalize()` has chance to execute before the test is over.\n      testScheduler.flush();\n      expect(executed).to.be.true;\n    });\n  });\n\n  it('should handle basic cold observable', () => {\n    const testScheduler = new TestScheduler(observableMatcher);\n    testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      let executed = false;\n      const e1 = cold(' --a--b--c--|');\n      const e1subs = '  ^----------!';\n      const expected = '--a--b--c--|';\n\n      const result = e1.pipe(finalize(() => (executed = true)));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n\n      // manually flush so `finalize()` has chance to execute before the test is over.\n      testScheduler.flush();\n      expect(executed).to.be.true;\n    });\n  });\n\n  it('should handle basic error', () => {\n    const testScheduler = new TestScheduler(observableMatcher);\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      let executed = false;\n      const e1 = hot('  --a--b--c--#');\n      const e1subs = '  ^----------!';\n      const expected = '--a--b--c--#';\n\n      const result = e1.pipe(finalize(() => (executed = true)));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n\n      // manually flush so `finalize()` has chance to execute before the test is over.\n      testScheduler.flush();\n      expect(executed).to.be.true;\n    });\n  });\n\n  it('should handle unsubscription', () => {\n    const testScheduler = new TestScheduler(observableMatcher);\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      let executed = false;\n      const e1 = hot('  --a--b--c--|');\n      const e1subs = '  ^-----!     ';\n      const expected = '--a--b-';\n      const unsub = '   ------!';\n\n      const result = e1.pipe(finalize(() => (executed = true)));\n\n      expectObservable(result, unsub).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n\n      // manually flush so `finalize()` has chance to execute before the test is over.\n      testScheduler.flush();\n      expect(executed).to.be.true;\n    });\n  });\n\n  it('should handle interop source observables', () => {\n    // https://github.com/ReactiveX/rxjs/issues/5237\n    let finalized = false;\n    const subscription = asInteropObservable(NEVER)\n      .pipe(finalize(() => (finalized = true)))\n      .subscribe();\n    subscription.unsubscribe();\n    expect(finalized).to.be.true;\n  });\n\n  it('should finalize sources before sinks', () => {\n    const finalized: string[] = [];\n    of(42)\n      .pipe(\n        finalize(() => finalized.push('source')),\n        finalize(() => finalized.push('sink'))\n      )\n      .subscribe();\n    expect(finalized).to.deep.equal(['source', 'sink']);\n  });\n\n  it('should finalize after the finalization', () => {\n    const order: string[] = [];\n    const source = new Observable<void>(() => {\n      return () => order.push('finalizer');\n    });\n    const subscription = source.pipe(finalize(() => order.push('finalize'))).subscribe();\n    subscription.unsubscribe();\n    expect(order).to.deep.equal(['finalizer', 'finalize']);\n  });\n\n  it('should finalize after the finalizer with synchronous completion', () => {\n    const order: string[] = [];\n    const source = new Observable<void>((subscriber) => {\n      subscriber.complete();\n      return () => order.push('finalizer');\n    });\n    source.pipe(finalize(() => order.push('finalize'))).subscribe();\n    expect(order).to.deep.equal(['finalizer', 'finalize']);\n  });\n\n  it('should stop listening to a synchronous observable when unsubscribed', () => {\n    const sideEffects: number[] = [];\n    const synchronousObservable = new Observable<number>((subscriber) => {\n      // This will check to see if the subscriber was closed on each loop\n      // when the unsubscribe hits (from the `take`), it should be closed\n      for (let i = 0; !subscriber.closed && i < 10; i++) {\n        sideEffects.push(i);\n        subscriber.next(i);\n      }\n    });\n\n    synchronousObservable\n      .pipe(\n        finalize(() => {\n          /* noop */\n        }),\n        take(3)\n      )\n      .subscribe(() => {\n        /* noop */\n      });\n\n    expect(sideEffects).to.deep.equal([0, 1, 2]);\n  });\n\n  it('should execute finalize even with a sync thrown error', () => {\n    let called = false;\n    const badObservable = new Observable(() => {\n      throw new Error('bad');\n    }).pipe(\n      finalize(() => {\n        called = true;\n      })\n    );\n\n    badObservable.subscribe({\n      error: noop,\n    });\n\n    expect(called).to.be.true;\n  });\n\n  it('should execute finalize in order even with a sync error', () => {\n    const results: any[] = [];\n    const badObservable = new Observable((subscriber) => {\n      subscriber.error(new Error('bad'));\n    }).pipe(\n      finalize(() => {\n        results.push(1);\n      }),\n      finalize(() => {\n        results.push(2);\n      })\n    );\n\n    badObservable.subscribe({\n      error: noop,\n    });\n\n    expect(results).to.deep.equal([1, 2]);\n  });\n\n  it('should execute finalize in order even with a sync thrown error', () => {\n    const results: any[] = [];\n    const badObservable = new Observable(() => {\n      throw new Error('bad');\n    }).pipe(\n      finalize(() => {\n        results.push(1);\n      }),\n      finalize(() => {\n        results.push(2);\n      })\n    );\n\n    badObservable.subscribe({\n      error: noop,\n    });\n    expect(results).to.deep.equal([1, 2]);\n  });\n\n  it('should finalize in the proper order', () => {\n    const results: any[] = [];\n    of(1)\n      .pipe(\n        finalize(() => results.push(1)),\n        finalize(() => results.push(2)),\n        finalize(() => results.push(3)),\n        finalize(() => results.push(4))\n      )\n      .subscribe();\n\n    expect(results).to.deep.equal([1, 2, 3, 4]);\n  });\n});\n"
  },
  {
    "path": "packages/rxjs/spec/operators/find-spec.ts",
    "content": "import { expect } from 'chai';\nimport { find, mergeMap, delay } from 'rxjs/operators';\nimport { TestScheduler } from 'rxjs/testing';\nimport { observableMatcher } from '../helpers/observableMatcher';\nimport { of, Observable, from } from 'rxjs';\n\n/** @test {find} */\ndescribe('find', () => {\n  let testScheduler: TestScheduler;\n\n  beforeEach(() => {\n    testScheduler = new TestScheduler(observableMatcher);\n  });\n\n  function truePredicate(x: any) {\n    return true;\n  }\n\n  it('should return matching element from source emits single element', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const values = { a: 3, b: 9, c: 15, d: 20 };\n      const e1 = hot('  ---a--b--c--d---|', values);\n      const e1subs = '  ^--------!       ';\n      const expected = '---------(c|)    ';\n\n      const predicate = function (x: number) {\n        return x % 5 === 0;\n      };\n\n      expectObservable(e1.pipe(find(predicate))).toBe(expected, values);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should not emit if source does not emit', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  -');\n      const e1subs = '  ^';\n      const expected = '-';\n\n      expectObservable(e1.pipe(find(truePredicate))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should return undefined if source is empty to match predicate', () => {\n    testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' |   ');\n      const e1subs = '  (^!)';\n      const expected = '(x|)';\n\n      const result = e1.pipe(find(truePredicate));\n\n      expectObservable(result).toBe(expected, { x: undefined });\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should return matching element from source emits single element', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  --a--|');\n      const e1subs = '  ^-!   ';\n      const expected = '--(a|)';\n\n      const predicate = function (value: string) {\n        return value === 'a';\n      };\n\n      expectObservable(e1.pipe(find(predicate))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should return matching element from source emits multiple elements', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  --a--b---c-|');\n      const e1subs = '  ^----!      ';\n      const expected = '-----(b|)   ';\n\n      const predicate = function (value: string) {\n        return value === 'b';\n      };\n\n      expectObservable(e1.pipe(find(predicate))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should return undefined if element does not match with predicate', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  --a--b--c--|   ');\n      const e1subs = '  ^----------!   ';\n      const expected = '-----------(x|)';\n\n      const predicate = function (value: string) {\n        return value === 'z';\n      };\n\n      expectObservable(e1.pipe(find(predicate))).toBe(expected, { x: undefined });\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should allow unsubscribing early and explicitly', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  --a--b--c--|');\n      const e1subs = '  ^-----!     ';\n      const expected = '-------     ';\n      const unsub = '   ------!     ';\n\n      const result = e1.pipe(find((value: string) => value === 'z'));\n\n      expectObservable(result, unsub).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should not break unsubscription chains when result is unsubscribed explicitly', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  --a--b--c--|');\n      const e1subs = '  ^-----!     ';\n      const expected = '-------     ';\n      const unsub = '   ------!     ';\n\n      const result = e1.pipe(\n        mergeMap((x) => of(x)),\n        find((value) => value === 'z'),\n        mergeMap((x) => of(x))\n      );\n\n      expectObservable(result, unsub).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should unsubscribe when the predicate is matched', () => {\n    testScheduler.run(({ hot, time, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  --a--b---c-|');\n      const e1subs = '  ^----!      ';\n      const t = time('    --|       ');\n      //                     --|\n      const expected = '-------(b|) ';\n\n      const result = e1.pipe(\n        find((value: string) => value === 'b'),\n        delay(t)\n      );\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should raise if source raise error while element does not match with predicate', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  --a--b--#');\n      const e1subs = '  ^-------!';\n      const expected = '--------#';\n\n      const predicate = function (value: string) {\n        return value === 'z';\n      };\n\n      expectObservable(e1.pipe(find(predicate))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should raise error if predicate throws error', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  --a--b--c--|');\n      const e1subs = '  ^-!         ';\n      const expected = '--#         ';\n\n      const predicate = function (value: string) {\n        throw 'error';\n      };\n\n      expectObservable(e1.pipe(find(predicate))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should support type guards without breaking previous behavior', () => {\n    // type guards with interfaces and classes\n    {\n      interface Bar {\n        bar?: string;\n      }\n      interface Baz {\n        baz?: number;\n      }\n      class Foo implements Bar, Baz {\n        constructor(public bar: string = 'name', public baz: number = 42) {}\n      }\n\n      const isBar = (x: any): x is Bar => x && (<Bar>x).bar !== undefined;\n      const isBaz = (x: any): x is Baz => x && (<Baz>x).baz !== undefined;\n\n      const foo: Foo = new Foo();\n      of(foo)\n        .pipe(find((foo) => foo.baz === 42))\n        .subscribe((x) => x!.baz); // x is still Foo\n      of(foo)\n        .pipe(find(isBar))\n        .subscribe((x) => x!.bar); // x is Bar!\n\n      const foobar: Bar = new Foo(); // type is interface, not the class\n      of(foobar)\n        .pipe(find((foobar) => foobar.bar === 'name'))\n        .subscribe((x) => x!.bar); // <-- x is still Bar\n      of(foobar)\n        .pipe(find(isBar))\n        .subscribe((x) => x!.bar); // <--- x is Bar!\n\n      const barish = { bar: 'quack', baz: 42 }; // type can quack like a Bar\n      of(barish)\n        .pipe(find((x) => x.bar === 'quack'))\n        .subscribe((x) => x!.bar); // x is still { bar: string; baz: number; }\n      of(barish)\n        .pipe(find(isBar))\n        .subscribe((bar) => bar!.bar); // x is Bar!\n    }\n\n    // type guards with primitive types\n    {\n      const xs: Observable<string | number> = from([1, 'aaa', 3, 'bb']);\n\n      // This type guard will narrow a `string | number` to a string in the examples below\n      const isString = (x: string | number): x is string => typeof x === 'string';\n\n      xs.pipe(find(isString)).subscribe((s) => s!.length); // s is string\n\n      // In contrast, this type of regular boolean predicate still maintains the original type\n      xs.pipe(find((x) => typeof x === 'number')).subscribe((x) => x); // x is still string | number\n      xs.pipe(find((x, i) => typeof x === 'number' && x > i)).subscribe((x) => x); // x is still string | number\n    }\n  });\n\n  it('should stop listening to a synchronous observable when unsubscribed', () => {\n    const sideEffects: number[] = [];\n    const synchronousObservable = new Observable<number>((subscriber) => {\n      // This will check to see if the subscriber was closed on each loop\n      // when the unsubscribe hits, it should be closed\n      for (let i = 0; !subscriber.closed && i < 10; i++) {\n        sideEffects.push(i);\n        subscriber.next(i);\n      }\n    });\n\n    synchronousObservable.pipe(find((value) => value === 2)).subscribe(() => {\n      /* noop */\n    });\n\n    expect(sideEffects).to.deep.equal([0, 1, 2]);\n  });\n});\n"
  },
  {
    "path": "packages/rxjs/spec/operators/findIndex-spec.ts",
    "content": "import { expect } from 'chai';\nimport { findIndex, mergeMap, delay } from 'rxjs/operators';\nimport { TestScheduler } from 'rxjs/testing';\nimport { observableMatcher } from '../helpers/observableMatcher';\nimport { of, Observable } from 'rxjs';\n\n/** @test {findIndex} */\ndescribe('findIndex', () => {\n  let testScheduler: TestScheduler;\n\n  beforeEach(() => {\n    testScheduler = new TestScheduler(observableMatcher);\n  });\n\n  function truePredicate(x: any) {\n    return true;\n  }\n\n  it('should return matching element from source emits single element', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const values = { a: 3, b: 9, c: 15, d: 20 };\n      const e1 = hot('  ---a--b--c--d---|', values);\n      const e1subs = '  ^--------!       ';\n      const expected = '---------(x|)    ';\n\n      const predicate = function (x: number) {\n        return x % 5 === 0;\n      };\n\n      expectObservable(e1.pipe(findIndex(predicate))).toBe(expected, { x: 2 });\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should not emit if source does not emit', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  -');\n      const e1subs = '  ^';\n      const expected = '-';\n\n      expectObservable(e1.pipe(findIndex(truePredicate))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should return negative index if source is empty to match predicate', () => {\n    testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' |   ');\n      const e1subs = '  (^!)';\n      const expected = '(x|)';\n\n      const result = e1.pipe(findIndex(truePredicate));\n\n      expectObservable(result).toBe(expected, { x: -1 });\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should return index of element from source emits single element', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  --a--|', { a: 1 });\n      const e1subs = '  ^-!   ';\n      const expected = '--(x|)';\n\n      const predicate = function (value: number) {\n        return value === 1;\n      };\n\n      expectObservable(e1.pipe(findIndex(predicate))).toBe(expected, { x: 0 });\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should return index of matching element from source emits multiple elements', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  --a--b---c-|', { b: 7 });\n      const e1subs = '  ^----!      ';\n      const expected = '-----(x|)   ';\n\n      const predicate = function (value: number) {\n        return value === 7;\n      };\n\n      expectObservable(e1.pipe(findIndex(predicate))).toBe(expected, { x: 1 });\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should return negative index if element does not match with predicate', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  --a--b--c--|   ');\n      const e1subs = '  ^----------!   ';\n      const expected = '-----------(x|)';\n\n      const predicate = function (value: string) {\n        return value === 'z';\n      };\n\n      expectObservable(e1.pipe(findIndex(predicate))).toBe(expected, { x: -1 });\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should allow unsubscribing early and explicitly', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  --a--b--c--|');\n      const e1subs = '  ^-----!     ';\n      const expected = '-------     ';\n      const unsub = '   ------!     ';\n\n      const result = e1.pipe(findIndex((value: string) => value === 'z'));\n\n      expectObservable(result, unsub).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should not break unsubscription chains when result is unsubscribed explicitly', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  --a--b--c--|');\n      const e1subs = '  ^-----!     ';\n      const expected = '-------     ';\n      const unsub = '   ------!     ';\n\n      const result = e1.pipe(\n        mergeMap((x: string) => of(x)),\n        findIndex((value: string) => value === 'z'),\n        mergeMap((x: number) => of(x))\n      );\n\n      expectObservable(result, unsub).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should unsubscribe when the predicate is matched', () => {\n    testScheduler.run(({ hot, time, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  --a--b---c-|');\n      const e1subs = '  ^----!      ';\n      const t = time('    --|       ');\n      //                     --|\n      const expected = '-------(x|) ';\n\n      const result = e1.pipe(\n        findIndex((value: string) => value === 'b'),\n        delay(t)\n      );\n\n      expectObservable(result).toBe(expected, { x: 1 });\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should raise if source raise error while element does not match with predicate', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  --a--b--#');\n      const e1subs = '  ^-------!';\n      const expected = '--------#';\n\n      const predicate = function (value: string) {\n        return value === 'z';\n      };\n\n      expectObservable(e1.pipe(findIndex(predicate))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should raise error if predicate throws error', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  --a--b--c--|');\n      const e1subs = '  ^-!         ';\n      const expected = '--#         ';\n\n      const predicate = function (value: string) {\n        throw 'error';\n      };\n\n      expectObservable(e1.pipe(findIndex(predicate))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should stop listening to a synchronous observable when unsubscribed', () => {\n    const sideEffects: number[] = [];\n    const synchronousObservable = new Observable<number>((subscriber) => {\n      // This will check to see if the subscriber was closed on each loop\n      // when the unsubscribe hits, it should be closed\n      for (let i = 0; !subscriber.closed && i < 10; i++) {\n        sideEffects.push(i);\n        subscriber.next(i);\n      }\n    });\n\n    synchronousObservable.pipe(findIndex((value) => value === 2)).subscribe(() => {\n      /* noop */\n    });\n\n    expect(sideEffects).to.deep.equal([0, 1, 2]);\n  });\n});\n"
  },
  {
    "path": "packages/rxjs/spec/operators/first-spec.ts",
    "content": "import { expect } from 'chai';\nimport { observableMatcher } from '../helpers/observableMatcher';\nimport { first, mergeMap, delay, tap } from 'rxjs/operators';\nimport { TestScheduler } from 'rxjs/testing';\nimport { of, from, Observable, Subject, EmptyError, merge } from 'rxjs';\n\n/** @test {first} */\ndescribe('first', () => {\n  let testScheduler: TestScheduler;\n\n  beforeEach(() => {\n    testScheduler = new TestScheduler(observableMatcher);\n  });\n\n  it('should take the first value of an observable with many values', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  -----a--b--c---d---|');\n      const e1subs = '  ^----!              ';\n      const expected = '-----(a|)           ';\n\n      expectObservable(e1.pipe(first())).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should take the first value of an observable with one value', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  ---(a|)');\n      const e1subs = '  ^--!   ';\n      const expected = '---(a|)';\n\n      expectObservable(e1.pipe(first())).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should allow undefined as a default value', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  -----a--a---a-|   ');\n      const e1subs = '  ^-------------!   ';\n      const expected = '--------------(U|)';\n\n      expectObservable(e1.pipe(first((value) => value === 'b', undefined))).toBe(expected, { U: undefined });\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should error on empty', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('--a--^----|');\n      const e1subs = '     ^----!';\n      const expected = '   -----#';\n\n      expectObservable(e1.pipe(first())).toBe(expected, null, new EmptyError());\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should return the default value if source observable was empty', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('-----^----|   ');\n      const e1subs = '     ^----!   ';\n      const expected = '   -----(a|)';\n\n      expectObservable(e1.pipe(first(null, 'a'))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should only emit one value in recursive cases', () => {\n    const subject = new Subject<number>();\n    const results: number[] = [];\n\n    subject.pipe(first()).subscribe((x) => {\n      results.push(x);\n      subject.next(x + 1);\n    });\n\n    subject.next(0);\n\n    expect(results).to.deep.equal([0]);\n  });\n\n  it('should propagate error from the source observable', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('---^---#');\n      const e1subs = '   ^---!';\n      const expected = ' ----#';\n\n      expectObservable(e1.pipe(first())).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should go on forever on never', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('--^-------');\n      const e1subs = '  ^-------';\n      const expected = '--------';\n\n      expectObservable(e1.pipe(first())).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should allow unsubscribing early and explicitly', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('--a--^-----b----c---d--|');\n      const e1subs = '     ^--!               ';\n      const expected = '   ----               ';\n      const unsub = '      ---!               ';\n\n      expectObservable(e1.pipe(first()), unsub).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should not break unsubscription chains when result is unsubscribed explicitly', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('--a--^-----b----c---d--|');\n      const e1subs = '     ^--!               ';\n      const expected = '   ----               ';\n      const unsub = '      ---!               ';\n\n      const result = e1.pipe(\n        mergeMap((x) => of(x)),\n        first(),\n        mergeMap((x) => of(x))\n      );\n\n      expectObservable(result, unsub).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should unsubscribe when the first value is received', () => {\n    testScheduler.run(({ hot, time, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  --a--b---c-|');\n      const e1subs = '  ^-!         ';\n      const t = time('    --|       ');\n      const expected = '----(a|)    ';\n\n      const result = e1.pipe(first(), delay(t));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should return first value that matches a predicate', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('--a-^--b--c--a--c--|');\n      const e1subs = '    ^-----!         ';\n      const expected = '  ------(c|)      ';\n\n      expectObservable(e1.pipe(first((value) => value === 'c'))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should return first value that matches a predicate for odd numbers', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const values = { a: 1, b: 2, c: 3, d: 4, e: 5 };\n      const e1 = hot('--a-^--b--c--d--e--|', values);\n      const e1subs = '    ^-----!         ';\n      const expected = '  ------(c|)      ';\n\n      expectObservable(e1.pipe(first((x) => x % 2 === 1))).toBe(expected, { c: 3 });\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should error when no value matches the predicate', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('--a-^--b--c--a--c--|');\n      const e1subs = '    ^--------------!';\n      const expected = '  ---------------#';\n\n      expectObservable(e1.pipe(first((x) => x === 's'))).toBe(expected, null, new EmptyError());\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should return the default value when no value matches the predicate', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('--a-^--b--c--a--c--|   ');\n      const e1subs = '    ^--------------!   ';\n      const expected = '  ---------------(d|)';\n\n      expectObservable(e1.pipe(first((x) => x === 's', 'd'))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should propagate error when no value matches the predicate', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('--a-^--b--c--a--#');\n      const e1subs = '    ^-----------!';\n      const expected = '  ------------#';\n\n      expectObservable(e1.pipe(first((x) => x === 's'))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should return first value that matches the index in the predicate', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('--a-^--b--c--a--c--|');\n      const e1subs = '    ^--------!      ';\n      const expected = '  ---------(a|)   ';\n\n      expectObservable(e1.pipe(first((_, i) => i === 2))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should propagate error from predicate', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const values = { a: 1, b: 2, c: 3, d: 4, e: 5 };\n      const e1 = hot('--a-^--b--c--d--e--|', values);\n      const e1subs = '    ^--------!      ';\n      const expected = '  ---------#      ';\n\n      const predicate = function (value: number) {\n        if (value < 4) {\n          return false;\n        } else {\n          throw 'error';\n        }\n      };\n\n      expectObservable(e1.pipe(first(predicate))).toBe(expected, null, 'error');\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should support type guards without breaking previous behavior', () => {\n    // type guards with interfaces and classes\n    {\n      interface Bar {\n        bar?: string;\n      }\n      interface Baz {\n        baz?: number;\n      }\n      class Foo implements Bar, Baz {\n        constructor(public bar: string = 'name', public baz: number = 42) {}\n      }\n\n      const isBar = (x: any): x is Bar => x && (x as Bar).bar !== undefined;\n      const isBaz = (x: any): x is Baz => x && (x as Baz).baz !== undefined;\n\n      const foo: Foo = new Foo();\n      of(foo)\n        .pipe(first())\n        .subscribe((x) => x.baz); // x is Foo\n      of(foo)\n        .pipe(first((foo) => foo.bar === 'name'))\n        .subscribe((x) => x.baz); // x is still Foo\n      of(foo)\n        .pipe(first(isBar))\n        .subscribe((x) => x.bar); // x is Bar!\n\n      const foobar: Bar = new Foo(); // type is the interface, not the class\n      of(foobar)\n        .pipe(first())\n        .subscribe((x) => x.bar); // x is Bar\n      of(foobar)\n        .pipe(first((foobar) => foobar.bar === 'name'))\n        .subscribe((x) => x.bar); // x is still Bar\n      of(foobar)\n        .pipe(first(isBaz))\n        .subscribe((x) => x.baz); // x is Baz!\n\n      const barish = { bar: 'quack', baz: 42 }; // type can quack like a Bar\n      of(barish)\n        .pipe(first())\n        .subscribe((x) => x.baz); // x is still { bar: string; baz: number; }\n      of(barish)\n        .pipe(first((x) => x.bar === 'quack'))\n        .subscribe((x) => x.bar); // x is still { bar: string; baz: number; }\n      of(barish)\n        .pipe(first(isBar))\n        .subscribe((x) => x.bar); // x is Bar!\n    }\n\n    // type guards with primitive types\n    {\n      const xs: Observable<string | number> = from([1, 'aaa', 3, 'bb']);\n\n      // This type guard will narrow a `string | number` to a string in the examples below\n      const isString = (x: string | number): x is string => typeof x === 'string';\n\n      // missing predicate preserves the type\n      xs.pipe(first()).subscribe((x) => x); // x is still string | number\n\n      // null predicate preserves the type\n      xs.pipe(first(null)).subscribe((x) => x); // x is still string | number\n\n      // undefined predicate preserves the type\n      xs.pipe(first(undefined)).subscribe((x) => x); // x is still string | number\n\n      // After the type guard `first` predicates, the type is narrowed to string\n      xs.pipe(first(isString)).subscribe((s) => s.length); // s is string\n\n      // boolean predicates preserve the type\n      xs.pipe(first((x) => typeof x === 'string')).subscribe((x) => x); // x is still string | number\n    }\n  });\n\n  it('should stop listening to a synchronous observable when unsubscribed', () => {\n    const sideEffects: number[] = [];\n    const synchronousObservable = new Observable<number>((subscriber) => {\n      // This will check to see if the subscriber was closed on each loop\n      // when the unsubscribe hits, it should be closed\n      for (let i = 0; !subscriber.closed && i < 10; i++) {\n        sideEffects.push(i);\n        subscriber.next(i);\n      }\n    });\n\n    synchronousObservable.pipe(first((value) => value === 2)).subscribe(() => {\n      /* noop */\n    });\n\n    expect(sideEffects).to.deep.equal([0, 1, 2]);\n  });\n\n  it('should not emit errors sent from the source *after* it found the first value in reentrant scenarios', () => {\n    testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const subject = new Subject();\n      const source = cold('-------a----b----c---|');\n      const expected = '   -------(a|)';\n      const subs = '       ^------!';\n\n      const result = merge(source, subject).pipe(\n        first(),\n        tap(() => {\n          subject.error(new Error('reentrant shennanigans'));\n        })\n      );\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(source.subscriptions).toBe(subs);\n    });\n  });\n\n  it('should not emit errors sent from the source *after* it found the first value in reentrant scenarios', () => {\n    testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const subject = new Subject();\n      const source = cold('-------a----b----c---|');\n      const expected = '   ------------(b|)';\n      const subs = '       ^-----------!';\n\n      const result = merge(source, subject).pipe(\n        first((value) => value === 'b'),\n        tap(() => {\n          subject.error(new Error('reentrant shennanigans'));\n        })\n      );\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(source.subscriptions).toBe(subs);\n    });\n  });\n\n  it('should not emit complete sent from the source *after* it found the first value in reentrant scenarios', () => {\n    testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const subject = new Subject();\n      const source = cold('-------a----b----c---|');\n      const expected = '   -------(a|)';\n      const subs = '       ^------!';\n\n      const result = merge(source, subject).pipe(\n        first(),\n        tap(() => {\n          subject.complete();\n        })\n      );\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(source.subscriptions).toBe(subs);\n    });\n  });\n\n  it('should not emit completions sent from the source *after* it found the first value in reentrant scenarios', () => {\n    testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const subject = new Subject();\n      const source = cold('-------a----b----c---|');\n      const expected = '   ------------(b|)';\n      const subs = '       ^-----------!';\n\n      const result = merge(source, subject).pipe(\n        first((value) => value === 'b'),\n        tap(() => {\n          subject.complete();\n        })\n      );\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(source.subscriptions).toBe(subs);\n    });\n  });\n});\n"
  },
  {
    "path": "packages/rxjs/spec/operators/groupBy-spec.ts",
    "content": "import { expect } from 'chai';\nimport { groupBy, delay, tap, map, take, mergeMap, materialize, skip, ignoreElements } from 'rxjs/operators';\nimport { TestScheduler } from 'rxjs/testing';\nimport type { NextNotification, ErrorNotification } from 'rxjs';\nimport { ReplaySubject, of, Observable, Subject } from 'rxjs';\nimport { createNotification } from '@rxjs/observable';\nimport { observableMatcher } from '../helpers/observableMatcher';\n\n/** @test {groupBy} */\ndescribe('groupBy operator', () => {\n  let testScheduler: TestScheduler;\n\n  beforeEach(() => {\n    testScheduler = new TestScheduler(observableMatcher);\n  });\n\n  it('should group numbers by odd/even', () => {\n    testScheduler.run(({ cold, hot, expectObservable }) => {\n      const e1 = hot('  --1---2---3---4---5---|');\n      const expected = '--x---y---------------|';\n      const x = cold('  1-------3-------5---|');\n      const y = cold('  2-------4-------|');\n      const expectedValues = { x: x, y: y };\n\n      const source = e1.pipe(groupBy((val: string) => parseInt(val) % 2));\n      expectObservable(source).toBe(expected, expectedValues);\n    });\n  });\n\n  function reverseString(str: string) {\n    return str.split('').reverse().join('');\n  }\n\n  function mapObject<T>(obj: Record<string, T>, fn: (val: T) => unknown) {\n    const out: Record<string, any> = {};\n    for (const p in obj) {\n      if (obj.hasOwnProperty(p)) {\n        out[p] = fn(obj[p]);\n      }\n    }\n    return out;\n  }\n\n  it('should group values', (done) => {\n    const expectedGroups = [\n      { key: 1, values: [1, 3] },\n      { key: 0, values: [2] },\n    ];\n\n    of(1, 2, 3)\n      .pipe(groupBy((x) => x % 2))\n      .subscribe({\n        next: (g: any) => {\n          const expectedGroup = expectedGroups.shift()!;\n          expect(g.key).to.equal(expectedGroup.key);\n\n          g.subscribe((x: any) => {\n            expect(x).to.deep.equal(expectedGroup.values.shift());\n          });\n        },\n        complete: done,\n      });\n  });\n\n  it('should group values with an element selector', (done) => {\n    const expectedGroups = [\n      { key: 1, values: ['1!', '3!'] },\n      { key: 0, values: ['2!'] },\n    ];\n\n    of(1, 2, 3)\n      .pipe(\n        groupBy(\n          (x) => x % 2,\n          (x) => x + '!'\n        )\n      )\n      .subscribe({\n        next: (g: any) => {\n          const expectedGroup = expectedGroups.shift()!;\n          expect(g.key).to.equal(expectedGroup.key);\n\n          g.subscribe((x: any) => {\n            expect(x).to.deep.equal(expectedGroup.values.shift());\n          });\n        },\n        complete: done,\n      });\n  });\n\n  it('should group values with a duration selector', () => {\n    const expectedGroups = [\n      { key: 1, values: [1, 3] },\n      { key: 0, values: [2, 4] },\n      { key: 1, values: [5] },\n      { key: 0, values: [6] },\n    ];\n\n    const resultingGroups: { key: number; values: number[] }[] = [];\n\n    of(1, 2, 3, 4, 5, 6)\n      .pipe(\n        groupBy((x) => x % 2, {\n          duration: (g) => g.pipe(skip(1)),\n        })\n      )\n      .subscribe((g: any) => {\n        const group = { key: g.key, values: [] as number[] };\n\n        g.subscribe((x: any) => {\n          group.values.push(x);\n        });\n\n        resultingGroups.push(group);\n      });\n\n    expect(resultingGroups).to.deep.equal(expectedGroups);\n  });\n\n  it('should group values with a subject selector', (done) => {\n    const expectedGroups = [\n      { key: 1, values: [3] },\n      { key: 0, values: [2] },\n    ];\n\n    of(1, 2, 3)\n      .pipe(\n        groupBy((x) => x % 2, {\n          connector: () => new ReplaySubject(1),\n        }),\n        // Ensure each inner group reaches the destination after the first event\n        // has been next'd to the group\n        delay(5)\n      )\n      .subscribe({\n        next: (g: any) => {\n          const expectedGroup = expectedGroups.shift()!;\n          expect(g.key).to.equal(expectedGroup.key);\n\n          g.subscribe((x: any) => {\n            expect(x).to.deep.equal(expectedGroup.values.shift());\n          });\n        },\n        complete: done,\n      });\n  });\n\n  it('should handle an empty Observable', () => {\n    testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' |   ');\n      const e1subs = '  (^!)';\n      const expected = '|   ';\n\n      const source = e1.pipe(groupBy((val: string) => val.toLowerCase().trim()));\n\n      expectObservable(source).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should handle a never Observable', () => {\n    testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' -');\n      const e1subs = '  ^';\n      const expected = '-';\n\n      const source = e1.pipe(groupBy((val: string) => val.toLowerCase().trim()));\n\n      expectObservable(source).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should handle a just-throw Observable', () => {\n    testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold('  #  ');\n      const e1subs = '  (^!)';\n      const expected = '#   ';\n\n      const source = e1.pipe(groupBy((val: string) => val.toLowerCase().trim()));\n\n      expectObservable(source).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should handle an Observable with a single value', () => {\n    testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => {\n      const values = { a: '  foo' };\n      const e1 = hot('  ^--a--|', values);\n      const e1subs = '  ^-----!';\n      const expected = '---g--|';\n      const g = cold('     a--|', values);\n      const expectedValues = { g: g };\n\n      const source = e1.pipe(groupBy((val: string) => val.toLowerCase().trim()));\n\n      expectObservable(source).toBe(expected, expectedValues);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should group values with a keySelector', () => {\n    testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => {\n      const values = {\n        a: '  foo',\n        b: ' FoO ',\n        c: 'baR  ',\n        d: 'foO ',\n        e: ' Baz   ',\n        f: '  qux ',\n        g: '   bar',\n        h: ' BAR  ',\n        i: 'FOO ',\n        j: 'baz  ',\n        k: ' bAZ ',\n        l: '    fOo    ',\n      };\n      const e1 = hot('-1--2--^-a-b-c-d-e-f-g-h-i-j-k-l-|', values);\n      const e1subs = '       ^-------------------------!';\n      const expected = '     --w---x---y-z-------------|';\n      const w = cold('         a-b---d---------i-----l-|', values);\n      const x = cold('             c-------g-h---------|', values);\n      const y = cold('                 e---------j-k---|', values);\n      const z = cold('                   f-------------|', values);\n      const expectedValues = { w: w, x: x, y: y, z: z };\n\n      const source = e1.pipe(groupBy((val: string) => val.toLowerCase().trim()));\n\n      expectObservable(source).toBe(expected, expectedValues);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should emit GroupObservables', () => {\n    testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => {\n      const values = {\n        a: '  foo',\n        b: ' FoO ',\n      };\n      const e1 = hot('-1--2--^-a-b----|', values);\n      const e1subs = '       ^--------!';\n      const expected = '     --g------|';\n      const expectedValues = { g: 'foo' };\n\n      const source = e1.pipe(\n        groupBy((val: string) => val.toLowerCase().trim()),\n        tap((group: any) => {\n          expect(group.key).to.equal('foo');\n          expect(group instanceof Observable).to.be.true;\n        }),\n        map((group: any) => {\n          return group.key;\n        })\n      );\n\n      expectObservable(source).toBe(expected, expectedValues);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should group values with a keySelector, assert GroupSubject key', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const values = {\n        a: '  foo',\n        b: ' FoO ',\n        c: 'baR  ',\n        d: 'foO ',\n        e: ' Baz   ',\n        f: '  qux ',\n        g: '   bar',\n        h: ' BAR  ',\n        i: 'FOO ',\n        j: 'baz  ',\n        k: ' bAZ ',\n        l: '    fOo    ',\n      };\n      const e1 = hot('-1--2--^-a-b-c-d-e-f-g-h-i-j-k-l-|', values);\n      const e1subs = '       ^-------------------------!';\n      const expected = '     --w---x---y-z-------------|';\n      const expectedValues = { w: 'foo', x: 'bar', y: 'baz', z: 'qux' };\n\n      const source = e1.pipe(\n        groupBy((val: string) => val.toLowerCase().trim()),\n        map((g: any) => g.key)\n      );\n\n      expectObservable(source).toBe(expected, expectedValues);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should group values with a keySelector, but outer throws', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const values = {\n        a: '  foo',\n        b: ' FoO ',\n        c: 'baR  ',\n        d: 'foO ',\n        e: ' Baz   ',\n        f: '  qux ',\n        g: '   bar',\n        h: ' BAR  ',\n        i: 'FOO ',\n        j: 'baz  ',\n        k: ' bAZ ',\n        l: '    fOo    ',\n      };\n      const e1 = hot('-1--2--^-a-b-c-d-e-f-g-h-i-j-k-l-#', values);\n      const e1subs = '       ^-------------------------!';\n      const expected = '     --w---x---y-z-------------#';\n      const expectedValues = { w: 'foo', x: 'bar', y: 'baz', z: 'qux' };\n\n      const source = e1.pipe(\n        groupBy((val: string) => val.toLowerCase().trim()),\n        map((g: any) => g.key)\n      );\n\n      expectObservable(source).toBe(expected, expectedValues);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should group values with a keySelector, inners propagate error from outer', () => {\n    testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => {\n      const values = {\n        a: '  foo',\n        b: ' FoO ',\n        c: 'baR  ',\n        d: 'foO ',\n        e: ' Baz   ',\n        f: '  qux ',\n        g: '   bar',\n        h: ' BAR  ',\n        i: 'FOO ',\n        j: 'baz  ',\n        k: ' bAZ ',\n        l: '    fOo    ',\n      };\n      const e1 = hot('-1--2--^-a-b-c-d-e-f-g-h-i-j-k-l-#', values);\n      const e1subs = '       ^-------------------------!';\n      const expected = '     --w---x---y-z-------------#';\n      const w = cold('         a-b---d---------i-----l-#', values);\n      const x = cold('             c-------g-h---------#', values);\n      const y = cold('                 e---------j-k---#', values);\n      const z = cold('                   f-------------#', values);\n      const expectedValues = { w: w, x: x, y: y, z: z };\n\n      const source = e1.pipe(groupBy((val: string) => val.toLowerCase().trim()));\n\n      expectObservable(source).toBe(expected, expectedValues);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should allow outer to be unsubscribed early', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const values = {\n        a: '  foo',\n        b: ' FoO ',\n        c: 'baR  ',\n        d: 'foO ',\n        e: ' Baz   ',\n        f: '  qux ',\n        g: '   bar',\n        h: ' BAR  ',\n        i: 'FOO ',\n        j: 'baz  ',\n        k: ' bAZ ',\n        l: '    fOo    ',\n      };\n      const e1 = hot('-1--2--^-a-b-c-d-e-f-g-h-i-j-k-l-|', values);\n      const unsub = '        -----------!               ';\n      const e1subs = '       ^----------!               ';\n      const expected = '     --w---x---y-               ';\n      const expectedValues = { w: 'foo', x: 'bar', y: 'baz' };\n\n      const source = e1.pipe(\n        groupBy((val: string) => val.toLowerCase().trim()),\n        map((group: any) => group.key)\n      );\n\n      expectObservable(source, unsub).toBe(expected, expectedValues);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should unsubscribe from the source when the outer and inner subscriptions are disposed', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const values = {\n        a: '  foo',\n        b: ' FoO ',\n        c: 'baR  ',\n        d: 'foO ',\n        e: ' Baz   ',\n        f: '  qux ',\n        g: '   bar',\n        h: ' BAR  ',\n        i: 'FOO ',\n        j: 'baz  ',\n        k: ' bAZ ',\n        l: '    fOo    ',\n      };\n      const e1 = hot('-1--2--^-a-b-c-d-e-f-g-h-i-j-k-l-|', values);\n      const e1subs = '       ^-!                        ';\n      const expected = '     --(a|)                     ';\n\n      const source = e1.pipe(\n        groupBy((val) => val.toLowerCase().trim()),\n        take(1),\n        mergeMap((group) => group.pipe(take(1)))\n      );\n\n      expectObservable(source).toBe(expected, values);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should not break unsubscription chain when unsubscribed explicitly', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const values = {\n        a: '  foo',\n        b: ' FoO ',\n        c: 'baR  ',\n        d: 'foO ',\n        e: ' Baz   ',\n        f: '  qux ',\n        g: '   bar',\n        h: ' BAR  ',\n        i: 'FOO ',\n        j: 'baz  ',\n        k: ' bAZ ',\n        l: '    fOo    ',\n      };\n      const e1 = hot('-1--2--^-a-b-c-d-e-f-g-h-i-j-k-l-|', values);\n      const e1subs = '       ^----------!               ';\n      const expected = '     --w---x---y-               ';\n      const unsub = '        -----------!               ';\n      const expectedValues = { w: 'foo', x: 'bar', y: 'baz' };\n\n      const source = e1.pipe(\n        mergeMap((x: string) => of(x)),\n        groupBy((x: string) => x.toLowerCase().trim()),\n        mergeMap((group: any) => of(group.key))\n      );\n\n      expectObservable(source, unsub).toBe(expected, expectedValues);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should group values with a keySelector which eventually throws', () => {\n    testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => {\n      const values = {\n        a: '  foo',\n        b: ' FoO ',\n        c: 'baR  ',\n        d: 'foO ',\n        e: ' Baz   ',\n        f: '  qux ',\n        g: '   bar',\n        h: ' BAR  ',\n        i: 'FOO ',\n        j: 'baz  ',\n        k: ' bAZ ',\n        l: '    fOo    ',\n      };\n      const e1 = hot('-1--2--^-a-b-c-d-e-f-g-h-i-j-k-l-|', values);\n      const e1subs = '       ^-------------------!';\n      const expected = '     --w---x---y-z-------#';\n      const w = cold('         a-b---d---------i-#', values);\n      const x = cold('             c-------g-h---#', values);\n      const y = cold('                 e---------#', values);\n      const z = cold('                   f-------#', values);\n      const expectedValues = { w: w, x: x, y: y, z: z };\n\n      let invoked = 0;\n      const source = e1.pipe(\n        groupBy((val: string) => {\n          invoked++;\n          if (invoked === 10) {\n            throw 'error';\n          }\n          return val.toLowerCase().trim();\n        })\n      );\n\n      expectObservable(source).toBe(expected, expectedValues);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should group values with a keySelector and elementSelector, but elementSelector throws', () => {\n    testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => {\n      const values = {\n        a: '  foo',\n        b: ' FoO ',\n        c: 'baR  ',\n        d: 'foO ',\n        e: ' Baz   ',\n        f: '  qux ',\n        g: '   bar',\n        h: ' BAR  ',\n        i: 'FOO ',\n        j: 'baz  ',\n        k: ' bAZ ',\n        l: '    fOo    ',\n      };\n      const reversedValues = mapObject(values, reverseString);\n      const e1 = hot('-1--2--^-a-b-c-d-e-f-g-h-i-j-k-l-|', values);\n      const e1subs = '       ^-------------------!';\n      const expected = '     --w---x---y-z-------#';\n      const w = cold('         a-b---d---------i-#', reversedValues);\n      const x = cold('             c-------g-h---#', reversedValues);\n      const y = cold('                 e---------#', reversedValues);\n      const z = cold('                   f-------#', reversedValues);\n      const expectedValues = { w: w, x: x, y: y, z: z };\n\n      let invoked = 0;\n      const source = e1.pipe(\n        groupBy(\n          (val: string) => val.toLowerCase().trim(),\n          (val: string) => {\n            invoked++;\n            if (invoked === 10) {\n              throw 'error';\n            }\n            return reverseString(val);\n          }\n        )\n      );\n\n      expectObservable(source).toBe(expected, expectedValues);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should unsubscribe inner subscriptions when the result unsubscribes', () => {\n    testScheduler.run(({ cold, hot, expectObservable }) => {\n      const values = {\n        a: '  foo',\n        b: ' FoO ',\n        c: 'baR  ',\n        d: 'foO ',\n        e: ' Baz   ',\n        f: '  qux ',\n        g: '   bar',\n        h: ' BAR  ',\n        i: 'FOO ',\n        j: 'baz  ',\n        k: ' bAZ ',\n        l: '    fOo    ',\n      };\n      const e1 = hot('-1--2--^-a-b-c-d-e-f-g-h-i-j-k-l-|', values);\n      const unsub = '        ----------!                ';\n      const expected = '     --w---x----                ';\n      const w = cold('         a-b---d--                ', values);\n      const x = cold('             c----                ', values);\n      const expectedValues = { w: w, x: x };\n\n      const source = e1.pipe(groupBy((val: string) => val.toLowerCase().trim()));\n\n      expectObservable(source, unsub).toBe(expected, expectedValues);\n    });\n  });\n\n  it('should allow an inner to be unsubscribed early but other inners continue', () => {\n    testScheduler.run(({ hot, expectObservable }) => {\n      const values = {\n        a: '  foo',\n        b: ' FoO ',\n        c: 'baR  ',\n        d: 'foO ',\n        e: ' Baz   ',\n        f: '  qux ',\n        g: '   bar',\n        h: ' BAR  ',\n        i: 'FOO ',\n        j: 'baz  ',\n        k: ' bAZ ',\n        l: '    fOo    ',\n      };\n      const e1 = hot('-1--2--^-a-b-c-d-e-f-g-h-i-j-k-l-|', values);\n      const expected = '     --w---x---y-z-------------|';\n      const w = '            --a-b---d-                 ';\n      const unsubw = '       ---------!                 ';\n      const x = '            ------c-------g-h---------|';\n      const y = '            ----------e---------j-k---|';\n      const z = '            ------------f-------------|';\n\n      const expectedGroups = {\n        w: TestScheduler.parseMarbles(w, values, undefined, undefined, true),\n        x: TestScheduler.parseMarbles(x, values, undefined, undefined, true),\n        y: TestScheduler.parseMarbles(y, values, undefined, undefined, true),\n        z: TestScheduler.parseMarbles(z, values, undefined, undefined, true),\n      };\n\n      const fooUnsubscriptionFrame = TestScheduler.parseMarblesAsSubscriptions(unsubw, true).unsubscribedFrame;\n\n      const source = e1.pipe(\n        groupBy((val) => val.toLowerCase().trim()),\n        map((group) => {\n          const arr: any[] = [];\n\n          const subscription = group.pipe(phonyMarbelize(testScheduler)).subscribe((value) => {\n            arr.push(value);\n          });\n\n          if (group.key === 'foo') {\n            testScheduler.schedule(() => {\n              subscription.unsubscribe();\n            }, fooUnsubscriptionFrame - testScheduler.frame);\n          }\n          return arr;\n        })\n      );\n\n      expectObservable(source).toBe(expected, expectedGroups);\n    });\n  });\n\n  it('should allow inners to be unsubscribed early at different times', () => {\n    testScheduler.run(({ hot, expectObservable }) => {\n      const values = {\n        a: '  foo',\n        b: ' FoO ',\n        c: 'baR  ',\n        d: 'foO ',\n        e: ' Baz   ',\n        f: '  qux ',\n        g: '   bar',\n        h: ' BAR  ',\n        i: 'FOO ',\n        j: 'baz  ',\n        k: ' bAZ ',\n        l: '    fOo    ',\n      };\n      const e1 = hot('-1--2--^-a-b-c-d-e-f-g-h-i-j-k-l-|', values);\n      const expected = '     --w---x---y-z-------------|';\n      const w = '            --a-b---d-                 ';\n      const unsubw = '       ---------!                 ';\n      const x = '            ------c------              ';\n      const unsubx = '       ------------!              ';\n      const y = '            ----------e------          ';\n      const unsuby = '       ----------------!          ';\n      const z = '            ------------f-------       ';\n      const unsubz = '       -------------------!       ';\n\n      const expectedGroups = {\n        w: TestScheduler.parseMarbles(w, values, undefined, undefined, true),\n        x: TestScheduler.parseMarbles(x, values, undefined, undefined, true),\n        y: TestScheduler.parseMarbles(y, values, undefined, undefined, true),\n        z: TestScheduler.parseMarbles(z, values, undefined, undefined, true),\n      };\n\n      const unsubscriptionFrames: Record<string, number> = {\n        foo: TestScheduler.parseMarblesAsSubscriptions(unsubw, true).unsubscribedFrame,\n        bar: TestScheduler.parseMarblesAsSubscriptions(unsubx, true).unsubscribedFrame,\n        baz: TestScheduler.parseMarblesAsSubscriptions(unsuby, true).unsubscribedFrame,\n        qux: TestScheduler.parseMarblesAsSubscriptions(unsubz, true).unsubscribedFrame,\n      };\n\n      const source = e1.pipe(\n        groupBy((val: string) => val.toLowerCase().trim()),\n        map((group: any) => {\n          const arr: any[] = [];\n\n          const subscription = group.pipe(phonyMarbelize(testScheduler)).subscribe((value: any) => {\n            arr.push(value);\n          });\n\n          testScheduler.schedule(() => {\n            subscription.unsubscribe();\n          }, unsubscriptionFrames[group.key] - testScheduler.frame);\n          return arr;\n        })\n      );\n\n      expectObservable(source).toBe(expected, expectedGroups);\n    });\n  });\n\n  it('should allow subscribing late to an inner Observable, outer completes', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions, time }) => {\n      const values = {\n        a: '  foo',\n        b: ' FoO ',\n        d: 'foO ',\n        i: 'FOO ',\n        l: '    fOo    ',\n      };\n      const e1 = hot('          --a-b---d---------i-----l-|  ', values);\n      const subs = '            ^-------------------------!  ';\n      const subDuration = time('--------------------------|  ');\n      const expected = '        ----------------------------|';\n\n      e1.pipe(groupBy((val: string) => val.toLowerCase().trim())).subscribe((group: any) => {\n        testScheduler.schedule(() => {\n          expectObservable(group).toBe(expected);\n        }, subDuration);\n      });\n      expectSubscriptions(e1.subscriptions).toBe(subs);\n    });\n  });\n\n  it('should allow subscribing late to an inner Observable, outer throws', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions, time }) => {\n      const values = {\n        a: '  foo',\n        b: ' FoO ',\n        d: 'foO ',\n        i: 'FOO ',\n        l: '    fOo    ',\n      };\n      const e1 = hot('           --a-b---d---------i-----l-#', values);\n      const subs = '             ^-------------------------! ';\n      const subsDuration = time('--------------------------| ');\n      const expected = '         ----------------------------#';\n\n      e1.pipe(groupBy((val: string) => val.toLowerCase().trim())).subscribe({\n        next: (group: any) => {\n          testScheduler.schedule(() => {\n            expectObservable(group).toBe(expected);\n          }, subsDuration);\n        },\n        error: () => {\n          //noop\n        },\n      });\n      expectSubscriptions(e1.subscriptions).toBe(subs);\n    });\n  });\n\n  it('should allow subscribing late to inner, unsubscribe outer early', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions, time }) => {\n      const values = {\n        a: '  foo',\n        b: ' FoO ',\n        d: 'foO ',\n        i: 'FOO ',\n        l: '    fOo    ',\n      };\n      const e1 = hot('           --a-b---d---------i-----l-#', values);\n      const unsub = '            ------------!              ';\n      const e1subs = '           ^-----------!              ';\n      const subsDuration = time('------------|              ');\n      const expectedOuter = '    --w----------              ';\n      const expectedInner = '    -------------              ';\n      const outerValues = { w: 'foo' };\n\n      const source = e1.pipe(\n        groupBy((val: string) => val.toLowerCase().trim()),\n        tap((group: any) => {\n          testScheduler.schedule(() => {\n            expectObservable(group).toBe(expectedInner);\n          }, subsDuration);\n        }),\n        map((group: any) => {\n          return group.key;\n        })\n      );\n\n      expectObservable(source, unsub).toBe(expectedOuter, outerValues);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should allow using a keySelector, elementSelector, and durationSelector', () => {\n    testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => {\n      const values = {\n        a: '  foo',\n        b: ' FoO ',\n        c: 'baR  ',\n        d: 'foO ',\n        e: ' Baz   ',\n        f: '  qux ',\n        g: '   bar',\n        h: ' BAR  ',\n        i: 'FOO ',\n        j: 'baz  ',\n        k: ' bAZ ',\n        l: '    fOo    ',\n      };\n      const reversedValues = mapObject(values, reverseString);\n      const e1 = hot('-1--2--^-a-b-c-d-e-f-g-h-i-j-k-l-|', values);\n      const e1subs = '       ^-------------------------!';\n      const expected = '     --v---w---x-y-----z-------|';\n      const v = cold('       a-b---(d|)                 ', reversedValues);\n      const w = cold('             c-------g-(h|)       ', reversedValues);\n      const x = cold('                  e---------j-(k|)', reversedValues);\n      const y = cold('                   f-------------|', reversedValues);\n      const z = cold('                         i-----l-|', reversedValues);\n      const expectedValues = { v: v, w: w, x: x, y: y, z: z };\n\n      const source = e1.pipe(\n        groupBy(\n          (val: string) => val.toLowerCase().trim(),\n          (val: string) => reverseString(val),\n          (group: any) => group.pipe(skip(2))\n        )\n      );\n\n      expectObservable(source).toBe(expected, expectedValues);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should allow using a keySelector, elementSelector, and durationSelector that throws', () => {\n    testScheduler.run(({ cold, hot, expectObservable }) => {\n      const values = {\n        a: '  foo',\n        b: ' FoO ',\n        c: 'baR  ',\n        d: 'foO ',\n        e: ' Baz   ',\n        f: '  qux ',\n        g: '   bar',\n        h: ' BAR  ',\n        i: 'FOO ',\n        j: 'baz  ',\n        k: ' bAZ ',\n        l: '    fOo    ',\n      };\n      const reversedValues = mapObject(values, reverseString);\n      const e1 = hot('-1--2--^-a-b-c-d-e-f-g-h-i-j-k-l-|', values);\n      const expected = '     --v---w---x-y-----z-------|';\n      const v = cold('         a-b---(d#)               ', reversedValues);\n      const w = cold('             c-------g-(h#)       ', reversedValues);\n      const x = cold('                 e---------j-(k#) ', reversedValues);\n      const y = cold('                   f-------------|', reversedValues);\n      const z = cold('                         i-----l-|', reversedValues);\n      const expectedValues = { v: v, w: w, x: x, y: y, z: z };\n\n      const source = e1.pipe(\n        groupBy(\n          (val: string) => val.toLowerCase().trim(),\n          (val: string) => reverseString(val),\n          (group: any) =>\n            group.pipe(\n              skip(2),\n              map(() => {\n                throw 'error';\n              })\n            )\n        )\n      );\n      expectObservable(source).toBe(expected, expectedValues);\n    });\n  });\n\n  it('should allow using a keySelector and a durationSelector, outer throws', () => {\n    testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => {\n      const values = {\n        a: '  foo',\n        b: ' FoO ',\n        c: 'baR  ',\n        d: 'foO ',\n        e: ' Baz   ',\n        f: '  qux ',\n        g: '   bar',\n        h: ' BAR  ',\n        i: 'FOO ',\n        j: 'baz  ',\n        k: ' bAZ ',\n        l: '    fOo    ',\n      };\n      const e1 = hot('-1--2--^-a-b-c-d-e-f-g-h-i-j-k-l-#', values);\n      const e1subs = '       ^-------------------------!';\n      const expected = '     --v---w---x-y-----z-------#';\n      const v = cold('         a-b---(d|)               ', values);\n      const w = cold('             c-------g-(h|)       ', values);\n      const x = cold('                 e---------j-(k|) ', values);\n      const y = cold('                   f-------------#', values);\n      const z = cold('                         i-----l-#', values);\n      const expectedValues = { v: v, w: w, x: x, y: y, z: z };\n\n      const source = e1.pipe(\n        groupBy((val) => val.toLowerCase().trim(), {\n          duration: (group) => group.pipe(skip(2)),\n        })\n      );\n\n      expectObservable(source).toBe(expected, expectedValues);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should allow using a durationSelector, and unsub from outer and inner at the same time', () => {\n    testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => {\n      const values = {\n        a: '  foo',\n        b: ' FoO ',\n        c: 'baR  ',\n        d: 'foO ',\n        e: ' Baz   ',\n        f: '  qux ',\n        g: '   bar',\n        h: ' BAR  ',\n        i: 'FOO ',\n        j: 'baz  ',\n        k: ' bAZ ',\n        l: '    fOo    ',\n      };\n      const e1 = hot('-1--2--^-a-b-c-d-e-f-g-h-i-j-k-l-|', values);\n      const unsub = '        -----------!               ';\n      const expected = '     --v---w---x-               ';\n      const v = cold('         a-b---(d|)               ', values);\n      const w = cold('             c-----               ', values);\n      const x = cold('                 e-               ', values);\n      const expectedValues = { v: v, w: w, x: x };\n\n      const source = e1.pipe(\n        groupBy((val) => val.toLowerCase().trim(), {\n          duration: (group) => group.pipe(skip(2)),\n        })\n      );\n\n      expectObservable(source, unsub).toBe(expected, expectedValues);\n    });\n  });\n\n  it('should allow using a durationSelector, outer and all inners unsubscribed early', () => {\n    testScheduler.run(({ hot, expectObservable }) => {\n      const values = {\n        a: '  foo',\n        b: ' FoO ',\n        c: 'baR  ',\n        d: 'foO ',\n        e: ' Baz   ',\n        f: '  qux ',\n        g: '   bar',\n        h: ' BAR  ',\n        i: 'FOO ',\n        j: 'baz  ',\n        k: ' bAZ ',\n        l: '    fOo    ',\n      };\n      const e1 = hot('-1--2--^-a-b-c-d-e-f-g-h-i-j-k-l-|', values);\n      const unsub = '        -----------!';\n      const expected = '     --v---w---x-';\n      const v = '            --a-b---(d|)';\n      const w = '            ------c-----';\n      const x = '            ----------e-';\n\n      const expectedGroups = {\n        v: TestScheduler.parseMarbles(v, values, undefined, undefined, true),\n        w: TestScheduler.parseMarbles(w, values, undefined, undefined, true),\n        x: TestScheduler.parseMarbles(x, values, undefined, undefined, true),\n      };\n\n      const unsubscriptionFrame = TestScheduler.parseMarblesAsSubscriptions(unsub, true).unsubscribedFrame;\n\n      const source = e1.pipe(\n        groupBy((val) => val.toLowerCase().trim(), {\n          duration: (group) => group.pipe(skip(2)),\n        }),\n        map((group) => {\n          const arr: any[] = [];\n\n          const subscription = group.pipe(phonyMarbelize(testScheduler)).subscribe((value) => {\n            arr.push(value);\n          });\n\n          testScheduler.schedule(() => {\n            subscription.unsubscribe();\n          }, unsubscriptionFrame - testScheduler.frame);\n          return arr;\n        })\n      );\n\n      expectObservable(source, unsub).toBe(expected, expectedGroups);\n    });\n  });\n\n  it('should dispose a durationSelector after closing the group', () => {\n    testScheduler.run(({ cold, hot, expectSubscriptions }) => {\n      const obs = hot(' -0-1--------2-| ');\n      const sub = '     ^--------------!';\n      // prettier-ignore\n      const unsubs = [\n        '              -^--!',\n        '              ---^--!',\n        '              ------------^-!',\n      ];\n      const dur = '     ---s';\n      const durations = [cold(dur), cold(dur), cold(dur)];\n\n      const unsubscribedFrame = TestScheduler.parseMarblesAsSubscriptions(sub, true).unsubscribedFrame;\n\n      obs\n        .pipe(\n          groupBy((val) => val, {\n            duration: (group) => durations[Number(group.key)],\n          })\n        )\n        .subscribe();\n\n      testScheduler.schedule(() => {\n        durations.forEach((d, i) => {\n          expectSubscriptions(d.subscriptions).toBe(unsubs[i]);\n        });\n      }, unsubscribedFrame);\n    });\n  });\n\n  it('should allow using a durationSelector, but keySelector throws', () => {\n    testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => {\n      const values = {\n        a: '  foo',\n        b: ' FoO ',\n        c: 'baR  ',\n        d: 'foO ',\n        e: ' Baz   ',\n        f: '  qux ',\n        g: '   bar',\n        h: ' BAR  ',\n        i: 'FOO ',\n        j: 'baz  ',\n        k: ' bAZ ',\n        l: '    fOo    ',\n      };\n      const e1 = hot('-1--2--^-a-b-c-d-e-f-g-h-i-j-k-l-|', values);\n      const e1subs = '       ^-------------------!      ';\n      const expected = '     --v---w---x-y-----z-#      ';\n      const v = cold('         a-b---(d|)               ', values);\n      const w = cold('             c-------g-(h|)       ', values);\n      const x = cold('                 e---------#      ', values);\n      const y = cold('                   f-------#      ', values);\n      const z = cold('                         i-#      ', values);\n      const expectedValues = { v: v, w: w, x: x, y: y, z: z };\n\n      let invoked = 0;\n      const source = e1.pipe(\n        groupBy(\n          (val: any) => {\n            invoked++;\n            if (invoked === 10) {\n              throw 'error';\n            }\n            return val.toLowerCase().trim();\n          },\n          (val: string) => val,\n          (group: any) => group.pipe(skip(2))\n        )\n      );\n\n      expectObservable(source).toBe(expected, expectedValues);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should allow using a durationSelector, but elementSelector throws', () => {\n    testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => {\n      const values = {\n        a: '  foo',\n        b: ' FoO ',\n        c: 'baR  ',\n        d: 'foO ',\n        e: ' Baz   ',\n        f: '  qux ',\n        g: '   bar',\n        h: ' BAR  ',\n        i: 'FOO ',\n        j: 'baz  ',\n        k: ' bAZ ',\n        l: '    fOo    ',\n      };\n      const e1 = hot('-1--2--^-a-b-c-d-e-f-g-h-i-j-k-l-|', values);\n      const e1subs = '       ^-------------------!      ';\n      const expected = '     --v---w---x-y-----z-#      ';\n      const v = cold('         a-b---(d|)               ', values);\n      const w = cold('             c-------g-(h|)       ', values);\n      const x = cold('                 e---------#      ', values);\n      const y = cold('                   f-------#      ', values);\n      const z = cold('                         i-#      ', values);\n      const expectedValues = { v: v, w: w, x: x, y: y, z: z };\n\n      let invoked = 0;\n      const source = e1.pipe(\n        groupBy(\n          (val: string) => val.toLowerCase().trim(),\n          (val: string) => {\n            invoked++;\n            if (invoked === 10) {\n              throw 'error';\n            }\n            return val;\n          },\n          (group: any) => group.pipe(skip(2))\n        )\n      );\n\n      expectObservable(source).toBe(expected, expectedValues);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should allow using a durationSelector which eventually throws', () => {\n    testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => {\n      const values = {\n        a: '  foo',\n        b: ' FoO ',\n        c: 'baR  ',\n        d: 'foO ',\n        e: ' Baz   ',\n        f: '  qux ',\n        g: '   bar',\n        h: ' BAR  ',\n        i: 'FOO ',\n        j: 'baz  ',\n        k: ' bAZ ',\n        l: '    fOo    ',\n      };\n      const e1 = hot('-1--2--^-a-b-c-d-e-f-g-h-i-j-k-l-|', values);\n      const e1subs = '       ^-----------!              ';\n      const expected = '  --v---w---x-(y#)              ';\n      const v = cold('         a-b---(d|)               ', values);\n      const w = cold('             c-----#              ', values);\n      const x = cold('                 e-#              ', values);\n      const y = cold('                   #              ', values);\n      const expectedValues = { v: v, w: w, x: x, y: y };\n\n      let invoked = 0;\n      const source = e1.pipe(\n        groupBy(\n          (val: string) => val.toLowerCase().trim(),\n          (val: string) => val,\n          (group: any) => {\n            invoked++;\n            if (invoked === 4) {\n              throw 'error';\n            }\n            return group.pipe(skip(2));\n          }\n        )\n      );\n\n      expectObservable(source).toBe(expected, expectedValues);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should allow an inner to be unsubscribed early but other inners continue, with durationSelector', () => {\n    testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => {\n      const values = {\n        a: '  foo',\n        b: ' FoO ',\n        c: 'baR  ',\n        d: 'foO ',\n        e: ' Baz   ',\n        f: '  qux ',\n        g: '   bar',\n        h: ' BAR  ',\n        i: 'FOO ',\n        j: 'baz  ',\n        k: ' bAZ ',\n        l: '    fOo    ',\n      };\n      const reversedValues = mapObject(values, reverseString);\n      const e1 = hot('-1--2--^-a-b-c-d-e-f-g-h-i-j-k-l-|', values);\n      const e1subs = '       ^-------------------------!';\n      const expected = '     --v---w---x-y-----z-------|';\n      const v = '            --a-b---                   ';\n      const unsubv = '       -------!                   ';\n      const w = '            ------c-------g-(h|)       ';\n      const x = '             ----------e---------j-(k|)';\n      const y = '            ------------f-------------|';\n      const z = '            ------------------i-----l-|';\n\n      const expectedGroups = {\n        v: TestScheduler.parseMarbles(v, reversedValues, undefined, undefined, true),\n        w: TestScheduler.parseMarbles(w, reversedValues, undefined, undefined, true),\n        x: TestScheduler.parseMarbles(x, reversedValues, undefined, undefined, true),\n        y: TestScheduler.parseMarbles(y, reversedValues, undefined, undefined, true),\n        z: TestScheduler.parseMarbles(z, reversedValues, undefined, undefined, true),\n      };\n\n      const fooUnsubscriptionFrame = TestScheduler.parseMarblesAsSubscriptions(unsubv, true).unsubscribedFrame;\n\n      const source = e1.pipe(\n        groupBy(\n          (val: string) => val.toLowerCase().trim(),\n          (val: string) => reverseString(val),\n          (group: any) => group.pipe(skip(2))\n        ),\n        map((group: any, index: number) => {\n          const arr: any[] = [];\n\n          const subscription = group.pipe(phonyMarbelize(testScheduler)).subscribe((value: any) => {\n            arr.push(value);\n          });\n\n          if (group.key === 'foo' && index === 0) {\n            testScheduler.schedule(() => {\n              subscription.unsubscribe();\n            }, fooUnsubscriptionFrame - testScheduler.frame);\n          }\n          return arr;\n        })\n      );\n\n      expectObservable(source).toBe(expected, expectedGroups);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should allow inners to be unsubscribed early at different times, with durationSelector', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const values = {\n        a: '  foo',\n        b: ' FoO ',\n        c: 'baR  ',\n        d: 'foO ',\n        e: ' Baz   ',\n        f: '  qux ',\n        g: '   bar',\n        h: ' BAR  ',\n        i: 'FOO ',\n        j: 'baz  ',\n        k: ' bAZ ',\n        l: '    fOo    ',\n      };\n      const e1 = hot('-1--2--^-a-b-c-d-e-f-g-h-i-j-k-l-|', values);\n      const e1subs = '       ^-------------------------!';\n      const expected = '     --v---w---x-y-----z-------|';\n      const v = '            --a-b---                   ';\n      const unsubv = '       -------!                   ';\n      const w = '            ------c---                 ';\n      const unsubw = '       ---------!                 ';\n      const x = '            ----------e---------j-     ';\n      const unsubx = '       ---------------------!     ';\n      const y = '            ------------f----          ';\n      const unsuby = '       ----------------!          ';\n      const z = '            ------------------i----    ';\n      const unsubz = '       ----------------------!    ';\n\n      const expectedGroups = {\n        v: TestScheduler.parseMarbles(v, values, undefined, undefined, true),\n        w: TestScheduler.parseMarbles(w, values, undefined, undefined, true),\n        x: TestScheduler.parseMarbles(x, values, undefined, undefined, true),\n        y: TestScheduler.parseMarbles(y, values, undefined, undefined, true),\n        z: TestScheduler.parseMarbles(z, values, undefined, undefined, true),\n      };\n\n      const unsubscriptionFrames: Record<string, number> = {\n        foo: TestScheduler.parseMarblesAsSubscriptions(unsubv, true).unsubscribedFrame,\n        bar: TestScheduler.parseMarblesAsSubscriptions(unsubw, true).unsubscribedFrame,\n        baz: TestScheduler.parseMarblesAsSubscriptions(unsubx, true).unsubscribedFrame,\n        qux: TestScheduler.parseMarblesAsSubscriptions(unsuby, true).unsubscribedFrame,\n        foo2: TestScheduler.parseMarblesAsSubscriptions(unsubz, true).unsubscribedFrame,\n      };\n      const hasUnsubscribed: Record<string, boolean> = {};\n\n      const source = e1.pipe(\n        groupBy(\n          (val: string) => val.toLowerCase().trim(),\n          (val: string) => val,\n          (group: any) => group.pipe(skip(2))\n        ),\n        map((group: any) => {\n          const arr: any[] = [];\n\n          const subscription = group.pipe(phonyMarbelize(testScheduler)).subscribe((value: any) => {\n            arr.push(value);\n          });\n\n          const unsubscriptionFrame = hasUnsubscribed[group.key] ? unsubscriptionFrames[group.key + '2'] : unsubscriptionFrames[group.key];\n          testScheduler.schedule(() => {\n            subscription.unsubscribe();\n            hasUnsubscribed[group.key] = true;\n          }, unsubscriptionFrame - testScheduler.frame);\n          return arr;\n        })\n      );\n\n      expectObservable(source).toBe(expected, expectedGroups);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should return inners that when subscribed late exhibit hot behavior', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const values = {\n        a: '  foo',\n        b: ' FoO ',\n        c: 'baR  ',\n        d: 'foO ',\n        e: ' Baz   ',\n        f: '  qux ',\n        g: '   bar',\n        h: ' BAR  ',\n        i: 'FOO ',\n        j: 'baz  ',\n        k: ' bAZ ',\n        l: '    fOo    ',\n      };\n      const e1 = hot('-1--2--^-a-b-c-d-e-f-g-h-i-j-k-l-|    ', values);\n      const e1subs = '       ^-------------------------!    ';\n      const expected = '     --v---w---x-y-------------|    ';\n      const subv = '         ---^                           '; // foo\n      const v = '            ----b---d---------i-----l-|    '; // foo\n      const subw = '         ---------^                     '; // bar\n      const w = '            --------------g-h---------|    '; // bar\n      const subx = '         -------------------^           '; // baz\n      const x = '            --------------------j-k---|    '; // baz\n      const suby = '         ------------------------------^'; // qux\n      const y = '            ------------------------------|'; // qux\n\n      const expectedGroups = {\n        v: TestScheduler.parseMarbles(v, values, undefined, undefined, true),\n        w: TestScheduler.parseMarbles(w, values, undefined, undefined, true),\n        x: TestScheduler.parseMarbles(x, values, undefined, undefined, true),\n        y: TestScheduler.parseMarbles(y, values, undefined, undefined, true),\n      };\n\n      const subscriptionFrames: Record<string, number> = {\n        foo: TestScheduler.parseMarblesAsSubscriptions(subv, true).subscribedFrame,\n        bar: TestScheduler.parseMarblesAsSubscriptions(subw, true).subscribedFrame,\n        baz: TestScheduler.parseMarblesAsSubscriptions(subx, true).subscribedFrame,\n        qux: TestScheduler.parseMarblesAsSubscriptions(suby, true).subscribedFrame,\n      };\n\n      const result = e1.pipe(\n        groupBy(\n          (val: string) => val.toLowerCase().trim(),\n          (val: string) => val\n        ),\n        map((group: any) => {\n          const innerNotifications: any[] = [];\n          const subscriptionFrame = subscriptionFrames[group.key];\n\n          testScheduler.schedule(() => {\n            group.pipe(phonyMarbelize(testScheduler)).subscribe((value: any) => {\n              innerNotifications.push(value);\n            });\n          }, subscriptionFrame - testScheduler.frame);\n\n          return innerNotifications;\n        })\n      );\n\n      expectObservable(result).toBe(expected, expectedGroups);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should return inner group that when subscribed late emits complete()', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const values = {\n        a: '  foo',\n        b: ' FoO ',\n        d: 'foO ',\n        i: 'FOO ',\n        l: '    fOo    ',\n      };\n      const e1 = hot('-1--2--^-a-b---d---------i-----l-|      ', values);\n      const e1subs = '       ^-------------------------!      ';\n      const expected = '     --g-----------------------|      ';\n      const innerSub = '     --------------------------------^';\n      const g = '            --------------------------------|';\n\n      const expectedGroups = {\n        g: TestScheduler.parseMarbles(g, values, undefined, undefined, true),\n      };\n\n      const innerSubscriptionFrame = TestScheduler.parseMarblesAsSubscriptions(innerSub, true).subscribedFrame;\n\n      const source = e1.pipe(\n        groupBy(\n          (val: string) => val.toLowerCase().trim(),\n          (val: string) => val,\n          (group: any) => group.pipe(skip(7))\n        ),\n        map((group: any) => {\n          const arr: any[] = [];\n\n          testScheduler.schedule(() => {\n            group.pipe(phonyMarbelize(testScheduler)).subscribe((value: any) => {\n              arr.push(value);\n            });\n          }, innerSubscriptionFrame - testScheduler.frame);\n\n          return arr;\n        })\n      );\n\n      expectObservable(source).toBe(expected, expectedGroups);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it.skip('should return inner group that when subscribed late emits error()', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const values = {\n        a: '  foo',\n        b: ' FoO ',\n        d: 'foO ',\n        i: 'FOO ',\n        l: '    fOo    ',\n      };\n      const e1 = hot('-1--2--^-a-b---d---------i-----l-#      ', values);\n      const e1subs = '       ^-------------------------!      ';\n      const expected = '     --g-----------------------#      ';\n      const innerSub = '     --------------------------------^';\n      const g = '            --------------------------------#';\n\n      const expectedGroups = {\n        g: TestScheduler.parseMarbles(g, values, undefined, undefined, true),\n      };\n\n      const innerSubscriptionFrame = TestScheduler.parseMarblesAsSubscriptions(innerSub, true).subscribedFrame;\n\n      const source = e1.pipe(\n        groupBy(\n          (val: string) => val.toLowerCase().trim(),\n          (val: string) => val,\n          (group: any) => group.pipe(skip(7))\n        ),\n        map((group: any) => {\n          const arr: any[] = [];\n\n          testScheduler.schedule(() => {\n            group.pipe(phonyMarbelize(testScheduler)).subscribe((value: any) => {\n              arr.push(value);\n            });\n          }, innerSubscriptionFrame - testScheduler.frame);\n\n          return arr;\n        })\n      );\n\n      expectObservable(source).toBe(expected, expectedGroups);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should not error for late subscribed inners if outer is unsubscribed before inners are subscribed', () => {\n    testScheduler.run(({ hot, expectObservable }) => {\n      const source = hot('-----^----a----b-----a------b----a----b---#');\n      // Unsubscribe before the error happens.\n      const unsub = '          -------------------!                  ';\n      // Used to hold two subjects we're going to use to subscribe to our groups\n      const subjects: Record<string, Subject<string>> = {\n        a: new Subject(),\n        b: new Subject(),\n      };\n      const result = source.pipe(\n        groupBy((char) => char),\n        tap({\n          // The real test is here, schedule each group to be subscribed to\n          // long after the source errors and long after the unsubscription happens.\n          next: (group) => {\n            testScheduler.schedule(() => group.subscribe(subjects[group.key]), 1000);\n          },\n        }),\n        // We don't are about what the outer is emitting\n        ignoreElements()\n      );\n      // Just to get the test going.\n      expectObservable(result, unsub).toBe('-');\n      // Our two groups should error immediately upon subscription.\n      expectObservable(subjects.a).toBe('-');\n      expectObservable(subjects.b).toBe('-');\n    });\n  });\n\n  it('should stop listening to a synchronous observable when unsubscribed', () => {\n    const sideEffects: number[] = [];\n    const synchronousObservable = new Observable<number>((subscriber) => {\n      // This will check to see if the subscriber was closed on each loop\n      // when the unsubscribe hits (from the `take`), it should be closed\n      for (let i = 0; !subscriber.closed && i < 10; i++) {\n        sideEffects.push(i);\n        subscriber.next(i);\n      }\n    });\n\n    synchronousObservable\n      .pipe(\n        groupBy((value) => value),\n        take(3)\n      )\n      .subscribe(() => {\n        /* noop */\n      });\n\n    expect(sideEffects).to.deep.equal([0, 1, 2]);\n  });\n});\n\n/**\n * TODO: A helper operator to deal with legacy tests above that could probably be written a different way\n */\nfunction phonyMarbelize<T>(testScheduler: TestScheduler) {\n  return (source: Observable<T>) =>\n    source.pipe(\n      materialize(),\n      map((notification) => {\n        // Because we're hacking some weird inner-observable marbles here, we need\n        // to make sure this is all the same shape as it would be from the TestScheduler\n        // assertions\n        return {\n          frame: testScheduler.frame,\n          notification: createNotification(\n            notification.kind,\n            (notification as NextNotification<T>).value,\n            (notification as ErrorNotification).error\n          ),\n        };\n      })\n    );\n}\n"
  },
  {
    "path": "packages/rxjs/spec/operators/ignoreElements-spec.ts",
    "content": "import { ignoreElements, mergeMap } from 'rxjs/operators';\nimport { TestScheduler } from 'rxjs/testing';\nimport { of } from 'rxjs';\nimport { observableMatcher } from '../helpers/observableMatcher';\n\n/** @test {ignoreElements} */\ndescribe('ignoreElements', () => {\n  let testScheduler: TestScheduler;\n\n  beforeEach(() => {\n    testScheduler = new TestScheduler(observableMatcher);\n  });\n\n  it('should ignore all the elements of the source', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  --a--b--c--d--|');\n      const e1subs = '  ^-------------!';\n      const expected = '--------------|';\n\n      expectObservable(e1.pipe(ignoreElements())).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should allow unsubscribing early and explicitly', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  --a--b--c--d--|');\n      const e1subs = '  ^------!       ';\n      const expected = '--------       ';\n      const unsub = '   -------!       ';\n\n      const result = e1.pipe(ignoreElements());\n\n      expectObservable(result, unsub).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should allow unsubscribing early and explicitly with higher order', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  --a--b--c--d--|');\n      const e1subs = '  ^------!       ';\n      const expected = '--------       ';\n      const unsub = '   -------!       ';\n\n      const result = e1.pipe(\n        mergeMap((x) => of(x)),\n        ignoreElements(),\n        mergeMap((x) => of(x))\n      );\n\n      expectObservable(result, unsub).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should propagate errors from the source', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  --a--#');\n      const e1subs = '  ^----!';\n      const expected = '-----#';\n\n      expectObservable(e1.pipe(ignoreElements())).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should handle empty', () => {\n    testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' |   ');\n      const e1subs = '  (^!)';\n      const expected = '|   ';\n\n      expectObservable(e1.pipe(ignoreElements())).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should handle never', () => {\n    testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' -');\n      const e1subs = '  ^';\n      const expected = '-';\n\n      expectObservable(e1.pipe(ignoreElements())).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should handle throw', () => {\n    testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold('  #  ');\n      const e1subs = '  (^!)';\n      const expected = '#   ';\n\n      expectObservable(e1.pipe(ignoreElements())).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n});\n"
  },
  {
    "path": "packages/rxjs/spec/operators/index-spec.ts",
    "content": "import * as index from 'rxjs/operators';\nimport { expect } from 'chai';\n\ndescribe('operators/index', () => {\n  it('should export operators', () => {\n    expect(index.audit).to.exist;\n    expect(index.auditTime).to.exist;\n    expect(index.buffer).to.exist;\n    expect(index.bufferCount).to.exist;\n    expect(index.bufferTime).to.exist;\n    expect(index.bufferToggle).to.exist;\n    expect(index.bufferWhen).to.exist;\n    expect(index.catchError).to.exist;\n    expect(index.combineLatestAll).to.exist;\n    expect(index.concatAll).to.exist;\n    expect(index.concatMap).to.exist;\n    expect(index.concatMapTo).to.exist;\n    expect(index.count).to.exist;\n    expect(index.debounce).to.exist;\n    expect(index.debounceTime).to.exist;\n    expect(index.defaultIfEmpty).to.exist;\n    expect(index.delay).to.exist;\n    expect(index.delayWhen).to.exist;\n    expect(index.dematerialize).to.exist;\n    expect(index.distinct).to.exist;\n    expect(index.distinctUntilChanged).to.exist;\n    expect(index.distinctUntilKeyChanged).to.exist;\n    expect(index.elementAt).to.exist;\n    expect(index.every).to.exist;\n    expect(index.exhaustAll).to.exist;\n    expect(index.exhaustMap).to.exist;\n    expect(index.expand).to.exist;\n    expect(index.filter).to.exist;\n    expect(index.finalize).to.exist;\n    expect(index.find).to.exist;\n    expect(index.findIndex).to.exist;\n    expect(index.first).to.exist;\n    expect(index.groupBy).to.exist;\n    expect(index.ignoreElements).to.exist;\n    expect(index.isEmpty).to.exist;\n    expect(index.last).to.exist;\n    expect(index.map).to.exist;\n    expect(index.mapTo).to.exist;\n    expect(index.materialize).to.exist;\n    expect(index.max).to.exist;\n    expect(index.mergeAll).to.exist;\n    expect(index.mergeMap).to.exist;\n    expect(index.mergeMap).to.exist;\n    expect(index.mergeMapTo).to.exist;\n    expect(index.mergeScan).to.exist;\n    expect(index.min).to.exist;\n    expect(index.observeOn).to.exist;\n    expect(index.pairwise).to.exist;\n    expect(index.partition).to.exist;\n    expect(index.reduce).to.exist;\n    expect(index.repeat).to.exist;\n    expect(index.repeatWhen).to.exist;\n    expect(index.retry).to.exist;\n    expect(index.retryWhen).to.exist;\n    expect(index.sample).to.exist;\n    expect(index.sampleTime).to.exist;\n    expect(index.scan).to.exist;\n    expect(index.sequenceEqual).to.exist;\n    expect(index.share).to.exist;\n    expect(index.shareReplay).to.exist;\n    expect(index.single).to.exist;\n    expect(index.skip).to.exist;\n    expect(index.skipLast).to.exist;\n    expect(index.skipUntil).to.exist;\n    expect(index.skipWhile).to.exist;\n    expect(index.startWith).to.exist;\n    expect(index.switchAll).to.exist;\n    expect(index.switchScan).to.exist;\n    expect(index.switchMap).to.exist;\n    expect(index.switchMapTo).to.exist;\n    expect(index.take).to.exist;\n    expect(index.takeLast).to.exist;\n    expect(index.takeUntil).to.exist;\n    expect(index.takeWhile).to.exist;\n    expect(index.tap).to.exist;\n    expect(index.throttle).to.exist;\n    expect(index.throttleTime).to.exist;\n    expect(index.timeInterval).to.exist;\n    expect(index.timeout).to.exist;\n    expect(index.timeoutWith).to.exist;\n    expect(index.timestamp).to.exist;\n    expect(index.toArray).to.exist;\n    expect(index.window).to.exist;\n    expect(index.windowCount).to.exist;\n    expect(index.windowTime).to.exist;\n    expect(index.windowToggle).to.exist;\n    expect(index.windowWhen).to.exist;\n    expect(index.withLatestFrom).to.exist;\n    expect(index.zipAll).to.exist;\n  });\n});\n"
  },
  {
    "path": "packages/rxjs/spec/operators/isEmpty-spec.ts",
    "content": "import { isEmpty, mergeMap } from 'rxjs/operators';\nimport { TestScheduler } from 'rxjs/testing';\nimport { of } from 'rxjs';\nimport { observableMatcher } from '../helpers/observableMatcher';\n\n/** @test {isEmpty} */\ndescribe('isEmpty', () => {\n  let testScheduler: TestScheduler;\n\n  beforeEach(() => {\n    testScheduler = new TestScheduler(observableMatcher);\n  });\n\n  it('should return true if source is empty', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  -----|   ');\n      const e1subs = '  ^----!   ';\n      const expected = '-----(T|)';\n\n      expectObservable(e1.pipe(isEmpty())).toBe(expected, { T: true });\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should return false if source emits element', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('--a--^--b--|');\n      const e1subs = '     ^--!   ';\n      const expected = '   ---(F|)';\n\n      expectObservable(e1.pipe(isEmpty())).toBe(expected, { F: false });\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should raise error if source raises error', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  --#');\n      const e1subs = '  ^-!';\n      const expected = '--#';\n\n      expectObservable(e1.pipe(isEmpty())).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should not complete if source never emits', () => {\n    testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' -');\n      const e1subs = '  ^';\n      const expected = '-';\n\n      expectObservable(e1.pipe(isEmpty())).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should return true if source is empty', () => {\n    testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' |   ');\n      const e1subs = '  (^!)';\n      const expected = '(T|)';\n\n      expectObservable(e1.pipe(isEmpty())).toBe(expected, { T: true });\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should allow unsubscribing explicitly and early', () => {\n    testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' -----------a--b--|');\n      const e1subs = '  ^-----!           ';\n      const expected = '-------           ';\n      const unsub = '   ------!           ';\n\n      expectObservable(e1.pipe(isEmpty()), unsub).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should not break unsubscription chains when result is unsubscribed explicitly', () => {\n    testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' -----------a--b--|');\n      const e1subs = '  ^-----!           ';\n      const expected = '-------           ';\n      const unsub = '   ------!           ';\n\n      const result = e1.pipe(\n        mergeMap((x) => of(x)),\n        isEmpty(),\n        mergeMap((x) => of(x))\n      );\n\n      expectObservable(result, unsub).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n});\n"
  },
  {
    "path": "packages/rxjs/spec/operators/last-spec.ts",
    "content": "import { TestScheduler } from 'rxjs/testing';\nimport { last, mergeMap } from 'rxjs/operators';\nimport type { Observable } from 'rxjs';\nimport { EmptyError, of, from } from 'rxjs';\nimport { observableMatcher } from '../helpers/observableMatcher';\n\n/** @test {last} */\ndescribe('last', () => {\n  let testScheduler: TestScheduler;\n\n  beforeEach(() => {\n    testScheduler = new TestScheduler(observableMatcher);\n  });\n\n  it('should take the last value of an observable', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  --a----b--c--|   ');\n      const e1subs = '  ^------------!   ';\n      const expected = '-------------(c|)';\n\n      expectObservable(e1.pipe(last())).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should error on nothing sent but completed', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('--a--^----|');\n      const e1subs = '     ^----!';\n      const expected = '   -----#';\n\n      expectObservable(e1.pipe(last())).toBe(expected, null, new EmptyError());\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should error on empty', () => {\n    testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' |   ');\n      const e1subs = '  (^!)';\n      const expected = '#   ';\n\n      expectObservable(e1.pipe(last())).toBe(expected, null, new EmptyError());\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should go on forever on never', () => {\n    testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' -');\n      const e1subs = '  ^';\n      const expected = '-';\n\n      expectObservable(e1.pipe(last())).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should allow undefined as a default value', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  -----a--a---a-|   ');\n      const e1subs = '  ^-------------!   ';\n      const expected = '--------------(U|)';\n\n      expectObservable(e1.pipe(last((value) => value === 'b', undefined))).toBe(expected, { U: undefined });\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should return last element matches with predicate', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  --a--b--a--b--|   ');\n      const e1subs = '  ^-------------!   ';\n      const expected = '--------------(b|)';\n\n      expectObservable(e1.pipe(last((value) => value === 'b'))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should allow unsubscribing explicitly and early', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  --a--b--c--d--|');\n      const e1subs = '  ^------!       ';\n      const expected = '--------       ';\n      const unsub = '   -------!       ';\n\n      expectObservable(e1.pipe(last()), unsub).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should not break unsubscription chains when result is unsubscribed explicitly', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  --a--b--c--d--|');\n      const e1subs = '  ^------!       ';\n      const expected = '--------       ';\n      const unsub = '   -------!       ';\n\n      const result = e1.pipe(\n        mergeMap((x) => of(x)),\n        last(),\n        mergeMap((x) => of(x))\n      );\n\n      expectObservable(result, unsub).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should return a default value if no element found', () => {\n    testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' |   ');\n      const e1subs = '  (^!)';\n      const expected = '(a|)';\n\n      expectObservable(e1.pipe(last(null, 'a'))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should not return default value if an element is found', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('--a---^---b---c---d---|   ');\n      const e1subs = '      ^---------------!   ';\n      const expected = '    ----------------(d|)';\n\n      expectObservable(e1.pipe(last(null, 'x'))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should raise error when predicate throws', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('--a--^---b---c---d---e--|');\n      const e1subs = '     ^-------!           ';\n      const expected = '   --------#           ';\n\n      const predicate = function (x: string) {\n        if (x === 'c') {\n          throw 'error';\n        } else {\n          return false;\n        }\n      };\n\n      expectObservable(e1.pipe(last(predicate))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should support type guards without breaking previous behavior', () => {\n    // type guards with interfaces and classes\n    {\n      interface Bar {\n        bar?: string;\n      }\n      interface Baz {\n        baz?: number;\n      }\n      class Foo implements Bar, Baz {\n        constructor(public bar: string = 'name', public baz: number = 42) {}\n      }\n\n      const isBar = (x: any): x is Bar => x && (x as Bar).bar !== undefined;\n      const isBaz = (x: any): x is Baz => x && (x as Baz).baz !== undefined;\n\n      const foo: Foo = new Foo();\n      of(foo)\n        .pipe(last())\n        .subscribe((x) => x.baz); // x is Foo\n      of(foo)\n        .pipe(last((foo) => foo.bar === 'name'))\n        .subscribe((x) => x.baz); // x is still Foo\n      of(foo)\n        .pipe(last(isBar))\n        .subscribe((x) => x.bar); // x is Bar!\n\n      const foobar: Bar = new Foo(); // type is the interface, not the class\n      of(foobar)\n        .pipe(last())\n        .subscribe((x) => x.bar); // x is Bar\n      of(foobar)\n        .pipe(last((foobar) => foobar.bar === 'name'))\n        .subscribe((x) => x.bar); // x is still Bar\n      of(foobar)\n        .pipe(last(isBaz))\n        .subscribe((x) => x.baz); // x is Baz!\n\n      const barish = { bar: 'quack', baz: 42 }; // type can quack like a Bar\n      of(barish)\n        .pipe(last())\n        .subscribe((x) => x.baz); // x is still { bar: string; baz: number; }\n      of(barish)\n        .pipe(last((x) => x.bar === 'quack'))\n        .subscribe((x) => x.bar); // x is still { bar: string; baz: number; }\n      of(barish)\n        .pipe(last(isBar))\n        .subscribe((x) => x.bar); // x is Bar!\n    }\n\n    // type guards with primitive types\n    {\n      const xs: Observable<string | number> = from([1, 'aaa', 3, 'bb']);\n\n      // This type guard will narrow a `string | number` to a string in the examples below\n      const isString = (x: string | number): x is string => typeof x === 'string';\n\n      // missing predicate preserves the type\n      xs.pipe(last()).subscribe((x) => x); // x is still string | number\n\n      // null predicate preserves the type\n      xs.pipe(last(null)).subscribe((x) => x); // x is still string | number\n\n      // undefined predicate preserves the type\n      xs.pipe(last(undefined)).subscribe((x) => x); // x is still string | number\n\n      // After the type guard `last` predicates, the type is narrowed to string\n      xs.pipe(last(isString)).subscribe((s) => s.length); // s is string\n\n      // boolean predicates preserve the type\n      xs.pipe(last((x) => typeof x === 'string')).subscribe((x) => x); // x is still string | number\n    }\n  });\n});\n"
  },
  {
    "path": "packages/rxjs/spec/operators/map-spec.ts",
    "content": "import { expect } from 'chai';\nimport { map, tap, mergeMap, take } from 'rxjs/operators';\nimport { TestScheduler } from 'rxjs/testing';\nimport type { Observer } from 'rxjs';\nimport { of, Observable, identity } from 'rxjs';\nimport { observableMatcher } from '../helpers/observableMatcher';\n\n// function shortcuts\nconst addDrama = (x: number | string) => x + '!';\n\n/** @test {map} */\ndescribe('map', () => {\n  let testScheduler: TestScheduler;\n\n  beforeEach(() => {\n    testScheduler = new TestScheduler(observableMatcher);\n  });\n\n  it('should map multiple values', () => {\n    testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' --1--2--3--|');\n      const e1subs = '  ^----------!';\n      const expected = '--x--y--z--|';\n\n      const result = e1.pipe(map((x) => 10 * +x));\n\n      expectObservable(result).toBe(expected, { x: 10, y: 20, z: 30 });\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should map one value', () => {\n    testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const values = { x: 42 };\n      const e1 = cold(' --x--|', values);\n      const e1subs = '  ^----!';\n      const expected = '--y--|';\n\n      const result = e1.pipe(map(addDrama));\n\n      expectObservable(result).toBe(expected, { y: '42!' });\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should map multiple values', () => {\n    testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' --1--2--3--|');\n      const e1subs = '  ^----------!';\n      const expected = '--x--y--z--|';\n\n      const result = e1.pipe(map(addDrama));\n\n      expectObservable(result).toBe(expected, { x: '1!', y: '2!', z: '3!' });\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should propagate errors from map function', () => {\n    testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const values = { x: 42 };\n      const e1 = cold(' --x--|', values);\n      const e1subs = '  ^-!   ';\n      const expected = '--#   ';\n\n      const result = e1.pipe(\n        map((x: any) => {\n          throw 'too bad';\n        })\n      );\n\n      expectObservable(result).toBe(expected, null, 'too bad');\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should propagate errors from observable that emits only errors', () => {\n    testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' #   ');\n      const e1subs = '  (^!)';\n      const expected = '#   ';\n\n      const result = e1.pipe(map(identity));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should propagate errors from observable that emit values', () => {\n    testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const values = { a: 1, b: 2 };\n      const e1 = cold(' --a--b--#', values, 'too bad');\n      const e1subs = '  ^-------!';\n      const expected = '--x--y--#';\n\n      const result = e1.pipe(map(addDrama));\n\n      expectObservable(result).toBe(expected, { x: '1!', y: '2!' }, 'too bad');\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should not map an empty observable', () => {\n    testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' |   ');\n      const e1subs = '  (^!)';\n      const expected = '|   ';\n\n      let invoked = 0;\n      const result = e1.pipe(\n        map((x: any) => {\n          invoked++;\n          return x;\n        }),\n        tap({\n          complete() {\n            expect(invoked).to.equal(0);\n          },\n        })\n      );\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should allow unsubscribing explicitly and early', () => {\n    testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' --1--2--3--|');\n      const e1subs = '  ^-----!     ';\n      const expected = '--x--y-     ';\n      const unsub = '   ------!     ';\n\n      const result = e1.pipe(map(addDrama));\n\n      expectObservable(result, unsub).toBe(expected, { x: '1!', y: '2!' });\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should map with index', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('-5-^-4--3---2----1--|');\n      const e1subs = '   ^----------------!';\n      const expected = ' --a--b---c----d--|';\n      const values = { a: 5, b: 14, c: 23, d: 32 };\n\n      let invoked = 0;\n      const result = e1.pipe(\n        map((x: string, index: number) => {\n          invoked++;\n          return parseInt(x) + 1 + index * 10;\n        }),\n        tap({\n          complete() {\n            expect(invoked).to.equal(4);\n          },\n        })\n      );\n\n      expectObservable(result).toBe(expected, values);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should map with index until completed', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('-5-^-4--3---2----1--|');\n      const e1subs = '   ^----------------!';\n      const expected = ' --a--b---c----d--|';\n      const values = { a: 5, b: 14, c: 23, d: 32 };\n\n      let invoked = 0;\n      const result = e1.pipe(\n        map((x: string, index: number) => {\n          invoked++;\n          return parseInt(x) + 1 + index * 10;\n        }),\n        tap({\n          complete() {\n            expect(invoked).to.equal(4);\n          },\n        })\n      );\n\n      expectObservable(result).toBe(expected, values);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should map with index until an error occurs', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('-5-^-4--3---2----1--#', undefined, 'too bad');\n      const e1subs = '   ^----------------!';\n      const expected = ' --a--b---c----d--#';\n      const values = { a: 5, b: 14, c: 23, d: 32 };\n\n      let invoked = 0;\n      const result = e1.pipe(\n        map((x: string, index: number) => {\n          invoked++;\n          return parseInt(x) + 1 + index * 10;\n        }),\n        tap({\n          error() {\n            expect(invoked).to.equal(4);\n          },\n        })\n      );\n\n      expectObservable(result).toBe(expected, values, 'too bad');\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should map twice', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('-0----1-^-2---3--4-5--6--7-8-|');\n      const e1subs = '        ^--------------------!';\n      const expected = '      --a---b--c-d--e--f-g-|';\n      const values = { a: 2, b: 3, c: 4, d: 5, e: 6, f: 7, g: 8 };\n\n      let invoked1 = 0;\n      let invoked2 = 0;\n      const result = e1.pipe(\n        map((x: string) => {\n          invoked1++;\n          return parseInt(x) * 2;\n        }),\n        map((x: number) => {\n          invoked2++;\n          return x / 2;\n        }),\n        tap({\n          complete() {\n            expect(invoked1).to.equal(7);\n            expect(invoked2).to.equal(7);\n          },\n        })\n      );\n\n      expectObservable(result).toBe(expected, values);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should not break unsubscription chain when unsubscribed explicitly', () => {\n    testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' --1--2--3--|');\n      const e1subs = '  ^-----!     ';\n      const expected = '--x--y-     ';\n      const unsub = '   ------!     ';\n\n      const result = e1.pipe(\n        mergeMap((x: string) => of(x)),\n        map(addDrama),\n        mergeMap((x: string) => of(x))\n      );\n\n      expectObservable(result, unsub).toBe(expected, { x: '1!', y: '2!' });\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should stop listening to a synchronous observable when unsubscribed', () => {\n    const sideEffects: number[] = [];\n    const synchronousObservable = new Observable<number>((subscriber) => {\n      // This will check to see if the subscriber was closed on each loop\n      // when the unsubscribe hits (from the `take`), it should be closed\n      for (let i = 0; !subscriber.closed && i < 10; i++) {\n        sideEffects.push(i);\n        subscriber.next(i);\n      }\n    });\n\n    synchronousObservable.pipe(map(identity), take(3)).subscribe(() => {\n      /* noop */\n    });\n\n    expect(sideEffects).to.deep.equal([0, 1, 2]);\n  });\n\n  describe(/* why u */ 'no lift' /* bro? */, () => {\n    it('can operate on any Observable-shaped object', () => {\n      const source = {\n        subscribe(observer: Observer<number>) {\n          observer.next(1);\n          observer.next(2);\n          observer.next(3);\n          observer.complete();\n          return {\n            unsubscribe() {\n              // noop\n            },\n          };\n        },\n      };\n      const results: any[] = [];\n\n      map((x: number) => x + '!!!')(source as any).subscribe((value: string) => {\n        results.push(value);\n      });\n\n      expect(results).to.deep.equal(['1!!!', '2!!!', '3!!!']);\n    });\n  });\n});\n"
  },
  {
    "path": "packages/rxjs/spec/operators/mapTo-spec.ts",
    "content": "import { expect } from 'chai';\nimport { mapTo, mergeMap, take } from 'rxjs/operators';\nimport { TestScheduler } from 'rxjs/testing';\nimport { of, Observable } from 'rxjs';\nimport { observableMatcher } from '../helpers/observableMatcher';\n\n/** @test {mapTo} */\ndescribe('mapTo', () => {\n  let testScheduler: TestScheduler;\n\n  beforeEach(() => {\n    testScheduler = new TestScheduler(observableMatcher);\n  });\n\n  it('should map multiple values', () => {\n    testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' --1--2--3--|');\n      const e1subs = '  ^----------!';\n      const expected = '--a--a--a--|';\n\n      expectObservable(e1.pipe(mapTo('a'))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should map one value', () => {\n    testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' --7--|');\n      const e1subs = '  ^----!';\n      const expected = '--y--|';\n\n      expectObservable(e1.pipe(mapTo('y'))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should allow unsubscribing explicitly and early', () => {\n    testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' --1--2--3--|');\n      const e1subs = '  ^-----!     ';\n      const expected = '--x--x-     ';\n      const unsub = '   ------!     ';\n\n      expectObservable(e1.pipe(mapTo('x')), unsub).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should propagate errors from observable that emits only errors', () => {\n    testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' --#', undefined, 'too bad');\n      const e1subs = '  ^-!';\n      const expected = '--#';\n\n      expectObservable(e1.pipe(mapTo(1))).toBe(expected, null, 'too bad');\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should propagate errors from observable that emit values, then errors', () => {\n    testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' --1--2--#', undefined, 'too bad');\n      const e1subs = '  ^-------!';\n      const expected = '--x--x--#';\n\n      expectObservable(e1.pipe(mapTo('x'))).toBe(expected, undefined, 'too bad');\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should not map an empty observable', () => {\n    testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' |   ');\n      const e1subs = '  (^!)';\n      const expected = '|   ';\n\n      expectObservable(e1.pipe(mapTo(-1))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should map twice', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('-0----1-^-2---3--4-5--6--7-8-|');\n      const e1subs = '        ^--------------------!';\n      const expected = '      --h---h--h-h--h--h-h-|';\n\n      // prettier-ignore\n      const result = e1.pipe(\n        mapTo(-1),\n        mapTo('h')\n      );\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should not break unsubscription chain when unsubscribed explicitly', () => {\n    testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' --1--2--3--|');\n      const e1subs = '  ^-----!     ';\n      const expected = '--x--x-     ';\n      const unsub = '   ------!     ';\n\n      const result = e1.pipe(\n        mergeMap((x: string) => of(x)),\n        mapTo('x'),\n        mergeMap((x: string) => of(x))\n      );\n\n      expectObservable(result, unsub).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should stop listening to a synchronous observable when unsubscribed', () => {\n    const sideEffects: number[] = [];\n    const synchronousObservable = new Observable<number>((subscriber) => {\n      // This will check to see if the subscriber was closed on each loop\n      // when the unsubscribe hits (from the `take`), it should be closed\n      for (let i = 0; !subscriber.closed && i < 10; i++) {\n        sideEffects.push(i);\n        subscriber.next(i);\n      }\n    });\n\n    synchronousObservable.pipe(mapTo(0), take(3)).subscribe(() => {\n      /* noop */\n    });\n\n    expect(sideEffects).to.deep.equal([0, 1, 2]);\n  });\n});\n"
  },
  {
    "path": "packages/rxjs/spec/operators/materialize-spec.ts",
    "content": "import { expect } from 'chai';\nimport { materialize, map, mergeMap, take } from 'rxjs/operators';\nimport { of, Observable } from 'rxjs';\nimport { TestScheduler } from 'rxjs/testing';\nimport { observableMatcher } from '../helpers/observableMatcher';\nimport { COMPLETE_NOTIFICATION, errorNotification, nextNotification } from '@rxjs/observable';\n\n/** @test {materialize} */\ndescribe('materialize', () => {\n  let testScheduler: TestScheduler;\n\n  beforeEach(() => {\n    testScheduler = new TestScheduler(observableMatcher);\n  });\n\n  it('should materialize an Observable', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  --x--y--z--|   ');\n      const e1subs = '  ^----------!   ';\n      const expected = '--a--b--c--(d|)';\n      const values = { a: '{x}', b: '{y}', c: '{z}', d: '|' };\n\n      const result = e1.pipe(\n        materialize(),\n        map((x: any) => {\n          if (x.kind === 'C') {\n            return '|';\n          } else {\n            return '{' + x.value + '}';\n          }\n        })\n      );\n\n      expectObservable(result).toBe(expected, values);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should materialize a happy stream', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  --a--b--c--|   ');\n      const e1subs = '  ^----------!   ';\n      const expected = '--w--x--y--(z|)';\n\n      const expectedValue = {\n        w: nextNotification('a'),\n        x: nextNotification('b'),\n        y: nextNotification('c'),\n        z: COMPLETE_NOTIFICATION,\n      };\n\n      expectObservable(e1.pipe(materialize())).toBe(expected, expectedValue);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should materialize a sad stream', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  --a--b--c--#   ');\n      const e1subs = '  ^----------!   ';\n      const expected = '--w--x--y--(z|)';\n\n      const expectedValue = {\n        w: nextNotification('a'),\n        x: nextNotification('b'),\n        y: nextNotification('c'),\n        z: errorNotification('error'),\n      };\n\n      expectObservable(e1.pipe(materialize())).toBe(expected, expectedValue);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should allow unsubscribing explicitly and early', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  --a--b--c--|');\n      const e1subs = '  ^-----!     ';\n      const expected = '--w--x-     ';\n      const unsub = '   ------!     ';\n\n      const expectedValue = {\n        w: nextNotification('a'),\n        x: nextNotification('b'),\n      };\n\n      expectObservable(e1.pipe(materialize()), unsub).toBe(expected, expectedValue);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should not break unsubscription chains when result is unsubscribed explicitly', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  --a--b--c--|');\n      const e1subs = '  ^-----!     ';\n      const expected = '--w--x-     ';\n      const unsub = '   ------!     ';\n\n      const expectedValue = {\n        w: nextNotification('a'),\n        x: nextNotification('b'),\n      };\n\n      const result = e1.pipe(\n        mergeMap((x: string) => of(x)),\n        materialize(),\n        mergeMap((x) => of(x))\n      );\n\n      expectObservable(result, unsub).toBe(expected, expectedValue);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should materialize stream that does not complete', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  -');\n      const e1subs = '  ^';\n      const expected = '-';\n\n      expectObservable(e1.pipe(materialize())).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should materialize stream that does not emit', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  ----|   ');\n      const e1subs = '  ^---!   ';\n      const expected = '----(x|)';\n\n      expectObservable(e1.pipe(materialize())).toBe(expected, { x: COMPLETE_NOTIFICATION });\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should materialize empty stream', () => {\n    testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' |   ');\n      const e1subs = '  (^!)';\n      const expected = '(x|)';\n\n      expectObservable(e1.pipe(materialize())).toBe(expected, { x: COMPLETE_NOTIFICATION });\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should materialize stream that throws', () => {\n    testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' #   ');\n      const e1subs = '  (^!)';\n      const expected = '(x|)';\n\n      expectObservable(e1.pipe(materialize())).toBe(expected, { x: errorNotification('error') });\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should stop listening to a synchronous observable when unsubscribed', () => {\n    const sideEffects: number[] = [];\n    const synchronousObservable = new Observable<number>((subscriber) => {\n      // This will check to see if the subscriber was closed on each loop\n      // when the unsubscribe hits (from the `take`), it should be closed\n      for (let i = 0; !subscriber.closed && i < 10; i++) {\n        sideEffects.push(i);\n        subscriber.next(i);\n      }\n    });\n\n    synchronousObservable.pipe(materialize(), take(3)).subscribe(() => {\n      /* noop */\n    });\n\n    expect(sideEffects).to.deep.equal([0, 1, 2]);\n  });\n});\n"
  },
  {
    "path": "packages/rxjs/spec/operators/max-spec.ts",
    "content": "import { expect } from 'chai';\nimport { max, mergeMap, skip, take } from 'rxjs/operators';\nimport { TestScheduler } from 'rxjs/testing';\nimport { of, range } from 'rxjs';\nimport { observableMatcher } from '../helpers/observableMatcher';\n\n/** @test {max} */\ndescribe('max', () => {\n  let testScheduler: TestScheduler;\n\n  beforeEach(() => {\n    testScheduler = new TestScheduler(observableMatcher);\n  });\n\n  it('should find the max of values of an observable', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  --a--b--c--|   ', { a: 42, b: -1, c: 3 });\n      const e1subs = '  ^----------!   ';\n      const expected = '-----------(x|)';\n\n      expectObservable(e1.pipe(max())).toBe(expected, { x: 42 });\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should be never when source is never', () => {\n    testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' -');\n      const e1subs = '  ^';\n      const expected = '-';\n\n      expectObservable(e1.pipe(max())).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should be zero when source is empty', () => {\n    testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' |   ');\n      const e1subs = '  (^!)';\n      const expected = '|   ';\n\n      expectObservable(e1.pipe(max())).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it(\"should be never when source doesn't complete\", () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('--x--^--y--');\n      const e1subs = '     ^-----';\n      const expected = '   ------';\n\n      expectObservable(e1.pipe(max())).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it(\"should complete when source doesn't have values\", () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('-x-^---|');\n      const e1subs = '   ^---!';\n      const expected = ' ----|';\n\n      expectObservable(e1.pipe(max())).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should max the unique value of an observable', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('-x-^--y--|   ', { y: 42 });\n      const e1subs = '   ^-----!   ';\n      const expected = ' ------(w|)';\n\n      expectObservable(e1.pipe(max())).toBe(expected, { w: 42 });\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should max the values of an ongoing hot observable', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('--a-^-b--c--d--|   ', { a: 42, b: -1, c: 0, d: 6 });\n      const e1subs = '    ^----------!   ';\n      const expected = '  -----------(x|)';\n\n      expectObservable(e1.pipe(max())).toBe(expected, { x: 6 });\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should allow unsubscribing explicitly and early', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  --a--b--c--|', { a: 42, b: -1, c: 0 });\n      const e1subs = '  ^-----!     ';\n      const expected = '-------     ';\n      const unsub = '   ------!     ';\n\n      expectObservable(e1.pipe(max()), unsub).toBe(expected, { x: 42 });\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should not break unsubscription chains when result is unsubscribed explicitly', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  --a--b--c--|', { a: 42, b: -1, c: 0 });\n      const e1subs = '  ^-----!     ';\n      const expected = '-------     ';\n      const unsub = '   ------!     ';\n\n      const result = e1.pipe(\n        mergeMap((x: number) => of(x)),\n        max(),\n        mergeMap((x: number) => of(x))\n      );\n\n      expectObservable(result, unsub).toBe(expected, { x: 42 });\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should max a range() source observable', (done) => {\n    range(1, 10000)\n      .pipe(max())\n      .subscribe({\n        next: (value: number) => {\n          expect(value).to.equal(10000);\n        },\n        error: () => {\n          done(new Error('should not be called'));\n        },\n        complete: () => {\n          done();\n        },\n      });\n  });\n\n  it('should max a range().pipe(skip(1)) source observable', (done) => {\n    range(1, 10)\n      .pipe(skip(1), max())\n      .subscribe({\n        next: (value: number) => {\n          expect(value).to.equal(10);\n        },\n        error: () => {\n          done(new Error('should not be called'));\n        },\n        complete: () => {\n          done();\n        },\n      });\n  });\n\n  it('should max a range().pipe(take(1)) source observable', (done) => {\n    range(1, 10)\n      .pipe(take(1), max())\n      .subscribe({\n        next: (value: number) => {\n          expect(value).to.equal(1);\n        },\n        error: () => {\n          done(new Error('should not be called'));\n        },\n        complete: () => {\n          done();\n        },\n      });\n  });\n\n  it('should work with error', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('-x-^--y--z--#', { x: 1, y: 2, z: 3 }, 'too bad');\n      const e1subs = '   ^--------!';\n      const expected = ' ---------#';\n\n      expectObservable(e1.pipe(max())).toBe(expected, null, 'too bad');\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should work with throw', () => {\n    testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' #   ');\n      const e1subs = '  (^!)';\n      const expected = '#   ';\n\n      expectObservable(e1.pipe(max())).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should handle a constant predicate on an empty hot observable', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('-x-^---|');\n      const e1subs = '   ^---!';\n      const expected = ' ----|';\n\n      const predicate = function <T>() {\n        return 42;\n      };\n\n      expectObservable(e1.pipe(max(predicate))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should handle a constant predicate on an never hot observable', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('-x-^----');\n      const e1subs = '   ^----';\n      const expected = ' -----';\n\n      const predicate = function <T>() {\n        return 42;\n      };\n\n      expectObservable(e1.pipe(max(predicate))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should handle a constant predicate on a simple hot observable', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('-x-^-a-|   ', { a: 1 });\n      const e1subs = '   ^---!   ';\n      const expected = ' ----(w|)';\n\n      const predicate = function () {\n        return 42;\n      };\n\n      expectObservable(e1.pipe(max(predicate))).toBe(expected, { w: 1 });\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should handle a reverse predicate on observable with many values', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('-a-^-b--c--d-|   ', { a: 42, b: -1, c: 0, d: 666 });\n      const e1subs = '   ^---------!   ';\n      const expected = ' ----------(w|)';\n\n      const predicate = function <T>(x: T, y: T) {\n        return x > y ? -1 : 1;\n      };\n\n      expectObservable(e1.pipe(max(predicate))).toBe(expected, { w: -1 });\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should handle a predicate for string on observable with many values', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('-a-^-b--c--d-|   ');\n      const e1subs = '   ^---------!   ';\n      const expected = ' ----------(w|)';\n\n      const predicate = function <T>(x: T, y: T) {\n        return x > y ? -1 : 1;\n      };\n\n      expectObservable(e1.pipe(max(predicate))).toBe(expected, { w: 'b' });\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should handle a constant predicate on observable that throws', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('-1-^---#');\n      const e1subs = '   ^---!';\n      const expected = ' ----#';\n\n      const predicate = () => {\n        return 42;\n      };\n\n      expectObservable(e1.pipe(max(predicate))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should handle a predicate that throws, on observable with many values', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('-1-^-2--3--|');\n      const e1subs = '   ^----!   ';\n      const expected = ' -----#   ';\n\n      const predicate = function (x: string, y: string) {\n        if (y === '3') {\n          throw 'error';\n        }\n        return x > y ? -1 : 1;\n      };\n\n      expectObservable(e1.pipe(max(predicate))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n});\n"
  },
  {
    "path": "packages/rxjs/spec/operators/mergeAll-spec.ts",
    "content": "import { expect } from 'chai';\nimport { mergeAll, mergeMap, take } from 'rxjs/operators';\nimport { TestScheduler } from 'rxjs/testing';\nimport { throwError, from, of, scheduled, queueScheduler, Observable } from 'rxjs';\nimport { observableMatcher } from '../helpers/observableMatcher';\n\n/** @test {mergeAll} */\ndescribe('mergeAll', () => {\n  let testScheduler: TestScheduler;\n\n  beforeEach(() => {\n    testScheduler = new TestScheduler(observableMatcher);\n  });\n\n  it('should merge a hot observable of cold observables', () => {\n    testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => {\n      const x = cold('    --a---b--c---d--|      ');\n      const xsubs = '   --^---------------!      ';\n      const y = cold('           ----e---f--g---|');\n      const ysubs = '   ---------^--------------!';\n      const e1 = hot('  --x------y-------|       ', { x: x, y: y });\n      const e1subs = '  ^----------------!       ';\n      const expected = '----a---b--c-e-d-f--g---|';\n\n      expectObservable(e1.pipe(mergeAll())).toBe(expected);\n      expectSubscriptions(x.subscriptions).toBe(xsubs);\n      expectSubscriptions(y.subscriptions).toBe(ysubs);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should merge all observables in an observable', () => {\n    testScheduler.run(({ expectObservable }) => {\n      // prettier-ignore\n      const e1 = from([\n        of('a'),\n        of('b'),\n        of('c')\n      ]);\n      const expected = '(abc|)';\n\n      expectObservable(e1.pipe(mergeAll())).toBe(expected);\n    });\n  });\n\n  it('should throw if any child observable throws', () => {\n    testScheduler.run(({ expectObservable }) => {\n      // prettier-ignore\n      const e1 = from([\n        of('a'),\n        throwError(() => ('error')),\n        of('c')\n      ]);\n      const expected = '(a#)';\n\n      expectObservable(e1.pipe(mergeAll())).toBe(expected);\n    });\n  });\n\n  it('should handle merging a hot observable of observables', () => {\n    testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => {\n      const x = cold('    a---b---c---|   ');\n      const xsubs = '   --^-----------!   ';\n      const y = cold('       d---e---f---|');\n      const ysubs = '   -----^-----------!';\n      const e1 = hot('  --x--y--|         ', { x: x, y: y });\n      const e1subs = '  ^-------!         ';\n      const expected = '--a--db--ec--f---|';\n\n      expectObservable(e1.pipe(mergeAll())).toBe(expected);\n      expectSubscriptions(x.subscriptions).toBe(xsubs);\n      expectSubscriptions(y.subscriptions).toBe(ysubs);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should merge one cold Observable at a time with parameter concurrency=1', () => {\n    testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => {\n      const x = cold('    a---b---c---|            ');\n      const xsubs = '   --^-----------!            ';\n      const y = cold('                d---e---f---|');\n      const ysubs = '   --------------^-----------!';\n      const e1 = hot('  --x--y--|                  ', { x: x, y: y });\n      const e1subs = '  ^-------!                  ';\n      const expected = '--a---b---c---d---e---f---|';\n\n      expectObservable(e1.pipe(mergeAll(1))).toBe(expected);\n      expectSubscriptions(x.subscriptions).toBe(xsubs);\n      expectSubscriptions(y.subscriptions).toBe(ysubs);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should merge two cold Observables at a time with parameter concurrency=2', () => {\n    testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => {\n      const x = cold('    a---b---c---|        ');\n      const xsubs = '   --^-----------!        ';\n      const y = cold('       d---e---f---|     ');\n      const ysubs = '   -----^-----------!     ';\n      const z = cold('                --g---h-|');\n      const zsubs = '   --------------^-------!';\n      const e1 = hot('  --x--y--z--|           ', { x: x, y: y, z: z });\n      const e1subs = '  ^----------!           ';\n      const expected = '--a--db--ec--f--g---h-|';\n\n      expectObservable(e1.pipe(mergeAll(2))).toBe(expected);\n      expectSubscriptions(x.subscriptions).toBe(xsubs);\n      expectSubscriptions(y.subscriptions).toBe(ysubs);\n      expectSubscriptions(z.subscriptions).toBe(zsubs);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should merge one hot Observable at a time with parameter concurrency=1', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const x = hot('   ---a---b---c---|          ');\n      const xsubs = '   --^------------!          ';\n      const y = hot('   -------------d---e---f---|');\n      const ysubs = '   ---------------^---------!';\n      const e1 = hot('  --x--y--|                 ', { x: x, y: y });\n      const e1subs = '  ^-------!                 ';\n      const expected = '---a---b---c-----e---f---|';\n\n      expectObservable(e1.pipe(mergeAll(1))).toBe(expected);\n      expectSubscriptions(x.subscriptions).toBe(xsubs);\n      expectSubscriptions(y.subscriptions).toBe(ysubs);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should merge two hot Observables at a time with parameter concurrency=2', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const x = hot('   i--a---b---c---|        ');\n      const xsubs = '   --^------------!        ';\n      const y = hot('   -i-i--d---e---f---|     ');\n      const ysubs = '   -----^------------!     ';\n      const z = hot('   --i--i--i--i-----g---h-|');\n      const zsubs = '   ---------------^-------!';\n      const e1 = hot('  --x--y--z--|            ', { x: x, y: y, z: z });\n      const e1subs = '  ^----------!            ';\n      const expected = '---a--db--ec--f--g---h-|';\n\n      expectObservable(e1.pipe(mergeAll(2))).toBe(expected);\n      expectSubscriptions(x.subscriptions).toBe(xsubs);\n      expectSubscriptions(y.subscriptions).toBe(ysubs);\n      expectSubscriptions(z.subscriptions).toBe(zsubs);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should handle merging a hot observable of observables, outer unsubscribed early', () => {\n    testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => {\n      const x = cold('    a---b---c---|   ');\n      const xsubs = '   --^---------!     ';\n      const y = cold('       d---e---f---|');\n      const ysubs = '   -----^------!     ';\n      const e1 = hot('  --x--y--|         ', { x: x, y: y });\n      const e1subs = '  ^-------!         ';\n      const expected = '--a--db--ec--     ';\n      const unsub = '   ------------!     ';\n\n      expectObservable(e1.pipe(mergeAll()), unsub).toBe(expected);\n      expectSubscriptions(x.subscriptions).toBe(xsubs);\n      expectSubscriptions(y.subscriptions).toBe(ysubs);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should not break unsubscription chains when result is unsubscribed explicitly', () => {\n    testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => {\n      const x = cold('    a---b---c---|   ');\n      const xsubs = '   --^---------!     ';\n      const y = cold('       d---e---f---|');\n      const ysubs = '   -----^------!     ';\n      const e1 = hot('  --x--y--|         ', { x: x, y: y });\n      const e1subs = '  ^-------!         ';\n      const expected = '--a--db--ec--     ';\n      const unsub = '   ------------!     ';\n\n      const result = e1.pipe(\n        mergeMap((x) => of(x)),\n        mergeAll(),\n        mergeMap((x) => of(x))\n      );\n\n      expectObservable(result, unsub).toBe(expected);\n      expectSubscriptions(x.subscriptions).toBe(xsubs);\n      expectSubscriptions(y.subscriptions).toBe(ysubs);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should merge parallel emissions', () => {\n    testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => {\n      const x = cold('    ----a----b----c---|');\n      const xsubs = '   --^-----------------!';\n      const y = cold('       -d----e----f---|');\n      const ysubs = '   -----^--------------!';\n      const e1 = hot('  --x--y--|            ', { x: x, y: y });\n      const e1subs = '  ^-------!            ';\n      const expected = '------(ad)-(be)-(cf)|';\n\n      expectObservable(e1.pipe(mergeAll())).toBe(expected);\n      expectSubscriptions(x.subscriptions).toBe(xsubs);\n      expectSubscriptions(y.subscriptions).toBe(ysubs);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should merge empty and empty', () => {\n    testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => {\n      const x = cold('    |      ');\n      const xsubs = '   --(^!)   ';\n      const y = cold('       |   ');\n      const ysubs = '   -----(^!)';\n      const e1 = hot('  --x--y--|', { x: x, y: y });\n      const e1subs = '  ^-------!';\n      const expected = '--------|';\n\n      expectObservable(e1.pipe(mergeAll())).toBe(expected);\n      expectSubscriptions(x.subscriptions).toBe(xsubs);\n      expectSubscriptions(y.subscriptions).toBe(ysubs);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should merge three empties', () => {\n    testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => {\n      const x = cold('    |         ');\n      const xsubs = '   --(^!)      ';\n      const y = cold('       |      ');\n      const ysubs = '   -----(^!)   ';\n      const z = cold('         |    ');\n      const zsubs = '   -------(^!) ';\n      const e1 = hot('  --x--y-z---|', { x: x, y: y, z: z });\n      const e1subs = '  ^----------!';\n      const expected = '-----------|';\n\n      expectObservable(e1.pipe(mergeAll())).toBe(expected);\n      expectSubscriptions(x.subscriptions).toBe(xsubs);\n      expectSubscriptions(y.subscriptions).toBe(ysubs);\n      expectSubscriptions(z.subscriptions).toBe(zsubs);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should merge never and empty', () => {\n    testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => {\n      const x = cold('    -      ');\n      const xsubs = '   --^      ';\n      const y = cold('       |   ');\n      const ysubs = '   -----(^!)';\n      const e1 = hot('  --x--y--|', { x: x, y: y });\n      const e1subs = '  ^-------!';\n      const expected = '---------';\n\n      expectObservable(e1.pipe(mergeAll())).toBe(expected);\n      expectSubscriptions(x.subscriptions).toBe(xsubs);\n      expectSubscriptions(y.subscriptions).toBe(ysubs);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should merge never and never', () => {\n    testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => {\n      const x = cold('    -      ');\n      const xsubs = '   --^      ';\n      const y = cold('       -   ');\n      const ysubs = '   -----^   ';\n      const e1 = hot('  --x--y--|', { x: x, y: y });\n      const e1subs = '  ^-------!';\n      const expected = '---------';\n\n      expectObservable(e1.pipe(mergeAll())).toBe(expected);\n      expectSubscriptions(x.subscriptions).toBe(xsubs);\n      expectSubscriptions(y.subscriptions).toBe(ysubs);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should merge empty and throw', () => {\n    testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => {\n      const x = cold('    |      ');\n      const xsubs = '   --(^!)   ';\n      const y = cold('       #   ');\n      const ysubs = '   -----(^!)';\n      const e1 = hot('  --x--y--|', { x: x, y: y });\n      const e1subs = '  ^----!   ';\n      const expected = '-----#   ';\n\n      expectObservable(e1.pipe(mergeAll())).toBe(expected);\n      expectSubscriptions(x.subscriptions).toBe(xsubs);\n      expectSubscriptions(y.subscriptions).toBe(ysubs);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should merge never and throw', () => {\n    testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => {\n      const x = cold('    -      ');\n      const xsubs = '   --^--!   ';\n      const y = cold('       #   ');\n      const ysubs = '   -----(^!)';\n      const e1 = hot('  --x--y--|', { x: x, y: y });\n      const e1subs = '  ^----!   ';\n      const expected = '-----#   ';\n\n      expectObservable(e1.pipe(mergeAll())).toBe(expected);\n      expectSubscriptions(x.subscriptions).toBe(xsubs);\n      expectSubscriptions(y.subscriptions).toBe(ysubs);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should merge empty and eventual error', () => {\n    testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => {\n      const x = cold('    |         ');\n      const xsubs = '   --(^!)      ';\n      const y = cold('       ------#');\n      const ysubs = '   -----^-----!';\n      const e1 = hot('  --x--y--|   ', { x: x, y: y });\n      const e1subs = '  ^-------!   ';\n      const expected = '-----------#';\n\n      expectObservable(e1.pipe(mergeAll())).toBe(expected);\n      expectSubscriptions(x.subscriptions).toBe(xsubs);\n      expectSubscriptions(y.subscriptions).toBe(ysubs);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should merge never and eventual error', () => {\n    testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => {\n      const x = cold('    -         ');\n      const xsubs = '   --^--------!';\n      const y = cold('       ------#');\n      const ysubs = '   -----^-----!';\n      const e1 = hot('  --x--y--|   ', { x: x, y: y });\n      const e1subs = '  ^-------!   ';\n      const expected = '-----------#';\n\n      expectObservable(e1.pipe(mergeAll())).toBe(expected);\n      expectSubscriptions(x.subscriptions).toBe(xsubs);\n      expectSubscriptions(y.subscriptions).toBe(ysubs);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should take an empty source and return empty too', () => {\n    testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' |   ');\n      const e1subs = '  (^!)';\n      const expected = '|   ';\n\n      expectObservable(e1.pipe(mergeAll())).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should take a never source and return never too', () => {\n    testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' -');\n      const e1subs = '  ^';\n      const expected = '-';\n\n      expectObservable(e1.pipe(mergeAll())).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should take a throw source and return throw too', () => {\n    testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' #   ');\n      const e1subs = '  (^!)';\n      const expected = '#   ';\n\n      expectObservable(e1.pipe(mergeAll())).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should handle merging a hot observable of non-overlapped observables', () => {\n    testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => {\n      const x = cold('    a-b---------|                 ');\n      const xsubs = '   --^-----------!                 ';\n      const y = cold('              c-d-e-f-|           ');\n      const ysubs = '   ------------^-------!           ';\n      const z = cold('                       g-h-i-j-k-|');\n      const zsubs = '   ---------------------^---------!';\n      const e1 = hot('  --x---------y--------z--------| ', { x: x, y: y, z: z });\n      const e1subs = '  ^-----------------------------! ';\n      const expected = '--a-b-------c-d-e-f--g-h-i-j-k-|';\n\n      expectObservable(e1.pipe(mergeAll())).toBe(expected);\n      expectSubscriptions(x.subscriptions).toBe(xsubs);\n      expectSubscriptions(y.subscriptions).toBe(ysubs);\n      expectSubscriptions(z.subscriptions).toBe(zsubs);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should raise error if inner observable raises error', () => {\n    testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => {\n      const x = cold('    a-b---------|                 ');\n      const xsubs = '   --^-----------!                 ';\n      const y = cold('              c-d-e-f-#           ');\n      const ysubs = '   ------------^-------!           ';\n      const z = cold('                       g-h-i-j-k-|');\n      const zsubs: string[] = [];\n      const e1 = hot('  --x---------y--------z--------| ', { x: x, y: y, z: z });\n      const e1subs = '  ^-------------------!           ';\n      const expected = '--a-b-------c-d-e-f-#           ';\n\n      expectObservable(e1.pipe(mergeAll())).toBe(expected);\n      expectSubscriptions(x.subscriptions).toBe(xsubs);\n      expectSubscriptions(y.subscriptions).toBe(ysubs);\n      expectSubscriptions(z.subscriptions).toBe(zsubs);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should raise error if outer observable raises error', () => {\n    testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => {\n      const x = cold('    a-b---------|      ');\n      const xsubs = '   --^-----------!      ';\n      const y = cold('              c-d-e-f-|');\n      const ysubs = '   ------------^---!    ';\n      const e1 = hot('  --x---------y---#    ', { x: x, y: y });\n      const e1subs = '  ^---------------!    ';\n      const expected = '--a-b-------c-d-#    ';\n\n      expectObservable(e1.pipe(mergeAll())).toBe(expected);\n      expectSubscriptions(x.subscriptions).toBe(xsubs);\n      expectSubscriptions(y.subscriptions).toBe(ysubs);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should merge all promises in an observable', (done) => {\n    const e1 = from([\n      new Promise<string>((res) => {\n        res('a');\n      }),\n      new Promise<string>((res) => {\n        res('b');\n      }),\n      new Promise<string>((res) => {\n        res('c');\n      }),\n      new Promise<string>((res) => {\n        res('d');\n      }),\n    ]);\n    const expected = ['a', 'b', 'c', 'd'];\n\n    const res: string[] = [];\n    e1.pipe(mergeAll()).subscribe({\n      next: (x) => {\n        res.push(x);\n      },\n      error: () => {\n        done(new Error('should not be called'));\n      },\n      complete: () => {\n        expect(res).to.deep.equal(expected);\n        done();\n      },\n    });\n  });\n\n  it('should raise error when promise rejects', (done) => {\n    const error = 'error';\n    const e1 = from([\n      new Promise<string>((res) => {\n        res('a');\n      }),\n      new Promise<string>((res: any, rej) => {\n        rej(error);\n      }),\n      new Promise<string>((res) => {\n        res('c');\n      }),\n      new Promise<string>((res) => {\n        res('d');\n      }),\n    ]);\n\n    const res: string[] = [];\n    e1.pipe(mergeAll()).subscribe({\n      next: (x) => {\n        res.push(x);\n      },\n      error: (err) => {\n        expect(res.length).to.equal(1);\n        expect(err).to.equal('error');\n        done();\n      },\n      complete: () => {\n        done(new Error('should not be called'));\n      },\n    });\n  });\n\n  it('should finalize generators when merged if the subscription ends', () => {\n    const iterable = {\n      finalized: false,\n      next() {\n        return { value: 'duck', done: false };\n      },\n      return() {\n        this.finalized = true;\n      },\n      [Symbol.iterator]() {\n        return this;\n      },\n    };\n\n    const results: string[] = [];\n\n    const iterableObservable = from<string>(iterable as any);\n    of(iterableObservable)\n      .pipe(mergeAll(), take(3))\n      .subscribe({ next: (x) => results.push(x), complete: () => results.push('GOOSE!') });\n\n    expect(results).to.deep.equal(['duck', 'duck', 'duck', 'GOOSE!']);\n    expect(iterable.finalized).to.be.true;\n  });\n\n  it('should merge two observables', (done) => {\n    const a = of(1, 2, 3);\n    const b = of(4, 5, 6, 7, 8);\n    const r = [1, 2, 3, 4, 5, 6, 7, 8];\n\n    of(a, b)\n      .pipe(mergeAll())\n      .subscribe({\n        next: (val) => {\n          expect(val).to.equal(r.shift());\n        },\n        complete: done,\n      });\n  });\n\n  it('should merge two immediately-scheduled observables', (done) => {\n    const a = scheduled([1, 2, 3], queueScheduler);\n    const b = scheduled([4, 5, 6, 7, 8], queueScheduler);\n    const r = [1, 2, 4, 3, 5, 6, 7, 8];\n\n    scheduled([a, b], queueScheduler)\n      .pipe(mergeAll())\n      .subscribe({\n        next: (val) => {\n          expect(val).to.equal(r.shift());\n        },\n        complete: done,\n      });\n  });\n\n  it('should stop listening to a synchronous observable when unsubscribed', () => {\n    const sideEffects: number[] = [];\n    const synchronousObservable = new Observable<number>((subscriber) => {\n      // This will check to see if the subscriber was closed on each loop\n      // when the unsubscribe hits (from the `take`), it should be closed\n      for (let i = 0; !subscriber.closed && i < 10; i++) {\n        sideEffects.push(i);\n        subscriber.next(i);\n      }\n    });\n\n    of(synchronousObservable)\n      .pipe(mergeAll(), take(3))\n      .subscribe(() => {\n        /* noop */\n      });\n\n    expect(sideEffects).to.deep.equal([0, 1, 2]);\n  });\n});\n"
  },
  {
    "path": "packages/rxjs/spec/operators/mergeMap-spec.ts",
    "content": "import { expect } from 'chai';\nimport { mergeMap, map, delay, take } from 'rxjs/operators';\nimport { asapScheduler, defer, Observable, from, of, scheduled, timer } from 'rxjs';\nimport { asInteropObservable } from '../helpers/interop-helper';\nimport { TestScheduler } from 'rxjs/testing';\nimport { observableMatcher } from '../helpers/observableMatcher';\n\n/** @test {mergeMap} */\ndescribe('mergeMap', () => {\n  let testScheduler: TestScheduler;\n\n  beforeEach(() => {\n    testScheduler = new TestScheduler(observableMatcher);\n  });\n\n  it('should map-and-flatten each item to an Observable', () => {\n    testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => {\n      const values = { x: 10, y: 30, z: 50 };\n      const x = cold('    x-x-x|             ', values);\n      //                        y-y-y|\n      //                           z-z-z|\n      const xsubs = [\n        '               --^----!             ',\n        '               --------^----!       ',\n        '               -----------^----!    ',\n      ];\n      const e1 = hot('  --1-----3--5--------|');\n      const e1subs = '  ^-------------------!';\n      const expected = '--x-x-x-y-yzyz-z----|';\n\n      const result = e1.pipe(mergeMap((value) => x.pipe(map((i) => i * +value))));\n\n      expectObservable(result).toBe(expected, values);\n      expectSubscriptions(x.subscriptions).toBe(xsubs);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should mergeMap many regular interval inners', () => {\n    testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => {\n      const a = cold('  ----a---a---a---(a|)                    ');\n      const asubs = '   ^---------------!                       ';\n      const b = cold('      ----b---b---(b|)                    ');\n      const bsubs = '   ----^-----------!                       ';\n      const c = cold('                  ----c---c---c---c---(c|)');\n      const csubs = '   ----------------^-------------------!   ';\n      const d = cold('                          ----(d|)        ');\n      const dsubs = '   ------------------------^---!           ';\n      const e1 = hot('  a---b-----------c-------d-------|       ');\n      const e1subs = '  ^-------------------------------!       ';\n      const expected = '----a---(ab)(ab)(ab)c---c---(cd)c---(c|)';\n\n      const observableLookup: Record<string, Observable<string>> = { a: a, b: b, c: c, d: d };\n      const source = e1.pipe(mergeMap((value) => observableLookup[value]));\n\n      expectObservable(source).toBe(expected);\n      expectSubscriptions(a.subscriptions).toBe(asubs);\n      expectSubscriptions(b.subscriptions).toBe(bsubs);\n      expectSubscriptions(c.subscriptions).toBe(csubs);\n      expectSubscriptions(d.subscriptions).toBe(dsubs);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should map values to constant resolved promises and merge', (done) => {\n    const source = from([4, 3, 2, 1]);\n    const project = () => from(Promise.resolve(42));\n\n    const results: number[] = [];\n    source.pipe(mergeMap(project)).subscribe({\n      next: (x) => {\n        results.push(x);\n      },\n      error: (err) => {\n        done(new Error('Subscriber error handler not supposed to be called.'));\n      },\n      complete: () => {\n        expect(results).to.deep.equal([42, 42, 42, 42]);\n        done();\n      },\n    });\n  });\n\n  it('should map values to constant rejected promises and merge', (done) => {\n    const source = from([4, 3, 2, 1]);\n    const project = () => from(Promise.reject<number>(42));\n\n    source.pipe(mergeMap(project)).subscribe({\n      next: (x) => {\n        done(new Error('Subscriber next handler not supposed to be called.'));\n      },\n      error: (err) => {\n        expect(err).to.equal(42);\n        done();\n      },\n      complete: () => {\n        done(new Error('Subscriber complete handler not supposed to be called.'));\n      },\n    });\n  });\n\n  it('should map values to resolved promises and merge', (done) => {\n    const source = from([4, 3, 2, 1]);\n    const project = (value: number, index: number) => from(Promise.resolve(value + index));\n\n    const results: number[] = [];\n    source.pipe(mergeMap(project)).subscribe({\n      next: (x) => {\n        results.push(x);\n      },\n      error: (err) => {\n        done(new Error('Subscriber error handler not supposed to be called.'));\n      },\n      complete: () => {\n        expect(results).to.deep.equal([4, 4, 4, 4]);\n        done();\n      },\n    });\n  });\n\n  it('should map values to rejected promises and merge', (done) => {\n    const source = from([4, 3, 2, 1]);\n    const project = (value: number, index: number) => from(Promise.reject<string>('' + value + '-' + index));\n\n    source.pipe(mergeMap(project)).subscribe({\n      next: (x) => {\n        done(new Error('Subscriber next handler not supposed to be called.'));\n      },\n      error: (err) => {\n        expect(err).to.equal('4-0');\n        done();\n      },\n      complete: () => {\n        done(new Error('Subscriber complete handler not supposed to be called.'));\n      },\n    });\n  });\n\n  it('should mergeMap many outer values to many inner values', () => {\n    testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => {\n      const x = cold('   ----i---j---k---l---|                        ');\n      //                         ----i---j---k---l---|\n      //                                 ----i---j---k---l---|\n      //                                         ----i---j---k---l---|\n      const xsubs = [\n        '               -^-------------------!                        ',\n        '               ---------^-------------------!                ',\n        '               -----------------^-------------------!        ',\n        '               -------------------------^-------------------!',\n      ];\n      const e1 = hot('  -a-------b-------c-------d-------|            ');\n      const e1subs = '  ^--------------------------------!            ';\n      const expected = '-----i---j---(ki)(lj)(ki)(lj)(ki)(lj)k---l---|';\n\n      const result = e1.pipe(mergeMap(() => x));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(x.subscriptions).toBe(xsubs);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should mergeMap many outer to many inner, complete late', () => {\n    testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => {\n      const x = cold('   ----i---j---k---l---|                            ');\n      //                         ----i---j---k---l---|\n      //                                 ----i---j---k---l---|\n      //                                         ----i---j---k---l---|\n      const xsubs = [\n        '               -^-------------------!                            ',\n        '               ---------^-------------------!                    ',\n        '               -----------------^-------------------!            ',\n        '               -------------------------^-------------------!    ',\n      ];\n      const e1 = hot('  -a-------b-------c-------d-----------------------|');\n      const e1subs = '  ^------------------------------------------------!';\n      const expected = '-----i---j---(ki)(lj)(ki)(lj)(ki)(lj)k---l-------|';\n\n      const result = e1.pipe(mergeMap(() => x));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(x.subscriptions).toBe(xsubs);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should mergeMap many outer to many inner, outer never completes', () => {\n    testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => {\n      const x = cold('   ----i---j---k---l---|                                  ');\n      //                         ----i---j---k---l---|\n      //                                 ----i---j---k---l---|\n      //                                         ----i---j---k---l---|\n      //                                                 ----i---j---k---l---|\n      //                                                                 ----i--\n      const xsubs = [\n        '               -^-------------------!                                  ',\n        '               ---------^-------------------!                          ',\n        '               -----------------^-------------------!                  ',\n        '               -------------------------^-------------------!          ',\n        '               ---------------------------------^-------------------!  ',\n        '               -------------------------------------------------^-----!',\n      ];\n      const e1 = hot('  -a-------b-------c-------d-------e---------------f------');\n      const e1subs = '  ^------------------------------------------------------!';\n      const expected = '-----i---j---(ki)(lj)(ki)(lj)(ki)(lj)(ki)(lj)k---l---i--';\n      const unsub = '   -------------------------------------------------------!';\n\n      const source = e1.pipe(mergeMap(() => x));\n\n      expectObservable(source, unsub).toBe(expected);\n      expectSubscriptions(x.subscriptions).toBe(xsubs);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should not break unsubscription chains when result is unsubscribed explicitly', () => {\n    testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => {\n      const x = cold('   ----i---j---k---l---|                                  ');\n      //                         ----i---j---k---l---|\n      //                                 ----i---j---k---l---|\n      //                                         ----i---j---k---l---|\n      //                                                 ----i---j---k---l---|\n      //                                                                 ----i--\n      const xsubs = [\n        '               -^-------------------!                                  ',\n        '               ---------^-------------------!                          ',\n        '               -----------------^-------------------!                  ',\n        '               -------------------------^-------------------!          ',\n        '               ---------------------------------^-------------------!  ',\n        '               -------------------------------------------------^-----!',\n      ];\n      const e1 = hot('  -a-------b-------c-------d-------e---------------f------');\n      const e1subs = '  ^------------------------------------------------------!';\n      const expected = '-----i---j---(ki)(lj)(ki)(lj)(ki)(lj)(ki)(lj)k---l---i--';\n      const unsub = '   -------------------------------------------------------!';\n\n      const source = e1.pipe(\n        map((x) => x),\n        mergeMap(() => x),\n        map((x) => x)\n      );\n\n      expectObservable(source, unsub).toBe(expected);\n      expectSubscriptions(x.subscriptions).toBe(xsubs);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should not break unsubscription chains with interop inners when result is unsubscribed explicitly', () => {\n    testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => {\n      const x = cold('           --a--b--c--d--e--|           ');\n      const xsubs = '   ---------^-----------!                ';\n      const y = cold('                     ---f---g---h---i--|');\n      const ysubs = '   -------------------^-!                ';\n      const e1 = hot('  ---------x---------y---------|        ');\n      const e1subs = '  ^--------------------!                ';\n      const expected = '-----------a--b--c--d-                ';\n      const unsub = '   ---------------------!                ';\n\n      const observableLookup: Record<string, Observable<string>> = { x: x, y: y };\n\n      // This test manipulates the observable to make it look like an interop\n      // observable - an observable from a foreign library. Interop subscribers\n      // are treated differently: they are wrapped in a safe subscriber. This\n      // test ensures that unsubscriptions are chained all the way to the\n      // interop subscriber.\n\n      const result = e1.pipe(\n        mergeMap((x) => of(x)),\n        mergeMap((value) => asInteropObservable(observableLookup[value])),\n        mergeMap((x) => of(x))\n      );\n\n      expectObservable(result, unsub).toBe(expected);\n      expectSubscriptions(x.subscriptions).toBe(xsubs);\n      expectSubscriptions(y.subscriptions).toBe(ysubs);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should mergeMap many outer to many inner, inner never completes', () => {\n    testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => {\n      const x = cold('   ----i---j---k---l-------------------------');\n      //                         ----i---j---k---l-----------------\n      //                                 ----i---j---k---l---------\n      //                                         ----i---j---k---l-\n      const xsubs = [\n        '               -^-----------------------------------------',\n        '               ---------^---------------------------------',\n        '               -----------------^-------------------------',\n        '               -------------------------^-----------------',\n      ];\n      const e1 = hot('  -a-------b-------c-------d-------|         ');\n      const e1subs = '  ^--------------------------------!         ';\n      const expected = '-----i---j---(ki)(lj)(ki)(lj)(ki)(lj)k---l-';\n\n      const result = e1.pipe(mergeMap(() => x));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(x.subscriptions).toBe(xsubs);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should mergeMap many outer to many inner, and inner throws', () => {\n    testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => {\n      const x = cold('   ----i---j---k---l-------#   ');\n      //                         ----i---j---k---l\n      //                                 ----i---j\n      //                                         -\n      const xsubs = [\n        '               -^-----------------------!   ',\n        '               ---------^---------------!   ',\n        '               -----------------^-------!   ',\n        '               -------------------------(^!)',\n      ];\n      const e1 = hot('  -a-------b-------c-------d   ');\n      const e1subs = '  ^------------------------!   ';\n      const expected = '-----i---j---(ki)(lj)(ki)#   ';\n\n      const result = e1.pipe(mergeMap(() => x));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(x.subscriptions).toBe(xsubs);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should mergeMap many outer to many inner, and outer throws', () => {\n    testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => {\n      const x = cold('   ----i---j---k---l---|            ');\n      //                         ----i---j---k---l---|\n      //                                 ----i---j---k---l\n      //                                         ----i---j\n      const xsubs = [\n        '               -^-------------------!            ',\n        '               ---------^-------------------!    ',\n        '               -----------------^---------------!',\n        '               -------------------------^-------!',\n      ];\n      const e1 = hot('  -a-------b-------c-------d-------#');\n      const e1subs = '  ^--------------------------------!';\n      const expected = '-----i---j---(ki)(lj)(ki)(lj)(ki)#';\n\n      const result = e1.pipe(mergeMap(() => x));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(x.subscriptions).toBe(xsubs);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should mergeMap many outer to many inner, both inner and outer throw', () => {\n    testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => {\n      const x = cold('   ----i---j---k---l---#            ');\n      //                         ----i---j---k\n      //                                 ----i\n      const xsubs = [\n        '               -^-------------------!            ',\n        '               ---------^-----------!            ',\n        '               -----------------^---!            ',\n      ];\n      const e1 = hot('  -a-------b-------c-------d-------#');\n      const e1subs = '  ^--------------------!            ';\n      const expected = '-----i---j---(ki)(lj)#            ';\n\n      const result = e1.pipe(mergeMap(() => x));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(x.subscriptions).toBe(xsubs);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should mergeMap to many cold Observable, with parameter concurrency=1', () => {\n    testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => {\n      const x = cold('   ----i---j---k---l---|                                        ');\n      //                                     ----i---j---k---l---|\n      //                                                         ----i---j---k---l---|\n      const xsubs = [\n        '               -^-------------------!                                        ',\n        '               ---------------------^-------------------!                    ',\n        '               -----------------------------------------^-------------------!',\n      ];\n      const e1 = hot('  -a-------b-------c---|                                        ');\n      const e1subs = '  ^--------------------!                                        ';\n      const expected = '-----i---j---k---l-------i---j---k---l-------i---j---k---l---|';\n\n      const project = () => x;\n      const result = e1.pipe(mergeMap(project, 1));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(x.subscriptions).toBe(xsubs);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should mergeMap to many cold Observable, with parameter concurrency=2', () => {\n    testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => {\n      const x = cold('   ----i---j---k---l---|                    ');\n      //                         ----i---j---k---l---|\n      //                                     ----i---j---k---l---|\n      const xsubs = [\n        '               -^-------------------!                    ',\n        '               ---------^-------------------!            ',\n        '               ---------------------^-------------------!',\n      ];\n      const e1 = hot('  -a-------b-------c---|                    ');\n      const e1subs = '  ^--------------------!                    ';\n      const expected = '-----i---j---(ki)(lj)k---(li)j---k---l---|';\n\n      const project = () => x;\n      const result = e1.pipe(mergeMap(project, 2));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(x.subscriptions).toBe(xsubs);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should mergeMap to many hot Observable, with parameter concurrency=1', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const a = hot('   x----i---j---k---l---|                                        ');\n      const asubs = '   -^-------------------!                                        ';\n      const b = hot('   -x-x-xxxx-x-x-xxxxx-x----i---j---k---l---|                    ');\n      const bsubs = '   ---------------------^-------------------!                    ';\n      const c = hot('   x-xxxx---x-x-x-x-x-xx--x--x-x--x--xxxx-x-----i---j---k---l---|');\n      const csubs = '   -----------------------------------------^-------------------!';\n      const e1 = hot('  -a-------b-------c---|                                        ');\n      const e1subs = '  ^--------------------!                                        ';\n      const expected = '-----i---j---k---l-------i---j---k---l-------i---j---k---l---|';\n      const inners: Record<string, Observable<string>> = { a: a, b: b, c: c };\n\n      const project = (x: string) => inners[x];\n      const result = e1.pipe(mergeMap(project, 1));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(a.subscriptions).toBe(asubs);\n      expectSubscriptions(b.subscriptions).toBe(bsubs);\n      expectSubscriptions(c.subscriptions).toBe(csubs);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should mergeMap to many hot Observable, with parameter concurrency=2', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const x = hot('   x----i---j---k---l---|                    ');\n      const xsubs = '   -^-------------------!                    ';\n      const y = hot('   -x-x-xxxx----i---j---k---l---|            ');\n      const ysubs = '   ---------^-------------------!            ';\n      const z = hot('   x-xxxx---x-x-x-x-x-xx----i---j---k---l---|');\n      const zsubs = '   ---------------------^-------------------!';\n      const e1 = hot('  -a-------b-------c---|                    ');\n      const e1subs = '  ^--------------------!                    ';\n      const expected = '-----i---j---(ki)(lj)k---(li)j---k---l---|';\n      const inners: Record<string, Observable<string>> = { a: x, b: y, c: z };\n\n      const project = (x: string) => inners[x];\n      const result = e1.pipe(mergeMap(project, 2));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(x.subscriptions).toBe(xsubs);\n      expectSubscriptions(y.subscriptions).toBe(ysubs);\n      expectSubscriptions(z.subscriptions).toBe(zsubs);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should mergeMap many complex, where all inners are finite', () => {\n    testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => {\n      const a = cold(' -#                                                  ');\n      const asubs: string[] = [];\n      const b = cold('   -#                                                ');\n      const bsubs: string[] = [];\n      const c = cold('        -2--3--4--5------------------6-|             ');\n      const csubs = '       --^------------------------------!             ';\n      const d = cold('              -----------2--3|                       ');\n      const dsubs = '       --------^--------------!                       ';\n      const e = cold('                     -1--------2--3-----4--5--------|');\n      const esubs = '       ---------------^------------------------------!';\n      const f = cold('                                      --|            ');\n      const fsubs = '       --------------------------------^-!            ';\n      const g = cold('                                            ---1-2|  ');\n      const gsubs = '       --------------------------------------^-----!  ';\n      const e1 = hot('-a-b--^-c-----d------e----------------f-----g|       ');\n      const e1subs = '      ^--------------------------------------!       ';\n      const expected = '    ---2--3--4--5---1--2--3--2--3--6--4--5---1-2--|';\n\n      const observableLookup: Record<string, Observable<string>> = { a: a, b: b, c: c, d: d, e: e, f: f, g: g };\n\n      const result = e1.pipe(mergeMap((value) => observableLookup[value]));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(a.subscriptions).toBe(asubs);\n      expectSubscriptions(b.subscriptions).toBe(bsubs);\n      expectSubscriptions(c.subscriptions).toBe(csubs);\n      expectSubscriptions(d.subscriptions).toBe(dsubs);\n      expectSubscriptions(e.subscriptions).toBe(esubs);\n      expectSubscriptions(f.subscriptions).toBe(fsubs);\n      expectSubscriptions(g.subscriptions).toBe(gsubs);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should mergeMap many complex, all inners finite except one', () => {\n    testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => {\n      const a = cold(' -#                                                  ');\n      const asubs: string[] = [];\n      const b = cold('   -#                                                ');\n      const bsubs: string[] = [];\n      const c = cold('        -2--3--4--5------------------6-|             ');\n      const csubs = '       --^------------------------------!             ';\n      const d = cold('              -----------2--3-                       ');\n      const dsubs = '       --------^---------------                       ';\n      const e = cold('                     -1--------2--3-----4--5--------|');\n      const esubs = '       ---------------^------------------------------!';\n      const f = cold('                                      --|            ');\n      const fsubs = '       --------------------------------^-!            ';\n      const g = cold('                                            ---1-2|  ');\n      const gsubs = '       --------------------------------------^-----!  ';\n      const e1 = hot('-a-b--^-c-----d------e----------------f-----g|       ');\n      const e1subs = '      ^--------------------------------------!       ';\n      const expected = '    ---2--3--4--5---1--2--3--2--3--6--4--5---1-2---';\n\n      const observableLookup: Record<string, Observable<string>> = { a: a, b: b, c: c, d: d, e: e, f: f, g: g };\n\n      const result = e1.pipe(mergeMap((value) => observableLookup[value]));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(a.subscriptions).toBe(asubs);\n      expectSubscriptions(b.subscriptions).toBe(bsubs);\n      expectSubscriptions(c.subscriptions).toBe(csubs);\n      expectSubscriptions(d.subscriptions).toBe(dsubs);\n      expectSubscriptions(e.subscriptions).toBe(esubs);\n      expectSubscriptions(f.subscriptions).toBe(fsubs);\n      expectSubscriptions(g.subscriptions).toBe(gsubs);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should mergeMap many complex, inners finite, outer does not complete', () => {\n    testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => {\n      const a = cold(' -#                                                  ');\n      const asubs: string[] = [];\n      const b = cold('   -#                                                ');\n      const bsubs: string[] = [];\n      const c = cold('        -2--3--4--5------------------6-|             ');\n      const csubs = '       --^------------------------------!             ';\n      const d = cold('              -----------2--3|                       ');\n      const dsubs = '       --------^--------------!                       ';\n      const e = cold('                     -1--------2--3-----4--5--------|');\n      const esubs = '       ---------------^------------------------------!';\n      const f = cold('                                      --|            ');\n      const fsubs = '       --------------------------------^-!            ';\n      const g = cold('                                            ---1-2|  ');\n      const gsubs = '       --------------------------------------^-----!  ';\n      const e1 = hot('-a-b--^-c-----d------e----------------f-----g--------');\n      const e1subs = '      ^----------------------------------------------';\n      const expected = '    ---2--3--4--5---1--2--3--2--3--6--4--5---1-2---';\n\n      const observableLookup: Record<string, Observable<string>> = { a: a, b: b, c: c, d: d, e: e, f: f, g: g };\n\n      const result = e1.pipe(mergeMap((value) => observableLookup[value]));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(a.subscriptions).toBe(asubs);\n      expectSubscriptions(b.subscriptions).toBe(bsubs);\n      expectSubscriptions(c.subscriptions).toBe(csubs);\n      expectSubscriptions(d.subscriptions).toBe(dsubs);\n      expectSubscriptions(e.subscriptions).toBe(esubs);\n      expectSubscriptions(f.subscriptions).toBe(fsubs);\n      expectSubscriptions(g.subscriptions).toBe(gsubs);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should mergeMap many complex, all inners finite, and outer throws', () => {\n    testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => {\n      const a = cold(' -#                                                  ');\n      const asubs: string[] = [];\n      const b = cold('   -#                                                ');\n      const bsubs: string[] = [];\n      const c = cold('        -2--3--4--5------------------6-|             ');\n      const csubs = '       --^------------------------------!             ';\n      const d = cold('              -----------2--3|                       ');\n      const dsubs = '       --------^--------------!                       ';\n      const e = cold('                     -1--------2--3-----4--5--------|');\n      const esubs = '       ---------------^-----------------------!       ';\n      const f = cold('                                      --|            ');\n      const fsubs = '       --------------------------------^-!            ';\n      const g = cold('                                            ---1-2|  ');\n      const gsubs = '       --------------------------------------^!       ';\n      const e1 = hot('-a-b--^-c-----d------e----------------f-----g#       ');\n      const e1subs = '      ^--------------------------------------!       ';\n      const expected = '    ---2--3--4--5---1--2--3--2--3--6--4--5-#       ';\n\n      const observableLookup: Record<string, Observable<string>> = { a: a, b: b, c: c, d: d, e: e, f: f, g: g };\n\n      const result = e1.pipe(mergeMap((value) => observableLookup[value]));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(a.subscriptions).toBe(asubs);\n      expectSubscriptions(b.subscriptions).toBe(bsubs);\n      expectSubscriptions(c.subscriptions).toBe(csubs);\n      expectSubscriptions(d.subscriptions).toBe(dsubs);\n      expectSubscriptions(e.subscriptions).toBe(esubs);\n      expectSubscriptions(f.subscriptions).toBe(fsubs);\n      expectSubscriptions(g.subscriptions).toBe(gsubs);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should mergeMap many complex, all inners complete except one throws', () => {\n    testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => {\n      const a = cold(' -#                                                  ');\n      const asubs: string[] = [];\n      const b = cold('   -#                                                ');\n      const bsubs: string[] = [];\n      const c = cold('        -2--3--4--5------------------6-#             ');\n      const csubs = '       --^------------------------------!             ';\n      const d = cold('              -----------2--3|                       ');\n      const dsubs = '       --------^--------------!                       ';\n      const e = cold('                     -1--------2--3-----4--5--------|');\n      const esubs = '       ---------------^-----------------!             ';\n      const f = cold('                                      --|            ');\n      const fsubs = '       --------------------------------^!             ';\n      const g = cold('                                            ---1-2|  ');\n      const gsubs: string[] = [];\n      const e1 = hot('-a-b--^-c-----d------e----------------f-----g|       ');\n      const e1subs = '      ^--------------------------------!             ';\n      const expected = '    ---2--3--4--5---1--2--3--2--3--6-#             ';\n\n      const observableLookup: Record<string, Observable<string>> = { a: a, b: b, c: c, d: d, e: e, f: f, g: g };\n\n      const result = e1.pipe(mergeMap((value) => observableLookup[value]));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(a.subscriptions).toBe(asubs);\n      expectSubscriptions(b.subscriptions).toBe(bsubs);\n      expectSubscriptions(c.subscriptions).toBe(csubs);\n      expectSubscriptions(d.subscriptions).toBe(dsubs);\n      expectSubscriptions(e.subscriptions).toBe(esubs);\n      expectSubscriptions(f.subscriptions).toBe(fsubs);\n      expectSubscriptions(g.subscriptions).toBe(gsubs);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should mergeMap many complex, all inners finite, outer is unsubscribed', () => {\n    testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => {\n      const a = cold(' -#                                                  ');\n      const asubs: string[] = [];\n      const b = cold('   -#                                                ');\n      const bsubs: string[] = [];\n      const c = cold('        -2--3--4--5------------------6-|             ');\n      const csubs = '       --^---------------------------!                ';\n      const d = cold('              -----------2--3|                       ');\n      const dsubs = '       --------^--------------!                       ';\n      const e = cold('                     -1--------2--3-----4--5--------|');\n      const esubs = '       ---------------^--------------!                ';\n      const f = cold('                                      --|            ');\n      const fsubs: string[] = [];\n      const g = cold('                                            ---1-2|  ');\n      const gsubs: string[] = [];\n      const e1 = hot('-a-b--^-c-----d------e----------------f-----g|');\n      const e1subs = '      ^-----------------------------!                ';\n      const expected = '    ---2--3--4--5---1--2--3--2--3--                ';\n      const unsub = '       ------------------------------!                ';\n\n      const observableLookup: Record<string, Observable<string>> = { a: a, b: b, c: c, d: d, e: e, f: f, g: g };\n\n      const source = e1.pipe(mergeMap((value) => observableLookup[value]));\n\n      expectObservable(source, unsub).toBe(expected);\n      expectSubscriptions(a.subscriptions).toBe(asubs);\n      expectSubscriptions(b.subscriptions).toBe(bsubs);\n      expectSubscriptions(c.subscriptions).toBe(csubs);\n      expectSubscriptions(d.subscriptions).toBe(dsubs);\n      expectSubscriptions(e.subscriptions).toBe(esubs);\n      expectSubscriptions(f.subscriptions).toBe(fsubs);\n      expectSubscriptions(g.subscriptions).toBe(gsubs);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should mergeMap many complex, all inners finite, project throws', () => {\n    testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => {\n      const a = cold(' -#                                                  ');\n      const asubs: string[] = [];\n      const b = cold('   -#                                                ');\n      const bsubs: string[] = [];\n      const c = cold('        -2--3--4--5------------------6-|             ');\n      const csubs = '       --^------------!                               ';\n      const d = cold('              -----------2--3|                       ');\n      const dsubs = '       --------^------!                               ';\n      const e = cold('                     -1--------2--3-----4--5--------|');\n      const esubs: string[] = [];\n      const f = cold('                                      --|            ');\n      const fsubs: string[] = [];\n      const g = cold('                                            ---1-2|  ');\n      const gsubs: string[] = [];\n      const e1 = hot('-a-b--^-c-----d------e----------------f-----g|       ');\n      const e1subs = '      ^--------------!                               ';\n      const expected = '    ---2--3--4--5--#                               ';\n\n      const observableLookup: Record<string, Observable<string>> = { a: a, b: b, c: c, d: d, e: e, f: f, g: g };\n      const source = e1.pipe(\n        mergeMap((value) => {\n          if (value === 'e') {\n            throw 'error';\n          }\n          return observableLookup[value];\n        })\n      );\n\n      expectObservable(source).toBe(expected);\n      expectSubscriptions(a.subscriptions).toBe(asubs);\n      expectSubscriptions(b.subscriptions).toBe(bsubs);\n      expectSubscriptions(c.subscriptions).toBe(csubs);\n      expectSubscriptions(d.subscriptions).toBe(dsubs);\n      expectSubscriptions(e.subscriptions).toBe(esubs);\n      expectSubscriptions(f.subscriptions).toBe(fsubs);\n      expectSubscriptions(g.subscriptions).toBe(gsubs);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  function arrayRepeat<T>(value: T, times: number): T[] {\n    const results: T[] = [];\n    for (let i = 0; i < times; i++) {\n      results.push(value);\n    }\n    return results;\n  }\n\n  it('should mergeMap many outer to an array for each value', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  2-----4--------3--------2-------|');\n      const e1subs = '  ^-------------------------------!';\n      const expected = '(22)--(4444)---(333)----(22)----|';\n\n      const source = e1.pipe(mergeMap((value) => arrayRepeat(value, +value)));\n\n      expectObservable(source).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should mergeMap many outer to inner arrays, and outer throws', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  2-----4--------3--------2-------#');\n      const e1subs = '  ^-------------------------------!';\n      const expected = '(22)--(4444)---(333)----(22)----#';\n\n      const source = e1.pipe(mergeMap((value) => arrayRepeat(value, +value)));\n\n      expectObservable(source).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should mergeMap many outer to inner arrays, outer gets unsubscribed', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  2-----4--------3--------2-------|');\n      const e1subs = '  ^------------!                   ';\n      const expected = '(22)--(4444)--                   ';\n      const unsub = '   -------------!                   ';\n\n      const source = e1.pipe(mergeMap((value) => arrayRepeat(value, +value)));\n\n      expectObservable(source, unsub).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should mergeMap many outer to inner arrays, project throws', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  2-----4--------3--------2-------|');\n      const e1subs = '  ^--------------!                 ';\n      const expected = '(22)--(4444)---#                 ';\n\n      const source = e1.pipe(\n        mergeMap((value) => {\n          if (value === '3') {\n            throw 'error';\n          }\n          return arrayRepeat(value, +value);\n        })\n      );\n\n      expectObservable(source).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should map and flatten', () => {\n    const source = of(1, 2, 3, 4).pipe(mergeMap((x) => of(x + '!')));\n\n    const expected = ['1!', '2!', '3!', '4!'];\n    let completed = false;\n\n    source.subscribe({\n      next: (x) => {\n        expect(x).to.equal(expected.shift());\n      },\n      complete: () => {\n        expect(expected.length).to.equal(0);\n        completed = true;\n      },\n    });\n\n    expect(completed).to.be.true;\n  });\n\n  it('should map and flatten an Array', () => {\n    const source = of(1, 2, 3, 4).pipe(mergeMap((x): any => [x + '!']));\n\n    const expected = ['1!', '2!', '3!', '4!'];\n    let completed = false;\n\n    source.subscribe({\n      next: (x) => {\n        expect(x).to.equal(expected.shift());\n      },\n      complete: () => {\n        expect(expected.length).to.equal(0);\n        completed = true;\n      },\n    });\n\n    expect(completed).to.be.true;\n  });\n\n  it('should support nested merges', (done) => {\n    // Added as a failing test when investigating:\n    // https://github.com/ReactiveX/rxjs/issues/4071\n\n    const results: (number | string)[] = [];\n\n    of(1)\n      .pipe(mergeMap(() => defer(() => scheduled([2], asapScheduler)).pipe(mergeMap(() => defer(() => scheduled([3], asapScheduler))))))\n      .subscribe({\n        next(value: any) {\n          results.push(value);\n        },\n        complete() {\n          results.push('done');\n        },\n      });\n\n    setTimeout(() => {\n      expect(results).to.deep.equal([3, 'done']);\n      done();\n    }, 0);\n  });\n\n  it('should support nested merges with promises', (done) => {\n    // Added as a failing test when investigating:\n    // https://github.com/ReactiveX/rxjs/issues/4071\n\n    const results: (number | string)[] = [];\n\n    of(1)\n      .pipe(mergeMap(() => from(Promise.resolve(2)).pipe(mergeMap(() => Promise.resolve(3)))))\n      .subscribe({\n        next(value) {\n          results.push(value);\n        },\n        complete() {\n          results.push('done');\n        },\n      });\n\n    setTimeout(() => {\n      expect(results).to.deep.equal([3, 'done']);\n      done();\n    }, 0);\n  });\n\n  it('should support wrapped sources', (done) => {\n    // Added as a failing test when investigating:\n    // https://github.com/ReactiveX/rxjs/issues/4095\n\n    const results: (number | string)[] = [];\n\n    const wrapped = new Observable<number>((subscriber) => {\n      const subscription = timer(0, asapScheduler).subscribe(subscriber);\n      return () => subscription.unsubscribe();\n    });\n    wrapped.pipe(mergeMap(() => timer(0, asapScheduler))).subscribe({\n      next(value) {\n        results.push(value);\n      },\n      complete() {\n        results.push('done');\n      },\n    });\n\n    setTimeout(() => {\n      expect(results).to.deep.equal([0, 'done']);\n      done();\n    }, 0);\n  });\n\n  // NOTE: From https://github.com/ReactiveX/rxjs/issues/5436\n  it('should properly handle errors from iterables that are processed after some async', () => {\n    testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const noXError = new Error('we do not allow x');\n      const e1 = cold(' -----a------------b-----|', { a: ['o', 'o', 'o'], b: ['o', 'x', 'o'] });\n      const e1subs = '  ^-----------------!      ';\n      const expected = '-----(ooo)--------(o#)   ';\n\n      const iterable = function* (data: string[]) {\n        for (const d of data) {\n          if (d === 'x') {\n            throw noXError;\n          }\n          yield d;\n        }\n      };\n      const result = e1.pipe(mergeMap((x) => of(x).pipe(delay(0), mergeMap(iterable))));\n\n      expectObservable(result).toBe(expected, undefined, noXError);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should stop listening to a synchronous observable when unsubscribed', () => {\n    const sideEffects: number[] = [];\n    const synchronousObservable = new Observable<number>((subscriber) => {\n      // This will check to see if the subscriber was closed on each loop\n      // when the unsubscribe hits (from the `take`), it should be closed\n      for (let i = 0; !subscriber.closed && i < 10; i++) {\n        sideEffects.push(i);\n        subscriber.next(i);\n      }\n    });\n\n    synchronousObservable\n      .pipe(\n        mergeMap((value) => of(value)),\n        take(3)\n      )\n      .subscribe(() => {\n        /* noop */\n      });\n\n    expect(sideEffects).to.deep.equal([0, 1, 2]);\n  });\n});\n"
  },
  {
    "path": "packages/rxjs/spec/operators/mergeMapTo-spec.ts",
    "content": "import { expect } from 'chai';\nimport { TestScheduler } from 'rxjs/testing';\nimport { mergeMapTo, map, take } from 'rxjs/operators';\nimport { from, of, Observable } from 'rxjs';\nimport { observableMatcher } from '../helpers/observableMatcher';\n\n/** @test {mergeMapTo} */\ndescribe('mergeMapTo', () => {\n  let testScheduler: TestScheduler;\n\n  beforeEach(() => {\n    testScheduler = new TestScheduler(observableMatcher);\n  });\n\n  it('should map-and-flatten each item to an Observable', () => {\n    testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => {\n      const x = cold('    x-x-x|            ');\n      //                        x-x-x|\n      //                           x-x-x|\n      // prettier-ignore\n      const xsubs = [\n        '               --^----!            ',\n        '               --------^----!      ',\n        '               -----------^----!   ',\n      ];\n      const e1 = hot('  --1-----3--5-------|');\n      const e1subs = '  ^------------------!';\n      const expected = '--x-x-x-x-xxxx-x---|';\n\n      const result = e1.pipe(mergeMapTo(x));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(x.subscriptions).toBe(xsubs);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should mergeMapTo many regular interval inners', () => {\n    testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => {\n      const x = cold('  ----1---2---3---(4|)                        ');\n      //                    ----1---2---3---(4|)\n      //                                ----1---2---3---(4|)\n      //                                        ----1---2---3---(4|)\n      const xsubs = [\n        '               ^---------------!                           ',\n        '               ----^---------------!                       ',\n        '               ----------------^---------------!           ',\n        '               ------------------------^---------------!   ',\n      ];\n      const e1 = hot('  a---b-----------c-------d-------|           ');\n      const e1subs = '  ^-------------------------------!           ';\n      const expected = '----1---(21)(32)(43)(41)2---(31)(42)3---(4|)';\n\n      const result = e1.pipe(mergeMapTo(x));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(x.subscriptions).toBe(xsubs);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should map values to constant resolved promises and merge', (done) => {\n    const source = from([4, 3, 2, 1]);\n\n    const results: number[] = [];\n    source.pipe(mergeMapTo(from(Promise.resolve(42)))).subscribe({\n      next: (x) => {\n        results.push(x);\n      },\n      error: () => {\n        done(new Error('Subscriber error handler not supposed to be called.'));\n      },\n      complete: () => {\n        expect(results).to.deep.equal([42, 42, 42, 42]);\n        done();\n      },\n    });\n  });\n\n  it('should map values to constant rejected promises and merge', (done) => {\n    const source = from([4, 3, 2, 1]);\n\n    source.pipe(mergeMapTo(from(Promise.reject(42)))).subscribe({\n      next: () => {\n        done(new Error('Subscriber next handler not supposed to be called.'));\n      },\n      error: (err) => {\n        expect(err).to.equal(42);\n        done();\n      },\n      complete: () => {\n        done(new Error('Subscriber complete handler not supposed to be called.'));\n      },\n    });\n  });\n\n  it('should mergeMapTo many outer values to many inner values', () => {\n    testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => {\n      const x = cold('   ----i---j---k---l---|                        ');\n      //                         ----i---j---k---l---|\n      //                                 ----i---j---k---l---|\n      //                                         ----i---j---k---l---|\n      const xsubs = [\n        '               -^-------------------!                        ',\n        '               ---------^-------------------!                ',\n        '               -----------------^-------------------!        ',\n        '               -------------------------^-------------------!',\n      ];\n      const e1 = hot('  -a-------b-------c-------d-------|            ');\n      const e1subs = '  ^--------------------------------!            ';\n      const expected = '-----i---j---(ki)(lj)(ki)(lj)(ki)(lj)k---l---|';\n\n      expectObservable(e1.pipe(mergeMapTo(x))).toBe(expected);\n      expectSubscriptions(x.subscriptions).toBe(xsubs);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should mergeMapTo many outer to many inner, complete late', () => {\n    testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => {\n      const x = cold('   ----i---j---k---l---|                            ');\n      //                         ----i---j---k---l---|\n      //                                 ----i---j---k---l---|\n      //                                         ----i---j---k---l---|\n      const xsubs = [\n        '               -^-------------------!                            ',\n        '               ---------^-------------------!                    ',\n        '               -----------------^-------------------!            ',\n        '               -------------------------^-------------------!    ',\n      ];\n      const e1 = hot('  -a-------b-------c-------d-----------------------|');\n      const e1subs = '  ^------------------------------------------------!';\n      const expected = '-----i---j---(ki)(lj)(ki)(lj)(ki)(lj)k---l-------|';\n\n      expectObservable(e1.pipe(mergeMapTo(x))).toBe(expected);\n      expectSubscriptions(x.subscriptions).toBe(xsubs);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should mergeMapTo many outer to many inner, outer never completes', () => {\n    testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => {\n      const x = cold('   ----i---j---k---l---|                                  ');\n      //                         ----i---j---k---l---|\n      //                                 ----i---j---k---l---|\n      //                                         ----i---j---k---l---|\n      //                                                 ----i---j---k---l---|\n      //                                                                 ----i--\n      const xsubs = [\n        '               -^-------------------!                                  ',\n        '               ---------^-------------------!                          ',\n        '               -----------------^-------------------!                  ',\n        '               -------------------------^-------------------!          ',\n        '               ---------------------------------^-------------------!  ',\n        '               -------------------------------------------------^-----!',\n      ];\n      const e1 = hot('  -a-------b-------c-------d-------e---------------f------');\n      const e1subs = '  ^------------------------------------------------------!';\n      const expected = '-----i---j---(ki)(lj)(ki)(lj)(ki)(lj)(ki)(lj)k---l---i-';\n      const unsub = '   -------------------------------------------------------!';\n\n      const result = e1.pipe(mergeMapTo(x));\n\n      expectObservable(result, unsub).toBe(expected);\n      expectSubscriptions(x.subscriptions).toBe(xsubs);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should not break unsubscription chains when result is unsubscribed explicitly', () => {\n    testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => {\n      const x = cold('   ----i---j---k---l---|                                  ');\n      //                         ----i---j---k---l---|\n      //                                 ----i---j---k---l---|\n      //                                         ----i---j---k---l---|\n      //                                                 ----i---j---k---l---|\n      //                                                                 ----i--\n      const xsubs = [\n        '               -^-------------------!                                  ',\n        '               ---------^-------------------!                          ',\n        '               -----------------^-------------------!                  ',\n        '               -------------------------^-------------------!          ',\n        '               ---------------------------------^-------------------!  ',\n        '               -------------------------------------------------^-----!',\n      ];\n      const e1 = hot('  -a-------b-------c-------d-------e---------------f------');\n      const e1subs = '  ^------------------------------------------------------!';\n      const expected = '-----i---j---(ki)(lj)(ki)(lj)(ki)(lj)(ki)(lj)k---l---i-';\n      const unsub = '   -------------------------------------------------------!';\n\n      const result = e1.pipe(\n        map((x) => x),\n        mergeMapTo(x),\n        map((x) => x)\n      );\n\n      expectObservable(result, unsub).toBe(expected);\n      expectSubscriptions(x.subscriptions).toBe(xsubs);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should mergeMapTo many outer to many inner, inner never completes', () => {\n    testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => {\n      const x = cold('   ----i---j---k---l-                        ');\n      //                         ----i---j---k---l-\n      //                                 ----i---j---k---l-\n      //                                         ----i---j---k---l-\n      const xsubs = [\n        '               -^-----------------------------------------',\n        '               ---------^---------------------------------',\n        '               -----------------^-------------------------',\n        '               -------------------------^-----------------',\n      ];\n      const e1 = hot('  -a-------b-------c-------d-------|         ');\n      const e1subs = '  ^--------------------------------!         ';\n      const expected = '-----i---j---(ki)(lj)(ki)(lj)(ki)(lj)k---l-';\n\n      expectObservable(e1.pipe(mergeMapTo(x))).toBe(expected);\n      expectSubscriptions(x.subscriptions).toBe(xsubs);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should mergeMapTo many outer to many inner, and inner throws', () => {\n    testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => {\n      const x = cold('   ----i---j---k---l-------#        ');\n      //                         ----i---j---k---l-------#\n      //                                 ----i---j---k---l\n      const xsubs = [\n        '               -^-----------------------!        ',\n        '               ---------^---------------!        ',\n        '               -----------------^-------!        ',\n        '               -------------------------(^!)     ',\n      ];\n      const e1 = hot('  -a-------b-------c-------d-------|');\n      const e1subs = '  ^------------------------!        ';\n      const expected = '-----i---j---(ki)(lj)(ki)#        ';\n\n      expectObservable(e1.pipe(mergeMapTo(x))).toBe(expected);\n      expectSubscriptions(x.subscriptions).toBe(xsubs);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should mergeMapTo many outer to many inner, and outer throws', () => {\n    testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => {\n      const x = cold('   ----i---j---k---l---|            ');\n      //                         ----i---j---k---l---|\n      //                                 ----i---j---k---l\n      //                                         ----i---j\n      const xsubs = [\n        '               -^-------------------!            ',\n        '               ---------^-------------------!    ',\n        '               -----------------^---------------!',\n        '               -------------------------^-------!',\n      ];\n      const e1 = hot('  -a-------b-------c-------d-------#');\n      const e1subs = '  ^--------------------------------!';\n      const expected = '-----i---j---(ki)(lj)(ki)(lj)(ki)#';\n\n      expectObservable(e1.pipe(mergeMapTo(x))).toBe(expected);\n      expectSubscriptions(x.subscriptions).toBe(xsubs);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should mergeMapTo many outer to many inner, both inner and outer throw', () => {\n    testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => {\n      const x = cold('   ----i---j---k---l---#            ');\n      //                         ----i---j---k\n      //                                 ----i\n      const xsubs = [\n        '               -^-------------------!            ',\n        '               ---------^-----------!            ',\n        '               -----------------^---!            ',\n      ];\n      const e1 = hot('  -a-------b-------c-------d-------#');\n      const e1subs = '  ^--------------------!            ';\n      const expected = '-----i---j---(ki)(lj)#            ';\n\n      expectObservable(e1.pipe(mergeMapTo(x))).toBe(expected);\n      expectSubscriptions(x.subscriptions).toBe(xsubs);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should mergeMapTo many cold Observable, with parameter concurrency=1, without resultSelector', () => {\n    testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => {\n      const x = cold('   ----i---j---k---l---|                                        ');\n      //                                     ----i---j---k---l---|\n      //                                                         ----i---j---k---l---|\n      const xsubs = [\n        '               -^-------------------!                                        ',\n        '               ---------------------^-------------------!                    ',\n        '               -----------------------------------------^-------------------!',\n      ];\n      const e1 = hot('  -a-------b-------c---|                                        ');\n      const e1subs = '  ^--------------------!                                        ';\n      const expected = '-----i---j---k---l-------i---j---k---l-------i---j---k---l---|';\n\n      const result = e1.pipe(mergeMapTo(x, 1));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(x.subscriptions).toBe(xsubs);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should mergeMapTo to many cold Observable, with parameter concurrency=2, without resultSelector', () => {\n    testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => {\n      const x = cold('   ----i---j---k---l---|                    ');\n      //                         ----i---j---k---l---|\n      //                                     ----i---j---k---l---|\n      const xsubs = [\n        '               -^-------------------!                    ',\n        '               ---------^-------------------!            ',\n        '               ---------------------^-------------------!',\n      ];\n      const e1 = hot('  -a-------b-------c---|                    ');\n      const e1subs = '  ^--------------------!                    ';\n      const expected = '-----i---j---(ki)(lj)k---(li)j---k---l---|';\n\n      const result = e1.pipe(mergeMapTo(x, 2));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(x.subscriptions).toBe(xsubs);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should mergeMapTo many outer to arrays', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  2-----4--------3--------2-------|');\n      const e1subs = '  ^-------------------------------!';\n      const expected = '(0123)(0123)---(0123)---(0123)--|';\n\n      const result = e1.pipe(mergeMapTo(['0', '1', '2', '3']));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should mergeMapTo many outer to inner arrays, and outer throws', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  2-----4--------3--------2-------#');\n      const e1subs = '  ^-------------------------------!';\n      const expected = '(0123)(0123)---(0123)---(0123)--#';\n\n      const result = e1.pipe(mergeMapTo(['0', '1', '2', '3']));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should mergeMapTo many outer to inner arrays, outer gets unsubscribed', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  2-----4--------3--------2-------|');\n      const e1subs = '  ^------------!                   ';\n      const expected = '(0123)(0123)--                   ';\n      const unsub = '   -------------!                   ';\n\n      const result = e1.pipe(mergeMapTo(['0', '1', '2', '3']));\n\n      expectObservable(result, unsub).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should map and flatten', () => {\n    const source = of(1, 2, 3, 4).pipe(mergeMapTo(of('!')));\n\n    const expected = ['!', '!', '!', '!'];\n    let completed = false;\n\n    source.subscribe({\n      next: (x) => {\n        expect(x).to.equal(expected.shift());\n      },\n      complete: () => {\n        expect(expected.length).to.equal(0);\n        completed = true;\n      },\n    });\n\n    expect(completed).to.be.true;\n  });\n\n  it('should map and flatten an Array', () => {\n    const source = of(1, 2, 3, 4).pipe(mergeMapTo(['!']));\n\n    const expected = ['!', '!', '!', '!'];\n    let completed = false;\n\n    source.subscribe({\n      next: (x) => {\n        expect(x).to.equal(expected.shift());\n      },\n      complete: () => {\n        expect(expected.length).to.equal(0);\n        completed = true;\n      },\n    });\n\n    expect(completed).to.be.true;\n  });\n\n  it('should stop listening to a synchronous observable when unsubscribed', () => {\n    const sideEffects: number[] = [];\n    const synchronousObservable = new Observable<number>((subscriber) => {\n      // This will check to see if the subscriber was closed on each loop\n      // when the unsubscribe hits (from the `take`), it should be closed\n      for (let i = 0; !subscriber.closed && i < 10; i++) {\n        sideEffects.push(i);\n        subscriber.next(i);\n      }\n    });\n\n    synchronousObservable.pipe(mergeMapTo(of(0)), take(3)).subscribe(() => {\n      /* noop */\n    });\n\n    expect(sideEffects).to.deep.equal([0, 1, 2]);\n  });\n});\n"
  },
  {
    "path": "packages/rxjs/spec/operators/mergeScan-spec.ts",
    "content": "import { TestScheduler } from 'rxjs/testing';\nimport { of, defer, EMPTY, NEVER, concat, throwError, Observable } from 'rxjs';\nimport { mergeScan, delay, mergeMap, takeWhile, startWith, take } from 'rxjs/operators';\nimport { expect } from 'chai';\nimport { observableMatcher } from '../helpers/observableMatcher';\n\n/** @test {mergeScan} */\ndescribe('mergeScan', () => {\n  let testScheduler: TestScheduler;\n\n  beforeEach(() => {\n    testScheduler = new TestScheduler(observableMatcher);\n  });\n\n  it('should mergeScan things', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('--a--^--b--c--d--e--f--g--|');\n      const e1subs = '     ^--------------------!';\n      const expected = '   ---u--v--w--x--y--z--|';\n\n      const values = {\n        u: ['b'],\n        v: ['b', 'c'],\n        w: ['b', 'c', 'd'],\n        x: ['b', 'c', 'd', 'e'],\n        y: ['b', 'c', 'd', 'e', 'f'],\n        z: ['b', 'c', 'd', 'e', 'f', 'g'],\n      };\n\n      const result = e1.pipe(mergeScan((acc, x) => of(acc.concat(x)), [] as string[]));\n\n      expectObservable(result).toBe(expected, values);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should handle errors', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('--a--^--b--c--d--#');\n      const e1subs = '     ^-----------!';\n      const expected = '   ---u--v--w--#';\n\n      const values = {\n        u: ['b'],\n        v: ['b', 'c'],\n        w: ['b', 'c', 'd'],\n      };\n\n      const result = e1.pipe(mergeScan((acc, x) => of(acc.concat(x)), [] as string[]));\n\n      expectObservable(result).toBe(expected, values);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should mergeScan values and be able to asynchronously project them', () => {\n    testScheduler.run(({ hot, time, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('--a--^--b--c--d--e--f--g--|');\n      const e1subs = '     ^--------------------!';\n      const t = time('        --|                '); // t = 2\n      //                         --|\n      //                            --|\n      //                               --|\n      //                                  --|\n      //                                     --|\n      const expected = '   -----u--v--w--x--y--z|';\n\n      const values = {\n        u: ['b'],\n        v: ['b', 'c'],\n        w: ['b', 'c', 'd'],\n        x: ['b', 'c', 'd', 'e'],\n        y: ['b', 'c', 'd', 'e', 'f'],\n        z: ['b', 'c', 'd', 'e', 'f', 'g'],\n      };\n\n      const result = e1.pipe(mergeScan((acc, x) => of(acc.concat(x)).pipe(delay(t)), [] as string[]));\n\n      expectObservable(result).toBe(expected, values);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should not stop ongoing async projections when source completes', () => {\n    testScheduler.run(({ hot, time, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('--a--^--b--c--d--e--f--g--|     ');\n      const e1subs = '     ^--------------------!     ';\n      const t = time('        -----|'); //          acc = []; x = 'b'; acc.concat(x) = ['b']; t = 5\n      //                         -----|             acc = []; x = 'c'; acc.concat(x) = ['c']\n      //                            -----|          acc = ['b']; x = 'd'; acc.concat(x) = ['b', 'd']\n      //                               -----|       acc = ['c']; x = 'e'; acc.concat(x) = ['c', 'e']\n      //                                  -----|    acc = ['b', 'd']; x = 'f'; acc.concat(x) = ['b', 'd', 'f']\n      //                                     -----| acc = ['c', 'e']; x = 'g'; acc.concat(x) = ['c', 'e', 'g']\n      const expected = '   --------u--v--w--x--y--(z|)';\n\n      const values = {\n        u: ['b'],\n        v: ['c'],\n        w: ['b', 'd'],\n        x: ['c', 'e'],\n        y: ['b', 'd', 'f'],\n        z: ['c', 'e', 'g'],\n      };\n\n      const result = e1.pipe(mergeScan((acc, x) => of(acc.concat(x)).pipe(delay(t)), [] as string[]));\n\n      expectObservable(result).toBe(expected, values);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should interrupt ongoing async projections when result is unsubscribed early', () => {\n    testScheduler.run(({ hot, time, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('--a--^--b--c--d--e--f--g--|');\n      const e1subs = '     ^---------------!     ';\n      const t = time('        -----|'); // acc = []; x = 'b'; acc.concat(x) = ['b']; t = 5\n      //                         -----|    acc = []; x = 'c'; acc.concat(x) = ['c']\n      //                            -----| acc = ['b']; x = 'd'; acc.concat(x) = ['b', 'd']\n      const expected = '   --------u--v--w--     ';\n      const unsub = '      ----------------!     ';\n\n      const values = {\n        u: ['b'],\n        v: ['c'],\n        w: ['b', 'd'],\n      };\n\n      const result = e1.pipe(mergeScan((acc, x) => of(acc.concat(x)).pipe(delay(t)), [] as string[]));\n\n      expectObservable(result, unsub).toBe(expected, values);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should not break unsubscription chains when result is unsubscribed explicitly', () => {\n    testScheduler.run(({ hot, time, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('--a--^--b--c--d--e--f--g--|');\n      const e1subs = '     ^---------------!     ';\n      const t = time('        -----|'); // acc = []; x = 'b'; acc.concat(x) = ['b']; t = 5\n      //                         -----|    acc = []; x = 'c'; acc.concat(x) = ['c']\n      //                            -----| acc = ['b']; x = 'd'; acc.concat(x) = ['b', 'd']\n      const expected = '   --------u--v--w--     ';\n      const unsub = '      ----------------!     ';\n\n      const values = {\n        u: ['b'],\n        v: ['c'],\n        w: ['b', 'd'],\n      };\n\n      const result = e1.pipe(\n        mergeMap((x) => of(x)),\n        mergeScan((acc, x) => of(acc.concat(x)).pipe(delay(t)), [] as string[]),\n        mergeMap((x) => of(x))\n      );\n\n      expectObservable(result, unsub).toBe(expected, values);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should stop listening to a synchronous observable when unsubscribed', () => {\n    const sideEffects: number[] = [];\n    const synchronousObservable = concat(\n      defer(() => {\n        sideEffects.push(1);\n        return of(1);\n      }),\n      defer(() => {\n        sideEffects.push(2);\n        return of(2);\n      }),\n      defer(() => {\n        sideEffects.push(3);\n        return of(3);\n      })\n    );\n\n    of(null)\n      .pipe(\n        mergeScan(() => synchronousObservable, 0),\n        takeWhile((x) => x != 2) // unsubscribe at the second side-effect\n      )\n      .subscribe(() => {\n        /* noop */\n      });\n\n    expect(sideEffects).to.deep.equal([1, 2]);\n  });\n\n  it('should handle errors in the projection function', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('--a--^--b--c--d--e--f--g--|');\n      const e1subs = '     ^--------!';\n      const expected = '   ---u--v--#';\n\n      const values = {\n        u: ['b'],\n        v: ['b', 'c'],\n      };\n\n      const result = e1.pipe(\n        mergeScan((acc, x) => {\n          if (x === 'd') {\n            throw new Error('bad!');\n          }\n          return of(acc.concat(x));\n        }, [] as string[])\n      );\n\n      expectObservable(result).toBe(expected, values, new Error('bad!'));\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should propagate errors from the projected Observable', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('--a--^--b--c--d--e--f--g--|');\n      const e1subs = '     ^--!';\n      const expected = '   ---#';\n\n      const result = e1.pipe(mergeScan(() => throwError(() => new Error('bad!')), []));\n\n      expectObservable(result).toBe(expected, undefined, new Error('bad!'));\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should handle an empty projected Observable', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('--a--^--b--c--d--e--f--g--|');\n      const e1subs = '     ^--------------------!';\n      const expected = '   ---------------------|';\n\n      const result = e1.pipe(mergeScan(() => EMPTY, []));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should handle a never projected Observable', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('--a--^--b--c--d--e--f--g--|');\n      const e1subs = '     ^--------------------!';\n      const expected = '   ----------------------';\n\n      const result = e1.pipe(mergeScan(() => NEVER, []));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('handle empty', () => {\n    testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' |   ');\n      const e1subs = '  (^!)';\n      const expected = '|   ';\n\n      const result = e1.pipe(mergeScan((acc, x) => of(acc.concat(x)), [] as string[]));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('handle never', () => {\n    testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' -');\n      const e1subs = '  ^';\n      const expected = '-';\n\n      const result = e1.pipe(mergeScan((acc, x) => of(acc.concat(x)), [] as string[]));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('handle throw', () => {\n    testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' #   ');\n      const e1subs = '  (^!)';\n      const expected = '#   ';\n\n      const result = e1.pipe(mergeScan((acc, x) => of(acc.concat(x)), [] as string[]));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should mergeScan unsubscription', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('--a--^--b--c--d--e--f--g--|');\n      const e1subs = '     ^-------------!       ';\n      const expected = '   ---u--v--w--x--       ';\n      const unsub = '      --------------!       ';\n\n      const values = {\n        u: ['b'],\n        v: ['b', 'c'],\n        w: ['b', 'c', 'd'],\n        x: ['b', 'c', 'd', 'e'],\n      };\n\n      const result = e1.pipe(mergeScan((acc, x) => of(acc.concat(x)), [] as string[]));\n\n      expectObservable(result, unsub).toBe(expected, values);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should mergeScan projects cold Observable with single concurrency', () => {\n    testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => {\n      const inner = [\n        cold('            --d--e--f--|                      '),\n        cold('                       --g--h--i--|           '),\n        cold('                                  --j--k--l--|'),\n      ];\n      const xsubs = '   --^----------!                      ';\n      const ysubs = '   -------------^----------!           ';\n      const zsubs = '   ------------------------^----------!';\n\n      const e1 = hot('  --0--1--2--|                        ');\n      const e1subs = '  ^----------!                        ';\n      const expected = '--x-d--e--f--f-g--h--i--i-j--k--l--|';\n\n      const result = e1.pipe(mergeScan((acc, x) => inner[+x].pipe(startWith(acc)), 'x', 1));\n\n      expectObservable(result).toBe(expected);\n\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(inner[0].subscriptions).toBe(xsubs);\n      expectSubscriptions(inner[1].subscriptions).toBe(ysubs);\n      expectSubscriptions(inner[2].subscriptions).toBe(zsubs);\n    });\n  });\n\n  it('should not emit accumulator if inner completes without value', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('--a--^--b--c--d--e--f--g--|');\n      const e1subs = '     ^--------------------!';\n      const expected = '   ---------------------|';\n\n      const result = e1.pipe(mergeScan(() => EMPTY, ['1']));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should not emit accumulator if inner completes without value after source completes', () => {\n    testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => {\n      const x = cold('        -----|   ');\n      //                         -----|\n      // prettier-ignore\n      const xsubs = [\n        '                  ---^----!   ',\n        '                  ------^----!',\n      ];\n      const e1 = hot('--a--^--b--c--|  ');\n      const e1subs = '     ^--------!  ';\n      const expected = '   -----------|';\n\n      const result = e1.pipe(mergeScan(() => x, '1'));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(x.subscriptions).toBe(xsubs);\n    });\n  });\n\n  it('should mergeScan projects hot Observable with single concurrency', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const inner = [\n        hot('           --d--e--f--|                 '),\n        hot('           ----g----h----i----|         '),\n        hot('           ------j------k-------l------|'),\n      ];\n      const xsubs = '   ---^-------!                 ';\n      const ysubs = '   -----------^-------!         ';\n      const zsubs = '   -------------------^--------!';\n      const e1 = hot('  ---0---1---2---|             ');\n      const e1subs = '  ^--------------!             ';\n      const expected = '---x-e--f--f--i----i-l------|';\n\n      const result = e1.pipe(mergeScan((acc, x) => inner[+x].pipe(startWith(acc)), 'x', 1));\n\n      expectObservable(result).toBe(expected);\n\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(inner[0].subscriptions).toBe(xsubs);\n      expectSubscriptions(inner[1].subscriptions).toBe(ysubs);\n      expectSubscriptions(inner[2].subscriptions).toBe(zsubs);\n    });\n  });\n\n  it('should mergeScan projects cold Observable with dual concurrency', () => {\n    testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => {\n      const inner = [\n        cold('              ---d---e---f---|               '),\n        cold('                   ---g---h---i---|          '),\n        cold('                             ---j---k---l---|'),\n      ];\n      const xsubs = '   ----^--------------!               ';\n      const ysubs = '   ---------^--------------!          ';\n      const zsubs = '   -------------------^--------------!';\n      const e1 = hot('  ----0----1----2----|               ');\n      const e1subs = '  ^------------------!               ';\n      const expected = '----x--d-d-eg--fh--hi-j---k---l---|';\n\n      const result = e1.pipe(mergeScan((acc, x) => inner[+x].pipe(startWith(acc)), 'x', 2));\n\n      expectObservable(result).toBe(expected);\n\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(inner[0].subscriptions).toBe(xsubs);\n      expectSubscriptions(inner[1].subscriptions).toBe(ysubs);\n      expectSubscriptions(inner[2].subscriptions).toBe(zsubs);\n    });\n  });\n\n  it('should mergeScan projects hot Observable with dual concurrency', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const inner = [\n        hot('           --d--e--f-----|              '),\n        hot('           ----g----h------i----|       '),\n        hot('           ------j--------k-----l------|'),\n      ];\n      const xsubs = '   ---^----------!              ';\n      const ysubs = '   -------^-------------!       ';\n      const zsubs = '   --------------^-------------!';\n      const e1 = hot('  ---0---1---2---|             ');\n      const e1subs = '  ^--------------!             ';\n      const expected = '---x-e-efh----hki----l------|';\n\n      const result = e1.pipe(mergeScan((acc, x) => inner[+x].pipe(startWith(acc)), 'x', 2));\n\n      expectObservable(result).toBe(expected);\n\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(inner[0].subscriptions).toBe(xsubs);\n      expectSubscriptions(inner[1].subscriptions).toBe(ysubs);\n      expectSubscriptions(inner[2].subscriptions).toBe(zsubs);\n    });\n  });\n\n  it('should pass current index to accumulator', () => {\n    const recorded: number[] = [];\n    const e1 = of('a', 'b', 'c', 'd');\n\n    e1.pipe(\n      mergeScan((acc, x, index) => {\n        recorded.push(index);\n        return of(index);\n      }, 0)\n    ).subscribe();\n\n    expect(recorded).to.deep.equal([0, 1, 2, 3]);\n  });\n\n  it('should stop listening to a synchronous observable when unsubscribed', () => {\n    const sideEffects: number[] = [];\n    const synchronousObservable = new Observable<number>((subscriber) => {\n      // This will check to see if the subscriber was closed on each loop\n      // when the unsubscribe hits (from the `take`), it should be closed\n      for (let i = 0; !subscriber.closed && i < 10; i++) {\n        sideEffects.push(i);\n        subscriber.next(i);\n      }\n    });\n\n    synchronousObservable\n      .pipe(\n        mergeScan((acc, value) => of(value), 0),\n        take(3)\n      )\n      .subscribe(() => {\n        /* noop */\n      });\n\n    expect(sideEffects).to.deep.equal([0, 1, 2]);\n  });\n});\n"
  },
  {
    "path": "packages/rxjs/spec/operators/mergeWith-spec.ts",
    "content": "import { expect } from 'chai';\nimport { mergeWith, map, mergeAll, take } from 'rxjs/operators';\nimport { TestScheduler } from 'rxjs/testing';\nimport { queueScheduler, of, scheduled, Observable } from 'rxjs';\nimport { observableMatcher } from '../helpers/observableMatcher';\n\n/** @test {merge} */\ndescribe('merge operator', () => {\n  let rxTestScheduler: TestScheduler;\n\n  beforeEach(() => {\n    rxTestScheduler = new TestScheduler(observableMatcher);\n  });\n\n  it('should handle merging two hot observables', () => {\n    rxTestScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  --a-----b-----c----|');\n      const e1subs = '  ^------------------!';\n      const e2 = hot('-----d-----e-----f---|');\n      const e2subs = '  ^--------------------!';\n      const expected = '--a--d--b--e--c--f---|';\n\n      const result = e1.pipe(mergeWith(e2));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should merge a source with a second', (done) => {\n    const a = of(1, 2, 3);\n    const b = of(4, 5, 6, 7, 8);\n    const r = [1, 2, 3, 4, 5, 6, 7, 8];\n\n    a.pipe(mergeWith(b)).subscribe({\n      next: (val) => {\n        expect(val).to.equal(r.shift());\n      },\n      error: () => {\n        done(new Error('should not be called'));\n      },\n      complete: () => {\n        done();\n      },\n    });\n  });\n\n  it('should merge cold and cold', () => {\n    rxTestScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' ---a-----b-----c----|');\n      const e1subs = '  ^-------------------!';\n      const e2 = cold(' ------x-----y-----z----|');\n      const e2subs = '  ^----------------------!';\n      const expected = '---a--x--b--y--c--z----|';\n\n      const result = e1.pipe(mergeWith(e2));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should merge hot and hot', () => {\n    rxTestScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('---a---^-b-----c----|');\n      const e1subs = '       ^------------!';\n      const e2 = hot('-----x-^----y-----z----|');\n      const e2subs = '       ^---------------!';\n      const expected = '     --b--y--c--z----|';\n\n      const result = e1.pipe(mergeWith(e2));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should merge hot and cold', () => {\n    rxTestScheduler.run(({ hot, cold, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('---a-^---b-----c----|');\n      const e1subs = '     ^--------------!';\n      const e2 = cold('    --x-----y-----z----|');\n      const e2subs = '     ^------------------!';\n      const expected = '   --x-b---y-c---z----|';\n\n      const result = e1.pipe(mergeWith(e2));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should merge parallel emissions', () => {\n    rxTestScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  ---a----b----c----|');\n      const e1subs = '  ^-----------------!';\n      const e2 = hot('  ---x----y----z----|');\n      const e2subs = '  ^-----------------!';\n      const expected = '---(ax)-(by)-(cz)-|';\n\n      const result = e1.pipe(mergeWith(e2));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should allow unsubscribing explicitly and early', () => {\n    rxTestScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  --a-----b-----c----|  ');\n      const e1subs = '  ^---------!           ';\n      const e2 = hot('  -----d-----e-----f---|');\n      const e2subs = '  ^---------!           ';\n      const expected = '--a--d--b--           ';\n      const unsub = '   ----------!           ';\n\n      const result = e1.pipe(mergeWith(e2));\n\n      expectObservable(result, unsub).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should not break unsubscription chains when result is unsubscribed explicitly', () => {\n    rxTestScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  --a-----b-----c----|  ');\n      const e1subs = '  ^---------!           ';\n      const e2 = hot('  -----d-----e-----f---|');\n      const e2subs = '  ^---------!           ';\n      const expected = '--a--d--b--           ';\n      const unsub = '   ----------!           ';\n\n      const result = e1.pipe(\n        map((x) => x),\n        mergeWith(e2),\n        map((x) => x)\n      );\n\n      expectObservable(result, unsub).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should merge empty and empty', () => {\n    rxTestScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold('|   ');\n      const e1subs = ' (^!)';\n      const e2 = cold('|   ');\n      const e2subs = ' (^!)';\n\n      const result = e1.pipe(mergeWith(e2));\n\n      expectObservable(result).toBe('|');\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should merge three empties', () => {\n    rxTestScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold('|');\n      const e1subs = ' (^!)';\n      const e2 = cold('|');\n      const e2subs = ' (^!)';\n      const e3 = cold('|');\n      const e3subs = ' (^!)';\n\n      const result = e1.pipe(mergeWith(e2, e3));\n\n      expectObservable(result).toBe('|');\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n      expectSubscriptions(e3.subscriptions).toBe(e3subs);\n    });\n  });\n\n  it('should merge never and empty', () => {\n    rxTestScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold('-');\n      const e1subs = ' ^';\n      const e2 = cold('|');\n      const e2subs = ' (^!)';\n\n      const result = e1.pipe(mergeWith(e2));\n\n      expectObservable(result).toBe('-');\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should merge never and never', () => {\n    rxTestScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold('-');\n      const e1subs = ' ^';\n      const e2 = cold('-');\n      const e2subs = ' ^';\n\n      const result = e1.pipe(mergeWith(e2));\n\n      expectObservable(result).toBe('-');\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should merge empty and throw', () => {\n    rxTestScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold('|');\n      const e1subs = ' (^!)';\n      const e2 = cold('#');\n      const e2subs = ' (^!)';\n\n      const result = e1.pipe(mergeWith(e2));\n\n      expectObservable(result).toBe('#');\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should merge hot and throw', () => {\n    rxTestScheduler.run(({ hot, cold, expectObservable, expectSubscriptions }) => {\n      const e1 = hot(' --a--b--c--|');\n      const e1subs = '(^!)';\n      const e2 = cold('#');\n      const e2subs = '(^!)';\n\n      const result = e1.pipe(mergeWith(e2));\n\n      expectObservable(result).toBe('#');\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should merge never and throw', () => {\n    rxTestScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold('-');\n      const e1subs = ' (^!)';\n      const e2 = cold('#');\n      const e2subs = ' (^!)';\n\n      const result = e1.pipe(mergeWith(e2));\n\n      expectObservable(result).toBe('#');\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should merge empty and eventual error', () => {\n    rxTestScheduler.run(({ hot, cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' |');\n      const e1subs = '  (^!)    ';\n      const e2 = hot('  -------#');\n      const e2subs = '  ^------!';\n      const expected = '-------#';\n\n      const result = e1.pipe(mergeWith(e2));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should merge hot and error', () => {\n    rxTestScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  --a--b--c--|');\n      const e1subs = '  ^------!    ';\n      const e2 = hot('  -------#    ');\n      const e2subs = '  ^------!    ';\n      const expected = '--a--b-#    ';\n\n      const result = e1.pipe(mergeWith(e2));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should merge never and error', () => {\n    rxTestScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  --------');\n      const e1subs = '  ^------!';\n      const e2 = hot('  -------#');\n      const e2subs = '  ^------!';\n      const expected = '-------#';\n\n      const result = e1.pipe(mergeWith(e2));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n});\n\ndescribe('mergeAll operator', () => {\n  it('should merge two observables', (done) => {\n    const a = of(1, 2, 3);\n    const b = of(4, 5, 6, 7, 8);\n    const r = [1, 2, 3, 4, 5, 6, 7, 8];\n\n    of(a, b)\n      .pipe(mergeAll())\n      .subscribe({\n        next: (val) => {\n          expect(val).to.equal(r.shift());\n        },\n        complete: done,\n      });\n  });\n\n  it('should merge two immediately-scheduled observables', (done) => {\n    const a = scheduled([1, 2, 3], queueScheduler);\n    const b = scheduled([4, 5, 6, 7, 8], queueScheduler);\n    const r = [1, 2, 4, 3, 5, 6, 7, 8];\n\n    scheduled([a, b], queueScheduler)\n      .pipe(mergeAll())\n      .subscribe({\n        next: (val) => {\n          expect(val).to.equal(r.shift());\n        },\n        complete: done,\n      });\n  });\n\n  it('should stop listening to a synchronous observable when unsubscribed', () => {\n    const sideEffects: number[] = [];\n    const synchronousObservable = new Observable<number>((subscriber) => {\n      // This will check to see if the subscriber was closed on each loop\n      // when the unsubscribe hits (from the `take`), it should be closed\n      for (let i = 0; !subscriber.closed && i < 10; i++) {\n        sideEffects.push(i);\n        subscriber.next(i);\n      }\n    });\n\n    synchronousObservable.pipe(mergeWith(of(0)), take(3)).subscribe(() => {\n      /* noop */\n    });\n\n    expect(sideEffects).to.deep.equal([0, 1, 2]);\n  });\n});\n"
  },
  {
    "path": "packages/rxjs/spec/operators/min-spec.ts",
    "content": "import { expect } from 'chai';\nimport { min, skip, take, mergeMap } from 'rxjs/operators';\nimport { range, of } from 'rxjs';\nimport { TestScheduler } from 'rxjs/testing';\nimport { observableMatcher } from '../helpers/observableMatcher';\n\n/** @test {min} */\ndescribe('min', () => {\n  let testScheduler: TestScheduler;\n\n  beforeEach(() => {\n    testScheduler = new TestScheduler(observableMatcher);\n  });\n\n  it('should min the values of an observable', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const source = hot('--a--b--c--|', { a: 42, b: -1, c: 3 });\n      const subs = '      ^----------!';\n      const expected = '  -----------(x|)';\n\n      expectObservable((<any>source).pipe(min())).toBe(expected, { x: -1 });\n      expectSubscriptions(source.subscriptions).toBe(subs);\n    });\n  });\n\n  it('should be never when source is never', () => {\n    testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' -');\n      const e1subs = '  ^';\n      const expected = '-';\n\n      expectObservable((<any>e1).pipe(min())).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should be zero when source is empty', () => {\n    testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' |');\n      const e1subs = '  (^!)';\n      const expected = '|';\n\n      expectObservable((<any>e1).pipe(min())).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it(\"should be never when source doesn't complete\", () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('--x--^--y--');\n      const e1subs = '     ^     ';\n      const expected = '   ------';\n\n      expectObservable((<any>e1).pipe(min())).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it(\"should be completes when source doesn't have values\", () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('-x-^---|');\n      const e1subs = '   ^---!';\n      const expected = ' ----|';\n\n      expectObservable((<any>e1).pipe(min())).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should min the unique value of an observable', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('-x-^--y--|', { y: 42 });\n      const e1subs = '   ^-----!';\n      const expected = ' ------(w|)';\n\n      expectObservable((<any>e1).pipe(min())).toBe(expected, { w: 42 });\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should min the values of an ongoing hot observable', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('--a-^-b--c--d--|', { a: 42, b: -1, c: 0, d: 666 });\n      const subs = '      ^----------!';\n      const expected = '  -----------(x|)';\n\n      expectObservable((<any>e1).pipe(min())).toBe(expected, { x: -1 });\n      expectSubscriptions(e1.subscriptions).toBe(subs);\n    });\n  });\n\n  it('should min a range() source observable', (done) => {\n    range(1, 10000)\n      .pipe(min())\n      .subscribe({\n        next: (value) => {\n          expect(value).to.equal(1);\n        },\n        error: () => {\n          done(new Error('should not be called'));\n        },\n        complete: done,\n      });\n  });\n\n  it('should min a range().skip(1) source observable', (done) => {\n    range(1, 10)\n      .pipe(skip(1), min())\n      .subscribe({\n        next: (value) => {\n          expect(value).to.equal(2);\n        },\n        error: () => {\n          done(new Error('should not be called'));\n        },\n        complete: done,\n      });\n  });\n\n  it('should min a range().take(1) source observable', (done) => {\n    range(1, 10)\n      .pipe(take(1), min())\n      .subscribe({\n        next: (value) => {\n          expect(value).to.equal(1);\n        },\n        error: () => {\n          done(new Error('should not be called'));\n        },\n        complete: done,\n      });\n  });\n\n  it('should work with error', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('-x-^--y--z--#', { x: 1, y: 2, z: 3 }, 'too bad');\n      const e1subs = '   ^--------!';\n      const expected = ' ---------#';\n\n      expectObservable((<any>e1).pipe(min())).toBe(expected, null, 'too bad');\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should work with throw', () => {\n    testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' #');\n      const e1subs = '  (^!)';\n      const expected = '#';\n\n      expectObservable((<any>e1).pipe(min())).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should handle a constant predicate on an empty hot observable', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('-x-^---|');\n      const e1subs = '   ^---!';\n      const expected = ' ----|';\n\n      const predicate = function <T>(x: T, y: T) {\n        return 42;\n      };\n\n      expectObservable((<any>e1).pipe(min(predicate))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should handle a constant predicate on an never hot observable', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('-x-^----');\n      const e1subs = '   ^----';\n      const expected = ' -----';\n\n      const predicate = function <T>(x: T, y: T) {\n        return 42;\n      };\n\n      expectObservable((<any>e1).pipe(min(predicate))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should handle a constant predicate on a simple hot observable', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('-x-^-a-|', { a: 1 });\n      const e1subs = '   ^---!';\n      const expected = ' ----(w|)';\n\n      const predicate = () => {\n        return 42;\n      };\n\n      expectObservable((<any>e1).pipe(min(predicate))).toBe(expected, { w: 1 });\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should allow unsubscribing explicitly and early', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('-x-^-a-b-c-d-e-f-g-|');\n      const unsub = '    -------!         ';\n      const e1subs = '   ^------!         ';\n      const expected = ' --------         ';\n\n      const predicate = () => {\n        return 42;\n      };\n\n      expectObservable((<any>e1).pipe(min(predicate)), unsub).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should not break unsubscription chains when result is unsubscribed explicitly', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('-x-^-a-b-c-d-e-f-g-|');\n      const e1subs = '   ^------!         ';\n      const expected = ' --------         ';\n      const unsub = '    -------!         ';\n\n      const predicate = function () {\n        return 42;\n      };\n\n      const result = (<any>e1).pipe(\n        mergeMap((x: string) => of(x)),\n        min(predicate),\n        mergeMap((x: number) => of(x))\n      );\n\n      expectObservable(result, unsub).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should handle a reverse predicate on observable with many values', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('-a-^-b--c--d-|', { a: 42, b: -1, c: 0, d: 666 });\n      const e1subs = '   ^---------!';\n      const expected = ' ----------(w|)';\n\n      const predicate = function <T>(x: T, y: T) {\n        return x > y ? -1 : 1;\n      };\n\n      expectObservable((<any>e1).pipe(min(predicate))).toBe(expected, { w: 666 });\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should handle a predicate for string on observable with many values', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('-a-^-b--c--d-|');\n      const e1subs = '   ^---------!';\n      const expected = ' ----------(w|)';\n\n      const predicate = function <T>(x: T, y: T) {\n        return x > y ? -1 : 1;\n      };\n\n      expectObservable((<any>e1).pipe(min(predicate))).toBe(expected, { w: 'd' });\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should handle a constant predicate on observable that throws', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('-1-^---#');\n      const e1subs = '   ^---!';\n      const expected = ' ----#';\n\n      const predicate = () => {\n        return 42;\n      };\n\n      expectObservable((<any>e1).pipe(min(predicate))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should handle a predicate that throws, on observable with many values', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('-1-^-2--3--|');\n      const e1subs = '   ^----!   ';\n      const expected = ' -----#   ';\n\n      const predicate = function (x: string, y: string) {\n        if (y === '3') {\n          throw 'error';\n        }\n        return x > y ? -1 : 1;\n      };\n\n      expectObservable((<any>e1).pipe(min(predicate))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n});\n"
  },
  {
    "path": "packages/rxjs/spec/operators/observeOn-spec.ts",
    "content": "import { observeOn, mergeMap, take } from 'rxjs/operators';\nimport { TestScheduler } from 'rxjs/testing';\nimport { expect } from 'chai';\nimport { of, Observable, queueScheduler } from 'rxjs';\nimport { observableMatcher } from '../helpers/observableMatcher';\n\n/** @test {observeOn} */\ndescribe('observeOn', () => {\n  let testScheduler: TestScheduler;\n\n  beforeEach(() => {\n    testScheduler = new TestScheduler(observableMatcher);\n  });\n\n  it('should observe on specified scheduler', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  --a--b--|');\n      const e1subs = '  ^-------!';\n      const expected = '--a--b--|';\n\n      expectObservable(e1.pipe(observeOn(testScheduler))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should observe after specified delay', () => {\n    testScheduler.run(({ hot, time, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('    --a----b-|   ');\n      const e1subs = '    ^--------!   ';\n      const delay = time('  ---|       ');\n      //                         ---|\n      //                           ---|\n      const expected = '  -----a----b-|';\n\n      expectObservable(e1.pipe(observeOn(testScheduler, delay))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should observe when source raises error', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  --a--#');\n      const e1subs = '  ^----!';\n      const expected = '--a--#';\n\n      expectObservable(e1.pipe(observeOn(testScheduler))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should observe when source is empty', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  -----|');\n      const e1subs = '  ^----!';\n      const expected = '-----|';\n\n      expectObservable(e1.pipe(observeOn(testScheduler))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should observe when source does not complete', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  -----');\n      const e1subs = '  ^----';\n      const expected = '-----';\n\n      expectObservable(e1.pipe(observeOn(testScheduler))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should allow unsubscribing early and explicitly', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  --a--b--|');\n      const e1subs = '  ^---!    ';\n      const expected = '--a--    ';\n      const unsub = '   ----!    ';\n\n      const result = e1.pipe(observeOn(testScheduler));\n\n      expectObservable(result, unsub).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should not break unsubscription chains when the result is unsubscribed explicitly', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  --a--b--|');\n      const e1subs = '  ^---!    ';\n      const expected = '--a--    ';\n      const unsub = '   ----!    ';\n\n      const result = e1.pipe(\n        mergeMap((x) => of(x)),\n        observeOn(testScheduler),\n        mergeMap((x) => of(x))\n      );\n\n      expectObservable(result, unsub).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should stop listening to a synchronous observable when unsubscribed', () => {\n    const sideEffects: number[] = [];\n    const synchronousObservable = new Observable<number>((subscriber) => {\n      // This will check to see if the subscriber was closed on each loop\n      // when the unsubscribe hits (from the `take`), it should be closed\n      for (let i = 0; !subscriber.closed && i < 10; i++) {\n        sideEffects.push(i);\n        subscriber.next(i);\n      }\n    });\n\n    synchronousObservable.pipe(observeOn(queueScheduler), take(3)).subscribe(() => {\n      /* noop */\n    });\n\n    expect(sideEffects).to.deep.equal([0, 1, 2]);\n  });\n});\n"
  },
  {
    "path": "packages/rxjs/spec/operators/onErrorResumeNext-spec.ts",
    "content": "import { expect } from 'chai';\nimport { TestScheduler } from 'rxjs/testing';\nimport { onErrorResumeNextWith, take, finalize, tap } from 'rxjs/operators';\nimport { concat, throwError, of, Observable } from 'rxjs';\nimport { asInteropObservable } from '../helpers/interop-helper';\nimport { observableMatcher } from '../helpers/observableMatcher';\n\ndescribe('onErrorResumeNextWith', () => {\n  let testScheduler: TestScheduler;\n\n  beforeEach(() => {\n    testScheduler = new TestScheduler(observableMatcher);\n  });\n\n  it('should continue observable sequence with next observable', () => {\n    testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  --a--b--#        ');\n      const e1subs = '  ^-------!        ';\n      const e2 = cold('         --c--d--|');\n      const e2subs = '  --------^-------!';\n      const expected = '--a--b----c--d--|';\n\n      expectObservable(e1.pipe(onErrorResumeNextWith(e2))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should continue with hot observables', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  --a--b--#        ');\n      const e1subs = '  ^-------!        ';\n      const e2 = hot('  -----x----c--d--|');\n      const e2subs = '  --------^-------!';\n      const expected = '--a--b----c--d--|';\n\n      expectObservable(e1.pipe(onErrorResumeNextWith(e2))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should continue with array of multiple observables that throw errors', () => {\n    testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  --a--b--#                     ');\n      const e1subs = '  ^-------!                     ';\n      const e2 = [\n        cold('                  --c--d--#             '),\n        cold('                          --e--#        '),\n        cold('                               --f--g--|'),\n      ];\n      const e2subs = [\n        '               --------^-------!',\n        '               ----------------^----!',\n        '               ---------------------^-------!',\n      ];\n      const expected = '--a--b----c--d----e----f--g--|';\n\n      expectObservable(e1.pipe(onErrorResumeNextWith(e2))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2[0].subscriptions).toBe(e2subs[0]);\n      expectSubscriptions(e2[1].subscriptions).toBe(e2subs[1]);\n      expectSubscriptions(e2[2].subscriptions).toBe(e2subs[2]);\n    });\n  });\n\n  it('should continue with multiple observables that throw errors', () => {\n    testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  --a--b--#                     ');\n      const e1subs = '  ^-------!                     ';\n      const e2 = cold('         --c--d--#             ');\n      const e2subs = '  --------^-------!             ';\n      const e3 = cold('                 --e--#        ');\n      const e3subs = '  ----------------^----!        ';\n      const e4 = cold('                      --f--g--|');\n      const e4subs = '  ---------------------^-------!';\n      const expected = '--a--b----c--d----e----f--g--|';\n\n      expectObservable(e1.pipe(onErrorResumeNextWith(e2, e3, e4))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n      expectSubscriptions(e3.subscriptions).toBe(e3subs);\n      expectSubscriptions(e4.subscriptions).toBe(e4subs);\n    });\n  });\n\n  it(\"should continue with multiple observables that don't throw error\", () => {\n    testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  --a--b--|                     ');\n      const e1subs = '  ^-------!                     ';\n      const e2 = cold('         --c--d--|             ');\n      const e2subs = '  --------^-------!             ';\n      const e3 = cold('                 --e--|        ');\n      const e3subs = '  ----------------^----!        ';\n      const e4 = cold('                      --f--g--|');\n      const e4subs = '  ---------------------^-------!';\n      const expected = '--a--b----c--d----e----f--g--|';\n\n      expectObservable(e1.pipe(onErrorResumeNextWith(e2, e3, e4))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n      expectSubscriptions(e3.subscriptions).toBe(e3subs);\n      expectSubscriptions(e4.subscriptions).toBe(e4subs);\n    });\n  });\n\n  it('should continue after empty observable', () => {\n    testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  |                     ');\n      const e1subs = '  (^!)                  ';\n      const e2 = cold(' --c--d--|             ');\n      const e2subs = '  ^-------!             ';\n      const e3 = cold('         --e--#        ');\n      const e3subs = '  --------^----!        ';\n      const e4 = cold('              --f--g--|');\n      const e4subs = '  -------------^-------!';\n      const expected = '--c--d----e----f--g--|';\n\n      expectObservable(e1.pipe(onErrorResumeNextWith(e2, e3, e4))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n      expectSubscriptions(e3.subscriptions).toBe(e3subs);\n      expectSubscriptions(e4.subscriptions).toBe(e4subs);\n    });\n  });\n\n  it('should not complete with observable that does not complete', () => {\n    testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  --a--b--| ');\n      const e1subs = '  ^-------! ';\n      const e2 = cold('         --');\n      const e2subs = '  --------^-';\n      const expected = '--a--b----';\n\n      expectObservable(e1.pipe(onErrorResumeNextWith(e2))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should not continue when source observable does not complete', () => {\n    testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  --a--');\n      const e1subs = '  ^----';\n      const e2 = cold('-b--c-');\n      const e2subs: string[] = [];\n      const expected = '--a--';\n\n      expectObservable(e1.pipe(onErrorResumeNextWith(e2))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should complete observable when next observable throws', () => {\n    testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  --a--b--#        ');\n      const e1subs = '  ^-------!        ';\n      const e2 = cold('         --c--d--#');\n      const e2subs = '  --------^-------!';\n      const expected = '--a--b----c--d--|';\n\n      expectObservable(e1.pipe(onErrorResumeNextWith(e2))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should stop listening to a synchronous observable when unsubscribed', () => {\n    const sideEffects: number[] = [];\n    const synchronousObservable = new Observable((subscriber) => {\n      // This will check to see if the subscriber was closed on each loop\n      // when the unsubscribe hits (from the `take`), it should be closed\n      for (let i = 0; !subscriber.closed && i < 10; i++) {\n        sideEffects.push(i);\n        subscriber.next(i);\n      }\n    });\n\n    throwError(() => new Error('Some error'))\n      .pipe(onErrorResumeNextWith(synchronousObservable), take(3))\n      .subscribe(() => {\n        /* noop */\n      });\n\n    expect(sideEffects).to.deep.equal([0, 1, 2]);\n  });\n\n  it('should unsubscribe from an interop observable upon explicit unsubscription', () => {\n    testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  --a--b--#       ');\n      const e1subs = '  ^-------!       ';\n      const e2 = cold('         --c--d--');\n      const e2subs = '  --------^---!   ';\n      const unsub = '   ------------!   ';\n      const expected = '--a--b----c--   ';\n\n      // This test manipulates the observable to make it look like an interop\n      // observable - an observable from a foreign library. Interop subscribers\n      // are treated differently: they are wrapped in a safe subscriber. This\n      // test ensures that unsubscriptions are chained all the way to the\n      // interop subscriber.\n\n      expectObservable(e1.pipe(onErrorResumeNextWith(asInteropObservable(e2))), unsub).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should work with promise', (done) => {\n    const expected = [1, 2];\n    const source = concat(\n      of(1),\n      throwError(() => 'meh')\n    );\n\n    source.pipe(onErrorResumeNextWith(Promise.resolve(2))).subscribe({\n      next: (x) => {\n        expect(expected.shift()).to.equal(x);\n      },\n      error: () => {\n        done(new Error('should not be called'));\n      },\n      complete: () => {\n        expect(expected).to.be.empty;\n        done();\n      },\n    });\n  });\n\n  it('should skip invalid sources and move on', () => {\n    const results: any[] = [];\n\n    of(1)\n      .pipe(onErrorResumeNextWith([2, 3, 4], { notValid: 'LOL' } as any, of(5, 6)))\n      .subscribe({\n        next: (value) => results.push(value),\n        complete: () => results.push('complete'),\n      });\n\n    expect(results).to.deep.equal([1, 2, 3, 4, 5, 6, 'complete']);\n  });\n\n  it('should call finalize after each sync observable', () => {\n    const results: any[] = [];\n\n    of(1)\n      .pipe(\n        finalize(() => results.push('finalize 1')),\n        onErrorResumeNextWith(\n          of(2).pipe(finalize(() => results.push('finalize 2'))),\n          of(3).pipe(finalize(() => results.push('finalize 3'))),\n          of(4).pipe(finalize(() => results.push('finalize 4')))\n        )\n      )\n      .subscribe({\n        next: (value) => results.push(value),\n        complete: () => results.push('complete'),\n      });\n\n    expect(results).to.deep.equal([1, 'finalize 1', 2, 'finalize 2', 3, 'finalize 3', 4, 'finalize 4', 'complete']);\n  });\n\n  it('should not subscribe to the next source until after the previous is finalized.', () => {\n    const results: any[] = [];\n\n    of(1)\n      .pipe(\n        tap({\n          subscribe: () => results.push('subscribe 1'),\n          finalize: () => results.push('finalize 1'),\n        }),\n        onErrorResumeNextWith(\n          of(2).pipe(\n            tap({\n              subscribe: () => results.push('subscribe 2'),\n              finalize: () => results.push('finalize 2'),\n            })\n          ),\n          of(3).pipe(\n            tap({\n              subscribe: () => results.push('subscribe 3'),\n              finalize: () => results.push('finalize 3'),\n            })\n          ),\n          of(4).pipe(\n            tap({\n              subscribe: () => results.push('subscribe 4'),\n              finalize: () => results.push('finalize 4'),\n            })\n          )\n        )\n      )\n      .subscribe({\n        next: (value) => results.push(value),\n        complete: () => results.push('complete'),\n      });\n\n    expect(results).to.deep.equal([\n      'subscribe 1',\n      1,\n      'finalize 1',\n      'subscribe 2',\n      2,\n      'finalize 2',\n      'subscribe 3',\n      3,\n      'finalize 3',\n      'subscribe 4',\n      4,\n      'finalize 4',\n      'complete',\n    ]);\n  });\n});\n"
  },
  {
    "path": "packages/rxjs/spec/operators/pairwise-spec.ts",
    "content": "import { TestScheduler } from 'rxjs/testing';\nimport { pairwise, take } from 'rxjs/operators';\nimport { Subject, Observable } from 'rxjs';\nimport { expect } from 'chai';\nimport { observableMatcher } from '../helpers/observableMatcher';\n\n/** @test {pairwise} */\ndescribe('pairwise operator', () => {\n  let testScheduler: TestScheduler;\n\n  beforeEach(() => {\n    testScheduler = new TestScheduler(observableMatcher);\n  });\n\n  it('should group consecutive emissions as arrays of two', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  --a--b-c----d--e---|');\n      const e1subs = '  ^------------------!';\n      const expected = '-----u-v----w--x---|';\n\n      const values = {\n        u: ['a', 'b'],\n        v: ['b', 'c'],\n        w: ['c', 'd'],\n        x: ['d', 'e'],\n      };\n\n      expectObservable(e1.pipe(pairwise())).toBe(expected, values);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should pairwise things', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('--a--^--b--c--d--e--f--g--|');\n      const e1subs = '     ^--------------------!';\n      const expected = '   ------v--w--x--y--z--|';\n\n      const values = {\n        v: ['b', 'c'],\n        w: ['c', 'd'],\n        x: ['d', 'e'],\n        y: ['e', 'f'],\n        z: ['f', 'g'],\n      };\n\n      expectObservable(e1.pipe(pairwise())).toBe(expected, values);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should not emit on single-element streams', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('--a--^--b----|');\n      const e1subs = '     ^-------!';\n      const expected = '   --------|';\n\n      expectObservable(e1.pipe(pairwise())).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should handle mid-stream throw', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('--a--^--b--c--d--e--#');\n      const e1subs = '     ^--------------!';\n      const expected = '   ------v--w--x--#';\n\n      const values = {\n        v: ['b', 'c'],\n        w: ['c', 'd'],\n        x: ['d', 'e'],\n      };\n\n      expectObservable(e1.pipe(pairwise())).toBe(expected, values);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should handle empty', () => {\n    testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' |   ');\n      const e1subs = '  (^!)';\n      const expected = '|   ';\n\n      expectObservable(e1.pipe(pairwise())).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should handle never', () => {\n    testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' -');\n      const e1subs = '  ^';\n      const expected = '-';\n\n      expectObservable(e1.pipe(pairwise())).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should handle throw', () => {\n    testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' #   ');\n      const e1subs = '  (^!)';\n      const expected = '#   ';\n\n      expectObservable(e1.pipe(pairwise())).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should be recursively re-enterable', () => {\n    const results = new Array<[string, string]>();\n\n    const subject = new Subject<string>();\n\n    subject.pipe(pairwise(), take(3)).subscribe((pair) => {\n      results.push(pair);\n      subject.next('c');\n    });\n\n    subject.next('a');\n    subject.next('b');\n\n    expect(results).to.deep.equal([\n      ['a', 'b'],\n      ['b', 'c'],\n      ['c', 'c'],\n    ]);\n  });\n\n  it('should stop listening to a synchronous observable when unsubscribed', () => {\n    const sideEffects: number[] = [];\n    const synchronousObservable = new Observable<number>((subscriber) => {\n      // This will check to see if the subscriber was closed on each loop\n      // when the unsubscribe hits (from the `take`), it should be closed\n      for (let i = 0; !subscriber.closed && i < 10; i++) {\n        sideEffects.push(i);\n        subscriber.next(i);\n      }\n    });\n\n    synchronousObservable.pipe(pairwise(), take(2)).subscribe(() => {\n      /* noop */\n    });\n\n    expect(sideEffects).to.deep.equal([0, 1, 2]);\n  });\n});\n"
  },
  {
    "path": "packages/rxjs/spec/operators/raceWith-spec.ts",
    "content": "import { expect } from 'chai';\nimport * as sinon from 'sinon';\nimport { EMPTY, NEVER, of, timer, defer, Observable, throwError } from 'rxjs';\nimport { raceWith, mergeMap, map, finalize, startWith, take } from 'rxjs/operators';\nimport { TestScheduler } from 'rxjs/testing';\nimport { observableMatcher } from '../helpers/observableMatcher';\n\n/** @test {raceWith} */\ndescribe('raceWith operator', () => {\n  let testScheduler: TestScheduler;\n\n  beforeEach(() => {\n    testScheduler = new TestScheduler(observableMatcher);\n  });\n\n  it('should race cold and cold', () => {\n    testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' ---a-----b-----c----|   ');\n      const e1subs = '  ^-------------------!   ';\n      const e2 = cold(' ------x-----y-----z----|');\n      const e2subs = '  ^--!                    ';\n      const expected = '---a-----b-----c----|   ';\n\n      const result = e1.pipe(raceWith(e2));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should race hot and hot', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  ---a-----b-----c----|   ');\n      const e1subs = '  ^-------------------!   ';\n      const e2 = hot('  ------x-----y-----z----|');\n      const e2subs = '  ^--!                    ';\n      const expected = '---a-----b-----c----|   ';\n\n      const result = e1.pipe(raceWith(e2));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should race hot and cold', () => {\n    testScheduler.run(({ hot, cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' ---a-----b-----c----|   ');\n      const e1subs = '  ^-------------------!   ';\n      const e2 = hot('  ------x-----y-----z----|');\n      const e2subs = '  ^--!                    ';\n      const expected = '---a-----b-----c----|   ';\n\n      const result = e1.pipe(raceWith(e2));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should race 2nd and 1st', () => {\n    testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' ------x-----y-----z----|');\n      const e1subs = '  ^--!                    ';\n      const e2 = cold(' ---a-----b-----c----|   ');\n      const e2subs = '  ^-------------------!   ';\n      const expected = '---a-----b-----c----|   ';\n\n      const result = e1.pipe(raceWith(e2));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should race emit and complete', () => {\n    testScheduler.run(({ hot, cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' -----|                  ');\n      const e1subs = '  ^----!                  ';\n      const e2 = hot('  ------x-----y-----z----|');\n      const e2subs = '  ^----!                  ';\n      const expected = '-----|                  ';\n\n      const result = e1.pipe(raceWith(e2));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should allow unsubscribing early and explicitly', () => {\n    testScheduler.run(({ hot, cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' ---a-----b-----c----|   ');\n      const e1subs = '  ^-----------!           ';\n      const e2 = hot('  ------x-----y-----z----|');\n      const e2subs = '  ^--!                    ';\n      const expected = '---a-----b---           ';\n      const unsub = '   ------------!           ';\n\n      const result = e1.pipe(raceWith(e2));\n\n      expectObservable(result, unsub).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should not break unsubscription chains when unsubscribed explicitly', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  --a--^--b--c---d-| ');\n      const e1subs = '       ^--------!    ';\n      const e2 = hot('  ---e-^---f--g---h-|');\n      const e2subs = '       ^--!          ';\n      const expected = '     ---b--c---    ';\n      const unsub = '        ---------!    ';\n\n      const result = e1.pipe(\n        mergeMap((x: string) => of(x)),\n        raceWith(e2),\n        mergeMap((x: string) => of(x))\n      );\n\n      expectObservable(result, unsub).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should never emit when given non emitting sources', () => {\n    testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' ---|');\n      const e2 = cold(' ---|');\n      const e1subs = '  ^--!';\n      const expected = '---|';\n\n      const source = e1.pipe(raceWith(e2));\n\n      expectObservable(source).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should throw when error occurs mid stream', () => {\n    testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' ---a-----#              ');\n      const e1subs = '  ^--------!              ';\n      const e2 = cold(' ------x-----y-----z----|');\n      const e2subs = '  ^--!                    ';\n      const expected = '---a-----#              ';\n\n      const result = e1.pipe(raceWith(e2));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should throw when error occurs before a winner is found', () => {\n    testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' ---#                    ');\n      const e1subs = '  ^--!                    ';\n      const e2 = cold(' ------x-----y-----z----|');\n      const e2subs = '  ^--!                    ';\n      const expected = '---#                    ';\n\n      const result = e1.pipe(raceWith(e2));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should allow observable emits immediately', (done) => {\n    const e1 = of(true);\n    const e2 = timer(200).pipe(map((_) => false));\n\n    e1.pipe(raceWith(e2)).subscribe({\n      next: (x) => {\n        expect(x).to.be.true;\n      },\n      error: done,\n      complete: done,\n    });\n  });\n\n  it('should ignore latter observables if a former one emits immediately', () => {\n    const onNext = sinon.spy();\n    const onSubscribe = sinon.spy() as any;\n    const e1 = of('a'); // Wins the race\n    const e2 = defer(onSubscribe); // Should be ignored\n\n    e1.pipe(raceWith(e2)).subscribe(onNext);\n    expect(onNext.calledWithExactly('a')).to.be.true;\n    expect(onSubscribe.called).to.be.false;\n  });\n\n  it('should ignore latter observables if a former one completes immediately', () => {\n    const onComplete = sinon.spy();\n    const onSubscribe = sinon.spy() as any;\n    const e1 = EMPTY; // Wins the race\n    const e2 = defer(onSubscribe); // Should be ignored\n\n    e1.pipe(raceWith(e2)).subscribe({ complete: onComplete });\n    expect(onComplete.calledWithExactly()).to.be.true;\n    expect(onSubscribe.called).to.be.false;\n  });\n\n  it('should ignore latter observables if a former one errors immediately', () => {\n    const onError = sinon.spy();\n    const onSubscribe = sinon.spy() as any;\n    const e1 = throwError(() => 'kaboom'); // Wins the race\n    const e2 = defer(onSubscribe); // Should be ignored\n\n    e1.pipe(raceWith(e2)).subscribe({ error: onError });\n    expect(onError.calledWithExactly('kaboom')).to.be.true;\n    expect(onSubscribe.called).to.be.false;\n  });\n\n  it('should unsubscribe former observables if a latter one emits immediately', () => {\n    const onNext = sinon.spy();\n    const onUnsubscribe = sinon.spy();\n    const e1 = NEVER.pipe(finalize(onUnsubscribe)); // Should be unsubscribed\n    const e2 = of('b'); // Wins the race\n\n    e1.pipe(raceWith(e2)).subscribe(onNext);\n    expect(onNext.calledWithExactly('b')).to.be.true;\n    expect(onUnsubscribe.calledOnce).to.be.true;\n  });\n\n  it('should unsubscribe from immediately emitting observable on unsubscription', () => {\n    const onNext = sinon.spy();\n    const onUnsubscribe = sinon.spy();\n    const e1 = <Observable<never>>NEVER.pipe(startWith('a'), finalize(onUnsubscribe)); // Wins the race\n    const e2 = NEVER; // Loses the race\n\n    const subscription = e1.pipe(raceWith(e2)).subscribe(onNext);\n    expect(onNext.calledWithExactly('a')).to.be.true;\n    expect(onUnsubscribe.called).to.be.false;\n    subscription.unsubscribe();\n    expect(onUnsubscribe.calledOnce).to.be.true;\n  });\n\n  it('should stop listening to a synchronous observable when unsubscribed', () => {\n    const sideEffects: number[] = [];\n    const synchronousObservable = new Observable<number>((subscriber) => {\n      // This will check to see if the subscriber was closed on each loop\n      // when the unsubscribe hits (from the `take`), it should be closed\n      for (let i = 0; !subscriber.closed && i < 10; i++) {\n        sideEffects.push(i);\n        subscriber.next(i);\n      }\n    });\n\n    synchronousObservable.pipe(raceWith(of(0)), take(3)).subscribe(() => {\n      /* noop */\n    });\n\n    expect(sideEffects).to.deep.equal([0, 1, 2]);\n  });\n});\n"
  },
  {
    "path": "packages/rxjs/spec/operators/reduce-spec.ts",
    "content": "import { expect } from 'chai';\nimport { TestScheduler } from 'rxjs/testing';\nimport { reduce, mergeMap } from 'rxjs/operators';\nimport { range, of } from 'rxjs';\nimport { observableMatcher } from '../helpers/observableMatcher';\n\n/** @test {reduce} */\ndescribe('reduce', () => {\n  let testScheduler: TestScheduler;\n\n  beforeEach(() => {\n    testScheduler = new TestScheduler(observableMatcher);\n  });\n\n  it('should reduce', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const values = { a: 1, b: 3, c: 5, x: 9 };\n      const e1 = hot('  --a--b--c--|   ', values);\n      const e1subs = '  ^----------!   ';\n      const expected = '-----------(x|)';\n\n      const result = e1.pipe(reduce((o, x) => o + x, 0));\n\n      expectObservable(result).toBe(expected, values);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should reduce with seed', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  --a--b--|   ');\n      const e1subs = '  ^-------!   ';\n      const expected = '--------(x|)';\n\n      const result = e1.pipe(reduce((o, x) => o + ' ' + x, 'n'));\n\n      expectObservable(result).toBe(expected, { x: 'n a b' });\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should reduce with a seed of undefined', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('--a--^--b--c--d--e--f--g--|   ');\n      const e1subs = '     ^--------------------!   ';\n      const expected = '   ---------------------(x|)';\n\n      const result = e1.pipe(reduce((o: string | undefined, x) => o + ' ' + x, undefined));\n\n      expectObservable(result).toBe(expected, { x: 'undefined b c d e f g' });\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should reduce without a seed', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('--a--^--b--c--d--e--f--g--|   ');\n      const e1subs = '     ^--------------------!   ';\n      const expected = '   ---------------------(x|)';\n\n      const result = e1.pipe(reduce((o, x) => o + ' ' + x));\n\n      expectObservable(result).toBe(expected, { x: 'b c d e f g' });\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should reduce with index without seed', () => {\n    const idx = [1, 2, 3, 4, 5];\n\n    range(0, 6)\n      .pipe(\n        reduce((acc, value, index) => {\n          expect(idx.shift()).to.equal(index);\n          return value;\n        })\n      )\n      .subscribe({\n        complete() {\n          expect(idx).to.be.empty;\n        },\n      });\n  });\n\n  it('should reduce with index with seed', () => {\n    const idx = [0, 1, 2, 3, 4, 5];\n\n    range(0, 6)\n      .pipe(\n        reduce((acc, value, index) => {\n          expect(idx.shift()).to.equal(index);\n          return value;\n        }, -1)\n      )\n      .subscribe({\n        complete() {\n          expect(idx).to.be.empty;\n        },\n      });\n  });\n\n  it('should reduce with seed if source is empty', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('--a--^-------|   ');\n      const e1subs = '     ^-------!   ';\n      const expected = '   --------(x|)';\n\n      const result = e1.pipe(reduce((o, x) => o + x, '42'));\n\n      expectObservable(result).toBe(expected, { x: '42' });\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should raise error if reduce function throws without seed', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  --a--b--|');\n      const e1subs = '  ^----!   ';\n      const expected = '-----#   ';\n\n      const result = e1.pipe(\n        reduce(() => {\n          throw 'error';\n        })\n      );\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should allow unsubscribing explicitly and early', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  --a--b--|');\n      const e1subs = '  ^-----!  ';\n      const expected = '-------  ';\n      const unsub = '   ------!  ';\n\n      const result = e1.pipe(reduce((o, x) => o + x));\n\n      expectObservable(result, unsub).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should not break unsubscription chains when result is unsubscribed explicitly', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  --a--b--|');\n      const e1subs = '  ^-----!  ';\n      const expected = '-------  ';\n      const unsub = '   ------!  ';\n\n      const result = e1.pipe(\n        mergeMap((x) => of(x)),\n        reduce((o, x) => o + x),\n        mergeMap((x) => of(x))\n      );\n\n      expectObservable(result, unsub).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should raise error if source emits and raises error with seed', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  --a--b--#');\n      const e1subs = '  ^-------!';\n      const expected = '--------#';\n\n      const result = e1.pipe(reduce((o, x) => o + x, '42'));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should raise error if source raises error with seed', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  ----#');\n      const e1subs = '  ^---!';\n      const expected = '----#';\n\n      const result = e1.pipe(reduce((o, x) => o + x, '42'));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should raise error if reduce function throws with seed', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  --a--b--|');\n      const e1subs = '  ^-!      ';\n      const expected = '--#      ';\n\n      const result = e1.pipe(\n        reduce(() => {\n          throw 'error';\n        }, 'n')\n      );\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should not complete with seed if source emits but does not complete', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  --a--');\n      const e1subs = '  ^----';\n      const expected = '-----';\n\n      const result = e1.pipe(reduce((o, x) => o + x, 'n'));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should not complete with seed if source never completes', () => {\n    testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' -');\n      const e1subs = '  ^';\n      const expected = '-';\n\n      const result = e1.pipe(reduce((o, x) => o + x, 'n'));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should not complete without seed if source emits but does not completes', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  --a--b--');\n      const e1subs = '  ^-------';\n      const expected = '--------';\n\n      const result = e1.pipe(reduce((o, x) => o + x));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should not complete without seed if source never completes', () => {\n    testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' -');\n      const e1subs = '  ^';\n      const expected = '-';\n\n      const result = e1.pipe(reduce((o, x) => o + x));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should reduce if source does not emit without seed', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('--a--^-------|');\n      const e1subs = '     ^-------!';\n      const expected = '   --------|';\n\n      const result = e1.pipe(reduce((o, x) => o + x));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should raise error if source emits and raises error without seed', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  --a--b--#');\n      const e1subs = '  ^-------!';\n      const expected = '--------#';\n\n      const result = e1.pipe(reduce((o, x) => o + x));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should raise error if source raises error without seed', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  ----#');\n      const e1subs = '  ^---!';\n      const expected = '----#';\n\n      const result = e1.pipe(reduce((o, x) => o + x));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n});\n"
  },
  {
    "path": "packages/rxjs/spec/operators/repeat-spec.ts",
    "content": "import { expect } from 'chai';\nimport { repeat, mergeMap, map, share, take } from 'rxjs/operators';\nimport { TestScheduler } from 'rxjs/testing';\nimport { of, Subject, Observable, timer } from 'rxjs';\nimport { observableMatcher } from '../helpers/observableMatcher';\n\n/** @test {repeat} */\ndescribe('repeat operator', () => {\n  let rxTest: TestScheduler;\n\n  beforeEach(() => {\n    rxTest = new TestScheduler(observableMatcher);\n  });\n\n  it('should resubscribe count number of times', () => {\n    rxTest.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' --a--b--|                ');\n      const subs = [\n        '               ^-------!                ', //\n        '               --------^-------!        ',\n        '               ----------------^-------!',\n      ];\n      const expected = '--a--b----a--b----a--b--|';\n\n      expectObservable(e1.pipe(repeat(3))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(subs);\n    });\n  });\n\n  it('should resubscribe multiple times', () => {\n    rxTest.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' --a--b--|                        ');\n      const subs = [\n        '               ^-------!                        ',\n        '               --------^-------!                ',\n        '               ----------------^-------!        ',\n        '               ------------------------^-------!',\n      ];\n      const expected = '--a--b----a--b----a--b----a--b--|';\n\n      expectObservable(e1.pipe(repeat(2), repeat(2))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(subs);\n    });\n  });\n\n  it('should complete without emit when count is zero', () => {\n    rxTest.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold('--a--b--|');\n      const subs: string[] = [];\n      const expected = '|';\n\n      expectObservable(e1.pipe(repeat(0))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(subs);\n    });\n  });\n\n  it('should emit source once when count is one', () => {\n    rxTest.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' --a--b--|');\n      const subs = '    ^-------!';\n      const expected = '--a--b--|';\n\n      expectObservable(e1.pipe(repeat(1))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(subs);\n    });\n  });\n\n  it('should repeat until gets unsubscribed', () => {\n    rxTest.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' --a--b--|      ');\n      const subs = [\n        '               ^-------!      ', //\n        '               --------^------!',\n      ];\n      const unsub = '   ---------------!';\n      const expected = '--a--b----a--b-';\n\n      expectObservable(e1.pipe(repeat(10)), unsub).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(subs);\n    });\n  });\n\n  it('should be able to repeat indefinitely until unsubscribed', () => {\n    rxTest.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' --a--b--|                                    ');\n      const subs = [\n        '               ^-------!                                    ',\n        '               --------^-------!                            ',\n        '               ----------------^-------!                    ',\n        '               ------------------------^-------!            ',\n        '               --------------------------------^-------!    ',\n        '               ----------------------------------------^---!',\n      ];\n      const unsub = '   --------------------------------------------!';\n      const expected = '--a--b----a--b----a--b----a--b----a--b----a--';\n\n      expectObservable(e1.pipe(repeat()), unsub).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(subs);\n    });\n  });\n\n  it('should not break unsubscription chain when unsubscribed explicitly', () => {\n    rxTest.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' --a--b--|                                    ');\n      const subs = [\n        '               ^-------!                                    ',\n        '               --------^-------!                            ',\n        '               ----------------^-------!                    ',\n        '               ------------------------^-------!            ',\n        '               --------------------------------^-------!    ',\n        '               ----------------------------------------^---!',\n      ];\n      const unsub = '   --------------------------------------------!';\n      const expected = '--a--b----a--b----a--b----a--b----a--b----a--';\n\n      const result = e1.pipe(\n        mergeMap((x: string) => of(x)),\n        repeat(),\n        mergeMap((x: string) => of(x))\n      );\n\n      expectObservable(result, unsub).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(subs);\n    });\n  });\n\n  it('should consider negative count as no repeat, and return EMPTY', () => {\n    rxTest.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold('--a--b--|                                    ');\n      const expected = '|';\n\n      expectObservable(e1.pipe(repeat(-1))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe([]);\n    });\n  });\n\n  it('should always finalization before starting the next cycle', async () => {\n    const results: any[] = [];\n    const source = new Observable<number>((subscriber) => {\n      Promise.resolve().then(() => {\n        subscriber.next(1);\n        Promise.resolve().then(() => {\n          subscriber.next(2);\n          Promise.resolve().then(() => {\n            subscriber.complete();\n          });\n        });\n      });\n      return () => {\n        results.push('finalizer');\n      };\n    });\n\n    await source.pipe(repeat(3)).forEach((value) => results.push(value));\n\n    expect(results).to.deep.equal([1, 2, 'finalizer', 1, 2, 'finalizer', 1, 2, 'finalizer']);\n  });\n\n  it('should always finalize before starting the next cycle, even when synchronous', () => {\n    const results: any[] = [];\n    const source = new Observable<number>((subscriber) => {\n      subscriber.next(1);\n      subscriber.next(2);\n      subscriber.complete();\n      return () => {\n        results.push('finalizer');\n      };\n    });\n    const subscription = source.pipe(repeat(3)).subscribe({\n      next: (value) => results.push(value),\n      complete: () => results.push('complete'),\n    });\n\n    expect(subscription.closed).to.be.true;\n    expect(results).to.deep.equal([1, 2, 'finalizer', 1, 2, 'finalizer', 1, 2, 'complete', 'finalizer']);\n  });\n\n  it('should not complete when source never completes', () => {\n    rxTest.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold('-');\n      const e1subs = '^';\n      const expected = '-';\n\n      expectObservable(e1.pipe(repeat(3))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should not complete when source does not completes', () => {\n    rxTest.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold('-');\n      const unsub = '------------------------------!';\n      const subs = ' ^-----------------------------!';\n      const expected = '-';\n\n      expectObservable(e1.pipe(repeat(3)), unsub).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(subs);\n    });\n  });\n\n  it('should complete immediately when source does not complete without emit but count is zero', () => {\n    rxTest.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold('-');\n      const subs: string[] = [];\n      const expected = '|';\n\n      expectObservable(e1.pipe(repeat(0))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(subs);\n    });\n  });\n\n  it('should complete immediately when source does not complete but count is zero', () => {\n    rxTest.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold('--a--b--');\n      const subs: string[] = [];\n      const expected = '|';\n\n      expectObservable(e1.pipe(repeat(0))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(subs);\n    });\n  });\n\n  it('should emit source once and does not complete when source emits but does not complete', () => {\n    rxTest.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' --a--b--');\n      const subs = ['   ^-------'];\n      const expected = '--a--b--';\n\n      expectObservable(e1.pipe(repeat(3))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(subs);\n    });\n  });\n\n  it('should complete when source is empty', () => {\n    rxTest.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold('|');\n      const e1subs = ['(^!)', '(^!)', '(^!)'];\n      const expected = '|';\n\n      expectObservable(e1.pipe(repeat(3))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should complete when source does not emit', () => {\n    rxTest.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold('----|        ');\n      const subs = [\n        '              ^---!        ', //\n        '              ----^---!    ',\n        '              --------^---!',\n      ];\n      const expected = '------------|';\n\n      expectObservable(e1.pipe(repeat(3))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(subs);\n    });\n  });\n\n  it('should complete immediately when source does not emit but count is zero', () => {\n    rxTest.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold('----|');\n      const subs: string[] = [];\n      const expected = '|';\n\n      expectObservable(e1.pipe(repeat(0))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(subs);\n    });\n  });\n\n  it('should raise error when source raises error', () => {\n    rxTest.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' --a--b--#');\n      const subs = '    ^-------!';\n      const expected = '--a--b--#';\n\n      expectObservable(e1.pipe(repeat(2))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(subs);\n    });\n  });\n\n  it('should raises error if source throws', () => {\n    rxTest.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold('#');\n      const e1subs = '(^!)';\n      const expected = '#';\n\n      expectObservable(e1.pipe(repeat(3))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should raises error if source throws when repeating infinitely', () => {\n    rxTest.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold('#');\n      const e1subs = '(^!)';\n      const expected = '#';\n\n      expectObservable(e1.pipe(repeat())).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should raise error after first emit succeed', () => {\n    rxTest.run(({ cold, expectObservable, expectSubscriptions }) => {\n      let repeated = false;\n\n      const e1 = cold('--a--|').pipe(\n        map((x: string) => {\n          if (repeated) {\n            throw 'error';\n          } else {\n            repeated = true;\n            return x;\n          }\n        })\n      );\n      const expected = '--a----#';\n\n      expectObservable(e1.pipe(repeat(2))).toBe(expected);\n    });\n  });\n\n  it('should repeat a synchronous source (multicasted and refCounted) multiple times', (done) => {\n    const expected = [1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3];\n\n    of(1, 2, 3)\n      .pipe(share({ connector: () => new Subject<number>() }), repeat(5))\n      .subscribe({\n        next: (x: number) => {\n          expect(x).to.equal(expected.shift());\n        },\n        error: (x) => {\n          done(new Error('should not be called'));\n        },\n        complete: () => {\n          expect(expected.length).to.equal(0);\n          done();\n        },\n      });\n  });\n\n  it('should stop listening to a synchronous observable when unsubscribed', () => {\n    const sideEffects: number[] = [];\n    const synchronousObservable = new Observable<number>((subscriber) => {\n      // This will check to see if the subscriber was closed on each loop\n      // when the unsubscribe hits (from the `take`), it should be closed\n      for (let i = 0; !subscriber.closed && i < 10; i++) {\n        sideEffects.push(i);\n        subscriber.next(i);\n      }\n    });\n\n    synchronousObservable.pipe(repeat(), take(3)).subscribe(() => {\n      /* noop */\n    });\n\n    expect(sideEffects).to.deep.equal([0, 1, 2]);\n  });\n\n  it('should allow count configuration', () => {\n    rxTest.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' --a--b--|                ');\n      const subs = [\n        '               ^-------!                ', //\n        '               --------^-------!        ',\n        '               ----------------^-------!',\n      ];\n      const expected = '--a--b----a--b----a--b--|';\n\n      expectObservable(e1.pipe(repeat({ count: 3 }))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(subs);\n    });\n  });\n\n  it('should allow delay time configuration', () => {\n    rxTest.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' --a--b--|                ');\n      const delay = 3; //       ---|       ---|\n      const subs = [\n        '               ^-------!                ', //\n        '               -----------^-------!        ',\n        '               ----------------------^-------!',\n      ];\n      const expected = '--a--b-------a--b-------a--b--|';\n\n      expectObservable(e1.pipe(repeat({ count: 3, delay }))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(subs);\n    });\n  });\n\n  it('should allow delay function configuration', () => {\n    rxTest.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const expectedCounts = [1, 2, 3];\n\n      const e1 = cold(' --a--b--|                ');\n      const delay = 3; //       ---|       ---|\n      const subs = [\n        '               ^-------!                ', //\n        '               -----------^-------!        ',\n        '               ----------------------^-------!',\n      ];\n      const expected = '--a--b-------a--b-------a--b--|';\n\n      expectObservable(\n        e1.pipe(\n          repeat({\n            count: 3,\n            delay: (count) => {\n              expect(count).to.equal(expectedCounts.shift());\n              return timer(delay);\n            },\n          })\n        )\n      ).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(subs);\n    });\n  });\n\n  it('should handle delay function throwing', () => {\n    rxTest.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const expectedCounts = [1, 2, 3];\n\n      const e1 = cold(' --a--b--|                ');\n      const delay = 3; //       ---|       ---|\n      const subs = [\n        '               ^-------!                ', //\n        '               -----------^-------!        ',\n      ];\n      const expected = '--a--b-------a--b--#';\n\n      expectObservable(\n        e1.pipe(\n          repeat({\n            count: 3,\n            delay: (count) => {\n              if (count === 2) {\n                throw 'bad';\n              }\n              return timer(delay);\n            },\n          })\n        )\n      ).toBe(expected, undefined, 'bad');\n      expectSubscriptions(e1.subscriptions).toBe(subs);\n    });\n  });\n});\n"
  },
  {
    "path": "packages/rxjs/spec/operators/repeatWhen-spec.ts",
    "content": "import { expect } from 'chai';\nimport { repeatWhen, map, mergeMap, takeUntil, takeWhile, take } from 'rxjs/operators';\nimport { of, EMPTY, Observable, Subscriber } from 'rxjs';\nimport { TestScheduler } from 'rxjs/testing';\nimport { observableMatcher } from '../helpers/observableMatcher';\n\n/** @test {repeatWhen} */\ndescribe('repeatWhen operator', () => {\n  let testScheduler: TestScheduler;\n\n  beforeEach(() => {\n    testScheduler = new TestScheduler(observableMatcher);\n  });\n\n  it('should handle a source with eventual complete using a hot notifier', () => {\n    testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => {\n      const source = cold('-1--2--|');\n      //                                 -1--2--|\n      //                                              -1--2--|\n      const subs = [\n        '                  ^------!                          ',\n        '                  -------------^------!             ',\n        '                  --------------------------^------!',\n      ];\n      const notifier = hot('-------------r------------r-|    ');\n      const expected = '    -1--2---------1--2---------1--2--|';\n\n      const result = source.pipe(repeatWhen((notifications: any) => notifier));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(source.subscriptions).toBe(subs);\n    });\n  });\n\n  it('should handle a source with eventual complete using a hot notifier that raises error', () => {\n    testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => {\n      const source = cold(' -1--2--|');\n      const subs = [\n        '                   ^------!                      ',\n        '                   -----------^------!           ',\n        '                   -------------------^------!   ',\n      ];\n      const notifier = hot('-----------r-------r---------#');\n      const expected = '    -1--2-------1--2----1--2-----#';\n\n      const result = source.pipe(repeatWhen((notifications: any) => notifier));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(source.subscriptions).toBe(subs);\n    });\n  });\n\n  it('should repeat when notified via returned notifier on complete', (done) => {\n    let retried = false;\n    const expected = [1, 2, 1, 2];\n    let i = 0;\n    try {\n      of(1, 2)\n        .pipe(\n          map((n: number) => {\n            return n;\n          }),\n          repeatWhen((notifications: any) =>\n            notifications.pipe(\n              map((x: any) => {\n                if (retried) {\n                  throw new Error('done');\n                }\n                retried = true;\n                return x;\n              })\n            )\n          )\n        )\n        .subscribe({\n          next: (x: any) => {\n            expect(x).to.equal(expected[i++]);\n          },\n          error: (err: any) => {\n            expect(err).to.be.an('error', 'done');\n            done();\n          },\n        });\n    } catch (err) {\n      done(err);\n    }\n  });\n\n  it('should not repeat when applying an empty notifier', (done) => {\n    const expected = [1, 2];\n    const nexted: number[] = [];\n    of(1, 2)\n      .pipe(\n        map((n: number) => {\n          return n;\n        }),\n        repeatWhen((notifications: any) => EMPTY)\n      )\n      .subscribe({\n        next: (n: number) => {\n          expect(n).to.equal(expected.shift());\n          nexted.push(n);\n        },\n        error: (err: any) => {\n          done(new Error('should not be called'));\n        },\n        complete: () => {\n          expect(nexted).to.deep.equal([1, 2]);\n          done();\n        },\n      });\n  });\n\n  it('should not error when applying an empty synchronous notifier', () => {\n    const errors: any[] = [];\n    // The current Subscriber.prototype.error implementation does nothing for\n    // stopped subscribers. This test was written to fail and expose a problem\n    // with synchronous notifiers. However, by the time the error occurs the\n    // subscriber is stopped, so the test logs errors by both patching the\n    // prototype and by using an error callback (for when/if the do-nothing-if-\n    // stopped behaviour is fixed).\n    const originalSubscribe = Observable.prototype.subscribe;\n    Observable.prototype.subscribe = function (...args: any[]): any {\n      let [subscriber] = args;\n      if (!(subscriber instanceof Subscriber)) {\n        subscriber = new Subscriber(...args);\n      }\n      subscriber.error = function (err: any): void {\n        errors.push(err);\n        Subscriber.prototype.error.call(this, err);\n      };\n      return originalSubscribe.call(this, subscriber);\n    };\n    of(1, 2)\n      .pipe(repeatWhen((notifications: any) => EMPTY))\n      .subscribe({ error: (err) => errors.push(err) });\n    Observable.prototype.subscribe = originalSubscribe;\n    expect(errors).to.deep.equal([]);\n  });\n\n  it('should not error when applying a non-empty synchronous notifier', () => {\n    const errors: any[] = [];\n    // The current Subscriber.prototype.error implementation does nothing for\n    // stopped subscribers. This test was written to fail and expose a problem\n    // with synchronous notifiers. However, by the time the error occurs the\n    // subscriber is stopped, so the test logs errors by both patching the\n    // prototype and by using an error callback (for when/if the do-nothing-if-\n    // stopped behaviour is fixed).\n    const originalSubscribe = Observable.prototype.subscribe;\n    Observable.prototype.subscribe = function (...args: any[]): any {\n      let [subscriber] = args;\n      if (!(subscriber instanceof Subscriber)) {\n        subscriber = new Subscriber(...args);\n      }\n      subscriber.error = function (err: any): void {\n        errors.push(err);\n        Subscriber.prototype.error.call(this, err);\n      };\n      return originalSubscribe.call(this, subscriber);\n    };\n    of(1, 2)\n      .pipe(repeatWhen((notifications: any) => of(1)))\n      .subscribe({ error: (err) => errors.push(err) });\n    Observable.prototype.subscribe = originalSubscribe;\n    expect(errors).to.deep.equal([]);\n  });\n\n  it('should apply an empty notifier on an empty source', () => {\n    testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const source = cold('  |   ');\n      const subs = '         (^!)';\n      const notifier = cold('|   ');\n      const expected = '     |   ';\n\n      const result = source.pipe(repeatWhen((notifications: any) => notifier));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(source.subscriptions).toBe(subs);\n    });\n  });\n\n  it('should apply a never notifier on an empty source', () => {\n    testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const source = cold('  |   ');\n      const subs = '         (^!)';\n      const notifier = cold('-   ');\n      const expected = '     -   ';\n\n      const result = source.pipe(repeatWhen((notifications: any) => notifier));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(source.subscriptions).toBe(subs);\n    });\n  });\n\n  it('should apply an empty notifier on a never source', () => {\n    testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const source = cold('  -                                         ');\n      const unsub = '        -----------------------------------------!';\n      const subs = '         ^----------------------------------------!';\n      const notifier = cold('|                                         ');\n      const expected = '     -                                         ';\n\n      const result = source.pipe(repeatWhen((notifications: any) => notifier));\n\n      expectObservable(result, unsub).toBe(expected);\n      expectSubscriptions(source.subscriptions).toBe(subs);\n    });\n  });\n\n  it('should apply a never notifier on a never source', () => {\n    testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const source = cold('  -                                         ');\n      const unsub = '        -----------------------------------------!';\n      const subs = '         ^----------------------------------------!';\n      const notifier = cold('-                                        ');\n      const expected = '     -                                        ';\n\n      const result = source.pipe(repeatWhen((notifications: any) => notifier));\n\n      expectObservable(result, unsub).toBe(expected);\n      expectSubscriptions(source.subscriptions).toBe(subs);\n    });\n  });\n\n  it('should return an empty observable given a just-throw source and empty notifier', () => {\n    testScheduler.run(({ cold, expectObservable }) => {\n      const source = cold('  #');\n      const notifier = cold('|');\n      const expected = '     #';\n\n      const result = source.pipe(repeatWhen((notifications: any) => notifier));\n\n      expectObservable(result).toBe(expected);\n    });\n  });\n\n  it('should return a error observable given a just-throw source and never notifier', () => {\n    testScheduler.run(({ cold, expectObservable }) => {\n      const source = cold('  #');\n      const notifier = cold('-');\n      const expected = '     #';\n\n      const result = source.pipe(repeatWhen((notifications: any) => notifier));\n\n      expectObservable(result).toBe(expected);\n    });\n  });\n\n  it('should return a never-ending result if the notifier is never', () => {\n    testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const source = cold('  --a--b--c--|                              ');\n      const subs = '         ^----------!                              ';\n      const notifier = cold('           -                              ');\n      const expected = '     --a--b--c---------------------------------';\n\n      const result = source.pipe(repeatWhen((notifications: any) => notifier));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(source.subscriptions).toBe(subs);\n    });\n  });\n\n  it('should propagate error thrown from notifierSelector function', () => {\n    testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const source = cold('--a--b--c--|');\n      const subs = '       ^----------!';\n      const expected = '   --a--b--c--#';\n\n      const result = source.pipe(\n        repeatWhen(<any>(() => {\n          throw 'bad!';\n        }))\n      );\n\n      expectObservable(result).toBe(expected, undefined, 'bad!');\n      expectSubscriptions(source.subscriptions).toBe(subs);\n    });\n  });\n\n  it('should complete if the notifier only completes', () => {\n    testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const source = cold('  --a--b--c--|');\n      const subs = '         ^----------!';\n      const notifier = cold('           |');\n      const expected = '     --a--b--c--|';\n\n      const result = source.pipe(repeatWhen((notifications: any) => notifier));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(source.subscriptions).toBe(subs);\n    });\n  });\n\n  it('should mirror a basic cold source with complete, given a never notifier', () => {\n    testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const source = cold('  --a--b--c--|');\n      const subs = '         ^----------!';\n      const notifier = cold('           |');\n      const expected = '     --a--b--c--|';\n\n      const result = source.pipe(repeatWhen((notifications: any) => notifier));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(source.subscriptions).toBe(subs);\n    });\n  });\n\n  it('should mirror a basic cold source with no termination, given a never notifier', () => {\n    testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const source = cold('  --a--b--c---');\n      const subs = '         ^-----------';\n      const notifier = cold('           |');\n      const expected = '     --a--b--c---';\n\n      const result = source.pipe(repeatWhen((notifications: any) => notifier));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(source.subscriptions).toBe(subs);\n    });\n  });\n\n  it('should mirror a basic hot source with complete, given a never notifier', () => {\n    testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => {\n      const source = hot('-a-^--b--c--|');\n      const subs = '         ^--------!';\n      const notifier = cold('         |');\n      const expected = '     ---b--c--|';\n\n      const result = source.pipe(repeatWhen((notifications: any) => notifier));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(source.subscriptions).toBe(subs);\n    });\n  });\n\n  // https://github.com/ReactiveX/rxjs/issues/6523\n  it.skip('should handle a host source that completes via operator like take, and a hot notifier', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const source = hot('  -1--2--3----4--5---|');\n      // prettier-ignore\n      const ssubs = [\n        '                   ^------!            ',\n        '                   -------------^----! '\n      ];\n      const notifier = hot('--------------r--------r---r--r--r---|');\n      const nsubs = '       -------^-----------!';\n      const expected = '    -1--2----------5---|';\n\n      const result = source.pipe(\n        takeWhile((value) => value !== '3'),\n        repeatWhen(() => notifier)\n      );\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(source.subscriptions).toBe(ssubs);\n      expectSubscriptions(notifier.subscriptions).toBe(nsubs);\n    });\n  });\n\n  it('should tear down resources when result is unsubscribed early', () => {\n    testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => {\n      const source = cold(' -1--2--|');\n      const unsub = '       --------------------!       ';\n      const subs = [\n        '                   ^------!                    ',\n        '                   ---------^------!           ',\n        '                   -----------------^--!       ',\n      ];\n      const notifier = hot('---------r-------r---------#');\n      const nsubs = '       -------^------------!       ';\n      const expected = '    -1--2-----1--2----1--       ';\n\n      const result = source.pipe(repeatWhen((notifications: any) => notifier));\n\n      expectObservable(result, unsub).toBe(expected);\n      expectSubscriptions(source.subscriptions).toBe(subs);\n      expectSubscriptions(notifier.subscriptions).toBe(nsubs);\n    });\n  });\n\n  it('should not break unsubscription chains when unsubscribed explicitly', () => {\n    testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => {\n      const source = cold(' -1--2--|');\n      const subs = [\n        '                   ^------!                    ',\n        '                   ---------^------!           ',\n        '                   -----------------^--!       ',\n      ];\n      const notifier = hot('---------r-------r-------r-#');\n      const nsubs = '       -------^------------!       ';\n      const expected = '    -1--2-----1--2----1--       ';\n      const unsub = '       --------------------!       ';\n\n      const result = source.pipe(\n        mergeMap((x: string) => of(x)),\n        repeatWhen((notifications: any) => notifier),\n        mergeMap((x: string) => of(x))\n      );\n\n      expectObservable(result, unsub).toBe(expected);\n      expectSubscriptions(source.subscriptions).toBe(subs);\n      expectSubscriptions(notifier.subscriptions).toBe(nsubs);\n    });\n  });\n\n  it('should handle a source with eventual error using a dynamic notifier selector which eventually throws', () => {\n    testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const source = cold('-1--2--|');\n      const subs = [\n        '                  ^------!              ',\n        '                  -------^------!       ',\n        '                  --------------^------!',\n      ];\n      const expected = '   -1--2---1--2---1--2--#';\n\n      let invoked = 0;\n      const result = source.pipe(\n        repeatWhen((notifications: any) =>\n          notifications.pipe(\n            map((err: any) => {\n              if (++invoked === 3) {\n                throw 'error';\n              } else {\n                return 'x';\n              }\n            })\n          )\n        )\n      );\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(source.subscriptions).toBe(subs);\n    });\n  });\n\n  it('should handle a source with eventual error using a dynamic notifier selector which eventually completes', () => {\n    testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const source = cold('-1--2--|');\n      const subs = [\n        '                  ^------!              ',\n        '                  -------^------!       ',\n        '                  --------------^------!',\n      ];\n      const expected = '   -1--2---1--2---1--2--|';\n\n      let invoked = 0;\n      const result = source.pipe(\n        repeatWhen((notifications: any) =>\n          notifications.pipe(\n            map(() => 'x'),\n            takeUntil(\n              notifications.pipe(\n                mergeMap(() => {\n                  if (++invoked < 3) {\n                    return EMPTY;\n                  } else {\n                    return of('stop!');\n                  }\n                })\n              )\n            )\n          )\n        )\n      );\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(source.subscriptions).toBe(subs);\n    });\n  });\n\n  it('should always finalize before starting the next cycle, even when synchronous', () => {\n    const results: any[] = [];\n    const source = new Observable<number>((subscriber) => {\n      subscriber.next(1);\n      subscriber.next(2);\n      subscriber.complete();\n      return () => {\n        results.push('finalizer');\n      };\n    });\n    const subscription = source.pipe(repeatWhen((completions$) => completions$.pipe(takeWhile((_, i) => i < 3)))).subscribe({\n      next: (value) => results.push(value),\n      complete: () => results.push('complete'),\n    });\n\n    expect(subscription.closed).to.be.true;\n    expect(results).to.deep.equal([1, 2, 'finalizer', 1, 2, 'finalizer', 1, 2, 'finalizer', 1, 2, 'complete', 'finalizer']);\n  });\n\n  it('should stop listening to a synchronous observable when unsubscribed', () => {\n    const sideEffects: number[] = [];\n    const synchronousObservable = new Observable<number>((subscriber) => {\n      // This will check to see if the subscriber was closed on each loop\n      // when the unsubscribe hits (from the `take`), it should be closed\n      for (let i = 0; !subscriber.closed && i < 10; i++) {\n        sideEffects.push(i);\n        subscriber.next(i);\n      }\n    });\n\n    synchronousObservable\n      .pipe(\n        repeatWhen(() => of(0)),\n        take(3)\n      )\n      .subscribe(() => {\n        /* noop */\n      });\n\n    expect(sideEffects).to.deep.equal([0, 1, 2]);\n  });\n});\n"
  },
  {
    "path": "packages/rxjs/spec/operators/retry-spec.ts",
    "content": "import { expect } from 'chai';\nimport { retry, map, take, mergeMap, concatWith, share } from 'rxjs/operators';\nimport type { Observer} from 'rxjs';\nimport { Observable, defer, range, of, throwError, Subject, timer, EMPTY } from 'rxjs';\nimport { TestScheduler } from 'rxjs/testing';\nimport { observableMatcher } from '../helpers/observableMatcher';\n\n/** @test {retry} */\ndescribe('retry', () => {\n  let rxTest: TestScheduler;\n\n  beforeEach(() => {\n    rxTest = new TestScheduler(observableMatcher);\n  });\n\n  it('should handle a basic source that emits next then errors, count=3', () => {\n    rxTest.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const source = cold('--1-2-3-#');\n      const subs = [\n        '                  ^-------!                ',\n        '                  --------^-------!        ',\n        '                  ----------------^-------!',\n      ];\n      const expected = '   --1-2-3---1-2-3---1-2-3-#';\n\n      const result = source.pipe(retry(2));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(source.subscriptions).toBe(subs);\n    });\n  });\n\n  it('should retry a number of times, without error, then complete', (done) => {\n    let errors = 0;\n    const retries = 2;\n    new Observable((observer: Observer<number>) => {\n      observer.next(42);\n      observer.complete();\n    })\n      .pipe(\n        map((x: any) => {\n          if (++errors < retries) {\n            throw 'bad';\n          }\n          errors = 0;\n          return x;\n        }),\n        retry(retries)\n      )\n      .subscribe({\n        next(x: number) {\n          expect(x).to.equal(42);\n        },\n        error() {\n          expect('this was called').to.be.true;\n        },\n        complete: done,\n      });\n  });\n\n  it('should retry a number of times, then call error handler', (done) => {\n    let errors = 0;\n    const retries = 2;\n    new Observable((observer: Observer<number>) => {\n      observer.next(42);\n      observer.complete();\n    })\n      .pipe(\n        map(() => {\n          errors += 1;\n          throw 'bad';\n        }),\n        retry(retries - 1)\n      )\n      .subscribe({\n        next() {\n          done(\"shouldn't next\");\n        },\n        error() {\n          expect(errors).to.equal(2);\n          done();\n        },\n        complete() {\n          done(\"shouldn't complete\");\n        },\n      });\n  });\n\n  it('should retry a number of times, then call error handler (with resetOnSuccess)', (done) => {\n    let errors = 0;\n    const retries = 2;\n    new Observable((observer: Observer<number>) => {\n      observer.next(42);\n      observer.complete();\n    })\n      .pipe(\n        map(() => {\n          errors += 1;\n          throw 'bad';\n        }),\n        retry({ count: retries - 1, resetOnSuccess: true })\n      )\n      .subscribe({\n        next() {\n          done(\"shouldn't next\");\n        },\n        error() {\n          expect(errors).to.equal(2);\n          done();\n        },\n        complete() {\n          done(\"shouldn't complete\");\n        },\n      });\n  });\n\n  it('should retry a number of times, then call next handler without error, then retry and complete', (done) => {\n    let index = 0;\n    let errors = 0;\n    const retries = 2;\n    defer(() => range(0, 4 - index))\n      .pipe(\n        mergeMap(() => {\n          index++;\n          if (index === 1 || index === 3) {\n            errors++;\n            return throwError(() => 'bad');\n          } else {\n            return of(42);\n          }\n        }),\n        retry({ count: retries - 1, resetOnSuccess: true })\n      )\n      .subscribe({\n        next(x: number) {\n          expect(x).to.equal(42);\n        },\n        error() {\n          done(\"shouldn't error\");\n        },\n        complete() {\n          expect(errors).to.equal(retries);\n          done();\n        },\n      });\n  });\n\n  it('should always finalize before starting the next cycle, even when synchronous', () => {\n    const results: any[] = [];\n    const source = new Observable<number>((subscriber) => {\n      subscriber.next(1);\n      subscriber.next(2);\n      subscriber.error('bad');\n      return () => {\n        results.push('finalizer');\n      };\n    });\n    const subscription = source.pipe(retry(3)).subscribe({\n      next: (value) => results.push(value),\n      error: (err) => results.push(err),\n    });\n\n    expect(subscription.closed).to.be.true;\n    expect(results).to.deep.equal([1, 2, 'finalizer', 1, 2, 'finalizer', 1, 2, 'finalizer', 1, 2, 'bad', 'finalizer']);\n  });\n\n  it('should retry a number of times, then call next handler without error, then retry and error', (done) => {\n    let index = 0;\n    let errors = 0;\n    const retries = 2;\n    defer(() => range(0, 4 - index))\n      .pipe(\n        mergeMap(() => {\n          index++;\n          if (index === 1 || index === 3) {\n            errors++;\n            return throwError(() => 'bad');\n          } else {\n            return of(42);\n          }\n        }),\n        retry({ count: retries - 1, resetOnSuccess: false })\n      )\n      .subscribe({\n        next(x: number) {\n          expect(x).to.equal(42);\n        },\n        error() {\n          expect(errors).to.equal(retries);\n          done();\n        },\n        complete() {\n          done(\"shouldn't complete\");\n        },\n      });\n  });\n\n  it('should retry until successful completion', (done) => {\n    let errors = 0;\n    const retries = 10;\n    new Observable((observer: Observer<number>) => {\n      observer.next(42);\n      observer.complete();\n    })\n      .pipe(\n        map((x: any) => {\n          if (++errors < retries) {\n            throw 'bad';\n          }\n          errors = 0;\n          return x;\n        }),\n        retry(),\n        take(retries)\n      )\n      .subscribe({\n        next(x: number) {\n          expect(x).to.equal(42);\n        },\n        error() {\n          expect('this was called').to.be.true;\n        },\n        complete: done,\n      });\n  });\n\n  it('should handle an empty source', () => {\n    rxTest.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const source = cold('|  ');\n      const subs = '      (^!)';\n      const expected = '   |  ';\n\n      const result = source.pipe(retry());\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(source.subscriptions).toBe(subs);\n    });\n  });\n\n  it('should handle a never source', () => {\n    rxTest.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const source = cold('-');\n      const subs = '       ^';\n      const expected = '   -';\n\n      const result = source.pipe(retry());\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(source.subscriptions).toBe(subs);\n    });\n  });\n\n  it('should return a never observable given an async just-throw source and no count', () => {\n    rxTest.run(({ cold, expectObservable }) => {\n      const source = cold('-#                                    '); // important that it's not a sync error\n      const unsub = '     -------------------------------------!';\n      const expected = '  --------------------------------------';\n\n      const result = source.pipe(retry());\n\n      expectObservable(result, unsub).toBe(expected);\n    });\n  });\n\n  it('should handle a basic source that emits next then completes', () => {\n    rxTest.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const source = hot('--1--2--^--3--4--5---|');\n      const subs = '              ^------------!';\n      const expected = '          ---3--4--5---|';\n\n      const result = source.pipe(retry());\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(source.subscriptions).toBe(subs);\n    });\n  });\n\n  it('should handle a basic source that emits next but does not complete', () => {\n    rxTest.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const source = hot('--1--2--^--3--4--5---');\n      const subs = '              ^------------';\n      const expected = '          ---3--4--5---';\n\n      const result = source.pipe(retry());\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(source.subscriptions).toBe(subs);\n    });\n  });\n\n  it('should handle a basic source that emits next then errors, no count', () => {\n    rxTest.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const source = cold('--1-2-3-#                             ');\n      //                           --1-2-3-#\n      //                                   --1-2-3-#\n      //                                           --1-2-3-#\n      //                                                   --1-2-3-#\n      const unsub = '      -------------------------------------!';\n      const subs = [\n        '                  ^-------!                             ',\n        '                  --------^-------!                     ',\n        '                  ----------------^-------!             ',\n        '                  ------------------------^-------!     ',\n        '                  --------------------------------^----!',\n      ];\n      const expected = '   --1-2-3---1-2-3---1-2-3---1-2-3---1-2-';\n\n      const result = source.pipe(retry());\n\n      expectObservable(result, unsub).toBe(expected);\n      expectSubscriptions(source.subscriptions).toBe(subs);\n    });\n  });\n\n  it('should handle a source which eventually throws, count=3, and result is unsubscribed early', () => {\n    rxTest.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const source = cold('--1-2-3-#     ');\n      //                           --1-2-3-#\n      const unsub = '      -------------!';\n      // prettier-ignore\n      const subs = [\n        '                  ^-------!     ',\n        '                  --------^----!',\n      ];\n      const expected = '   --1-2-3---1-2-';\n\n      const result = source.pipe(retry(3));\n\n      expectObservable(result, unsub).toBe(expected);\n      expectSubscriptions(source.subscriptions).toBe(subs);\n    });\n  });\n\n  it('should not break unsubscription chain when unsubscribed explicitly', () => {\n    rxTest.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const source = cold('--1-2-3-#     ');\n      //                           --1-2-3-#\n      // prettier-ignore\n      const subs = [\n        '                  ^-------!     ',\n        '                  --------^----!',\n      ];\n      const expected = '   --1-2-3---1-2-';\n      const unsub = '      -------------!';\n\n      const result = source.pipe(\n        mergeMap((x: string) => of(x)),\n        retry(100),\n        mergeMap((x: string) => of(x))\n      );\n\n      expectObservable(result, unsub).toBe(expected);\n      expectSubscriptions(source.subscriptions).toBe(subs);\n    });\n  });\n\n  it('should retry a synchronous source (multicasted and refCounted) multiple times', (done) => {\n    const expected = [1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3];\n\n    of(1, 2, 3)\n      .pipe(concatWith(throwError(() => 'bad!')), share({ connector: () => new Subject<number>() }), retry(4))\n      .subscribe({\n        next(x: number) {\n          expect(x).to.equal(expected.shift());\n        },\n        error(err: any) {\n          expect(err).to.equal('bad!');\n          expect(expected.length).to.equal(0);\n          done();\n        },\n        complete() {\n          done(new Error('should not be called'));\n        },\n      });\n  });\n\n  it('should stop listening to a synchronous observable when unsubscribed', () => {\n    const sideEffects: number[] = [];\n    const synchronousObservable = new Observable<number>((subscriber) => {\n      // This will check to see if the subscriber was closed on each loop\n      // when the unsubscribe hits (from the `take`), it should be closed\n      for (let i = 0; !subscriber.closed && i < 10; i++) {\n        sideEffects.push(i);\n        subscriber.next(i);\n      }\n    });\n\n    synchronousObservable.pipe(retry(1), take(3)).subscribe(() => {\n      /* noop */\n    });\n\n    expect(sideEffects).to.deep.equal([0, 1, 2]);\n  });\n\n  it('should not alter the source when the number of retries is smaller than 1', () => {\n    rxTest.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const source = cold('--1-2-3-# ');\n      const subs = ['      ^-------! '];\n\n      const expected = '   --1-2-3-# ';\n      const unsub = '      ---------!';\n\n      const result = source.pipe(retry(0));\n\n      expectObservable(result, unsub).toBe(expected);\n      expectSubscriptions(source.subscriptions).toBe(subs);\n    });\n  });\n\n  describe('with delay config', () => {\n    describe('of a number', () => {\n      it('should delay the retry by a specified amount of time', () => {\n        rxTest.run(({ cold, time, expectSubscriptions, expectObservable }) => {\n          const source = cold('---a---b---#');\n          const t = time('                ----|');\n          const subs = [\n            //\n            '                  ^----------!',\n            '                  ---------------^----------!',\n            '                  ------------------------------^----------!',\n            '                  ---------------------------------------------^----!',\n          ];\n          const unsub = '      ^-------------------------------------------------!';\n          const expected = '   ---a---b----------a---b----------a---b----------a--';\n          const result = source.pipe(\n            retry({\n              delay: t,\n            })\n          );\n          expectObservable(result, unsub).toBe(expected);\n          expectSubscriptions(source.subscriptions).toBe(subs);\n        });\n      });\n\n      it('should act like a normal retry if delay is set to 0', () => {\n        rxTest.run(({ cold, expectSubscriptions, expectObservable }) => {\n          const source = cold('---a---b---#');\n          const subs = [\n            //\n            '                  ^----------!',\n            '                  -----------^----------!',\n            '                  ----------------------^----------!',\n            '                  ---------------------------------^----!',\n          ];\n          const unsub = '      ^-------------------------------------!';\n          const expected = '   ---a---b------a---b------a---b------a--';\n          const result = source.pipe(\n            retry({\n              delay: 0,\n            })\n          );\n          expectObservable(result, unsub).toBe(expected);\n          expectSubscriptions(source.subscriptions).toBe(subs);\n        });\n      });\n\n      it('should act like a normal retry if delay is less than 0', () => {\n        rxTest.run(({ cold, expectSubscriptions, expectObservable }) => {\n          const source = cold('---a---b---#');\n          const subs = [\n            //\n            '                  ^----------!',\n            '                  -----------^----------!',\n            '                  ----------------------^----------!',\n            '                  ---------------------------------^----!',\n          ];\n          const unsub = '      ^-------------------------------------!';\n          const expected = '   ---a---b------a---b------a---b------a--';\n          const result = source.pipe(\n            retry({\n              delay: -100,\n            })\n          );\n          expectObservable(result, unsub).toBe(expected);\n          expectSubscriptions(source.subscriptions).toBe(subs);\n        });\n      });\n\n      it('should honor count as the max retries', () => {\n        rxTest.run(({ cold, time, expectSubscriptions, expectObservable }) => {\n          const source = cold('---a---b---#');\n          const t = time('                ----|');\n          const subs = [\n            //\n            '                  ^----------!',\n            '                  ---------------^----------!',\n            '                  ------------------------------^----------!',\n          ];\n          const expected = '   ---a---b----------a---b----------a---b---#';\n          const result = source.pipe(\n            retry({\n              count: 2,\n              delay: t,\n            })\n          );\n          expectObservable(result).toBe(expected);\n          expectSubscriptions(source.subscriptions).toBe(subs);\n        });\n      });\n    });\n\n    describe('of a function', () => {\n      it('should delay the retry with a function that returns a notifier', () => {\n        rxTest.run(({ cold, expectSubscriptions, expectObservable }) => {\n          const source = cold('---a---b---#');\n          const subs = [\n            //\n            '                  ^----------!',\n            '                  ------------^----------!',\n            '                  -------------------------^----------!',\n            '                  ---------------------------------------^----!',\n          ];\n          const unsub = '      ^-------------------------------------------!';\n          const expected = '   ---a---b-------a---b--------a---b---------a--';\n          const result = source.pipe(\n            retry({\n              delay: (_err, retryCount) => {\n                // retryCount will be 1, 2, 3, etc.\n                return timer(retryCount);\n              },\n            })\n          );\n          expectObservable(result, unsub).toBe(expected);\n          expectSubscriptions(source.subscriptions).toBe(subs);\n        });\n      });\n\n      it('should delay the retry with a function that returns a hot observable', () => {\n        rxTest.run(({ cold, hot, expectSubscriptions, expectObservable }) => {\n          const source = cold(' ---a---b---#');\n          const notifier = hot('--------------x----------------x----------------x------');\n          const subs = [\n            //\n            '                   ^----------!',\n            '                   --------------^----------!',\n            '                   -------------------------------^----------!',\n          ];\n          const notifierSubs = [\n            //\n            '                   -----------^--!',\n            '                   -------------------------^-----!',\n            '                   ------------------------------------------^-!',\n          ];\n          const unsub = '       ^-------------------------------------------!';\n          const expected = '    ---a---b---------a---b------------a---b------';\n          const result = source.pipe(\n            retry({\n              delay: () => notifier,\n            })\n          );\n          expectObservable(result, unsub).toBe(expected);\n          expectSubscriptions(source.subscriptions).toBe(subs);\n          expectSubscriptions(notifier.subscriptions).toBe(notifierSubs);\n        });\n      });\n\n      it('should complete if the notifier completes', () => {\n        rxTest.run(({ cold, expectSubscriptions, expectObservable }) => {\n          const source = cold('---a---b---#');\n          const subs = [\n            //\n            '                  ^----------!',\n            '                  ------------^----------!',\n            '                  -------------------------^----------!',\n            '                  ------------------------------------!',\n          ];\n          const expected = '   ---a---b-------a---b--------a---b---|';\n          const result = source.pipe(\n            retry({\n              delay: (_err, retryCount) => {\n                return retryCount <= 2 ? timer(retryCount) : EMPTY;\n              },\n            })\n          );\n          expectObservable(result).toBe(expected);\n          expectSubscriptions(source.subscriptions).toBe(subs);\n        });\n      });\n\n      it('should error if the notifier errors', () => {\n        rxTest.run(({ cold, expectSubscriptions, expectObservable }) => {\n          const source = cold('---a---b---#');\n          const subs = [\n            //\n            '                  ^----------!',\n            '                  ------------^----------!',\n            '                  -------------------------^----------!',\n            '                  ------------------------------------!',\n          ];\n          const expected = '   ---a---b-------a---b--------a---b---#';\n          const result = source.pipe(\n            retry({\n              delay: (_err, retryCount) => {\n                return retryCount <= 2 ? timer(retryCount) : throwError(() => new Error('blah'));\n              },\n            })\n          );\n          expectObservable(result).toBe(expected, undefined, new Error('blah'));\n          expectSubscriptions(source.subscriptions).toBe(subs);\n        });\n      });\n\n      it('should error if the delay function throws', () => {\n        rxTest.run(({ cold, expectSubscriptions, expectObservable }) => {\n          const source = cold('---a---b---#');\n          const subs = [\n            //\n            '                  ^----------!',\n            '                  ------------^----------!',\n            '                  -------------------------^----------!',\n            '                  ------------------------------------!',\n          ];\n          const expected = '   ---a---b-------a---b--------a---b---#';\n          const result = source.pipe(\n            retry({\n              delay: (_err, retryCount) => {\n                if (retryCount <= 2) {\n                  return timer(retryCount);\n                } else {\n                  throw new Error('blah');\n                }\n              },\n            })\n          );\n          expectObservable(result).toBe(expected, undefined, new Error('blah'));\n          expectSubscriptions(source.subscriptions).toBe(subs);\n        });\n      });\n\n      it('should be usable for exponential backoff', () => {\n        rxTest.run(({ cold, expectObservable, expectSubscriptions }) => {\n          const source = cold('---a---#');\n          const subs = [\n            //\n            '                  ^------!',\n            '                  ---------^------!',\n            '                  --------------------^------!',\n            '                  -----------------------------------^------!',\n          ];\n          const expected = '   ---a--------a----------a--------------a---#';\n          const result = source.pipe(\n            retry({\n              count: 3,\n              delay: (_err, retryCount) => timer(2 ** retryCount),\n            })\n          );\n          expectObservable(result).toBe(expected);\n          expectSubscriptions(source.subscriptions).toBe(subs);\n        });\n      });\n    });\n  });\n});\n"
  },
  {
    "path": "packages/rxjs/spec/operators/retryWhen-spec.ts",
    "content": "import { expect } from 'chai';\nimport { retryWhen, map, mergeMap, takeUntil, take } from 'rxjs/operators';\nimport { of, EMPTY, Observable, throwError } from 'rxjs';\nimport { TestScheduler } from 'rxjs/testing';\nimport { observableMatcher } from '../helpers/observableMatcher';\n\n/** @test {retryWhen} */\ndescribe('retryWhen', () => {\n  let rxTest: TestScheduler;\n\n  beforeEach(() => {\n    rxTest = new TestScheduler(observableMatcher);\n  });\n\n  it('should handle a source with eventual error using a hot notifier', () => {\n    rxTest.run(({ cold, hot, expectObservable, expectSubscriptions }) => {\n      const source = cold(' -1--2--#                     ');\n      //                                 -1--2--#\n      //                                              -1--2--#\n      const subs = [\n        '                   ^------!                     ',\n        '                   -------------^------!        ',\n        '                   --------------------------^-!',\n      ];\n      const notifier = hot('-------------r------------r-|');\n      const expected = '    -1--2---------1--2---------1|';\n\n      const result = source.pipe(retryWhen(() => notifier));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(source.subscriptions).toBe(subs);\n    });\n  });\n\n  it('should handle a source with eventual error using a hot notifier that raises error', () => {\n    rxTest.run(({ cold, hot, expectObservable, expectSubscriptions }) => {\n      const source = cold(' -1--2--#                      ');\n      //                               -1--2--#\n      //                                       -1--2--#\n      const subs = [\n        '                   ^------!                      ',\n        '                   -----------^------!           ',\n        '                   -------------------^------!   ',\n      ];\n      const notifier = hot('-----------r-------r---------#');\n      const expected = '    -1--2-------1--2----1--2-----#';\n\n      const result = source.pipe(retryWhen(() => notifier));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(source.subscriptions).toBe(subs);\n    });\n  });\n\n  it('should retry when notified via returned notifier on thrown error', (done) => {\n    let retried = false;\n    const expected = [1, 2, 1, 2];\n    let i = 0;\n    of(1, 2, 3)\n      .pipe(\n        map((n: number) => {\n          if (n === 3) {\n            throw 'bad';\n          }\n          return n;\n        }),\n        retryWhen((errors: any) =>\n          errors.pipe(\n            map((x: any) => {\n              expect(x).to.equal('bad');\n              if (retried) {\n                throw new Error('done');\n              }\n              retried = true;\n              return x;\n            })\n          )\n        )\n      )\n      .subscribe({\n        next(x: any) {\n          expect(x).to.equal(expected[i++]);\n        },\n        error(err: any) {\n          expect(err).to.be.an('error', 'done');\n          done();\n        },\n      });\n  });\n\n  it('should retry when notified and complete on returned completion', (done) => {\n    const expected = [1, 2, 1, 2];\n    of(1, 2, 3)\n      .pipe(\n        map((n: number) => {\n          if (n === 3) {\n            throw 'bad';\n          }\n          return n;\n        }),\n        retryWhen(() => EMPTY)\n      )\n      .subscribe({\n        next(n: number) {\n          expect(n).to.equal(expected.shift());\n        },\n        error() {\n          done(new Error('should not be called'));\n        },\n        complete() {\n          done();\n        },\n      });\n  });\n\n  it('should apply an empty notifier on an empty source', () => {\n    rxTest.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const source = cold('  |   ');\n      const subs = '         (^!)';\n      const notifier = cold('|   ');\n      const expected = '     |   ';\n\n      const result = source.pipe(retryWhen(() => notifier));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(source.subscriptions).toBe(subs);\n    });\n  });\n\n  it('should apply a never notifier on an empty source', () => {\n    rxTest.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const source = cold('  |   ');\n      const subs = '         (^!)';\n      const notifier = cold('-   ');\n      const expected = '     |   ';\n\n      const result = source.pipe(retryWhen(() => notifier));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(source.subscriptions).toBe(subs);\n    });\n  });\n\n  it('should apply an empty notifier on a never source', () => {\n    rxTest.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const source = cold('  ------------------------------------------');\n      const unsub = '        -----------------------------------------!';\n      const subs = '         ^----------------------------------------!';\n      const notifier = cold('|                                         ');\n      const expected = '     ------------------------------------------';\n\n      const result = source.pipe(retryWhen(() => notifier));\n\n      expectObservable(result, unsub).toBe(expected);\n      expectSubscriptions(source.subscriptions).toBe(subs);\n    });\n  });\n\n  it('should apply a never notifier on a never source', () => {\n    rxTest.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const source = cold('  -----------------------------------------');\n      const unsub = '        -----------------------------------------!';\n      const subs = '         ^----------------------------------------!';\n      const notifier = cold('------------------------------------------');\n      const expected = '     -----------------------------------------';\n\n      const result = source.pipe(retryWhen(() => notifier));\n\n      expectObservable(result, unsub).toBe(expected);\n      expectSubscriptions(source.subscriptions).toBe(subs);\n    });\n  });\n\n  it('should return an empty observable given a just-throw source and empty notifier', () => {\n    rxTest.run(({ cold, expectObservable }) => {\n      const source = cold('  #');\n      const notifier = cold('|');\n      const expected = '     |';\n\n      const result = source.pipe(retryWhen(() => notifier));\n\n      expectObservable(result).toBe(expected);\n    });\n  });\n\n  it('should return a never observable given a just-throw source and never notifier', () => {\n    rxTest.run(({ cold, expectObservable }) => {\n      const source = cold('  #');\n      const notifier = cold('-');\n      const expected = '     -';\n\n      const result = source.pipe(retryWhen(() => notifier));\n\n      expectObservable(result).toBe(expected);\n    });\n  });\n\n  it('should hide errors using a never notifier on a source with eventual error', () => {\n    rxTest.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const source = cold('  --a--b--c--#                              ');\n      const subs = '         ^----------!                              ';\n      const notifier = cold('           -------------------------------');\n      const expected = '     --a--b--c---------------------------------';\n\n      const result = source.pipe(retryWhen(() => notifier));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(source.subscriptions).toBe(subs);\n    });\n  });\n\n  it('should propagate error thrown from notifierSelector function', () => {\n    rxTest.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const source = cold('--a--b--c--#');\n      const subs = '       ^----------!';\n      const expected = '   --a--b--c--#';\n\n      const result = source.pipe(\n        retryWhen(() => {\n          throw 'bad!';\n        })\n      );\n\n      expectObservable(result).toBe(expected, undefined, 'bad!');\n      expectSubscriptions(source.subscriptions).toBe(subs);\n    });\n  });\n\n  it('should replace error with complete using an empty notifier on a source with eventual error', () => {\n    rxTest.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const source = cold('  --a--b--c--#');\n      const subs = '         ^----------!';\n      const notifier = cold('           |');\n      const expected = '     --a--b--c--|';\n\n      const result = source.pipe(retryWhen(() => notifier));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(source.subscriptions).toBe(subs);\n    });\n  });\n\n  it('should mirror a basic cold source with complete, given an empty notifier', () => {\n    rxTest.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const source = cold('  --a--b--c--|');\n      const subs = '         ^----------!';\n      const notifier = cold('           |');\n      const expected = '     --a--b--c--|';\n\n      const result = source.pipe(retryWhen(() => notifier));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(source.subscriptions).toBe(subs);\n    });\n  });\n\n  it('should mirror a basic cold source with no termination, given an empty notifier', () => {\n    rxTest.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const source = cold('  --a--b--c---');\n      const subs = '         ^-----------';\n      const notifier = cold('           |');\n      const expected = '     --a--b--c---';\n\n      const result = source.pipe(retryWhen(() => notifier));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(source.subscriptions).toBe(subs);\n    });\n  });\n\n  it('should mirror a basic hot source with complete, given an empty notifier', () => {\n    rxTest.run(({ cold, hot, expectObservable, expectSubscriptions }) => {\n      const source = hot('-a-^--b--c--|');\n      const subs = '         ^--------!';\n      const notifier = cold('         |');\n      const expected = '     ---b--c--|';\n\n      const result = source.pipe(retryWhen(() => notifier));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(source.subscriptions).toBe(subs);\n    });\n  });\n\n  it('should handle a hot source that raises error but eventually completes', () => {\n    rxTest.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const source = hot('  -1--2--3----4--5---|                  ');\n      const ssubs = [\n        '                   ^------!                              ',\n        '                   --------------^----!                  ',\n      ];\n      const notifier = hot('--------------r--------r---r--r--r---|');\n      const nsubs = '       -------^-----------!                  ';\n      const expected = '    -1--2----------5---|                  ';\n\n      const result = source.pipe(\n        map((x: string) => {\n          if (x === '3') {\n            throw 'error';\n          }\n          return x;\n        }),\n        retryWhen(() => notifier)\n      );\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(source.subscriptions).toBe(ssubs);\n      expectSubscriptions(notifier.subscriptions).toBe(nsubs);\n    });\n  });\n\n  it('should tear down resources when result is unsubscribed early', () => {\n    rxTest.run(({ hot, cold, expectObservable, expectSubscriptions }) => {\n      const source = cold(' -1--2--#                    ');\n      //                             -1--2--#\n      //                                     -1--2--#\n      const unsub = '       --------------------!       ';\n      const subs = [\n        '                   ^------!                    ',\n        '                   ---------^------!           ',\n        '                   -----------------^--!       ',\n      ];\n      const notifier = hot('---------r-------r---------#');\n      const nsubs = '       -------^------------!       ';\n      const expected = '    -1--2-----1--2----1--       ';\n\n      const result = source.pipe(retryWhen(() => notifier));\n\n      expectObservable(result, unsub).toBe(expected);\n      expectSubscriptions(source.subscriptions).toBe(subs);\n      expectSubscriptions(notifier.subscriptions).toBe(nsubs);\n    });\n  });\n\n  it('should not break unsubscription chains when unsubscribed explicitly', () => {\n    rxTest.run(({ hot, cold, expectObservable, expectSubscriptions }) => {\n      const source = cold(' -1--2--#                    ');\n      //                             -1--2--#\n      //                                     -1--2--#\n      const subs = [\n        '                   ^------!                    ',\n        '                   ---------^------!           ',\n        '                   -----------------^--!       ',\n      ];\n      const notifier = hot('---------r-------r-------r-#');\n      const nsubs = '       -------^------------!       ';\n      const expected = '    -1--2-----1--2----1--       ';\n      const unsub = '       --------------------!       ';\n\n      const result = source.pipe(\n        mergeMap((x: string) => of(x)),\n        retryWhen(() => notifier),\n        mergeMap((x: string) => of(x))\n      );\n\n      expectObservable(result, unsub).toBe(expected);\n      expectSubscriptions(source.subscriptions).toBe(subs);\n      expectSubscriptions(notifier.subscriptions).toBe(nsubs);\n    });\n  });\n\n  it('should handle a source with eventual error using a dynamic notifier selector which eventually throws', () => {\n    rxTest.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const source = cold('-1--2--#              ');\n      //                          -1--2--#\n      //                                 -1--2--#\n      const subs = [\n        '                  ^------!              ',\n        '                  -------^------!       ',\n        '                  --------------^------!',\n      ];\n      const expected = '   -1--2---1--2---1--2--#';\n\n      let invoked = 0;\n      const result = source.pipe(\n        retryWhen((errors: any) =>\n          errors.pipe(\n            map(() => {\n              if (++invoked === 3) {\n                throw 'error';\n              } else {\n                return 'x';\n              }\n            })\n          )\n        )\n      );\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(source.subscriptions).toBe(subs);\n    });\n  });\n\n  it('should handle a source with eventual error using a dynamic notifier selector which eventually completes', () => {\n    rxTest.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const source = cold('-1--2--#              ');\n      //                          -1--2--#\n      //                                 -1--2--#\n      const subs = [\n        '                  ^------!              ',\n        '                  -------^------!       ',\n        '                  --------------^------!',\n      ];\n      const expected = '   -1--2---1--2---1--2--|';\n\n      let invoked = 0;\n      const result = source.pipe(\n        retryWhen((errors: any) =>\n          errors.pipe(\n            map(() => 'x'),\n            takeUntil(\n              errors.pipe(\n                mergeMap(() => {\n                  if (++invoked < 3) {\n                    return EMPTY;\n                  } else {\n                    return of('stop!');\n                  }\n                })\n              )\n            )\n          )\n        )\n      );\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(source.subscriptions).toBe(subs);\n    });\n  });\n\n  it('should always finalize before starting the next cycle, even when synchronous', () => {\n    const results: any[] = [];\n    const source = new Observable<number>((subscriber) => {\n      subscriber.next(1);\n      subscriber.next(2);\n      subscriber.error('bad');\n      return () => {\n        results.push('finalizer');\n      };\n    });\n    const subscription = source\n      .pipe(retryWhen((errors$) => errors$.pipe(mergeMap((err, i) => (i < 3 ? of(true) : throwError(() => err))))))\n      .subscribe({\n        next: (value) => results.push(value),\n        error: (err) => results.push(err),\n      });\n\n    expect(subscription.closed).to.be.true;\n    expect(results).to.deep.equal([1, 2, 'finalizer', 1, 2, 'finalizer', 1, 2, 'finalizer', 1, 2, 'bad', 'finalizer']);\n  });\n\n  it('should stop listening to a synchronous observable when unsubscribed', () => {\n    const sideEffects: number[] = [];\n    const synchronousObservable = new Observable<number>((subscriber) => {\n      // This will check to see if the subscriber was closed on each loop\n      // when the unsubscribe hits (from the `take`), it should be closed\n      for (let i = 0; !subscriber.closed && i < 10; i++) {\n        sideEffects.push(i);\n        subscriber.next(i);\n      }\n    });\n\n    synchronousObservable\n      .pipe(\n        retryWhen(() => of(0)),\n        take(3)\n      )\n      .subscribe(() => {\n        /* noop */\n      });\n\n    expect(sideEffects).to.deep.equal([0, 1, 2]);\n  });\n});\n"
  },
  {
    "path": "packages/rxjs/spec/operators/sample-spec.ts",
    "content": "import { expect } from 'chai';\nimport { sample, mergeMap } from 'rxjs/operators';\nimport { Subject, of } from 'rxjs';\nimport { TestScheduler } from 'rxjs/testing';\nimport { observableMatcher } from '../helpers/observableMatcher';\n\n/** @test {sample} */\ndescribe('sample', () => {\n  let rxTest: TestScheduler;\n\n  beforeEach(() => {\n    rxTest = new TestScheduler(observableMatcher);\n  });\n\n  it('should get samples when the notifier emits', () => {\n    rxTest.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  ---a----b---c----------d-----|   ');\n      const e1subs = '  ^----------------------------!   ';\n      const e2 = hot('  -----x----------x---x------x---| ');\n      const e2subs = '  ^----------------------------!   ';\n      const expected = '-----a----------c----------d-|   ';\n\n      expectObservable(e1.pipe(sample(e2))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should sample nothing if source has not nexted at all', () => {\n    rxTest.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('----a-^------------|');\n      const e1subs = '      ^------------!';\n      const e2 = hot('      -----x-------|');\n      const e2subs = '      ^------------!';\n      const expected = '    -------------|';\n\n      expectObservable(e1.pipe(sample(e2))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should behave properly when notified by the same observable as the source (issue #2075)', () => {\n    const item$ = new Subject<number>();\n    const results: number[] = [];\n\n    item$.pipe(sample(item$)).subscribe((value) => results.push(value));\n\n    item$.next(1);\n    item$.next(2);\n    item$.next(3);\n\n    expect(results).to.deep.equal([1, 2, 3]);\n  });\n\n  it('should sample nothing if source has nexted after all notifications, but notifier does not complete', () => {\n    rxTest.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  ----a-^------b-----|');\n      const e1subs = '        ^------------!';\n      const e2 = hot('        -----x--------');\n      const e2subs = '        ^------------!';\n      const expected = '      -------------|';\n\n      expectObservable(e1.pipe(sample(e2))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should not sample when the notifier completes', () => {\n    rxTest.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  ----a-^------b----------|');\n      const e1subs = '        ^-----------------!';\n      const e2 = hot('        -----x-----|       ');\n      const e2subs = '        ^----------!       ';\n      const expected = '      ------------------|';\n\n      expectObservable(e1.pipe(sample(e2))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should not complete when the notifier completes, nor should it emit', () => {\n    rxTest.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  ----a----b----c----d----e----f----');\n      const e1subs = '  ^---------------------------------';\n      const e2 = hot('  ------x-|                         ');\n      const e2subs = '  ^-------!                         ';\n      const expected = '------a---------------------------';\n\n      expectObservable(e1.pipe(sample(e2))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should complete only when the source completes, if notifier completes early', () => {\n    rxTest.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  ----a----b----c----d----e----f---|');\n      const e1subs = '  ^--------------------------------!';\n      const e2 = hot('  ------x-|                         ');\n      const e2subs = '  ^-------!                         ';\n      const expected = '------a--------------------------|';\n\n      expectObservable(e1.pipe(sample(e2))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should allow unsubscribing explicitly and early', () => {\n    rxTest.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  ----a-^--b----c----d----e----f----|          ');\n      const unsub = '         --------------!                        ';\n      const e1subs = '        ^-------------!                        ';\n      const e2 = hot('        -----x----------x----------x----------|');\n      const e2subs = '        ^-------------!                        ';\n      const expected = '      -----b---------                        ';\n\n      expectObservable(e1.pipe(sample(e2)), unsub).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should not break unsubscription chains when result is unsubscribed explicitly', () => {\n    rxTest.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  ----a-^--b----c----d----e----f----|          ');\n      const e1subs = '        ^-------------!                        ';\n      const e2 = hot('        -----x----------x----------x----------|');\n      const e2subs = '        ^-------------!                        ';\n      const expected = '      -----b---------                        ';\n      const unsub = '         --------------!                        ';\n\n      const result = e1.pipe(\n        mergeMap((x: string) => of(x)),\n        sample(e2),\n        mergeMap((x: string) => of(x))\n      );\n\n      expectObservable(result, unsub).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should only sample when a new value arrives, even if it is the same value', () => {\n    rxTest.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  ----a----b----c----c----e----f----|  ');\n      const e1subs = '  ^---------------------------------!  ';\n      const e2 = hot('  ------x-x------xx-x---x----x--------|');\n      const e2subs = '  ^---------------------------------!  ';\n      const expected = '------a--------c------c----e------|  ';\n\n      expectObservable(e1.pipe(sample(e2))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should raise error if source raises error', () => {\n    rxTest.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  ----a-^--b----c----d----#                    ');\n      const e1subs = '        ^-----------------!                    ';\n      const e2 = hot('        -----x----------x----------x----------|');\n      const e2subs = '        ^-----------------!                    ';\n      const expected = '      -----b----------d-#                    ';\n\n      expectObservable(e1.pipe(sample(e2))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should completes if source does not emits', () => {\n    rxTest.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  |              ');\n      const e2 = hot('  ------x-------|');\n      const expected = '|              ';\n      const e1subs = '  (^!)           ';\n      const e2subs = '  (^!)           ';\n\n      expectObservable(e1.pipe(sample(e2))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should raise error if source throws immediately', () => {\n    rxTest.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  #              ');\n      const e2 = hot('  ------x-------|');\n      const expected = '#              ';\n      const e1subs = '  (^!)           ';\n      const e2subs = '  (^!)           ';\n\n      expectObservable(e1.pipe(sample(e2))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should raise error if notification raises error', () => {\n    rxTest.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  --a-----|');\n      const e2 = hot('  ----#    ');\n      const expected = '----#    ';\n      const e1subs = '  ^---!    ';\n      const e2subs = '  ^---!    ';\n\n      expectObservable(e1.pipe(sample(e2))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should not completes if source does not complete', () => {\n    rxTest.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  ---------------');\n      const e1subs = '  ^--------------';\n      const e2 = hot('  ------x-------|');\n      const e2subs = '  ^-------------!';\n      const expected = '---------------';\n\n      expectObservable(e1.pipe(sample(e2))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should sample only until source completes', () => {\n    rxTest.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  ----a----b----c----d-|              ');\n      const e1subs = '  ^--------------------!              ';\n      const e2 = hot('  -----------x----------x------------|');\n      const e2subs = '  ^--------------------!              ';\n      const expected = '-----------b---------|              ';\n\n      expectObservable(e1.pipe(sample(e2))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should complete sampling if sample observable completes', () => {\n    rxTest.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  ----a----b----c----d-|');\n      const e1subs = '  ^--------------------!';\n      const e2 = hot('  |                     ');\n      const e2subs = '  (^!)                  ';\n      const expected = '---------------------|';\n\n      expectObservable(e1.pipe(sample(e2))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n});\n"
  },
  {
    "path": "packages/rxjs/spec/operators/sampleTime-spec.ts",
    "content": "import { sampleTime, mergeMap } from 'rxjs/operators';\nimport { TestScheduler } from 'rxjs/testing';\nimport { of } from 'rxjs';\nimport { observableMatcher } from '../helpers/observableMatcher';\n\n/** @test {sampleTime} */\ndescribe('sampleTime', () => {\n  let rxTest: TestScheduler;\n\n  beforeEach(() => {\n    rxTest = new TestScheduler(observableMatcher);\n  });\n\n  it('should get samples on a delay', () => {\n    rxTest.run(({ hot, expectObservable, expectSubscriptions, time }) => {\n      const e1 = hot('     a---b-c---------d--e---f-g-h--|');\n      const e1subs = '     ^-----------------------------!';\n      const expected = '   -------c-------------e------h-|';\n      // period            -------!------!------!------!--\n      const period = time('-------|                       ');\n\n      expectObservable(e1.pipe(sampleTime(period, rxTest))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should sample nothing if new value has not arrived', () => {\n    rxTest.run(({ hot, expectObservable, expectSubscriptions, time }) => {\n      const e1 = hot('  ----a-^--b----c--------------f----|');\n      const e1subs = '        ^---------------------------!';\n      const expected = '      -----------c----------------|';\n      // period               -----------!----------!---------\n      const period = time('   -----------|                 ');\n\n      expectObservable(e1.pipe(sampleTime(period, rxTest))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should sample if new value has arrived, even if it is the same value', () => {\n    rxTest.run(({ hot, expectObservable, expectSubscriptions, time }) => {\n      const e1 = hot('----a-^--b----c----------c---f----|');\n      const e1subs = '      ^---------------------------!';\n      const expected = '    -----------c----------c-----|';\n      // period             -----------!----------!---------\n      const period = time(' -----------|                 ');\n\n      expectObservable(e1.pipe(sampleTime(period, rxTest))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should sample nothing if source has not nexted by time of sample', () => {\n    rxTest.run(({ hot, expectObservable, expectSubscriptions, time }) => {\n      const e1 = hot('----a-^-------------b-------------|');\n      const e1subs = '      ^---------------------------!';\n      const expected = '    ----------------------b-----|';\n      // period             -----------!----------!---------\n      const period = time(' -----------|                 ');\n\n      expectObservable(e1.pipe(sampleTime(period, rxTest))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should raise error if source raises error', () => {\n    rxTest.run(({ hot, expectObservable, expectSubscriptions, time }) => {\n      const e1 = hot('----a-^--b----c----d----#');\n      const e1subs = '      ^-----------------!';\n      const expected = '    -----------c------#';\n      // period             -----------!----------!---------\n      const period = time(' -----------|       ');\n\n      expectObservable(e1.pipe(sampleTime(period, rxTest))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should allow unsubscribing explicitly and early', () => {\n    rxTest.run(({ hot, expectObservable, expectSubscriptions, time }) => {\n      const e1 = hot('----a-^--b----c----d----e----f----|');\n      const unsub = '       ----------------!            ';\n      const e1subs = '      ^---------------!            ';\n      const expected = '    -----------c-----            ';\n      // period             -----------!----------!---------\n      const period = time(' -----------|                 ');\n\n      expectObservable(e1.pipe(sampleTime(period, rxTest)), unsub).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should not break unsubscription chains when result is unsubscribed explicitly', () => {\n    rxTest.run(({ hot, expectObservable, expectSubscriptions, time }) => {\n      const e1 = hot('----a-^--b----c----d----e----f----|');\n      const e1subs = '      ^---------------!            ';\n      // period             -----------!----------!---------\n      const period = time(' -----------|                 ');\n      const expected = '    -----------c-----            ';\n      const unsub = '       ----------------!            ';\n\n      const result = e1.pipe(\n        mergeMap((x: string) => of(x)),\n        sampleTime(period, rxTest),\n        mergeMap((x: string) => of(x))\n      );\n\n      expectObservable(result, unsub).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should completes if source does not emits', () => {\n    rxTest.run(({ cold, expectObservable, expectSubscriptions, time }) => {\n      const e1 = cold('    |     ');\n      const e1subs = '     (^!)  ';\n      const expected = '   |     ';\n      const period = time('-----|');\n\n      expectObservable(e1.pipe(sampleTime(period, rxTest))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should raise error if source throws immediately', () => {\n    rxTest.run(({ cold, expectObservable, expectSubscriptions, time }) => {\n      const e1 = cold('    #     ');\n      const e1subs = '     (^!)  ';\n      const expected = '   #     ';\n      const period = time('-----|');\n\n      expectObservable(e1.pipe(sampleTime(period, rxTest))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should not complete if source does not complete', () => {\n    rxTest.run(({ cold, expectObservable, expectSubscriptions, time }) => {\n      const e1 = cold('    --------');\n      const e1subs = '     ^------!';\n      const expected = '   --------';\n      const period = time('-----|  ');\n      const e1unsbs = '    -------!';\n\n      expectObservable(e1.pipe(sampleTime(period, rxTest)), e1unsbs).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n});\n"
  },
  {
    "path": "packages/rxjs/spec/operators/scan-spec.ts",
    "content": "import { expect } from 'chai';\nimport { scan, mergeMap, finalize, take } from 'rxjs/operators';\nimport { of, Observable } from 'rxjs';\nimport { TestScheduler } from 'rxjs/testing';\nimport { observableMatcher } from '../helpers/observableMatcher';\n\n/** @test {scan} */\ndescribe('scan', () => {\n  let testScheduler: TestScheduler;\n\n  beforeEach(() => {\n    testScheduler = new TestScheduler(observableMatcher);\n  });\n\n  it('should scan', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      // prettier-ignore\n      const values = {\n        a: 1, b: 3, c: 5,\n        x: 1, y: 4, z: 9,\n      };\n      const e1 = hot('  --a--b--c--|', values);\n      const e1subs = '  ^----------!';\n      const expected = '--x--y--z--|';\n\n      const scanFunction = function (o: number, x: number) {\n        return o + x;\n      };\n\n      expectObservable(e1.pipe(scan(scanFunction, 0))).toBe(expected, values);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should scan things', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('--a--^--b--c--d--e--f--g--|');\n      const e1subs = '     ^--------------------!';\n      const expected = '   ---u--v--w--x--y--z--|';\n\n      const values = {\n        u: ['b'],\n        v: ['b', 'c'],\n        w: ['b', 'c', 'd'],\n        x: ['b', 'c', 'd', 'e'],\n        y: ['b', 'c', 'd', 'e', 'f'],\n        z: ['b', 'c', 'd', 'e', 'f', 'g'],\n      };\n\n      const source = e1.pipe(scan((acc, x) => acc.concat(x), [] as string[]));\n\n      expectObservable(source).toBe(expected, values);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should provide the proper index if seed is skipped', () => {\n    const expected = [1, 2];\n    of(3, 3, 3)\n      .pipe(\n        scan((_: any, __, i) => {\n          expect(i).to.equal(expected.shift());\n          return null;\n        })\n      )\n      .subscribe();\n  });\n\n  it('should scan with a seed of undefined', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('--a--^--b--c--d--e--f--g--|');\n      const e1subs = '     ^--------------------!';\n      const expected = '   ---u--v--w--x--y--z--|';\n\n      const values = {\n        u: 'undefined b',\n        v: 'undefined b c',\n        w: 'undefined b c d',\n        x: 'undefined b c d e',\n        y: 'undefined b c d e f',\n        z: 'undefined b c d e f g',\n      };\n\n      const source = e1.pipe(scan((acc: any, x: string) => acc + ' ' + x, undefined));\n\n      expectObservable(source).toBe(expected, values);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should scan without seed', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('--a--^--b--c--d--|');\n      const e1subs = '     ^-----------!';\n      const expected = '   ---x--y--z--|';\n\n      const values = {\n        x: 'b',\n        y: 'bc',\n        z: 'bcd',\n      };\n\n      const source = e1.pipe(scan((acc: any, x: string) => acc + x));\n\n      expectObservable(source).toBe(expected, values);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should handle errors', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('--a--^--b--c--d--#');\n      const e1subs = '     ^-----------!';\n      const expected = '   ---u--v--w--#';\n\n      const values = {\n        u: ['b'],\n        v: ['b', 'c'],\n        w: ['b', 'c', 'd'],\n      };\n\n      const source = e1.pipe(scan((acc, x) => acc.concat(x), [] as string[]));\n\n      expectObservable(source).toBe(expected, values);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should handle errors in the projection function', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('--a--^--b--c--d--e--f--g--|');\n      const e1subs = '     ^--------!            ';\n      const expected = '   ---u--v--#            ';\n\n      const values = {\n        u: ['b'],\n        v: ['b', 'c'],\n        w: ['b', 'c', 'd'],\n        x: ['b', 'c', 'd', 'e'],\n        y: ['b', 'c', 'd', 'e', 'f'],\n        z: ['b', 'c', 'd', 'e', 'f', 'g'],\n      };\n\n      const source = e1.pipe(\n        scan((acc, x) => {\n          if (x === 'd') {\n            throw 'bad!';\n          }\n          return acc.concat(x);\n        }, [] as string[])\n      );\n\n      expectObservable(source).toBe(expected, values, 'bad!');\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('handle empty', () => {\n    testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' |   ');\n      const e1subs = '  (^!)';\n      const expected = '|   ';\n\n      const source = e1.pipe(scan((acc, x) => acc.concat(x), [] as string[]));\n\n      expectObservable(source).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('handle never', () => {\n    testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' -');\n      const e1subs = '  ^';\n      const expected = '-';\n\n      const source = e1.pipe(scan((acc, x) => acc.concat(x), [] as string[]));\n\n      expectObservable(source).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('handle throw', () => {\n    testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' #   ');\n      const e1subs = '  (^!)';\n      const expected = '#   ';\n\n      const source = e1.pipe(scan((acc, x) => acc.concat(x), [] as string[]));\n\n      expectObservable(source).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should allow unsubscribing explicitly and early', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('--a--^--b--c--d--e--f--g--|');\n      const unsub = '      --------------!       ';\n      const e1subs = '     ^-------------!       ';\n      const expected = '   ---u--v--w--x--       ';\n      const values = {\n        u: ['b'],\n        v: ['b', 'c'],\n        w: ['b', 'c', 'd'],\n        x: ['b', 'c', 'd', 'e'],\n        y: ['b', 'c', 'd', 'e', 'f'],\n        z: ['b', 'c', 'd', 'e', 'f', 'g'],\n      };\n\n      const source = e1.pipe(scan((acc, x) => acc.concat(x), [] as string[]));\n\n      expectObservable(source, unsub).toBe(expected, values);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should not break unsubscription chains when result is unsubscribed explicitly', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('--a--^--b--c--d--e--f--g--|');\n      const e1subs = '     ^-------------!       ';\n      const expected = '   ---u--v--w--x--       ';\n      const unsub = '      --------------!       ';\n      const values = {\n        u: ['b'],\n        v: ['b', 'c'],\n        w: ['b', 'c', 'd'],\n        x: ['b', 'c', 'd', 'e'],\n        y: ['b', 'c', 'd', 'e', 'f'],\n        z: ['b', 'c', 'd', 'e', 'f', 'g'],\n      };\n\n      const source = e1.pipe(\n        mergeMap((x: string) => of(x)),\n        scan((acc, x) => acc.concat(x), [] as string[]),\n        mergeMap((x: string[]) => of(x))\n      );\n\n      expectObservable(source, unsub).toBe(expected, values);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should pass current index to accumulator', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      // prettier-ignore\n      const values = {\n        a: 1, b: 3, c: 5,\n        x: 1, y: 4, z: 9,\n      };\n      const idx = [0, 1, 2];\n\n      const e1 = hot('  --a--b--c--|', values);\n      const e1subs = '  ^----------!';\n      const expected = '--x--y--z--|';\n\n      const scanFunction = (o: number, value: number, index: number) => {\n        expect(index).to.equal(idx.shift());\n        return o + value;\n      };\n\n      const scanObs = e1.pipe(\n        scan(scanFunction, 0),\n        finalize(() => {\n          expect(idx).to.be.empty;\n        })\n      );\n\n      expectObservable(scanObs).toBe(expected, values);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should stop listening to a synchronous observable when unsubscribed', () => {\n    const sideEffects: number[] = [];\n    const synchronousObservable = new Observable<number>((subscriber) => {\n      // This will check to see if the subscriber was closed on each loop\n      // when the unsubscribe hits (from the `take`), it should be closed\n      for (let i = 0; !subscriber.closed && i < 10; i++) {\n        sideEffects.push(i);\n        subscriber.next(i);\n      }\n    });\n\n    synchronousObservable\n      .pipe(\n        scan((_acc, value: number) => value, 0),\n        take(3)\n      )\n      .subscribe(() => {\n        /* noop */\n      });\n\n    expect(sideEffects).to.deep.equal([0, 1, 2]);\n  });\n});\n"
  },
  {
    "path": "packages/rxjs/spec/operators/sequenceEqual-spec.ts",
    "content": "import { sequenceEqual } from 'rxjs/operators';\nimport { TestScheduler } from 'rxjs/testing';\nimport { observableMatcher } from '../helpers/observableMatcher';\n\nconst booleans = { T: true, F: false };\n\n/** @test {sequenceEqual} */\ndescribe('sequenceEqual', () => {\n  let rxTestScheduler: TestScheduler;\n\n  beforeEach(() => {\n    rxTestScheduler = new TestScheduler(observableMatcher);\n  });\n\n  it('should return true for two equal sequences', () => {\n    rxTestScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const s1 = hot('--a--^--b--c--d--e--f--g--|       ');\n      const s1subs = '     ^--------------------!       ';\n      const s2 = hot('-----^-----b--c--d-e-f------g-|   ');\n      const s2subs = '     ^------------------------!   ';\n      const expected = '   -------------------------(T|)';\n\n      const source = s1.pipe(sequenceEqual(s2));\n\n      expectObservable(source).toBe(expected, booleans);\n      expectSubscriptions(s1.subscriptions).toBe(s1subs);\n      expectSubscriptions(s2.subscriptions).toBe(s2subs);\n    });\n  });\n\n  it('should return false for two sync observables that are unequal in length', () => {\n    rxTestScheduler.run(({ cold, expectObservable }) => {\n      const s1 = cold(' (abcdefg|)');\n      const s2 = cold(' (abc|)    ');\n      const expected = '(F|)      ';\n\n      const source = s1.pipe(sequenceEqual(s2));\n\n      expectObservable(source).toBe(expected, booleans);\n    });\n  });\n\n  it('should return true for two sync observables that match', () => {\n    rxTestScheduler.run(({ cold, expectObservable }) => {\n      const s1 = cold(' (abcdefg|)');\n      const s2 = cold(' (abcdefg|)');\n      const expected = '(T|)      ';\n\n      const source = s1.pipe(sequenceEqual(s2));\n\n      expectObservable(source).toBe(expected, booleans);\n    });\n  });\n\n  it('should return true for two observables that match when the last one emits and completes in the same frame', () => {\n    rxTestScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const s1 = hot('--a--^--b--c--d--e--f--g--|       ');\n      const s1subs = '     ^--------------------!       ';\n      const s2 = hot('-----^--b--c--d--e--f--g------|   ');\n      const s2subs = '     ^------------------------!   ';\n      const expected = '   -------------------------(T|)';\n\n      const source = s1.pipe(sequenceEqual(s2));\n\n      expectObservable(source).toBe(expected, booleans);\n      expectSubscriptions(s1.subscriptions).toBe(s1subs);\n      expectSubscriptions(s2.subscriptions).toBe(s2subs);\n    });\n  });\n\n  it('should return true for two observables that match when the last one emits and completes in the same frame', () => {\n    rxTestScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const s1 = hot('--a--^--b--c--d--e--f--g--|       ');\n      const s1subs = '     ^--------------------!       ';\n      const s2 = hot('-----^--b--c--d--e--f---------(g|)');\n      const s2subs = '     ^------------------------!   ';\n      const expected = '   -------------------------(T|)';\n\n      const source = s1.pipe(sequenceEqual(s2));\n\n      expectObservable(source).toBe(expected, booleans);\n      expectSubscriptions(s1.subscriptions).toBe(s1subs);\n      expectSubscriptions(s2.subscriptions).toBe(s2subs);\n    });\n  });\n\n  it('should error with an errored source', () => {\n    rxTestScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const s1 = hot('--a--^--b---c---#  ');\n      const s2 = hot('--a--^--b---c-----|');\n      const expected = '   -----------#  ';\n      const sub = '        ^----------!  ';\n\n      const source = s1.pipe(sequenceEqual(s2));\n\n      expectObservable(source).toBe(expected, booleans);\n      expectSubscriptions(s1.subscriptions).toBe(sub);\n      expectSubscriptions(s2.subscriptions).toBe(sub);\n    });\n  });\n\n  it('should error with an errored compareTo', () => {\n    rxTestScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const s1 = hot('--a--^--b---c-----|');\n      const s2 = hot('--a--^--b---c---#  ');\n      const expected = '   -----------#  ';\n      const sub = '        ^----------!  ';\n\n      const source = s1.pipe(sequenceEqual(s2));\n\n      expectObservable(source).toBe(expected, booleans);\n      expectSubscriptions(s1.subscriptions).toBe(sub);\n      expectSubscriptions(s2.subscriptions).toBe(sub);\n    });\n  });\n\n  it('should error if the source is a throw', () => {\n    rxTestScheduler.run(({ cold, expectObservable }) => {\n      const s1 = cold(' #            ');\n      const s2 = cold(' ---a--b--c--|');\n      const expected = '#            ';\n\n      const source = s1.pipe(sequenceEqual(s2));\n\n      expectObservable(source).toBe(expected);\n    });\n  });\n\n  it('should never return if source is a never', () => {\n    rxTestScheduler.run(({ cold, expectObservable }) => {\n      const s1 = cold(' ------------');\n      const s2 = cold(' --a--b--c--|');\n      const expected = '------------';\n\n      const source = s1.pipe(sequenceEqual(s2));\n\n      expectObservable(source).toBe(expected);\n    });\n  });\n\n  it('should never return if compareTo is a never', () => {\n    rxTestScheduler.run(({ cold, expectObservable }) => {\n      const s1 = cold(' --a--b--c--|');\n      const s2 = cold(' ------------');\n      const expected = '------------';\n\n      const source = s1.pipe(sequenceEqual(s2));\n\n      expectObservable(source).toBe(expected);\n    });\n  });\n\n  it('should return false if source is empty and compareTo is not', () => {\n    rxTestScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const s1 = cold(' |            ');\n      const s1subs = '  (^!)          ';\n      const s2 = cold(' ------a------');\n      const s2subs = '  ^-----!      ';\n      const expected = '------(F|)   ';\n\n      const source = s1.pipe(sequenceEqual(s2));\n\n      expectObservable(source).toBe(expected, booleans);\n      expectSubscriptions(s1.subscriptions).toBe(s1subs);\n      expectSubscriptions(s2.subscriptions).toBe(s2subs);\n    });\n  });\n\n  it('should return false if compareTo is empty and source is not', () => {\n    rxTestScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const s1 = cold(' ------a------');\n      const s2 = cold(' |            ');\n      const expected = '------(F|)   ';\n      const s1subs = '  ^-----!      ';\n      const s2subs = '  (^!)         ';\n\n      const source = s1.pipe(sequenceEqual(s2));\n\n      expectObservable(source).toBe(expected, booleans);\n      expectSubscriptions(s1.subscriptions).toBe(s1subs);\n      expectSubscriptions(s2.subscriptions).toBe(s2subs);\n    });\n  });\n\n  it('should return never if compareTo is empty and source is never', () => {\n    rxTestScheduler.run(({ cold, expectObservable }) => {\n      const s1 = cold(' -');\n      const s2 = cold(' |');\n      const expected = '-';\n\n      const source = s1.pipe(sequenceEqual(s2));\n\n      expectObservable(source).toBe(expected);\n    });\n  });\n\n  it('should return never if source is empty and compareTo is never', () => {\n    rxTestScheduler.run(({ cold, expectObservable }) => {\n      const s1 = cold(' |');\n      const s2 = cold(' -');\n      const expected = '-';\n\n      const source = s1.pipe(sequenceEqual(s2));\n\n      expectObservable(source).toBe(expected);\n    });\n  });\n\n  it('should error if the comparator function errors', () => {\n    rxTestScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const values: { [key: string]: any } = {\n        a: null,\n        b: { value: 'bees knees' },\n        c: { value: 'carpy dumb' },\n        d: { value: 'derp' },\n        x: { value: 'bees knees', foo: 'lol' },\n        y: { value: 'carpy dumb', scooby: 'doo' },\n        z: { value: 'derp', weCouldBe: 'dancin, yeah' },\n      };\n\n      const s1 = hot('--a--^--b-----c------d--|      ', values);\n      const s1subs = '     ^------------!            ';\n      const s2 = hot('-----^--------x---y---z-------|', values);\n      const s2subs = '     ^------------!            ';\n      const expected = '   -------------#            ';\n\n      let i = 0;\n      const source = s1.pipe(\n        sequenceEqual(s2, (a: any, b: any) => {\n          if (++i === 2) {\n            throw new Error('shazbot');\n          }\n          return a.value === b.value;\n        })\n      );\n\n      expectObservable(source).toBe(expected, booleans, new Error('shazbot'));\n      expectSubscriptions(s1.subscriptions).toBe(s1subs);\n      expectSubscriptions(s2.subscriptions).toBe(s2subs);\n    });\n  });\n\n  it('should use the provided comparator function', () => {\n    rxTestScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const values: { [key: string]: any } = {\n        a: null,\n        b: { value: 'bees knees' },\n        c: { value: 'carpy dumb' },\n        d: { value: 'derp' },\n        x: { value: 'bees knees', foo: 'lol' },\n        y: { value: 'carpy dumb', scooby: 'doo' },\n        z: { value: 'derp', weCouldBe: 'dancin, yeah' },\n      };\n\n      const s1 = hot('--a--^--b-----c------d--|         ', values);\n      const s1subs = '     ^------------------!         ';\n      const s2 = hot('-----^--------x---y---z-------|   ', values);\n      const s2subs = '     ^------------------------!   ';\n      const expected = '   -------------------------(T|)';\n\n      const source = s1.pipe(sequenceEqual(s2, (a: any, b: any) => a.value === b.value));\n\n      expectObservable(source).toBe(expected, booleans);\n      expectSubscriptions(s1.subscriptions).toBe(s1subs);\n      expectSubscriptions(s2.subscriptions).toBe(s2subs);\n    });\n  });\n\n  it('should return false for two unequal sequences, compareTo finishing last', () => {\n    rxTestScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const s1 = hot('--a--^--b--c--d--e--f--g--|    ');\n      const s1subs = '     ^--------------------!    ';\n      const s2 = hot('-----^-----b--c--d-e-f------z-|');\n      const s2subs = '     ^----------------------!   ';\n      const expected = '   -----------------------(F|)';\n\n      const source = s1.pipe(sequenceEqual(s2));\n\n      expectObservable(source).toBe(expected, booleans);\n      expectSubscriptions(s1.subscriptions).toBe(s1subs);\n      expectSubscriptions(s2.subscriptions).toBe(s2subs);\n    });\n  });\n\n  it('should return false for two unequal sequences, early wrong value from source', () => {\n    rxTestScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const s1 = hot('--a--^--b--c---x-----------|');\n      const s1subs = '     ^---------!            ';\n      const s2 = hot('-----^--b--c--d--e--f--|    ');\n      const s2subs = '     ^---------!            ';\n      const expected = '   ----------(F|)         ';\n\n      const source = s1.pipe(sequenceEqual(s2));\n\n      expectObservable(source).toBe(expected, booleans);\n      expectSubscriptions(s1.subscriptions).toBe(s1subs);\n      expectSubscriptions(s2.subscriptions).toBe(s2subs);\n    });\n  });\n\n  it('should return false when the source emits an extra value after the compareTo completes', () => {\n    rxTestScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const s1 = hot('--a--^--b--c--d--e--f--g--h--|');\n      const s1subs = '     ^-----------!            ';\n      const s2 = hot('-----^--b--c--d-|             ');\n      const s2subs = '     ^----------!             ';\n      const expected = '   ------------(F|)         ';\n\n      const source = s1.pipe(sequenceEqual(s2));\n\n      expectObservable(source).toBe(expected, booleans);\n      expectSubscriptions(s1.subscriptions).toBe(s1subs);\n      expectSubscriptions(s2.subscriptions).toBe(s2subs);\n    });\n  });\n\n  it('should return false when the compareTo emits an extra value after the source completes', () => {\n    rxTestScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const s1 = hot('--a--^--b--c--d-|             ');\n      const s1subs = '     ^----------!             ';\n      const s2 = hot('-----^--b--c--d--e--f--g--h--|');\n      const s2subs = '     ^-----------!            ';\n      const expected = '   ------------(F|)         ';\n\n      const source = s1.pipe(sequenceEqual(s2));\n\n      expectObservable(source).toBe(expected, booleans);\n      expectSubscriptions(s1.subscriptions).toBe(s1subs);\n      expectSubscriptions(s2.subscriptions).toBe(s2subs);\n    });\n  });\n\n  it('should return true for two empty observables', () => {\n    rxTestScheduler.run(({ cold, expectObservable }) => {\n      const s1 = cold(' |   ');\n      const s2 = cold(' |   ');\n      const expected = '(T|)';\n\n      const source = s1.pipe(sequenceEqual(s2));\n      expectObservable(source).toBe(expected, booleans);\n    });\n  });\n\n  it('should return false for an empty observable and an observable that emits', () => {\n    rxTestScheduler.run(({ cold, expectObservable }) => {\n      const s1 = cold(' |      ');\n      const s2 = cold(' ---a--|');\n      const expected = '---(F|)';\n\n      const source = s1.pipe(sequenceEqual(s2));\n      expectObservable(source).toBe(expected, booleans);\n    });\n  });\n\n  it('should return compare hot and cold observables', () => {\n    rxTestScheduler.run(({ hot, cold, expectObservable, expectSubscriptions }) => {\n      const s1 = hot('---a--^---b---c---d---e---f---g---h---i---j---|   ');\n      const s2 = cold('     ----b---c-|                                 ');\n      const s2subs = '      ^---------!                                 ';\n      const expected1 = '   ------------(F|)                            ';\n      const s3 = cold('                        -f---g---h---i---j---|   ');\n      const test2subs = '   -------------------^                        ';\n      const expected2 = '   ----------------------------------------(T|)';\n      const s3subs = '      -------------------^--------------------!   ';\n\n      const test1 = s1.pipe(sequenceEqual(s2));\n      const test2 = s1.pipe(sequenceEqual(s3));\n\n      expectObservable(test1).toBe(expected1, booleans);\n      expectObservable(test2, test2subs).toBe(expected2, booleans);\n      expectSubscriptions(s2.subscriptions).toBe(s2subs);\n      expectSubscriptions(s3.subscriptions).toBe(s3subs);\n    });\n  });\n});\n"
  },
  {
    "path": "packages/rxjs/spec/operators/share-spec.ts",
    "content": "import { expect } from 'chai';\nimport { asapScheduler, concat, config, defer, EMPTY, NEVER, Observable, of, scheduled, Subject, throwError, pipe } from 'rxjs';\nimport {\n  map,\n  mergeMap,\n  mergeMapTo,\n  onErrorResumeNextWith,\n  repeat,\n  retry,\n  share,\n  startWith,\n  take,\n  takeUntil,\n  takeWhile,\n  tap,\n  toArray,\n  withLatestFrom,\n} from 'rxjs/operators';\nimport { TestScheduler } from 'rxjs/testing';\nimport { observableMatcher } from '../helpers/observableMatcher';\nimport { spy } from 'sinon';\n\nconst syncNotify = of(1);\nconst asapNotify = scheduled(syncNotify, asapScheduler);\nconst syncError = throwError(() => new Error());\n\n/** @test {share} */\ndescribe('share', () => {\n  let rxTest: TestScheduler;\n\n  beforeEach(() => {\n    rxTest = new TestScheduler(observableMatcher);\n  });\n\n  for (const { title, options } of [\n    { title: 'share()', options: {} },\n    {\n      title: 'share() using sync reset notifiers equivalent to default config',\n      options: {\n        resetOnError: () => syncNotify,\n        resetOnComplete: () => syncNotify,\n        resetOnRefCountZero: () => syncNotify,\n      },\n    },\n    {\n      title: 'share() using sync reset notifiers equivalent to default config and notifying again after reset is notified',\n      options: {\n        resetOnError: () => concat(syncNotify, syncNotify),\n        resetOnComplete: () => concat(syncNotify, syncNotify),\n        resetOnRefCountZero: () => concat(syncNotify, syncNotify),\n      },\n    },\n    {\n      title: 'share() using sync reset notifiers equivalent to default config and never completing after reset is notified',\n      options: {\n        resetOnError: () => concat(syncNotify, NEVER),\n        resetOnComplete: () => concat(syncNotify, NEVER),\n        resetOnRefCountZero: () => concat(syncNotify, NEVER),\n      },\n    },\n    {\n      title: 'share() using sync reset notifiers equivalent to default config and throwing an error after reset is notified',\n      options: {\n        resetOnError: () => concat(syncNotify, syncError),\n        resetOnComplete: () => concat(syncNotify, syncError),\n        resetOnRefCountZero: () => concat(syncNotify, syncError),\n      },\n    },\n  ]) {\n    describe(title, () => {\n      it('should mirror a simple source Observable', () => {\n        rxTest.run(({ cold, expectObservable, expectSubscriptions }) => {\n          const source = cold('--1-2---3-4--5-|');\n          const sourceSubs = ' ^--------------!';\n          const expected = '   --1-2---3-4--5-|';\n\n          const shared = source.pipe(share(options));\n\n          expectObservable(shared).toBe(expected);\n          expectSubscriptions(source.subscriptions).toBe(sourceSubs);\n        });\n      });\n\n      it('should share a single subscription', () => {\n        let subscriptionCount = 0;\n        const obs = new Observable<never>(() => {\n          subscriptionCount++;\n        });\n\n        const source = obs.pipe(share(options));\n\n        expect(subscriptionCount).to.equal(0);\n\n        source.subscribe();\n        source.subscribe();\n\n        expect(subscriptionCount).to.equal(1);\n      });\n\n      it('should not change the output of the observable when error', () => {\n        rxTest.run(({ hot, expectObservable, expectSubscriptions }) => {\n          const e1 = hot('---a--^--b--c--d--e--#');\n          const e1subs = '      ^--------------!';\n          const expected = '    ---b--c--d--e--#';\n\n          expectObservable(e1.pipe(share(options))).toBe(expected);\n          expectSubscriptions(e1.subscriptions).toBe(e1subs);\n        });\n      });\n\n      it('should not change the output of the observable when successful with cold observable', () => {\n        rxTest.run(({ cold, expectObservable, expectSubscriptions }) => {\n          const e1 = cold(' ---a--b--c--d--e--|');\n          const e1subs = '  ^-----------------!';\n          const expected = '---a--b--c--d--e--|';\n\n          expectObservable(e1.pipe(share(options))).toBe(expected);\n          expectSubscriptions(e1.subscriptions).toBe(e1subs);\n        });\n      });\n\n      it('should not change the output of the observable when error with cold observable', () => {\n        rxTest.run(({ cold, expectObservable, expectSubscriptions }) => {\n          const e1 = cold(' ---a--b--c--d--e--#');\n          const e1subs = '  ^-----------------!';\n          const expected = '---a--b--c--d--e--#';\n\n          expectObservable(e1.pipe(share(options))).toBe(expected);\n          expectSubscriptions(e1.subscriptions).toBe(e1subs);\n        });\n      });\n\n      it('should retry just fine', () => {\n        rxTest.run(({ cold, expectObservable, expectSubscriptions }) => {\n          const e1 = cold(' ---a--b--c--d--e--#                  ');\n          // prettier-ignore\n          const e1subs = [\n            '               ^-----------------!                  ',\n            '               ------------------^-----------------!'\n          ];\n          const expected = '---a--b--c--d--e-----a--b--c--d--e--#';\n\n          expectObservable(e1.pipe(share(options), retry(1))).toBe(expected);\n          expectSubscriptions(e1.subscriptions).toBe(e1subs);\n        });\n      });\n\n      it('should share the same values to multiple observers', () => {\n        rxTest.run(({ cold, hot, expectObservable, expectSubscriptions }) => {\n          const source = cold('    -1-2-3----4-|');\n          const sourceSubs = '     ^-----------!';\n          const subscriber1 = hot('a|           ');\n          const expected1 = '      -1-2-3----4-|';\n          const subscriber2 = hot('----b|       ');\n          const expected2 = '      -----3----4-|';\n          const subscriber3 = hot('--------c|   ');\n          const expected3 = '      ----------4-|';\n\n          const shared = source.pipe(share(options));\n\n          expectObservable(subscriber1.pipe(mergeMapTo(shared))).toBe(expected1);\n          expectObservable(subscriber2.pipe(mergeMapTo(shared))).toBe(expected2);\n          expectObservable(subscriber3.pipe(mergeMapTo(shared))).toBe(expected3);\n          expectSubscriptions(source.subscriptions).toBe(sourceSubs);\n        });\n      });\n\n      it('should share an error from the source to multiple observers', () => {\n        rxTest.run(({ cold, hot, expectObservable, expectSubscriptions }) => {\n          const source = cold('    -1-2-3----4-#');\n          const sourceSubs = '     ^-----------!';\n          const subscriber1 = hot('a|           ');\n          const expected1 = '      -1-2-3----4-#';\n          const subscriber2 = hot('----b|       ');\n          const expected2 = '      -----3----4-#';\n          const subscriber3 = hot('--------c|   ');\n          const expected3 = '      ----------4-#';\n\n          const shared = source.pipe(share(options));\n\n          expectObservable(subscriber1.pipe(mergeMapTo(shared))).toBe(expected1);\n          expectObservable(subscriber2.pipe(mergeMapTo(shared))).toBe(expected2);\n          expectObservable(subscriber3.pipe(mergeMapTo(shared))).toBe(expected3);\n          expectSubscriptions(source.subscriptions).toBe(sourceSubs);\n        });\n      });\n\n      it('should share the same values to multiple observers, but is unsubscribed explicitly and early', () => {\n        rxTest.run(({ cold, hot, expectObservable, expectSubscriptions }) => {\n          const source = cold('    -1-2-3----4-|');\n          const sourceSubs = '     ^--------!   ';\n          const unsub = '          ---------!   ';\n          const subscriber1 = hot('a|           ');\n          const expected1 = '      -1-2-3----   ';\n          const subscriber2 = hot('----b|       ');\n          const expected2 = '      -----3----   ';\n          const subscriber3 = hot('--------c|   ');\n          const expected3 = '      ----------   ';\n\n          const shared = source.pipe(share(options));\n\n          expectObservable(subscriber1.pipe(mergeMapTo(shared)), unsub).toBe(expected1);\n          expectObservable(subscriber2.pipe(mergeMapTo(shared)), unsub).toBe(expected2);\n          expectObservable(subscriber3.pipe(mergeMapTo(shared)), unsub).toBe(expected3);\n          expectSubscriptions(source.subscriptions).toBe(sourceSubs);\n        });\n      });\n\n      it('should share an empty source', () => {\n        rxTest.run(({ cold, expectObservable, expectSubscriptions }) => {\n          const source = cold('|   ');\n          const sourceSubs = ' (^!)';\n          const expected = '   |   ';\n\n          const shared = source.pipe(share(options));\n\n          expectObservable(shared).toBe(expected);\n          expectSubscriptions(source.subscriptions).toBe(sourceSubs);\n        });\n      });\n\n      it('should share a never source', () => {\n        rxTest.run(({ cold, expectObservable, expectSubscriptions }) => {\n          const source = cold('-');\n          const sourceSubs = ' ^';\n          const expected = '   -';\n\n          const shared = source.pipe(share(options));\n\n          expectObservable(shared).toBe(expected);\n          expectSubscriptions(source.subscriptions).toBe(sourceSubs);\n        });\n      });\n\n      it('should share a throw source', () => {\n        rxTest.run(({ cold, expectObservable, expectSubscriptions }) => {\n          const source = cold('#   ');\n          const sourceSubs = ' (^!)';\n          const expected = '   #   ';\n\n          const shared = source.pipe(share(options));\n\n          expectObservable(shared).toBe(expected);\n          expectSubscriptions(source.subscriptions).toBe(sourceSubs);\n        });\n      });\n\n      it('should connect when first subscriber subscribes', () => {\n        rxTest.run(({ cold, hot, expectObservable, expectSubscriptions }) => {\n          const source = cold('       -1-2-3----4-|');\n          const sourceSubs = '     ---^-----------!';\n          const subscriber1 = hot('---a|           ');\n          const expected1 = '      ----1-2-3----4-|';\n          const subscriber2 = hot('-------b|       ');\n          const expected2 = '      --------3----4-|';\n          const subscriber3 = hot('-----------c|   ');\n          const expected3 = '      -------------4-|';\n\n          const shared = source.pipe(share(options));\n\n          expectObservable(subscriber1.pipe(mergeMapTo(shared))).toBe(expected1);\n          expectObservable(subscriber2.pipe(mergeMapTo(shared))).toBe(expected2);\n          expectObservable(subscriber3.pipe(mergeMapTo(shared))).toBe(expected3);\n          expectSubscriptions(source.subscriptions).toBe(sourceSubs);\n        });\n      });\n\n      it('should disconnect when last subscriber unsubscribes', () => {\n        rxTest.run(({ cold, hot, expectObservable, expectSubscriptions }) => {\n          const source = cold('       -1-2-3----4-|');\n          const sourceSubs = '     ---^--------!   ';\n          const subscriber1 = hot('---a|           ');\n          const unsub1 = '         ----------!     ';\n          const expected1 = '      ----1-2-3--     ';\n          const subscriber2 = hot('-------b|       ');\n          const unsub2 = '         ------------!   ';\n          const expected2 = '      --------3----   ';\n\n          const shared = source.pipe(share(options));\n\n          expectObservable(subscriber1.pipe(mergeMapTo(shared)), unsub1).toBe(expected1);\n          expectObservable(subscriber2.pipe(mergeMapTo(shared)), unsub2).toBe(expected2);\n          expectSubscriptions(source.subscriptions).toBe(sourceSubs);\n        });\n      });\n\n      it('should not break unsubscription chain when last subscriber unsubscribes', () => {\n        rxTest.run(({ cold, hot, expectObservable, expectSubscriptions }) => {\n          const source = cold('       -1-2-3----4-|');\n          const sourceSubs = '     ---^--------!   ';\n          const subscriber1 = hot('---a|           ');\n          const unsub1 = '         ----------!     ';\n          const expected1 = '      ----1-2-3--     ';\n          const subscriber2 = hot('-------b|       ');\n          const unsub2 = '         ------------!   ';\n          const expected2 = '      --------3----   ';\n\n          const shared = source.pipe(\n            mergeMap((x: string) => of(x)),\n            share(options),\n            mergeMap((x: string) => of(x))\n          );\n\n          expectObservable(subscriber1.pipe(mergeMapTo(shared)), unsub1).toBe(expected1);\n          expectObservable(subscriber2.pipe(mergeMapTo(shared)), unsub2).toBe(expected2);\n          expectSubscriptions(source.subscriptions).toBe(sourceSubs);\n        });\n      });\n\n      it('should be retryable when cold source is synchronous', () => {\n        rxTest.run(({ cold, hot, expectObservable, expectSubscriptions }) => {\n          const source = cold('(123#)    ');\n          const subscribe1 = ' s         ';\n          const expected1 = '  (123123#) ';\n          const subscribe2 = ' -s        ';\n          const expected2 = '  -(123123#)';\n          const sourceSubs = [\n            '                  (^!)      ',\n            '                  (^!)      ',\n            '                  -(^!)     ',\n            '                  -(^!)     ',\n          ];\n\n          const shared = source.pipe(share(options));\n\n          expectObservable(\n            hot(subscribe1).pipe(\n              tap(() => {\n                expectObservable(shared.pipe(retry(1))).toBe(expected1);\n              })\n            )\n          ).toBe(subscribe1);\n\n          expectObservable(\n            hot(subscribe2).pipe(\n              tap(() => {\n                expectObservable(shared.pipe(retry(1))).toBe(expected2);\n              })\n            )\n          ).toBe(subscribe2);\n\n          expectSubscriptions(source.subscriptions).toBe(sourceSubs);\n        });\n      });\n\n      it('should be repeatable when cold source is synchronous', () => {\n        rxTest.run(({ cold, hot, expectObservable, expectSubscriptions }) => {\n          const source = cold('(123|)    ');\n          const subscribe1 = ' s         ';\n          const expected1 = '  (123123|) ';\n          const subscribe2 = ' -s        ';\n          const expected2 = '  -(123123|)';\n          const sourceSubs = [\n            '                  (^!)      ',\n            '                  (^!)      ',\n            '                  -(^!)     ',\n            '                  -(^!)     ',\n          ];\n\n          const shared = source.pipe(share(options));\n\n          expectObservable(\n            hot(subscribe1).pipe(\n              tap(() => {\n                expectObservable(shared.pipe(repeat(2))).toBe(expected1);\n              })\n            )\n          ).toBe(subscribe1);\n\n          expectObservable(\n            hot(subscribe2).pipe(\n              tap(() => {\n                expectObservable(shared.pipe(repeat(2))).toBe(expected2);\n              })\n            )\n          ).toBe(subscribe2);\n\n          expectSubscriptions(source.subscriptions).toBe(sourceSubs);\n        });\n      });\n\n      it('should be retryable', () => {\n        rxTest.run(({ cold, hot, expectObservable, expectSubscriptions }) => {\n          const source = cold('-1-2-3----4-#                        ');\n          const sourceSubs = [\n            '                  ^-----------!                        ',\n            '                  ------------^-----------!            ',\n            '                  ------------------------^-----------!',\n          ];\n          const subscribe1 = ' s------------------------------------';\n          const expected1 = '  -1-2-3----4--1-2-3----4--1-2-3----4-#';\n          const subscribe2 = ' ----s--------------------------------';\n          const expected2 = '  -----3----4--1-2-3----4--1-2-3----4-#';\n\n          const shared = source.pipe(share(options));\n\n          expectObservable(\n            hot(subscribe1).pipe(\n              tap(() => {\n                expectObservable(shared.pipe(retry(2))).toBe(expected1);\n              })\n            )\n          ).toBe(subscribe1);\n\n          expectObservable(\n            hot(subscribe2).pipe(\n              tap(() => {\n                expectObservable(shared.pipe(retry(2))).toBe(expected2);\n              })\n            )\n          ).toBe(subscribe2);\n\n          expectSubscriptions(source.subscriptions).toBe(sourceSubs);\n        });\n      });\n\n      it('should be repeatable', () => {\n        rxTest.run(({ cold, hot, expectObservable, expectSubscriptions }) => {\n          const source = cold('-1-2-3----4-|                        ');\n          const sourceSubs = [\n            '                  ^-----------!                        ',\n            '                  ------------^-----------!            ',\n            '                  ------------------------^-----------!',\n          ];\n          const subscribe1 = ' s------------------------------------';\n          const expected1 = '  -1-2-3----4--1-2-3----4--1-2-3----4-|';\n          const subscribe2 = ' ----s--------------------------------';\n          const expected2 = '  -----3----4--1-2-3----4--1-2-3----4-|';\n\n          const shared = source.pipe(share(options));\n\n          expectObservable(\n            hot(subscribe1).pipe(\n              tap(() => {\n                expectObservable(shared.pipe(repeat(3))).toBe(expected1);\n              })\n            )\n          ).toBe(subscribe1);\n\n          expectObservable(\n            hot(subscribe2).pipe(\n              tap(() => {\n                expectObservable(shared.pipe(repeat(3))).toBe(expected2);\n              })\n            )\n          ).toBe(subscribe2);\n\n          expectSubscriptions(source.subscriptions).toBe(sourceSubs);\n        });\n      });\n\n      it('should not change the output of the observable when never', () => {\n        rxTest.run(({ expectObservable }) => {\n          const e1 = NEVER;\n          const expected = '-';\n\n          expectObservable(e1.pipe(share(options))).toBe(expected);\n        });\n      });\n\n      it('should not change the output of the observable when empty', () => {\n        rxTest.run(({ expectObservable }) => {\n          const e1 = EMPTY;\n          const expected = '|';\n\n          expectObservable(e1.pipe(share(options))).toBe(expected);\n        });\n      });\n\n      it('should stop listening to a synchronous observable when unsubscribed', () => {\n        const sideEffects: number[] = [];\n        const synchronousObservable = new Observable<number>((subscriber) => {\n          // This will check to see if the subscriber was closed on each loop\n          // when the unsubscribe hits (from the `take`), it should be closed\n          for (let i = 0; !subscriber.closed && i < 10; i++) {\n            sideEffects.push(i);\n            subscriber.next(i);\n          }\n        });\n\n        synchronousObservable.pipe(share(options), take(3)).subscribe(() => {\n          /* noop */\n        });\n\n        expect(sideEffects).to.deep.equal([0, 1, 2]);\n      });\n\n      it('should not fail on reentrant subscription', () => {\n        rxTest.run(({ cold, expectObservable, expectSubscriptions }) => {\n          // https://github.com/ReactiveX/rxjs/issues/6144\n          const source = cold('(123|)');\n          const subs = '       (^!)  ';\n          const expected = '   (136|)';\n\n          const deferred = defer(() => shared).pipe(startWith(0));\n          const shared: Observable<string> = source.pipe(\n            withLatestFrom(deferred),\n            map(([a, b]) => String(Number(a) + Number(b))),\n            share(options)\n          );\n\n          expectObservable(shared).toBe(expected);\n          expectSubscriptions(source.subscriptions).toBe(subs);\n        });\n      });\n    });\n  }\n\n  for (const { title, resetOnError, resetOnComplete, resetOnRefCountZero } of [\n    { title: 'share(config)', resetOnError: false, resetOnComplete: false, resetOnRefCountZero: false },\n    {\n      title: 'share(config) using EMPTY as sync reset notifier equivalents',\n      resetOnError: () => EMPTY,\n      resetOnComplete: () => EMPTY,\n      resetOnRefCountZero: () => EMPTY,\n    },\n    {\n      title: 'share(config) using NEVER as sync reset notifier equivalents',\n      resetOnError: () => NEVER,\n      resetOnComplete: () => NEVER,\n      resetOnRefCountZero: () => NEVER,\n    },\n  ]) {\n    describe(title, () => {\n      it('should not reset on error if configured to do so', () => {\n        rxTest.run(({ hot, expectObservable, expectSubscriptions }) => {\n          const source = hot('---a---b---c---d---e---f----#');\n          const expected = '  ---a---b---c---d---e---f----#';\n          const sourceSubs = [\n            '                 ^----------!                 ',\n            '                 -----------^-----------!     ',\n            '                 -----------------------^----!',\n          ];\n          const result = source.pipe(\n            // takes a, b, c... then repeat causes it to take d, e, f\n            take(3),\n            share({ resetOnError }),\n            repeat()\n          );\n\n          expectObservable(result).toBe(expected);\n          expectSubscriptions(source.subscriptions).toBe(sourceSubs);\n        });\n      });\n\n      it('should not reset on complete if configured to do so', () => {\n        rxTest.run(({ cold, expectObservable, expectSubscriptions }) => {\n          const source = cold('---a---b---c---#                          ');\n          const expected = '   ---a---b---c------a---b---c------a---b---|';\n          const sourceSubs = [\n            '                  ^--------------!                          ',\n            '                  ---------------^--------------!           ',\n            '                  ------------------------------^----------!',\n          ];\n\n          // Used to trigger the source to complete at a given moment.\n          const triggerComplete = new Subject<void>();\n\n          // just used to count how many values have made it through the share.\n          let count = 0;\n\n          const result = source.pipe(\n            takeUntil(triggerComplete),\n            share({ resetOnComplete }),\n            // Retry on any error.\n            retry(),\n            tap(() => {\n              if (++count === 9) {\n                // If we see the ninth value, complete the source this time.\n                triggerComplete.next();\n              }\n            })\n          );\n\n          expectObservable(result).toBe(expected);\n          expectSubscriptions(source.subscriptions).toBe(sourceSubs);\n        });\n      });\n\n      it('should not reset on refCount 0 if configured to do so', () => {\n        rxTest.run(({ hot, expectObservable, expectSubscriptions }) => {\n          const source = hot('  ---v---v---v---E--v---v---v---C---v----v------v---');\n          const expected = '    ---v---v---v------v---v---v-------v----v----      ';\n          const subscription = '^-------------------------------------------!     ';\n          const sourceSubs = [\n            '                   ^--------------!',\n            '                   ---------------^--------------!',\n            // Note this last subscription never ends, because refCount hitting zero isn't going to reset.\n            '                   ------------------------------^--------------     ',\n          ];\n\n          const result = source.pipe(\n            tap((value) => {\n              if (value === 'E') {\n                throw new Error('E');\n              }\n            }),\n            takeWhile((value) => value !== 'C'),\n            share({ resetOnRefCountZero }),\n            retry(),\n            repeat()\n          );\n\n          expectObservable(result, subscription).toBe(expected);\n          expectSubscriptions(source.subscriptions).toBe(sourceSubs);\n        });\n      });\n\n      it('should be referentially-transparent', () => {\n        rxTest.run(({ cold, expectObservable, expectSubscriptions }) => {\n          const source1 = cold('-1-2-3-4-5-|');\n          const source1Subs = ' ^----------!';\n          const expected1 = '   -1-2-3-4-5-|';\n          const source2 = cold('-6-7-8-9-0-|');\n          const source2Subs = ' ^----------!';\n          const expected2 = '   -6-7-8-9-0-|';\n\n          // Calls to the _operator_ must be referentially-transparent.\n          const partialPipeLine = pipe(share({ resetOnRefCountZero }));\n\n          // The non-referentially-transparent sharing occurs within the _operator function_\n          // returned by the _operator_ and that happens when the complete pipeline is composed.\n          const shared1 = source1.pipe(partialPipeLine);\n          const shared2 = source2.pipe(partialPipeLine);\n\n          expectObservable(shared1).toBe(expected1);\n          expectSubscriptions(source1.subscriptions).toBe(source1Subs);\n          expectObservable(shared2).toBe(expected2);\n          expectSubscriptions(source2.subscriptions).toBe(source2Subs);\n        });\n      });\n    });\n  }\n\n  describe('share(config)', () => {\n    it('should use the connector function provided', () => {\n      const connector = spy(() => new Subject());\n\n      rxTest.run(({ hot, expectObservable }) => {\n        const source = hot('  ---v---v---v---E--v---v---v---C---v----v--------v----v---');\n        const subs1 = '       ^-------------------------------------------!            ';\n        const expResult1 = '  ---v---v---v------v---v---v-------v----v-----            ';\n        const subs2 = '       ----------------------------------------------^---------!';\n        const expResult2 = '  ------------------------------------------------v----v---';\n\n        const result = source.pipe(\n          tap((value) => {\n            if (value === 'E') {\n              throw new Error('E');\n            }\n          }),\n          takeWhile((value) => value !== 'C'),\n          share({\n            connector,\n          }),\n          retry(),\n          repeat()\n        );\n\n        expectObservable(result, subs1).toBe(expResult1);\n        expectObservable(result, subs2).toBe(expResult2);\n      });\n\n      expect(connector).to.have.callCount(4);\n    });\n  });\n\n  describe('share(config) with async/deferred reset notifiers', () => {\n    it('should reset on refCount 0 when synchronously resubscribing to a firehose and using a sync reset notifier', () => {\n      let subscriptionCount = 0;\n      const source = new Observable((subscriber) => {\n        subscriptionCount++;\n        for (let i = 0; i < 3 && !subscriber.closed; i++) {\n          subscriber.next(i);\n        }\n        if (!subscriber.closed) {\n          subscriber.complete();\n        }\n      });\n\n      let result;\n      source\n        .pipe(share({ resetOnRefCountZero: () => syncNotify }), take(2), repeat(2), toArray())\n        .subscribe((numbers) => void (result = numbers));\n\n      expect(subscriptionCount).to.equal(2);\n      expect(result).to.deep.equal([0, 1, 0, 1]);\n    });\n\n    it('should reset on refCount 0 when synchronously resubscribing and using a sync reset notifier', () => {\n      rxTest.run(({ hot, expectObservable, expectSubscriptions }) => {\n        const source = hot('  ---1---2---3---(4 )---5---|');\n        const sourceSubs = [\n          '                   ^------!                   ',\n          // break the line, please\n          '                   -------^-------(! )        ',\n        ];\n        const expected = '    ---1---2---3---(4|)        ';\n        const subscription = '^--------------(- )        ';\n\n        const sharedSource = source.pipe(share({ resetOnRefCountZero: () => syncNotify }), take(2));\n\n        const result = concat(sharedSource, sharedSource);\n\n        expectObservable(result, subscription).toBe(expected);\n        expectSubscriptions(source.subscriptions).toBe(sourceSubs);\n      });\n    });\n\n    it('should not reset on refCount 0 when synchronously resubscribing and using a deferred reset notifier', () => {\n      rxTest.run(({ cold, expectObservable, expectSubscriptions }) => {\n        const source = cold(' ---1---2---3---4---5---|');\n        const sourceSubs = '  ^----------------------!';\n        const expected = '    ---1---2---3---4---5---|';\n        const subscription = '^-----------------------';\n\n        const sharedSource = source.pipe(share({ resetOnRefCountZero: () => asapNotify }), take(3));\n\n        const result = concat(sharedSource, sharedSource);\n\n        expectObservable(result, subscription).toBe(expected);\n        expectSubscriptions(source.subscriptions).toBe(sourceSubs);\n      });\n    });\n\n    it('should reset on refCount 0 only after reset notifier emitted', () => {\n      rxTest.run(({ hot, cold, expectObservable, expectSubscriptions }) => {\n        const source = hot('      ---1---2---3---4---5---|');\n        const sourceSubs = [\n          '                       ^----------------!      ',\n          // break the line, please\n          '                       ------------------^----!',\n        ];\n        const expected = '        ---1---2---3---4---5---|';\n        const subscription = '    ^-----------------------';\n        const firstPause = cold('        -|               ');\n        const reset = cold('             --r              ');\n        const secondPause = cold('               ---|     ');\n        // reset: '                              --r      '\n\n        const sharedSource = source.pipe(share({ resetOnRefCountZero: () => reset }), take(2));\n\n        const result = concat(sharedSource, firstPause, sharedSource, secondPause, sharedSource);\n\n        expectObservable(result, subscription).toBe(expected);\n        expectSubscriptions(source.subscriptions).toBe(sourceSubs);\n      });\n    });\n\n    it('should reset on error only after reset notifier emitted', () => {\n      rxTest.run(({ cold, expectObservable, expectSubscriptions }) => {\n        const source = cold('     ---1---2---#                ');\n        // source: '                            ---1---2---#  '\n        const sourceSubs = [\n          '                       ^----------!                ',\n          // break the line, please\n          '                       --------------^----------!  ',\n        ];\n        const expected = '        ---1---2---------1---2----# ';\n        const subscription = '    ^-------------------------- ';\n        const firstPause = cold('        -------|             ');\n        const reset = cold('                 --r              ');\n        const secondPause = cold('                     -----| ');\n        // reset: '                                        --r'\n\n        const sharedSource = source.pipe(share({ resetOnError: () => reset, resetOnRefCountZero: false }), take(2));\n\n        const result = concat(sharedSource, firstPause, sharedSource, secondPause, sharedSource);\n\n        expectObservable(result, subscription).toBe(expected);\n        expectSubscriptions(source.subscriptions).toBe(sourceSubs);\n      });\n    });\n\n    it('should reset on complete only after reset notifier emitted', () => {\n      rxTest.run(({ cold, expectObservable, expectSubscriptions }) => {\n        const source = cold('     ---1---2---|                ');\n        // source: '                            ---1---2---|  '\n        const sourceSubs = [\n          '                       ^----------!                ',\n          // break the line, please\n          '                       --------------^----------!  ',\n        ];\n        const expected = '        ---1---2---------1---2----| ';\n        const subscription = '    ^-------------------------- ';\n        const firstPause = cold('        -------|             ');\n        const reset = cold('                 --r              ');\n        const secondPause = cold('                     -----| ');\n        // reset: '                                        --r'\n\n        const sharedSource = source.pipe(share({ resetOnComplete: () => reset, resetOnRefCountZero: false }), take(2));\n\n        const result = concat(sharedSource, firstPause, sharedSource, secondPause, sharedSource);\n\n        expectObservable(result, subscription).toBe(expected);\n        expectSubscriptions(source.subscriptions).toBe(sourceSubs);\n      });\n    });\n\n    describe('when config.onUnhandledError is set', () => {\n      afterEach(() => {\n        config.onUnhandledError = null;\n      });\n\n      it('should not reset on refCount 0 if reset notifier errors before emitting any value', (done) => {\n        const error = new Error();\n        let calls = 0;\n\n        config.onUnhandledError = spy((err) => {\n          calls++;\n          expect(err).to.equal(error);\n          if (calls === 2) {\n            done();\n          }\n        });\n\n        rxTest.run(({ hot, cold, expectObservable, expectSubscriptions }) => {\n          const source = hot('       ---1---2---3---4---(5 )---|');\n          const sourceSubs = '       ^------------------(- )---!';\n          const expected = '         ---1---2-------4---(5|)    ';\n          const subscription = '     ^------------------(- )    ';\n          const firstPause = cold('         ------|             ');\n          const reset = cold('              --#                 ', undefined, error);\n          // reset: '                                   (- )-#  '\n\n          const sharedSource = source.pipe(share({ resetOnRefCountZero: () => reset }), take(2));\n\n          const result = concat(sharedSource, firstPause, sharedSource);\n\n          expectObservable(result, subscription).toBe(expected);\n          expectSubscriptions(source.subscriptions).toBe(sourceSubs);\n        });\n      });\n\n      it('should not reset on error if reset notifier errors before emitting any value', (done) => {\n        const error = new Error();\n\n        config.onUnhandledError = spy((err) => {\n          expect(err).to.equal(error);\n          done();\n        });\n\n        rxTest.run(({ cold, expectObservable, expectSubscriptions }) => {\n          const source = cold('    ---1---2---#   ');\n          const sourceSubs = '     ^----------!   ';\n          const expected = '       ---1---2------#';\n          const subscription = '   ^--------------';\n          const firstPause = cold('       -------|');\n          const reset = cold('                --# ', undefined, error);\n\n          const sharedSource = source.pipe(share({ resetOnError: () => reset, resetOnRefCountZero: false }), take(2));\n\n          const result = concat(sharedSource, firstPause, sharedSource);\n\n          expectObservable(result, subscription).toBe(expected);\n          expectSubscriptions(source.subscriptions).toBe(sourceSubs);\n        });\n      });\n    });\n\n    it('should not reset on complete if reset notifier errors before emitting any value', (done) => {\n      const error = new Error();\n\n      config.onUnhandledError = spy((err) => {\n        expect(err).to.equal(error);\n        done();\n      });\n\n      rxTest.run(({ cold, expectObservable, expectSubscriptions }) => {\n        const source = cold('    ---1---2---|   ');\n        const sourceSubs = '     ^----------!   ';\n        const expected = '       ---1---2------|';\n        const subscription = '   ^--------------';\n        const firstPause = cold('       -------|');\n        const reset = cold('                --# ', undefined, error);\n\n        const sharedSource = source.pipe(share({ resetOnComplete: () => reset, resetOnRefCountZero: false }), take(2));\n\n        const result = concat(sharedSource, firstPause, sharedSource);\n\n        expectObservable(result, subscription).toBe(expected);\n        expectSubscriptions(source.subscriptions).toBe(sourceSubs);\n      });\n    });\n  });\n\n  it('should not call \"resetOnRefCountZero\" on error', () => {\n    rxTest.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const resetOnRefCountZero = spy(() => EMPTY);\n\n      const source = cold('    ---1---(2#)                ');\n      // source: '                           ---1---(2#)  '\n      const sourceSubs = [\n        '                      ^------(! )                ',\n        // break the line, please\n        '                      -------(- )---^------(! )  ',\n      ];\n      const expected = '       ---1---(2 )------1---(2#)  ';\n      const subscription = '   ^------(- )----------(- )  ';\n      const firstPause = cold('       (- )---|            ');\n      const reset = cold('            (- )-r              ');\n      // reset: '                                   (- )-r'\n\n      const sharedSource = source.pipe(share({ resetOnError: () => reset, resetOnRefCountZero }));\n\n      const result = concat(sharedSource.pipe(onErrorResumeNextWith(firstPause)), sharedSource);\n\n      expectObservable(result, subscription).toBe(expected);\n      expectSubscriptions(source.subscriptions).toBe(sourceSubs);\n      expect(resetOnRefCountZero).to.not.have.been.called;\n    });\n  });\n\n  it('should not call \"resetOnRefCountZero\" on complete', () => {\n    rxTest.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const resetOnRefCountZero = spy(() => EMPTY);\n\n      const source = cold('    ---1---(2|)                ');\n      // source: '                           ---1---(2|)  '\n      const sourceSubs = [\n        '                      ^------(! )                ',\n        // break the line, please\n        '                      -------(- )---^------(! )  ',\n      ];\n      const expected = '       ---1---(2 )------1---(2|)  ';\n      const subscription = '   ^------(- )----------(- )  ';\n      const firstPause = cold('       (- )---|            ');\n      const reset = cold('            (- )-r              ');\n      // reset: '                                   (- )-r'\n\n      const sharedSource = source.pipe(share({ resetOnComplete: () => reset, resetOnRefCountZero }));\n\n      const result = concat(sharedSource, firstPause, sharedSource);\n\n      expectObservable(result, subscription).toBe(expected);\n      expectSubscriptions(source.subscriptions).toBe(sourceSubs);\n      expect(resetOnRefCountZero).to.not.have.been.called;\n    });\n  });\n});\n"
  },
  {
    "path": "packages/rxjs/spec/operators/shareReplay-spec.ts",
    "content": "import { expect } from 'chai';\nimport * as sinon from 'sinon';\nimport { shareReplay, mergeMapTo, retry, take } from 'rxjs/operators';\nimport { TestScheduler } from 'rxjs/testing';\nimport { Observable, Operator, Observer, of, from, defer, pipe, combineLatest, firstValueFrom, BehaviorSubject } from 'rxjs';\nimport { observableMatcher } from '../helpers/observableMatcher';\n\n/** @test {shareReplay} */\ndescribe('shareReplay', () => {\n  let testScheduler: TestScheduler;\n\n  beforeEach(() => {\n    testScheduler = new TestScheduler(observableMatcher);\n  });\n\n  it('should mirror a simple source Observable', () => {\n    testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const source = cold('--1-2---3-4--5-|');\n      const sourceSubs = ' ^--------------!';\n      const expected = '   --1-2---3-4--5-|';\n\n      const published = source.pipe(shareReplay());\n\n      expectObservable(published).toBe(expected);\n      expectSubscriptions(source.subscriptions).toBe(sourceSubs);\n    });\n  });\n\n  it('should do nothing if result is not subscribed', () => {\n    let subscribed = false;\n    const source = new Observable(() => {\n      subscribed = true;\n    });\n    source.pipe(shareReplay());\n    expect(subscribed).to.be.false;\n  });\n\n  it('should multicast the same values to multiple observers, bufferSize=1', () => {\n    testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => {\n      const source = cold('    -1-2-3----4-|');\n      const sourceSubs = '     ^-----------!';\n      const subscriber1 = hot('a|           ');\n      const expected1 = '      -1-2-3----4-|';\n      const subscriber2 = hot('----b|       ');\n      const expected2 = '      ----23----4-|';\n      const subscriber3 = hot('--------c|   ');\n      const expected3 = '      --------3-4-|';\n\n      const shared = source.pipe(shareReplay(1));\n\n      expectObservable(subscriber1.pipe(mergeMapTo(shared))).toBe(expected1);\n      expectObservable(subscriber2.pipe(mergeMapTo(shared))).toBe(expected2);\n      expectObservable(subscriber3.pipe(mergeMapTo(shared))).toBe(expected3);\n      expectSubscriptions(source.subscriptions).toBe(sourceSubs);\n    });\n  });\n\n  it('should multicast the same values to multiple observers, bufferSize=2', () => {\n    testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => {\n      const source = cold('    -1-2-----3------4-|');\n      const sourceSubs = '     ^-----------------!';\n      const subscriber1 = hot('a|                 ');\n      const expected1 = '      -1-2-----3------4-|';\n      const subscriber2 = hot('----b|             ');\n      const expected2 = '      ----(12)-3------4-|';\n      const subscriber3 = hot('-----------c|      ');\n      const expected3 = '      -----------(23)-4-|';\n\n      const shared = source.pipe(shareReplay(2));\n\n      expectObservable(subscriber1.pipe(mergeMapTo(shared))).toBe(expected1);\n      expectObservable(subscriber2.pipe(mergeMapTo(shared))).toBe(expected2);\n      expectObservable(subscriber3.pipe(mergeMapTo(shared))).toBe(expected3);\n      expectSubscriptions(source.subscriptions).toBe(sourceSubs);\n    });\n  });\n\n  it('should multicast an error from the source to multiple observers', () => {\n    testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => {\n      const source = cold('    -1-2-3----4-#');\n      const sourceSubs = '     ^-----------!';\n      const subscriber1 = hot('a|           ');\n      const expected1 = '      -1-2-3----4-#';\n      const subscriber2 = hot('----b|       ');\n      const expected2 = '      ----23----4-#';\n      const subscriber3 = hot('--------c|   ');\n      const expected3 = '      --------3-4-#';\n\n      const shared = source.pipe(shareReplay(1));\n\n      expectObservable(subscriber1.pipe(mergeMapTo(shared))).toBe(expected1);\n      expectObservable(subscriber2.pipe(mergeMapTo(shared))).toBe(expected2);\n      expectObservable(subscriber3.pipe(mergeMapTo(shared))).toBe(expected3);\n      expectSubscriptions(source.subscriptions).toBe(sourceSubs);\n    });\n  });\n\n  it('should multicast an empty source', () => {\n    testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const source = cold('|   ');\n      const sourceSubs = ' (^!)';\n      const expected = '   |   ';\n\n      const shared = source.pipe(shareReplay(1));\n\n      expectObservable(shared).toBe(expected);\n      expectSubscriptions(source.subscriptions).toBe(sourceSubs);\n    });\n  });\n\n  it('should multicast a never source', () => {\n    testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const source = cold('-');\n      const sourceSubs = ' ^';\n      const expected = '   -';\n\n      const shared = source.pipe(shareReplay(1));\n\n      expectObservable(shared).toBe(expected);\n      expectSubscriptions(source.subscriptions).toBe(sourceSubs);\n    });\n  });\n\n  it('should multicast a throw source', () => {\n    testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const source = cold('#   ');\n      const sourceSubs = ' (^!)';\n      const expected = '   #   ';\n\n      const shared = source.pipe(shareReplay(1));\n\n      expectObservable(shared).toBe(expected);\n      expectSubscriptions(source.subscriptions).toBe(sourceSubs);\n    });\n  });\n\n  it('should replay results to subsequent subscriptions if source completes, bufferSize=2', () => {\n    testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => {\n      const source = cold('    -1-2-----3-|        ');\n      const sourceSubs = '     ^----------!        ';\n      const subscriber1 = hot('a|                  ');\n      const expected1 = '      -1-2-----3-|        ';\n      const subscriber2 = hot('----b|              ');\n      const expected2 = '      ----(12)-3-|        ';\n      const subscriber3 = hot('---------------(c|) ');\n      const expected3 = '      ---------------(23|)';\n\n      const shared = source.pipe(shareReplay(2));\n\n      expectObservable(subscriber1.pipe(mergeMapTo(shared))).toBe(expected1);\n      expectObservable(subscriber2.pipe(mergeMapTo(shared))).toBe(expected2);\n      expectObservable(subscriber3.pipe(mergeMapTo(shared))).toBe(expected3);\n      expectSubscriptions(source.subscriptions).toBe(sourceSubs);\n    });\n  });\n\n  it('should completely restart for subsequent subscriptions if source errors, bufferSize=2', () => {\n    testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => {\n      const source = cold('    -1-2-----3-#               ');\n      const sourceSubs1 = '    ^----------!               ';\n      const subscriber1 = hot('a|                         ');\n      const expected1 = '      -1-2-----3-#               ';\n      const subscriber2 = hot('----b|                     ');\n      const expected2 = '      ----(12)-3-#               ';\n      const subscriber3 = hot('---------------(c|)        ');\n      const expected3 = '      ----------------1-2-----3-#';\n      const sourceSubs2 = '    ---------------^----------!';\n\n      const shared = source.pipe(shareReplay(2));\n\n      expectObservable(subscriber1.pipe(mergeMapTo(shared))).toBe(expected1);\n      expectObservable(subscriber2.pipe(mergeMapTo(shared))).toBe(expected2);\n      expectObservable(subscriber3.pipe(mergeMapTo(shared))).toBe(expected3);\n      expectSubscriptions(source.subscriptions).toBe([sourceSubs1, sourceSubs2]);\n    });\n  });\n\n  it('should be retryable, bufferSize=2', () => {\n    testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => {\n      const subs = [];\n      const source = cold('    -1-2-----3-#                      ');\n      subs.push('              ^----------!                      ');\n      subs.push('              -----------^----------!           ');\n      subs.push('              ----------------------^----------!');\n      const subscriber1 = hot('a|                                ');\n      const expected1 = '      -1-2-----3--1-2-----3-#           ';\n      const subscriber2 = hot('----b|                            ');\n      const expected2 = '      ----(12)-3--1-2-----3-#           ';\n      const subscriber3 = hot('---------------(c|)               ');\n      const expected3 = '      ---------------(12)-3--1-2-----3-#';\n\n      const shared = source.pipe(shareReplay(2), retry(1));\n\n      expectObservable(subscriber1.pipe(mergeMapTo(shared))).toBe(expected1);\n      expectObservable(subscriber2.pipe(mergeMapTo(shared))).toBe(expected2);\n      expectObservable(subscriber3.pipe(mergeMapTo(shared))).toBe(expected3);\n      expectSubscriptions(source.subscriptions).toBe(subs);\n    });\n  });\n\n  it('when no windowTime is given ReplaySubject should be in _infiniteTimeWindow mode', () => {\n    const spy = sinon.spy(testScheduler, 'now');\n\n    of(1).pipe(shareReplay(1, undefined, testScheduler)).subscribe();\n    spy.restore();\n    expect(spy, 'ReplaySubject should not call scheduler.now() when no windowTime is given').to.be.not.called;\n  });\n\n  it('should not restart due to unsubscriptions if refCount is false', () => {\n    testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const source = cold('a-b-c-d-e-f-g-h-i-j');\n      const sourceSubs = ' ^------------------';\n      const sub1 = '       ^------!           ';\n      const expected1 = '  a-b-c-d-           ';\n      const sub2 = '       -----------^-------';\n      const expected2 = '  -----------fg-h-i-j';\n\n      const shared = source.pipe(shareReplay({ bufferSize: 1, refCount: false }));\n\n      expectObservable(shared, sub1).toBe(expected1);\n      expectObservable(shared, sub2).toBe(expected2);\n      expectSubscriptions(source.subscriptions).toBe(sourceSubs);\n    });\n  });\n\n  it('should restart due to unsubscriptions if refCount is true', () => {\n    testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const sourceSubs = [];\n      const source = cold('a-b-c-d-e-f-g-h-i-j           ');\n      sourceSubs.push('    ^------!----------------------');\n      sourceSubs.push('    -----------^------------------');\n      const sub1 = '       ^------!                      ';\n      const expected1 = '  a-b-c-d-                      ';\n      const sub2 = '       -----------^------------------';\n      const expected2 = '  -----------a-b-c-d-e-f-g-h-i-j';\n\n      const shared = source.pipe(shareReplay({ bufferSize: 1, refCount: true }));\n\n      expectObservable(shared, sub1).toBe(expected1);\n      expectObservable(shared, sub2).toBe(expected2);\n      expectSubscriptions(source.subscriptions).toBe(sourceSubs);\n    });\n  });\n\n  it('should not restart due to unsubscriptions if refCount is true when the source has completed', () => {\n    testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const source = cold('a-(b|)         ');\n      const sourceSubs = ' ^-!            ';\n      const sub1 = '       ^------!       ';\n      const expected1 = '  a-(b|)         ';\n      const sub2 = '       -----------^!  ';\n      const expected2 = '  -----------(b|)';\n\n      const shared = source.pipe(shareReplay({ bufferSize: 1, refCount: true }));\n\n      expectObservable(shared, sub1).toBe(expected1);\n      expectObservable(shared, sub2).toBe(expected2);\n      expectSubscriptions(source.subscriptions).toBe(sourceSubs);\n    });\n  });\n\n  it('should not restart a synchronous source due to unsubscriptions if refCount is true when the source has completed', () => {\n    // The test above this one doesn't actually test completely synchronous\n    // behaviour because of this problem:\n    // https://github.com/ReactiveX/rxjs/issues/5523\n\n    let subscriptions = 0;\n    const source = defer(() => {\n      ++subscriptions;\n      return of(42);\n    }).pipe(shareReplay({ bufferSize: 1, refCount: true }));\n    source.subscribe();\n    source.subscribe();\n    expect(subscriptions).to.equal(1);\n  });\n\n  it('should only subscribe once each with multiple synchronous subscriptions and unsubscriptions ', async () => {\n    // This may seem very specific, but it's a regression test for https://github.com/ReactiveX/rxjs/issues/6760\n\n    let subscriptions = 0;\n    const source = defer(() => {\n      ++subscriptions;\n      // Needs to be an observable that doesn't complete\n      return new BehaviorSubject(1);\n    }).pipe(shareReplay({ bufferSize: 1, refCount: true }));\n\n    await firstValueFrom(combineLatest([source, source]));\n    expect(subscriptions).to.equal(1);\n  });\n\n  it('should default to refCount being false', () => {\n    testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const source = cold('a-b-c-d-e-f-g-h-i-j');\n      const sourceSubs = ' ^------------------';\n      const sub1 = '       ^------!           ';\n      const expected1 = '  a-b-c-d-           ';\n      const sub2 = '       -----------^-------';\n      const expected2 = '  -----------fg-h-i-j';\n\n      const shared = source.pipe(shareReplay(1));\n\n      expectObservable(shared, sub1).toBe(expected1);\n      expectObservable(shared, sub2).toBe(expected2);\n      expectSubscriptions(source.subscriptions).toBe(sourceSubs);\n    });\n  });\n\n  it('should not skip values on a sync source', () => {\n    testScheduler.run(({ cold, expectObservable }) => {\n      const a = from(['a', 'b', 'c', 'd']);\n      // We would like for the previous line to read like this:\n      //\n      // const a = cold('(abcd|)');\n      //\n      // However, that would synchronously emit multiple values at frame 0,\n      // but it's not synchronous upon-subscription.\n      // TODO: revisit once https://github.com/ReactiveX/rxjs/issues/5523 is fixed\n\n      const x = cold('  x-------x');\n      const expected = '(abcd)--d';\n\n      const shared = a.pipe(shareReplay(1));\n      const result = x.pipe(mergeMapTo(shared));\n      expectObservable(result).toBe(expected);\n    });\n  });\n\n  it('should stop listening to a synchronous observable when unsubscribed', () => {\n    const sideEffects: number[] = [];\n    const synchronousObservable = new Observable<number>((subscriber) => {\n      // This will check to see if the subscriber was closed on each loop\n      // when the unsubscribe hits (from the `take`), it should be closed\n      for (let i = 0; !subscriber.closed && i < 10; i++) {\n        sideEffects.push(i);\n        subscriber.next(i);\n      }\n    });\n\n    synchronousObservable.pipe(shareReplay({ refCount: true }), take(3)).subscribe(() => {\n      /* noop */\n    });\n\n    expect(sideEffects).to.deep.equal([0, 1, 2]);\n  });\n\n  const FinalizationRegistry = (global as any).FinalizationRegistry;\n  if (FinalizationRegistry && global.gc) {\n    it('should not leak the subscriber for sync sources', (done) => {\n      let callback: (() => void) | undefined = () => {\n        /* noop */\n      };\n\n      const registry = new FinalizationRegistry((value: any) => {\n        expect(value).to.equal('callback');\n        done();\n      });\n      registry.register(callback, 'callback');\n\n      const shared = of(42).pipe(shareReplay(1));\n      shared.subscribe(callback);\n\n      callback = undefined;\n      global.gc?.();\n    });\n  } else {\n    console.warn(`No support for FinalizationRegistry in Node ${process.version}`);\n  }\n\n  it('should be referentially-transparent', () => {\n    testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const source1 = cold('-1-2-3-4-5-|');\n      const source1Subs = ' ^----------!';\n      const expected1 = '   -1-2-3-4-5-|';\n      const source2 = cold('-6-7-8-9-0-|');\n      const source2Subs = ' ^----------!';\n      const expected2 = '   -6-7-8-9-0-|';\n\n      // Calls to the _operator_ must be referentially-transparent.\n      const partialPipeLine = pipe(shareReplay({ refCount: false }));\n\n      // The non-referentially-transparent sharing occurs within the _operator function_\n      // returned by the _operator_ and that happens when the complete pipeline is composed.\n      const shared1 = source1.pipe(partialPipeLine);\n      const shared2 = source2.pipe(partialPipeLine);\n\n      expectObservable(shared1).toBe(expected1);\n      expectSubscriptions(source1.subscriptions).toBe(source1Subs);\n      expectObservable(shared2).toBe(expected2);\n      expectSubscriptions(source2.subscriptions).toBe(source2Subs);\n    });\n  });\n});\n"
  },
  {
    "path": "packages/rxjs/spec/operators/single-spec.ts",
    "content": "import { expect } from 'chai';\nimport { single, mergeMap, tap } from 'rxjs/operators';\nimport { of, EmptyError, SequenceError, NotFoundError, Observable } from 'rxjs';\nimport { TestScheduler } from 'rxjs/testing';\nimport { observableMatcher } from '../helpers/observableMatcher';\n\n/** @test {single} */\ndescribe('single operator', () => {\n  let rxTest: TestScheduler;\n\n  beforeEach(() => {\n    rxTest = new TestScheduler(observableMatcher);\n  });\n\n  it('should raise error from empty predicate if observable emits multiple time', () => {\n    rxTest.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  --a--b--c--|');\n      const e1subs = '  ^----!      ';\n      const expected = '-----#      ';\n\n      expectObservable(e1.pipe(single())).toBe(expected, null, new SequenceError('Too many matching values'));\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should raise error from empty predicate if observable does not emit', () => {\n    rxTest.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('--a--^--|');\n      const e1subs = '     ^--!';\n      const expected = '   ---#';\n\n      expectObservable(e1.pipe(single())).toBe(expected, null, new EmptyError());\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should return only element from empty predicate if observable emits only once', () => {\n    rxTest.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  --a--|');\n      const e1subs = '  ^----!';\n      const expected = '-----(a|)';\n\n      expectObservable(e1.pipe(single())).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should allow unsubscribing explicitly and early', () => {\n    rxTest.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  --a--b--c--|');\n      const unsub = '   ----!        ';\n      const e1subs = '  ^---!        ';\n      const expected = '------------';\n\n      expectObservable(e1.pipe(single()), unsub).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should not break unsubscription chains when result is unsubscribed explicitly', () => {\n    rxTest.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  --a--b--c--|');\n      const e1subs = '  ^--!        ';\n      const expected = '----        ';\n      const unsub = '   ---!        ';\n\n      const result = e1.pipe(\n        mergeMap((x) => of(x)),\n        single(),\n        mergeMap((x) => of(x))\n      );\n\n      expectObservable(result, unsub).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should raise error from empty predicate if observable emits error', () => {\n    rxTest.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  --a--b^--#');\n      const e1subs = '        ^--!';\n      const expected = '      ---#';\n\n      expectObservable(e1.pipe(single())).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should raise error from predicate if observable emits error', () => {\n    rxTest.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('--a--b^--#');\n      const e1subs = '      ^--!';\n      const expected = '    ---#';\n\n      expectObservable(e1.pipe(single((v) => v === 'c'))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should raise error if predicate throws error', () => {\n    rxTest.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  --a--b--c--d--|');\n      const e1subs = '  ^----------!   ';\n      const expected = '-----------#   ';\n\n      expectObservable(\n        e1.pipe(\n          single((v) => {\n            if (v !== 'd') {\n              return false;\n            }\n            throw 'error';\n          })\n        )\n      ).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should return element from predicate if observable have single matching element', () => {\n    rxTest.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  --a--b--c--|');\n      const e1subs = '  ^----------!';\n      const expected = '-----------(b|)';\n\n      expectObservable(e1.pipe(single((v) => v === 'b'))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should raise error from predicate if observable have multiple matching element', () => {\n    rxTest.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  --a--b--a--b--b--|');\n      const e1subs = '  ^----------!      ';\n      const expected = '-----------#      ';\n\n      expectObservable(e1.pipe(single((v) => v === 'b'))).toBe(expected, null, new SequenceError('Too many matching values'));\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should raise error from predicate if observable does not emit', () => {\n    rxTest.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('--a--^--|');\n      const e1subs = '     ^--!';\n      const expected = '   ---#';\n\n      expectObservable(e1.pipe(single((v) => v === 'a'))).toBe(expected, null, new EmptyError());\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should raise error from predicate if observable does not contain matching element', () => {\n    rxTest.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  --a--b--c--|');\n      const e1subs = '  ^----------!';\n      const expected = '-----------#';\n\n      expectObservable(e1.pipe(single((v) => v === 'x'))).toBe(expected, undefined, new NotFoundError('No matching values'));\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should call predicate with indices starting at 0', () => {\n    rxTest.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  --a--b--c--|');\n      const e1subs = '  ^----------!';\n      const expected = '-----------(b|)';\n\n      const indices: number[] = [];\n      const predicate = function (value: string, index: number) {\n        indices.push(index);\n        return value === 'b';\n      };\n\n      expectObservable(\n        e1.pipe(\n          single(predicate),\n          tap({\n            complete: () => {\n              expect(indices).to.deep.equal([0, 1, 2]);\n            },\n          })\n        )\n      ).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should error for synchronous empty observables when no arguments are provided', () => {\n    rxTest.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const source = cold('|');\n      const expected = '   #';\n      const subs = ['      (^!)'];\n      const result = source.pipe(single());\n\n      expectObservable(result).toBe(expected, undefined, new EmptyError());\n      expectSubscriptions(source.subscriptions).toBe(subs);\n    });\n  });\n\n  it('should error for async empty observables when no arguments are provided', () => {\n    rxTest.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const source = cold('-------|');\n      const expected = '   -------#';\n      const subs = ['      ^------!'];\n      const result = source.pipe(single());\n\n      expectObservable(result).toBe(expected, undefined, new EmptyError());\n      expectSubscriptions(source.subscriptions).toBe(subs);\n    });\n  });\n\n  it('should error for hot observables that do not emit while active when no arguments are provided', () => {\n    rxTest.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const source = hot('--a--b--^----|');\n      const expected = '          -----#';\n      const subs = ['             ^----!'];\n      const result = source.pipe(single());\n\n      expectObservable(result).toBe(expected, undefined, new EmptyError());\n      expectSubscriptions(source.subscriptions).toBe(subs);\n    });\n  });\n\n  it('should error for synchronous empty observables when predicate never passes', () => {\n    rxTest.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const source = cold('|');\n      const expected = '   #';\n      const subs = ['      (^!)'];\n      const result = source.pipe(single(() => false));\n\n      expectObservable(result).toBe(expected, undefined, new EmptyError());\n      expectSubscriptions(source.subscriptions).toBe(subs);\n    });\n  });\n\n  it('should error for async empty observables when predicate never passes', () => {\n    rxTest.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const source = cold('-------|');\n      const expected = '   -------#';\n      const subs = ['      ^------!'];\n      const result = source.pipe(single(() => false));\n\n      expectObservable(result).toBe(expected, undefined, new EmptyError());\n      expectSubscriptions(source.subscriptions).toBe(subs);\n    });\n  });\n\n  it('should error for hot observables that do not emit while active when predicate never passes', () => {\n    rxTest.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const source = hot('--a--b--^----|');\n      const expected = '          -----#';\n      const subs = ['             ^----!'];\n      const result = source.pipe(single(() => false));\n\n      expectObservable(result).toBe(expected, undefined, new EmptyError());\n      expectSubscriptions(source.subscriptions).toBe(subs);\n    });\n  });\n\n  it('should error for synchronous observables that emit when predicate never passes', () => {\n    rxTest.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const source = cold('(a|)');\n      const expected = '   #';\n      const subs = ['      (^!)'];\n      const result = source.pipe(single(() => false));\n\n      expectObservable(result).toBe(expected, undefined, new NotFoundError('No matching values'));\n      expectSubscriptions(source.subscriptions).toBe(subs);\n    });\n  });\n\n  it('should error for async observables that emit when predicate never passes', () => {\n    rxTest.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const source = cold('--a--b-|');\n      const expected = '   -------#';\n      const subs = ['      ^------!'];\n      const result = source.pipe(single(() => false));\n\n      expectObservable(result).toBe(expected, undefined, new NotFoundError('No matching values'));\n      expectSubscriptions(source.subscriptions).toBe(subs);\n    });\n  });\n\n  it('should error for hot observables that emit while active when predicate never passes', () => {\n    rxTest.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const source = hot('--a--b--^--c--d--|');\n      const expected = '          ---------#';\n      const subs = ['             ^--------!'];\n      const result = source.pipe(single(() => false));\n\n      expectObservable(result).toBe(expected, undefined, new NotFoundError('No matching values'));\n      expectSubscriptions(source.subscriptions).toBe(subs);\n    });\n  });\n\n  it('should error for synchronous observables when the predicate passes more than once', () => {\n    rxTest.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const source = cold('(axbxc|)');\n      const expected = '   #';\n      const subs = ['      (^!)'];\n      const result = source.pipe(single((v) => v === 'x'));\n\n      expectObservable(result).toBe(expected, undefined, new SequenceError('Too many matching values'));\n      expectSubscriptions(source.subscriptions).toBe(subs);\n    });\n  });\n\n  it('should error for async observables that emit when the predicate passes more than once', () => {\n    rxTest.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const source = cold('--a-x-b-x-c-|');\n      const expected = '   --------#';\n      const subs = ['      ^-------!'];\n      const result = source.pipe(single((v) => v === 'x'));\n\n      expectObservable(result).toBe(expected, undefined, new SequenceError('Too many matching values'));\n      expectSubscriptions(source.subscriptions).toBe(subs);\n    });\n  });\n\n  it('should error for hot observables that emit while active when the predicate passes more than once', () => {\n    rxTest.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const source = hot('--a--b--^--c--x--d--x--|');\n      const expected = '          ------------#';\n      const subs = ['             ^-----------!'];\n      const result = source.pipe(single((v) => v === 'x'));\n\n      expectObservable(result).toBe(expected, undefined, new SequenceError('Too many matching values'));\n      expectSubscriptions(source.subscriptions).toBe(subs);\n    });\n  });\n\n  it('should stop listening to a synchronous observable when unsubscribed', () => {\n    const sideEffects: number[] = [];\n    const synchronousObservable = new Observable<number>((subscriber) => {\n      // This will check to see if the subscriber was closed on each loop\n      // when the unsubscribe hits, it should be closed\n      for (let i = 0; !subscriber.closed && i < 10; i++) {\n        sideEffects.push(i);\n        subscriber.next(i);\n      }\n    });\n\n    synchronousObservable.pipe(single()).subscribe({\n      next: () => {\n        /* noop */\n      },\n      error: () => {\n        /* noop */\n      },\n    });\n\n    expect(sideEffects).to.deep.equal([0, 1]);\n  });\n});\n"
  },
  {
    "path": "packages/rxjs/spec/operators/skip-spec.ts",
    "content": "import { expect } from 'chai';\nimport { skip, mergeMap, take } from 'rxjs/operators';\nimport { TestScheduler } from 'rxjs/testing';\nimport { observableMatcher } from '../helpers/observableMatcher';\nimport { of, Observable } from 'rxjs';\n\n/** @test {skip} */\ndescribe('skip', () => {\n  let testScheduler: TestScheduler;\n\n  beforeEach(() => {\n    testScheduler = new TestScheduler(observableMatcher);\n  });\n\n  it('should skip values before a total', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const source = hot('--a--b--c--d--e--|');\n      const subs = '      ^----------------!';\n      const expected = '  -----------d--e--|';\n\n      expectObservable(source.pipe(skip(3))).toBe(expected);\n      expectSubscriptions(source.subscriptions).toBe(subs);\n    });\n  });\n\n  it('should skip all values without error if total is more than actual number of values', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const source = hot('--a--b--c--d--e--|');\n      const subs = '      ^----------------!';\n      const expected = '  -----------------|';\n\n      expectObservable(source.pipe(skip(6))).toBe(expected);\n      expectSubscriptions(source.subscriptions).toBe(subs);\n    });\n  });\n\n  it('should skip all values without error if total is same as actual number of values', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const source = hot('--a--b--c--d--e--|');\n      const subs = '      ^----------------!';\n      const expected = '  -----------------|';\n\n      expectObservable(source.pipe(skip(5))).toBe(expected);\n      expectSubscriptions(source.subscriptions).toBe(subs);\n    });\n  });\n\n  it('should not skip if count is zero', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const source = hot('--a--b--c--d--e--|');\n      const subs = '      ^----------------!';\n      const expected = '  --a--b--c--d--e--|';\n\n      expectObservable(source.pipe(skip(0))).toBe(expected);\n      expectSubscriptions(source.subscriptions).toBe(subs);\n    });\n  });\n\n  it('should not skip if count is negative value', () => {\n    testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const source = cold('--a--b--c--d--e--|');\n      const subs = '       ^----------------!';\n      const expected = '   --a--b--c--d--e--|';\n\n      expectObservable(source.pipe(skip(-42))).toBe(expected);\n      expectSubscriptions(source.subscriptions).toBe(subs);\n    });\n  });\n\n  it('should allow unsubscribing explicitly and early', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const source = hot('--a--b--c--d--e--|');\n      const unsub = '     ----------!       ';\n      const subs = '      ^---------!       ';\n      const expected = '  --------c--       ';\n\n      expectObservable(source.pipe(skip(2)), unsub).toBe(expected);\n      expectSubscriptions(source.subscriptions).toBe(subs);\n    });\n  });\n\n  it('should not break unsubscription chains when result is unsubscribed explicitly', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const source = hot('--a--b--c--d--e--|');\n      const subs = '      ^---------!       ';\n      const expected = '  --------c--       ';\n      const unsub = '     ----------!       ';\n\n      const result = source.pipe(\n        mergeMap((x: string) => of(x)),\n        skip(2),\n        mergeMap((x: string) => of(x))\n      );\n\n      expectObservable(result, unsub).toBe(expected);\n      expectSubscriptions(source.subscriptions).toBe(subs);\n    });\n  });\n\n  it('should raise error if skip count is more than actual number of emits and source raises error', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const source = hot('--a--b--c--d--#');\n      const subs = '      ^-------------!';\n      const expected = '  --------------#';\n\n      expectObservable(source.pipe(skip(6))).toBe(expected);\n      expectSubscriptions(source.subscriptions).toBe(subs);\n    });\n  });\n\n  it('should raise error if skip count is same as emits of source and source raises error', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const source = hot('--a--b--c--d--#');\n      const subs = '      ^-------------!';\n      const expected = '  --------------#';\n\n      expectObservable(source.pipe(skip(4))).toBe(expected);\n      expectSubscriptions(source.subscriptions).toBe(subs);\n    });\n  });\n\n  it('should skip values before a total and raises error if source raises error', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const source = hot('--a--b--c--d--#');\n      const subs = '      ^-------------!';\n      const expected = '  -----------d--#';\n\n      expectObservable(source.pipe(skip(3))).toBe(expected);\n      expectSubscriptions(source.subscriptions).toBe(subs);\n    });\n  });\n\n  it('should complete regardless of skip count if source is empty', () => {\n    testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' |');\n      const e1subs = '  (^!)';\n      const expected = '|';\n\n      expectObservable(e1.pipe(skip(3))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should not complete if source never completes without emit', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  -');\n      const e1subs = '  ^';\n      const expected = '-';\n\n      expectObservable(e1.pipe(skip(3))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should skip values before total and never completes if source emits and does not complete', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  --a--b--c-');\n      const e1subs = '  ^         ';\n      const expected = '-----b--c-';\n\n      expectObservable(e1.pipe(skip(1))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should skip all values and never completes if total is more than numbers of value and source does not complete', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  --a--b--c-');\n      const e1subs = '  ^         ';\n      const expected = '----------';\n\n      expectObservable(e1.pipe(skip(6))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should skip all values and never completes if total is same asnumbers of value and source does not complete', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  --a--b--c-');\n      const e1subs = '  ^         ';\n      const expected = '----------';\n\n      expectObservable(e1.pipe(skip(3))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should raise error if source throws', () => {\n    testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' #');\n      const e1subs = '  (^!)';\n      const expected = '#';\n\n      expectObservable(e1.pipe(skip(3))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should stop listening to a synchronous observable when unsubscribed', () => {\n    const sideEffects: number[] = [];\n    const synchronousObservable = new Observable<number>((subscriber) => {\n      // This will check to see if the subscriber was closed on each loop\n      // when the unsubscribe hits (from the `take`), it should be closed\n      for (let i = 0; !subscriber.closed && i < 10; i++) {\n        sideEffects.push(i);\n        subscriber.next(i);\n      }\n    });\n\n    synchronousObservable.pipe(skip(1), take(2)).subscribe(() => {\n      /* noop */\n    });\n\n    expect(sideEffects).to.deep.equal([0, 1, 2]);\n  });\n});\n"
  },
  {
    "path": "packages/rxjs/spec/operators/skipLast-spec.ts",
    "content": "import { expect } from 'chai';\nimport { skipLast, mergeMap, take } from 'rxjs/operators';\nimport { of, Observable } from 'rxjs';\nimport { TestScheduler } from 'rxjs/testing';\nimport { observableMatcher } from '../helpers/observableMatcher';\n\n/** @test {skipLast} */\ndescribe('skipLast operator', () => {\n  let testScheduler: TestScheduler;\n\n  beforeEach(() => {\n    testScheduler = new TestScheduler(observableMatcher);\n  });\n\n  it('should skip two values of an observable with many values', () => {\n    testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' --a-----b----c---d--|');\n      const e1subs = '  ^-------------------!';\n      const expected = '-------------a---b--|';\n\n      expectObservable(e1.pipe(skipLast(2))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should skip last three values', () => {\n    testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' --a-----b----c---d--|');\n      const e1subs = '  ^-------------------!';\n      const expected = '-----------------a--|';\n\n      expectObservable(e1.pipe(skipLast(3))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should skip all elements when trying to skip larger then source', () => {\n    testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' --a-----b----c---d--|');\n      const e1subs = '  ^-------------------!';\n      const expected = '--------------------|';\n\n      expectObservable(e1.pipe(skipLast(5))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should skip all elements when trying to skip exact', () => {\n    testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' --a-----b----c---d--|');\n      const e1subs = '  ^-------------------!';\n      const expected = '--------------------|';\n\n      expectObservable(e1.pipe(skipLast(4))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should not skip any values', () => {\n    testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' --a-----b----c---d--|');\n      const e1subs = '  ^-------------------!';\n      const expected = '--a-----b----c---d--|';\n\n      expectObservable(e1.pipe(skipLast(0))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should not skip any values if provided with negative value', () => {\n    testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' --a-----b----c---d--|');\n      const e1subs = '  ^-------------------!';\n      const expected = '--a-----b----c---d--|';\n\n      expectObservable(e1.pipe(skipLast(-42))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should work with empty', () => {\n    testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' |');\n      const e1subs = '  (^!)';\n      const expected = '|';\n\n      expectObservable(e1.pipe(skipLast(42))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should go on forever on never', () => {\n    testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' -');\n      const e1subs = '  ^';\n      const expected = '-';\n\n      expectObservable(e1.pipe(skipLast(42))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should skip one value from an observable with one value', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  ---(a|)');\n      const e1subs = '  ^--!   ';\n      const expected = '---|   ';\n\n      expectObservable(e1.pipe(skipLast(1))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should skip one value from an observable with many values', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('--a--^--b----c---d--|');\n      const e1subs = '     ^--------------!';\n      const expected = '   --------b---c--|';\n\n      expectObservable(e1.pipe(skipLast(1))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should work with empty and early emission', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('--a--^----|');\n      const e1subs = '     ^----!';\n      const expected = '   -----|';\n\n      expectObservable(e1.pipe(skipLast(42))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should propagate error from the source observable', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('---^---#', undefined, 'too bad');\n      const e1subs = '   ^---!';\n      const expected = ' ----#';\n\n      expectObservable(e1.pipe(skipLast(42))).toBe(expected, null, 'too bad');\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should propagate error from an observable with values', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('---^--a--b--#');\n      const e1subs = '   ^--------!';\n      const expected = ' ---------#';\n\n      expectObservable(e1.pipe(skipLast(42))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should allow unsubscribing explicitly and early', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('---^--a--b-----c--d--e--|');\n      const unsub = '    ---------!            ';\n      const e1subs = '   ^--------!            ';\n      const expected = ' ----------            ';\n\n      expectObservable(e1.pipe(skipLast(42)), unsub).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should work with throw', () => {\n    testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' #');\n      const e1subs = '  (^!)';\n      const expected = '#';\n\n      expectObservable(e1.pipe(skipLast(42))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should not break unsubscription chain when unsubscribed explicitly', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('---^--a--b-----c--d--e--|');\n      const unsub = '    ---------!            ';\n      const e1subs = '   ^--------!            ';\n      const expected = ' ----------            ';\n\n      const result = e1.pipe(\n        mergeMap((x: string) => of(x)),\n        skipLast(42),\n        mergeMap((x: string) => of(x))\n      );\n\n      expectObservable(result, unsub).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should stop listening to a synchronous observable when unsubscribed', () => {\n    const sideEffects: number[] = [];\n    const synchronousObservable = new Observable<number>((subscriber) => {\n      // This will check to see if the subscriber was closed on each loop\n      // when the unsubscribe hits (from the `take`), it should be closed\n      for (let i = 0; !subscriber.closed && i < 10; i++) {\n        sideEffects.push(i);\n        subscriber.next(i);\n      }\n    });\n\n    synchronousObservable.pipe(skipLast(1), take(3)).subscribe(() => {\n      /* noop */\n    });\n\n    // This expectation might seem a little strange, but the implementation of\n    // skipLast works by eating the number of elements that are to be skipped,\n    // so it will consume the number skipped in addition to the number taken.\n    expect(sideEffects).to.deep.equal([0, 1, 2, 3]);\n  });\n});\n"
  },
  {
    "path": "packages/rxjs/spec/operators/skipUntil-spec.ts",
    "content": "import { expect } from 'chai';\nimport { concat, defer, of, Subject, Observable, interval } from 'rxjs';\nimport { skipUntil, mergeMap, take } from 'rxjs/operators';\nimport { asInteropObservable } from '../helpers/interop-helper';\nimport { TestScheduler } from 'rxjs/testing';\nimport { observableMatcher } from '../helpers/observableMatcher';\n\n/** @test {skipUntil} */\ndescribe('skipUntil', () => {\n  let testScheduler: TestScheduler;\n\n  beforeEach(() => {\n    testScheduler = new TestScheduler(observableMatcher);\n  });\n\n  it('should skip values until another observable notifies', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('    --a--b--c--d--e----|');\n      const e1subs = '    ^------------------!';\n      const skip = hot('  ---------x------|   ');\n      const skipSubs = '  ^--------!          ';\n      const expected = '  -----------d--e----|';\n\n      expectObservable(e1.pipe(skipUntil(skip))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(skip.subscriptions).toBe(skipSubs);\n    });\n  });\n\n  it('should emit elements after notifier emits', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('    --a--b--c--d--e--|');\n      const e1subs = '    ^----------------!';\n      const skip = hot('  ---------x----|   ');\n      const skipSubs = '  ^--------!        ';\n      const expected = '  -----------d--e--|';\n\n      expectObservable(e1.pipe(skipUntil(skip))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(skip.subscriptions).toBe(skipSubs);\n    });\n  });\n\n  it('should emit elements after a synchronous notifier emits', () => {\n    const values: string[] = [];\n\n    of('a', 'b')\n      .pipe(skipUntil(of('x')))\n      .subscribe({\n        next(value) {\n          values.push(value);\n        },\n        error(err) {\n          throw err;\n        },\n        complete() {\n          expect(values).to.deep.equal(['a', 'b']);\n        },\n      });\n  });\n\n  it('should raise an error if notifier throws and source is hot', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  --a--b--c--d--e--|');\n      const e1subs = '  ^------------!    ';\n      const skip = hot('-------------#    ');\n      const skipSubs = '^------------!    ';\n      const expected = '-------------#    ';\n\n      expectObservable(e1.pipe(skipUntil(skip))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(skip.subscriptions).toBe(skipSubs);\n    });\n  });\n\n  it('should skip all elements when notifier does not emit and completes early', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  --a--b--c--d--e--|');\n      const e1subs = '  ^----------------!';\n      const skip = hot('------------|     ');\n      const skipSubs = '^-----------!     ';\n      const expected = '-----------------|';\n\n      expectObservable(e1.pipe(skipUntil(skip))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(skip.subscriptions).toBe(skipSubs);\n    });\n  });\n\n  it('should allow unsubscribing explicitly and early', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('    --a--b--c--d--e----|');\n      const unsub = '     ---------!          ';\n      const e1subs = '    ^--------!          ';\n      const skip = hot('  -------------x--|   ');\n      const skipSubs = '  ^--------!          ';\n      const expected = '  ----------          ';\n\n      expectObservable(e1.pipe(skipUntil(skip)), unsub).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(skip.subscriptions).toBe(skipSubs);\n    });\n  });\n\n  it('should not break unsubscription chains when result is unsubscribed explicitly', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('    --a--b--c--d--e----|');\n      const e1subs = '    ^--------!          ';\n      const skip = hot('  -------------x--|   ');\n      const skipSubs = '  ^--------!          ';\n      const expected = '  ----------          ';\n      const unsub = '     ---------!          ';\n\n      const result = e1.pipe(\n        mergeMap((x) => of(x)),\n        skipUntil(skip),\n        mergeMap((x) => of(x))\n      );\n\n      expectObservable(result, unsub).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(skip.subscriptions).toBe(skipSubs);\n    });\n  });\n\n  it('should not break unsubscription chains with interop inners when result is unsubscribed explicitly', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('    --a--b--c--d--e----|');\n      const e1subs = '    ^--------!          ';\n      const skip = hot('  -------------x--|   ');\n      const skipSubs = '  ^--------!          ';\n      const expected = '  ----------          ';\n      const unsub = '     ---------!          ';\n\n      // This test is the same as the previous test, but the observable is\n      // manipulated to make it look like an interop observable - an observable\n      // from a foreign library. Interop subscribers are treated differently:\n      // they are wrapped in a safe subscriber. This test ensures that\n      // unsubscriptions are chained all the way to the interop subscriber.\n\n      const result = e1.pipe(\n        mergeMap((x) => of(x)),\n        skipUntil(asInteropObservable(skip)),\n        mergeMap((x) => of(x))\n      );\n\n      expectObservable(result, unsub).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(skip.subscriptions).toBe(skipSubs);\n    });\n  });\n\n  it('should skip all elements when notifier is empty', () => {\n    testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('   --a--b--c--d--e--|');\n      const e1subs = '   ^----------------!';\n      const skip = cold('|                 ');\n      const skipSubs = ' (^!)              ';\n      const expected = ' -----------------|';\n\n      expectObservable(e1.pipe(skipUntil(skip))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(skip.subscriptions).toBe(skipSubs);\n    });\n  });\n\n  it('should keep subscription to source, to wait for its eventual completion', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  ------------------------------|');\n      const e1subs = '  ^-----------------------------!';\n      const skip = hot('-------|                       ');\n      const skipSubs = '^------!                       ';\n      const expected = '------------------------------|';\n\n      expectObservable(e1.pipe(skipUntil(skip))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(skip.subscriptions).toBe(skipSubs);\n    });\n  });\n\n  it('should not complete if hot source observable does not complete', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  -                ');\n      const e1subs = '  ^                ';\n      const skip = hot('-------------x--|');\n      const skipSubs = '^------------!   ';\n      const expected = '-                ';\n\n      expectObservable(e1.pipe(skipUntil(skip))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(skip.subscriptions).toBe(skipSubs);\n    });\n  });\n\n  it('should not complete if cold source observable never completes', () => {\n    testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' -                ');\n      const e1subs = '  ^                ';\n      const skip = hot('-------------x--|');\n      const skipSubs = '^------------!   ';\n      const expected = '-                ';\n\n      expectObservable(e1.pipe(skipUntil(skip))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(skip.subscriptions).toBe(skipSubs);\n    });\n  });\n\n  it('should raise error if cold source is never and notifier errors', () => {\n    testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' -             ');\n      const e1subs = '  ^------------!';\n      const skip = hot('-------------#');\n      const skipSubs = '^------------!';\n      const expected = '-------------#';\n\n      expectObservable(e1.pipe(skipUntil(skip))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(skip.subscriptions).toBe(skipSubs);\n    });\n  });\n\n  it('should skip all elements and complete if notifier is cold never', () => {\n    testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('   --a--b--c--d--e--|');\n      const e1subs = '   ^----------------!';\n      const skip = cold('-                 ');\n      const skipSubs = ' ^----------------!';\n      const expected = ' -----------------|';\n\n      expectObservable(e1.pipe(skipUntil(skip))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(skip.subscriptions).toBe(skipSubs);\n    });\n  });\n\n  it('should skip all elements and complete if notifier is a hot never', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  --a--b--c--d--e--|');\n      const e1subs = '  ^----------------!';\n      const skip = hot('-                 ');\n      const skipSubs = '^----------------!';\n      const expected = '-----------------|';\n\n      expectObservable(e1.pipe(skipUntil(skip))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(skip.subscriptions).toBe(skipSubs);\n    });\n  });\n\n  it('should skip all elements and complete, even if notifier would not complete until later', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  ^-a--b--c--d--e--|       ');\n      const e1subs = '  ^----------------!       ';\n      const skip = hot('^-----------------------|');\n      const skipSubs = '^----------------!       ';\n      const expected = '-----------------|       ';\n\n      expectObservable(e1.pipe(skipUntil(skip))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(skip.subscriptions).toBe(skipSubs);\n    });\n  });\n\n  it('should not complete if source does not complete if notifier completes without emission', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  -              ');\n      const e1subs = '  ^              ';\n      const skip = hot('--------------|');\n      const skipSubs = '^-------------!';\n      const expected = '-              ';\n\n      expectObservable(e1.pipe(skipUntil(skip))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(skip.subscriptions).toBe(skipSubs);\n    });\n  });\n\n  it('should not complete if source and notifier are both hot never', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  -');\n      const e1subs = '  ^';\n      const skip = hot('-');\n      const skipSubs = '^';\n      const expected = '-';\n\n      expectObservable(e1.pipe(skipUntil(skip))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(skip.subscriptions).toBe(skipSubs);\n    });\n  });\n\n  it('should skip all elements if notifier is unsubscribed explicitly before the notifier emits', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  --a--b--c--d--e--|');\n      const e1subs = [\n        '               ^----------------!',\n        '               ^----------------!', // for the explicit subscribe some lines below\n      ];\n      const skip = new Subject<string>();\n      const expected = '-----------------|';\n\n      e1.subscribe((x: string) => {\n        if (x === 'd' && !skip.closed) {\n          skip.next('x');\n        }\n\n        skip.unsubscribe();\n      });\n\n      expectObservable(e1.pipe(skipUntil(skip))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should unsubscribe the notifier after its first nexted value', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const source = hot('  -^-o---o---o---o---o---o---|');\n      const notifier = hot('-^--------n--n--n--n--n--n-|');\n      const nSubs = '        ^--------!                 ';\n      const expected = '    -^---------o---o---o---o---|';\n      const result = source.pipe(skipUntil(notifier));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(notifier.subscriptions).toBe(nSubs);\n    });\n  });\n\n  it('should stop listening to a synchronous notifier after its first nexted value', () => {\n    const sideEffects: number[] = [];\n    const synchronousNotifier = concat(\n      defer(() => {\n        sideEffects.push(1);\n        return of(1);\n      }),\n      defer(() => {\n        sideEffects.push(2);\n        return of(2);\n      }),\n      defer(() => {\n        sideEffects.push(3);\n        return of(3);\n      })\n    );\n    of(null)\n      .pipe(skipUntil(synchronousNotifier))\n      .subscribe(() => {\n        /* noop */\n      });\n    expect(sideEffects).to.deep.equal([1]);\n  });\n\n  it('should stop listening to a synchronous observable when unsubscribed', () => {\n    const sideEffects: number[] = [];\n    const synchronousObservable = new Observable<number>((subscriber) => {\n      // This will check to see if the subscriber was closed on each loop\n      // when the unsubscribe hits (from the `take`), it should be closed\n      for (let i = 0; !subscriber.closed && i < 10; i++) {\n        sideEffects.push(i);\n        subscriber.next(i);\n      }\n    });\n\n    synchronousObservable.pipe(skipUntil(of(0)), take(3)).subscribe(() => {\n      /* noop */\n    });\n\n    expect(sideEffects).to.deep.equal([0, 1, 2]);\n  });\n\n  it('should skip until Promise resolves', (done) => {\n    const e1 = interval(3).pipe(take(5));\n    const expected = [2, 3, 4];\n\n    e1.pipe(skipUntil(new Promise<void>((resolve) => setTimeout(() => resolve(), 8)))).subscribe({\n      next: (x) => {\n        expect(x).to.deep.equal(expected.shift());\n      },\n      error: () => done(new Error('should not be called')),\n      complete: () => {\n        expect(expected.length).to.equal(0);\n        done();\n      },\n    });\n  });\n\n  it('should raise error when Promise rejects', (done) => {\n    const e1 = interval(1).pipe(take(5));\n    const error = new Error('err');\n\n    e1.pipe(skipUntil(Promise.reject(error))).subscribe({\n      next: () => {\n        done(new Error('should not be called'));\n      },\n      error: (err: any) => {\n        expect(err).to.be.an('error');\n        done();\n      },\n      complete: () => {\n        done(new Error('should not be called'));\n      },\n    });\n  });\n});\n"
  },
  {
    "path": "packages/rxjs/spec/operators/skipWhile-spec.ts",
    "content": "import { expect } from 'chai';\nimport { skipWhile, mergeMap, tap, take } from 'rxjs/operators';\nimport { of, Observable } from 'rxjs';\nimport { TestScheduler } from 'rxjs/testing';\nimport { observableMatcher } from '../helpers/observableMatcher';\n\n/** @test {skipWhile} */\ndescribe('skipWhile', () => {\n  let testScheduler: TestScheduler;\n\n  beforeEach(() => {\n    testScheduler = new TestScheduler(observableMatcher);\n  });\n\n  it('should skip all elements until predicate is false', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const source = hot('-1-^2--3--4--5--6--|');\n      const sourceSubs = '   ^---------------!';\n      const expected = '     -------4--5--6--|';\n\n      const predicate = function (v: string) {\n        return +v < 4;\n      };\n\n      const result = source.pipe(skipWhile(predicate));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(source.subscriptions).toBe(sourceSubs);\n    });\n  });\n\n  it('should skip all elements with a true predicate', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const source = hot('-1-^2--3--4--5--6--|');\n      const sourceSubs = '   ^---------------!';\n      const expected = '     ----------------|';\n\n      const result = source.pipe(skipWhile(() => true));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(source.subscriptions).toBe(sourceSubs);\n    });\n  });\n\n  it('should skip all elements with a truthy predicate', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const source = hot('-1-^2--3--4--5--6--|');\n      const sourceSubs = '   ^---------------!';\n      const expected = '     ----------------|';\n\n      const result = source.pipe(\n        skipWhile((): any => {\n          return {};\n        })\n      );\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(source.subscriptions).toBe(sourceSubs);\n    });\n  });\n\n  it('should not skip any element with a false predicate', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const source = hot('-1-^2--3--4--5--6--|');\n      const sourceSubs = '   ^---------------!';\n      const expected = '     -2--3--4--5--6--|';\n\n      const result = source.pipe(skipWhile(() => false));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(source.subscriptions).toBe(sourceSubs);\n    });\n  });\n\n  it('should not skip any elements with a falsy predicate', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const source = hot('-1-^2--3--4--5--6--|');\n      const sourceSubs = '   ^---------------!';\n      const expected = '     -2--3--4--5--6--|';\n\n      const result = source.pipe(skipWhile(() => undefined as any));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(source.subscriptions).toBe(sourceSubs);\n    });\n  });\n\n  it('should skip elements on hot source', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const source = hot('--1--2-^-3--4--5--6--7--8--');\n      const sourceSubs = '       ^-------------------';\n      const expected = '         --------5--6--7--8--';\n\n      const predicate = function (v: string) {\n        return +v < 5;\n      };\n\n      const result = source.pipe(skipWhile(predicate));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(source.subscriptions).toBe(sourceSubs);\n    });\n  });\n\n  it(\"should be possible to skip using the element's index\", () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const source = hot('--a--b-^-c--d--e--f--g--h--|');\n      const sourceSubs = '       ^-------------------!';\n      const expected = '         --------e--f--g--h--|';\n\n      const predicate = function (_v: string, index: number) {\n        return index < 2;\n      };\n\n      const result = source.pipe(skipWhile(predicate));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(source.subscriptions).toBe(sourceSubs);\n    });\n  });\n\n  it('should skip using index with source unsubscribes early', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const source = hot('--a--b-^-c--d--e--f--g--h--|');\n      const sourceSubs = '       ^----------!         ';\n      const unsub = '            -----------!         ';\n      const expected = '         -----d--e---         ';\n\n      const predicate = function (_v: string, index: number) {\n        return index < 1;\n      };\n\n      const result = source.pipe(skipWhile(predicate));\n\n      expectObservable(result, unsub).toBe(expected);\n      expectSubscriptions(source.subscriptions).toBe(sourceSubs);\n    });\n  });\n\n  it('should not break unsubscription chains when result is unsubscribed explicitly', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const source = hot('--a--b-^-c--d--e--f--g--h--|');\n      const sourceSubs = '       ^----------!         ';\n      const expected = '         -----d--e---         ';\n      const unsub = '            -----------!         ';\n\n      const predicate = function (_v: string, index: number) {\n        return index < 1;\n      };\n\n      const result = source.pipe(\n        mergeMap(function (x) {\n          return of(x);\n        }),\n        skipWhile(predicate),\n        mergeMap(function (x) {\n          return of(x);\n        })\n      );\n\n      expectObservable(result, unsub).toBe(expected);\n      expectSubscriptions(source.subscriptions).toBe(sourceSubs);\n    });\n  });\n\n  it('should skip using value with source throws', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const source = hot('--a--b-^-c--d--e--f--g--h--#');\n      const sourceSubs = '       ^-------------------!';\n      const expected = '         -----d--e--f--g--h--#';\n\n      const predicate = function (v: string) {\n        return v !== 'd';\n      };\n\n      const result = source.pipe(skipWhile(predicate));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(source.subscriptions).toBe(sourceSubs);\n    });\n  });\n\n  it('should invoke predicate while its false and never again', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const source = hot('--a--b-^-c--d--e--f--g--h--|');\n      const sourceSubs = '       ^-------------------!';\n      const expected = '         --------e--f--g--h--|';\n\n      let invoked = 0;\n      const predicate = function (v: string) {\n        invoked++;\n        return v !== 'e';\n      };\n\n      const result = source.pipe(\n        skipWhile(predicate),\n        tap({\n          complete() {\n            expect(invoked).to.equal(3);\n          },\n        })\n      );\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(source.subscriptions).toBe(sourceSubs);\n    });\n  });\n\n  it('should handle predicate that throws', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const source = hot('--a--b-^-c--d--e--f--g--h--|');\n      const sourceSubs = '       ^-------!            ';\n      const expected = '         --------#            ';\n\n      const predicate = function (v: string) {\n        if (v === 'e') {\n          throw new Error(\"nom d'une pipe !\");\n        }\n\n        return v !== 'f';\n      };\n\n      const result = source.pipe(skipWhile(predicate));\n\n      expectObservable(result).toBe(expected, undefined, new Error(\"nom d'une pipe !\"));\n      expectSubscriptions(source.subscriptions).toBe(sourceSubs);\n    });\n  });\n\n  it('should handle Observable.empty', () => {\n    testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const source = cold('|   ');\n      const subs = '       (^!)';\n      const expected = '   |   ';\n\n      const result = source.pipe(skipWhile(() => true));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(source.subscriptions).toBe(subs);\n    });\n  });\n\n  it('should handle Observable.never', () => {\n    testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const source = cold('-');\n      const subs = '       ^';\n      const expected = '   -';\n\n      const result = source.pipe(skipWhile(() => true));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(source.subscriptions).toBe(subs);\n    });\n  });\n\n  it('should handle Observable.throw', () => {\n    testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const source = cold('#   ');\n      const subs = '       (^!)';\n      const expected = '   #   ';\n\n      const result = source.pipe(skipWhile(() => true));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(source.subscriptions).toBe(subs);\n    });\n  });\n\n  it('should stop listening to a synchronous observable when unsubscribed', () => {\n    const sideEffects: number[] = [];\n    const synchronousObservable = new Observable<number>((subscriber) => {\n      // This will check to see if the subscriber was closed on each loop\n      // when the unsubscribe hits (from the `take`), it should be closed\n      for (let i = 0; !subscriber.closed && i < 10; i++) {\n        sideEffects.push(i);\n        subscriber.next(i);\n      }\n    });\n\n    synchronousObservable\n      .pipe(\n        skipWhile((value) => value < 2),\n        take(1)\n      )\n      .subscribe(() => {\n        /* noop */\n      });\n\n    expect(sideEffects).to.deep.equal([0, 1, 2]);\n  });\n});\n"
  },
  {
    "path": "packages/rxjs/spec/operators/startWith-spec.ts",
    "content": "import { expect } from 'chai';\nimport { TestScheduler } from 'rxjs/testing';\nimport { of, Observable, startWith, mergeMap, take } from 'rxjs';\nimport { observableMatcher } from '../helpers/observableMatcher';\n\n/** @test {startWith} */\ndescribe('startWith', () => {\n  const defaultStartValue = 'x';\n  let testScheduler: TestScheduler;\n\n  beforeEach(() => {\n    testScheduler = new TestScheduler(observableMatcher);\n  });\n\n  it('should prepend to a cold Observable', () => {\n    testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' ---a--b--c--|');\n      const e1subs = '  ^-----------!';\n      const expected = 's--a--b--c--|';\n\n      const result = e1.pipe(startWith('s'));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should start an observable with given value', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  --a--|');\n      const e1subs = '  ^----!';\n      const expected = 'x-a--|';\n\n      const result = e1.pipe(startWith(defaultStartValue));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should start with given value and does not completes if source does not completes', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  ----a-');\n      const e1subs = '  ^-----';\n      const expected = 'x---a-';\n\n      const result = e1.pipe(startWith(defaultStartValue));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should start with given value and does not completes if source never emits', () => {\n    testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' - ');\n      const e1subs = '  ^ ';\n      const expected = 'x-';\n\n      const result = e1.pipe(startWith(defaultStartValue));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should start with given value and completes if source does not emits', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  ---|');\n      const e1subs = '  ^--!';\n      const expected = 'x--|';\n\n      const result = e1.pipe(startWith(defaultStartValue));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should start with given value and complete immediately if source is empty', () => {\n    testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' |   ');\n      const e1subs = '  (^!)';\n      const expected = '(x|)';\n\n      const result = e1.pipe(startWith(defaultStartValue));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should start with given value and source both if source emits single value', () => {\n    testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' (a|)');\n      const e1subs = '  (^!)';\n      const expected = '(xa|)';\n\n      const result = e1.pipe(startWith(defaultStartValue));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should start with given values when given value is more than one', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  -----a--|');\n      const e1subs = '  ^-------!';\n      const expected = '(yz)-a--|';\n\n      const result = e1.pipe(startWith('y', 'z'));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should start with given value and raises error if source raises error', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  --#');\n      const e1subs = '  ^-!';\n      const expected = 'x-#';\n\n      const result = e1.pipe(startWith(defaultStartValue));\n\n      expectObservable(result).toBe(expected, defaultStartValue);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should start with given value and raises error immediately if source throws error', () => {\n    testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' #   ');\n      const e1subs = '  (^!)';\n      const expected = '(x#)';\n\n      const result = e1.pipe(startWith(defaultStartValue));\n\n      expectObservable(result).toBe(expected, defaultStartValue);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should not break unsubscription chains when result is unsubscribed explicitly', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  ---a--b----c--d--|');\n      const e1subs = '  ^--------!        ';\n      const expected = 's--a--b---        ';\n      const unsub = '   ---------!        ';\n      const values = { s: 's', a: 'a', b: 'b' };\n\n      const result = e1.pipe(\n        mergeMap((x: string) => of(x)),\n        startWith('s'),\n        mergeMap((x: string) => of(x))\n      );\n\n      expectObservable(result, unsub).toBe(expected, values);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should stop listening to a synchronous observable when unsubscribed', () => {\n    const sideEffects: number[] = [];\n    const synchronousObservable = new Observable<number>((subscriber) => {\n      // This will check to see if the subscriber was closed on each loop\n      // when the unsubscribe hits (from the `take`), it should be closed\n      for (let i = 0; !subscriber.closed && i < 10; i++) {\n        sideEffects.push(i);\n        subscriber.next(i);\n      }\n    });\n\n    synchronousObservable.pipe(startWith(-1), take(4)).subscribe(() => {\n      /* noop */\n    });\n\n    expect(sideEffects).to.deep.equal([0, 1, 2]);\n  });\n});\n"
  },
  {
    "path": "packages/rxjs/spec/operators/subscribeOn-spec.ts",
    "content": "import { expect } from 'chai';\nimport { subscribeOn, mergeMap, take } from 'rxjs/operators';\nimport { TestScheduler } from 'rxjs/testing';\nimport { of, Observable, queueScheduler } from 'rxjs';\nimport { observableMatcher } from '../helpers/observableMatcher';\n\n/** @test {subscribeOn} */\ndescribe('subscribeOn', () => {\n  let testScheduler: TestScheduler;\n\n  beforeEach(() => {\n    testScheduler = new TestScheduler(observableMatcher);\n  });\n\n  it('should subscribe on specified scheduler', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  --a--b--|');\n      const expected = '--a--b--|';\n      const sub = '     ^-------!';\n\n      const result = e1.pipe(subscribeOn(testScheduler));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(sub);\n    });\n  });\n\n  it('should start subscribe after specified delay', () => {\n    testScheduler.run(({ hot, time, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('    --a--b--|');\n      const expected = '  -----b--|';\n      const delay = time('---|     ');\n      const sub = '       ---^----!';\n\n      const result = e1.pipe(subscribeOn(testScheduler, delay));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(sub);\n    });\n  });\n\n  it('should unsubscribe when source raises error', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  --a--#');\n      const expected = '--a--#';\n      const sub = '     ^----!';\n\n      const result = e1.pipe(subscribeOn(testScheduler));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(sub);\n    });\n  });\n\n  it('should subscribe when source is empty', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  ----|');\n      const expected = '----|';\n      const sub = '     ^---!';\n\n      const result = e1.pipe(subscribeOn(testScheduler));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(sub);\n    });\n  });\n\n  it('should subscribe when source does not complete', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  ----');\n      const expected = '----';\n      const sub = '     ^---';\n\n      const result = e1.pipe(subscribeOn(testScheduler));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(sub);\n    });\n  });\n\n  it('should allow unsubscribing early and explicitly', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  --a--b--|');\n      const sub = '     ^---!    ';\n      const expected = '--a--    ';\n      const unsub = '   ----!    ';\n\n      const result = e1.pipe(subscribeOn(testScheduler));\n\n      expectObservable(result, unsub).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(sub);\n    });\n  });\n\n  it('should not break unsubscription chains when the result is unsubscribed explicitly', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  --a--b--|');\n      const sub = '     ^---!    ';\n      const expected = '--a--    ';\n      const unsub = '   ----!    ';\n\n      const result = e1.pipe(\n        mergeMap((x: string) => of(x)),\n        subscribeOn(testScheduler),\n        mergeMap((x: string) => of(x))\n      );\n\n      expectObservable(result, unsub).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(sub);\n    });\n  });\n\n  it('should properly support a delayTime of Infinity', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  --a--b--|');\n      const expected = '---------';\n\n      const result = e1.pipe(subscribeOn(testScheduler, Infinity));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe([]);\n    });\n  });\n\n  it('should stop listening to a synchronous observable when unsubscribed', () => {\n    const sideEffects: number[] = [];\n    const synchronousObservable = new Observable<number>((subscriber) => {\n      // This will check to see if the subscriber was closed on each loop\n      // when the unsubscribe hits (from the `take`), it should be closed\n      for (let i = 0; !subscriber.closed && i < 10; i++) {\n        sideEffects.push(i);\n        subscriber.next(i);\n      }\n    });\n\n    synchronousObservable.pipe(subscribeOn(queueScheduler), take(3)).subscribe(() => {\n      /* noop */\n    });\n\n    expect(sideEffects).to.deep.equal([0, 1, 2]);\n  });\n});\n"
  },
  {
    "path": "packages/rxjs/spec/operators/switchAll-spec.ts",
    "content": "import { expect } from 'chai';\nimport { Observable, of, NEVER, queueScheduler, Subject, scheduled } from 'rxjs';\nimport { map, switchAll, mergeMap, take } from 'rxjs/operators';\nimport { TestScheduler } from 'rxjs/testing';\nimport { observableMatcher } from '../helpers/observableMatcher';\n\n/** @test {switch} */\ndescribe('switchAll', () => {\n  let testScheduler: TestScheduler;\n\n  beforeEach(() => {\n    testScheduler = new TestScheduler(observableMatcher);\n  });\n\n  it('should switch a hot observable of cold observables', () => {\n    testScheduler.run(({ hot, cold, expectObservable, expectSubscriptions }) => {\n      const x = cold('    --a---b--c---d--|      ');\n      const xsubs = '   --^------!               ';\n      const y = cold('           ----e---f--g---|');\n      const ysubs = '   ---------^--------------!';\n      const e1 = hot('  --x------y-------|       ', { x: x, y: y });\n      const e1subs = '  ^----------------!       ';\n      const expected = '----a---b----e---f--g---|';\n\n      const result = e1.pipe(switchAll());\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(x.subscriptions).toBe(xsubs);\n      expectSubscriptions(y.subscriptions).toBe(ysubs);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should switch to each immediately-scheduled inner Observable', (done) => {\n    const a = scheduled([1, 2, 3], queueScheduler);\n    const b = scheduled([4, 5, 6], queueScheduler);\n    const r = [1, 4, 5, 6];\n    let i = 0;\n    scheduled([a, b], queueScheduler)\n      .pipe(switchAll())\n      .subscribe({\n        next(x) {\n          expect(x).to.equal(r[i++]);\n        },\n        complete: done,\n      });\n  });\n\n  it('should unsub inner observables', () => {\n    const unsubbed: string[] = [];\n\n    of('a', 'b')\n      .pipe(\n        map(\n          (x) =>\n            new Observable<string>((subscriber) => {\n              subscriber.complete();\n              return () => {\n                unsubbed.push(x);\n              };\n            })\n        ),\n        switchAll()\n      )\n      .subscribe();\n\n    expect(unsubbed).to.deep.equal(['a', 'b']);\n  });\n\n  it('should switch to each inner Observable', (done) => {\n    const a = of(1, 2, 3);\n    const b = of(4, 5, 6);\n    const r = [1, 2, 3, 4, 5, 6];\n    let i = 0;\n    of(a, b)\n      .pipe(switchAll())\n      .subscribe({\n        next(x) {\n          expect(x).to.equal(r[i++]);\n        },\n        complete: done,\n      });\n  });\n\n  it('should handle a hot observable of observables', () => {\n    testScheduler.run(({ hot, cold, expectObservable, expectSubscriptions }) => {\n      const x = cold('        --a---b---c--|         ');\n      const xsubs = '   ------^-------!              ';\n      const y = cold('                ---d--e---f---|');\n      const ysubs = '   --------------^-------------!';\n      const e1 = hot('  ------x-------y------|       ', { x: x, y: y });\n      const e1subs = '  ^--------------------!       ';\n      const expected = '--------a---b----d--e---f---|';\n\n      const result = e1.pipe(switchAll());\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(x.subscriptions).toBe(xsubs);\n      expectSubscriptions(y.subscriptions).toBe(ysubs);\n    });\n  });\n\n  it('should handle a hot observable of observables, outer is unsubscribed early', () => {\n    testScheduler.run(({ hot, cold, expectObservable, expectSubscriptions }) => {\n      const x = cold('        --a---b---c--|         ');\n      const xsubs = '   ------^-------!              ';\n      const y = cold('                ---d--e---f---|');\n      const ysubs = '   --------------^-!            ';\n      const e1 = hot('  ------x-------y------|       ', { x: x, y: y });\n      const unsub = '   ----------------!            ';\n      const expected = '--------a---b---             ';\n\n      const result = e1.pipe(switchAll());\n\n      expectObservable(result, unsub).toBe(expected);\n      expectSubscriptions(x.subscriptions).toBe(xsubs);\n      expectSubscriptions(y.subscriptions).toBe(ysubs);\n    });\n  });\n\n  it('should not break unsubscription chains when result is unsubscribed explicitly', () => {\n    testScheduler.run(({ hot, cold, expectObservable, expectSubscriptions }) => {\n      const x = cold('        --a---b---c--|         ');\n      const xsubs = '   ------^-------!              ';\n      const y = cold('                ---d--e---f---|');\n      const ysubs = '   --------------^-!            ';\n      const e1 = hot('  ------x-------y------|       ', { x: x, y: y });\n      const expected = '--------a---b----            ';\n      const unsub = '   ----------------!            ';\n\n      const result = e1.pipe(\n        mergeMap((x) => of(x)),\n        switchAll(),\n        mergeMap((x) => of(x))\n      );\n\n      expectObservable(result, unsub).toBe(expected);\n      expectSubscriptions(x.subscriptions).toBe(xsubs);\n      expectSubscriptions(y.subscriptions).toBe(ysubs);\n    });\n  });\n\n  it('should handle a hot observable of observables, inner never completes', () => {\n    testScheduler.run(({ hot, cold, expectObservable, expectSubscriptions }) => {\n      const x = cold('        --a---b---c--|          ');\n      const xsubs = '   ------^-------!               ';\n      const y = cold('                ---d--e---f-----');\n      const ysubs = '   --------------^               ';\n      const e1 = hot('  ------x-------y------|        ', { x: x, y: y });\n      const expected = '--------a---b----d--e---f-----';\n\n      const result = e1.pipe(switchAll());\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(x.subscriptions).toBe(xsubs);\n      expectSubscriptions(y.subscriptions).toBe(ysubs);\n    });\n  });\n\n  it('should handle a synchronous switch to the second inner observable', () => {\n    testScheduler.run(({ hot, cold, expectObservable, expectSubscriptions }) => {\n      const x = cold('        --a---b---c--|   ');\n      const xsubs = '   ------(^!)             ';\n      const y = cold('        ---d--e---f---|  ');\n      const ysubs = '   ------^-------------!  ';\n      const e1 = hot('  ------(xy)------------|', { x: x, y: y });\n      const expected = '---------d--e---f-----|';\n\n      const result = e1.pipe(switchAll());\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(x.subscriptions).toBe(xsubs);\n      expectSubscriptions(y.subscriptions).toBe(ysubs);\n    });\n  });\n\n  it('should handle a hot observable of observables, one inner throws', () => {\n    testScheduler.run(({ hot, cold, expectObservable, expectSubscriptions }) => {\n      const x = cold('        --a---#                ');\n      const xsubs = '   ------^-----!                ';\n      const y = cold('                ---d--e---f---|');\n      const ysubs = '                                ';\n      const e1 = hot('  ------x-------y------|       ', { x: x, y: y });\n      const expected = '--------a---#                ';\n\n      const result = e1.pipe(switchAll());\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(x.subscriptions).toBe(xsubs);\n      expectSubscriptions(y.subscriptions).toBe(ysubs);\n    });\n  });\n\n  it('should handle a hot observable of observables, outer throws', () => {\n    testScheduler.run(({ hot, cold, expectObservable, expectSubscriptions }) => {\n      const x = cold('        --a---b---c--|         ');\n      const xsubs = '   ------^-------!              ';\n      const y = cold('                ---d--e---f---|');\n      const ysubs = '   --------------^-------!      ';\n      const e1 = hot('  ------x-------y-------#      ', { x: x, y: y });\n      const expected = '--------a---b----d--e-#      ';\n\n      const result = e1.pipe(switchAll());\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(x.subscriptions).toBe(xsubs);\n      expectSubscriptions(y.subscriptions).toBe(ysubs);\n    });\n  });\n\n  it('should handle an empty hot observable', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  ------|');\n      const e1subs = '  ^-----!';\n      const expected = '------|';\n\n      const result = e1.pipe(switchAll());\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should handle a never hot observable', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  -');\n      const e1subs = '  ^';\n      const expected = '-';\n\n      const result = e1.pipe(switchAll());\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should complete not before the outer completes', () => {\n    testScheduler.run(({ hot, cold, expectObservable, expectSubscriptions }) => {\n      const x = cold('        --a---b---c--|   ');\n      const xsubs = '   ------^------------!   ';\n      const e1 = hot('  ------x---------------|', { x: x });\n      const e1subs = '  ^---------------------!';\n      const expected = '--------a---b---c-----|';\n\n      const result = e1.pipe(switchAll());\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(x.subscriptions).toBe(xsubs);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should handle an observable of promises', (done) => {\n    const expected = [3];\n\n    of(Promise.resolve(1), Promise.resolve(2), Promise.resolve(3))\n      .pipe(switchAll())\n      .subscribe({\n        next(x) {\n          expect(x).to.equal(expected.shift());\n        },\n        complete() {\n          expect(expected.length).to.equal(0);\n          done();\n        },\n      });\n  });\n\n  it('should handle an observable of promises, where last rejects', (done) => {\n    of(Promise.resolve(1), Promise.resolve(2), Promise.reject(3))\n      .pipe(switchAll())\n      .subscribe({\n        next() {\n          done(new Error('should not be called'));\n        },\n        error(err) {\n          expect(err).to.equal(3);\n          done();\n        },\n        complete() {\n          done(new Error('should not be called'));\n        },\n      });\n  });\n\n  it('should handle an observable with Arrays in it', () => {\n    const expected = [1, 2, 3, 4];\n    let completed = false;\n\n    of(NEVER, NEVER, [1, 2, 3, 4])\n      .pipe(switchAll())\n      .subscribe({\n        next(x) {\n          expect(x).to.equal(expected.shift());\n        },\n        complete() {\n          completed = true;\n          expect(expected.length).to.equal(0);\n        },\n      });\n\n    expect(completed).to.be.true;\n  });\n\n  it('should not leak when child completes before each switch (prevent memory leaks #2355)', () => {\n    let iStream: Subject<number>;\n    const oStreamControl = new Subject<number>();\n    const oStream = oStreamControl.pipe(map(() => (iStream = new Subject<number>())));\n    const switcher = oStream.pipe(switchAll());\n    const result: number[] = [];\n    const subscription = switcher.subscribe((x) => result.push(x));\n\n    [0, 1, 2, 3, 4].forEach((n) => {\n      oStreamControl.next(n); // creates inner\n      iStream.complete();\n    });\n\n    // HACK: Extracting the inner subscription.\n    const innerSubscription = [...(subscription as any)._finalizers!.values()][0];\n\n    // At this point, we expect two finalizers:\n    // 1. The finalizer for the outer subscription\n    // 2. The finalizer for the inner subscription to remove itself from the outer subscription\n    expect(innerSubscription._finalizers?.size).to.equal(2);\n\n    subscription.unsubscribe();\n  });\n\n  it('should not leak if we switch before child completes (prevent memory leaks #2355)', () => {\n    const oStreamControl = new Subject<number>();\n    const oStream = oStreamControl.pipe(map(() => new Subject<number>()));\n    const switcher = oStream.pipe(switchAll());\n    const result: number[] = [];\n    const subscription: any = switcher.subscribe((x) => result.push(x));\n\n    [0, 1, 2, 3, 4].forEach((n) => {\n      oStreamControl.next(n); // creates inner\n    });\n\n    const innerSubscription = [...subscription._finalizers!.values()][0];\n\n    // At this point, the finalizers for the inner subscription should have 2 children:\n    // 1. The finalizer for the inner subscription itself\n    // 2. The finalizer for the inner subscription to remove itself from the parent subscription.\n    expect(innerSubscription._finalizers?.size).to.equal(2);\n\n    // At this point, the finalizers for outer subscription should have 2 children:\n    // 1. The finalizer for the outer subscription.\n    // 2. The finalizer to unsubscribe the inner subscription.\n    expect(subscription._finalizers?.size).to.equal(2);\n\n    subscription.unsubscribe();\n  });\n\n  it('should stop listening to a synchronous observable when unsubscribed', () => {\n    const sideEffects: number[] = [];\n    const synchronousObservable = new Observable<number>((subscriber) => {\n      // This will check to see if the subscriber was closed on each loop\n      // when the unsubscribe hits (from the `take`), it should be closed\n      for (let i = 0; !subscriber.closed && i < 10; i++) {\n        sideEffects.push(i);\n        subscriber.next(i);\n      }\n    });\n\n    of(synchronousObservable)\n      .pipe(switchAll(), take(3))\n      .subscribe(() => {\n        /* noop */\n      });\n\n    expect(sideEffects).to.deep.equal([0, 1, 2]);\n  });\n});\n"
  },
  {
    "path": "packages/rxjs/spec/operators/switchMap-spec.ts",
    "content": "import { expect } from 'chai';\nimport { switchMap, mergeMap, map, takeWhile, take } from 'rxjs/operators';\nimport { concat, defer, of, Observable, BehaviorSubject } from 'rxjs';\nimport { asInteropObservable } from '../helpers/interop-helper';\nimport { TestScheduler } from 'rxjs/testing';\nimport { observableMatcher } from '../helpers/observableMatcher';\n\n/** @test {switchMap} */\ndescribe('switchMap', () => {\n  let testScheduler: TestScheduler;\n\n  beforeEach(() => {\n    testScheduler = new TestScheduler(observableMatcher);\n  });\n\n  it('should map-and-flatten each item to an Observable', () => {\n    testScheduler.run(({ hot, cold, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('   --1-----3--5-------|');\n      const e1subs = '   ^------------------!';\n      const e2 = cold('    x-x-x|            ', { x: 10 });\n      //                         x-x-x|\n      //                            x-x-x|\n      const expected = ' --x-x-x-y-yz-z-z---|';\n      const values = { x: 10, y: 30, z: 50 };\n\n      const result = e1.pipe(switchMap((x) => e2.pipe(map((i) => i * +x))));\n\n      expectObservable(result).toBe(expected, values);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should unsub inner observables', () => {\n    const unsubbed: string[] = [];\n\n    of('a', 'b')\n      .pipe(\n        switchMap(\n          (x) =>\n            new Observable<string>((subscriber) => {\n              subscriber.complete();\n              return () => {\n                unsubbed.push(x);\n              };\n            })\n        )\n      )\n      .subscribe();\n\n    expect(unsubbed).to.deep.equal(['a', 'b']);\n  });\n\n  it('should switch inner cold observables', () => {\n    testScheduler.run(({ hot, cold, expectObservable, expectSubscriptions }) => {\n      const x = cold('           --a--b--c--d--e--|           ');\n      const xsubs = '   ---------^---------!                  ';\n      const y = cold('                     ---f---g---h---i--|');\n      const ysubs = '   -------------------^-----------------!';\n      const e1 = hot('  ---------x---------y---------|        ');\n      const e1subs = '  ^----------------------------!        ';\n      const expected = '-----------a--b--c----f---g---h---i--|';\n\n      const observableLookup: Record<string, Observable<string>> = { x: x, y: y };\n\n      const result = e1.pipe(switchMap((value) => observableLookup[value]));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(x.subscriptions).toBe(xsubs);\n      expectSubscriptions(y.subscriptions).toBe(ysubs);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should raise error when projection throws', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  -------x-----y---|');\n      const e1subs = '  ^------!          ';\n      const expected = '-------#          ';\n      function project(): any[] {\n        throw 'error';\n      }\n\n      expectObservable(e1.pipe(switchMap(project))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should switch inner cold observables, outer is unsubscribed early', () => {\n    testScheduler.run(({ hot, cold, expectObservable, expectSubscriptions }) => {\n      const x = cold('           --a--b--c--d--e--|           ');\n      const xsubs = '   ---------^---------!                  ';\n      const y = cold('                     ---f---g---h---i--|');\n      const ysubs = '   -------------------^-!                ';\n      const e1 = hot('  ---------x---------y---------|        ');\n      const e1subs = '  ^--------------------!                ';\n      const unsub = '   ---------------------!                ';\n      const expected = '-----------a--b--c----                ';\n\n      const observableLookup: Record<string, Observable<string>> = { x: x, y: y };\n\n      const result = e1.pipe(switchMap((value) => observableLookup[value]));\n\n      expectObservable(result, unsub).toBe(expected);\n      expectSubscriptions(x.subscriptions).toBe(xsubs);\n      expectSubscriptions(y.subscriptions).toBe(ysubs);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should not break unsubscription chains when result is unsubscribed explicitly', () => {\n    testScheduler.run(({ hot, cold, expectObservable, expectSubscriptions }) => {\n      const x = cold('           --a--b--c--d--e--|           ');\n      const xsubs = '   ---------^---------!                  ';\n      const y = cold('                     ---f---g---h---i--|');\n      const ysubs = '   -------------------^-!                ';\n      const e1 = hot('  ---------x---------y---------|        ');\n      const e1subs = '  ^--------------------!                ';\n      const expected = '-----------a--b--c----                ';\n      const unsub = '   ---------------------!                ';\n\n      const observableLookup: Record<string, Observable<string>> = { x: x, y: y };\n\n      const result = e1.pipe(\n        mergeMap((x) => of(x)),\n        switchMap((value) => observableLookup[value]),\n        mergeMap((x) => of(x))\n      );\n\n      expectObservable(result, unsub).toBe(expected);\n      expectSubscriptions(x.subscriptions).toBe(xsubs);\n      expectSubscriptions(y.subscriptions).toBe(ysubs);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should not break unsubscription chains with interop inners when result is unsubscribed explicitly', () => {\n    testScheduler.run(({ hot, cold, expectObservable, expectSubscriptions }) => {\n      const x = cold('           --a--b--c--d--e--|           ');\n      const xsubs = '   ---------^---------!                  ';\n      const y = cold('                     ---f---g---h---i--|');\n      const ysubs = '   -------------------^-!                ';\n      const e1 = hot('  ---------x---------y---------|        ');\n      const e1subs = '  ^--------------------!                ';\n      const expected = '-----------a--b--c----                ';\n      const unsub = '   ---------------------!                ';\n\n      const observableLookup: Record<string, Observable<string>> = { x: x, y: y };\n\n      // This test is the same as the previous test, but the observable is\n      // manipulated to make it look like an interop observable - an observable\n      // from a foreign library. Interop subscribers are treated differently:\n      // they are wrapped in a safe subscriber. This test ensures that\n      // unsubscriptions are chained all the way to the interop subscriber.\n\n      const result = e1.pipe(\n        mergeMap((x) => of(x)),\n        switchMap((value) => asInteropObservable(observableLookup[value])),\n        mergeMap((x) => of(x))\n      );\n\n      expectObservable(result, unsub).toBe(expected);\n      expectSubscriptions(x.subscriptions).toBe(xsubs);\n      expectSubscriptions(y.subscriptions).toBe(ysubs);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should stop listening to a synchronous observable when unsubscribed', () => {\n    const sideEffects: number[] = [];\n    const synchronousObservable = concat(\n      defer(() => {\n        sideEffects.push(1);\n        return of(1);\n      }),\n      defer(() => {\n        sideEffects.push(2);\n        return of(2);\n      }),\n      defer(() => {\n        sideEffects.push(3);\n        return of(3);\n      })\n    );\n\n    of(null)\n      .pipe(\n        switchMap(() => synchronousObservable),\n        takeWhile((x) => x != 2) // unsubscribe at the second side-effect\n      )\n      .subscribe(() => {\n        /* noop */\n      });\n\n    expect(sideEffects).to.deep.equal([1, 2]);\n  });\n\n  it('should switch inner cold observables, inner never completes', () => {\n    testScheduler.run(({ hot, cold, expectObservable, expectSubscriptions }) => {\n      const x = cold('           --a--b--c--d--e--|          ');\n      const xsubs = '   ---------^---------!                 ';\n      const y = cold('                     ---f---g---h---i--');\n      const ysubs = '   -------------------^                 ';\n      const e1 = hot('  ---------x---------y---------|       ');\n      const e1subs = '  ^----------------------------!       ';\n      const expected = '-----------a--b--c----f---g---h---i--';\n\n      const observableLookup: Record<string, Observable<string>> = { x: x, y: y };\n\n      const result = e1.pipe(switchMap((value) => observableLookup[value]));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(x.subscriptions).toBe(xsubs);\n      expectSubscriptions(y.subscriptions).toBe(ysubs);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should handle a synchronous switch to the second inner observable', () => {\n    testScheduler.run(({ hot, cold, expectObservable, expectSubscriptions }) => {\n      const x = cold('           --a--b--c--d--e--|   ');\n      const xsubs = '   ---------(^!)                 ';\n      const y = cold('           ---f---g---h---i--|  ');\n      const ysubs = '   ---------^-----------------!  ';\n      const e1 = hot('  ---------(xy)----------------|');\n      const e1subs = '  ^----------------------------!';\n      const expected = '------------f---g---h---i----|';\n\n      const observableLookup: Record<string, Observable<string>> = { x: x, y: y };\n\n      const result = e1.pipe(switchMap((value) => observableLookup[value]));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(x.subscriptions).toBe(xsubs);\n      expectSubscriptions(y.subscriptions).toBe(ysubs);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should switch inner cold observables, one inner throws', () => {\n    testScheduler.run(({ hot, cold, expectObservable, expectSubscriptions }) => {\n      const x = cold('           --a--b--#--d--e--|          ');\n      const xsubs = '   ---------^-------!                   ';\n      const y = cold('                     ---f---g---h---i--');\n      const ysubs = '                                        ';\n      const e1 = hot('  ---------x---------y---------|       ');\n      const e1subs = '  ^----------------!                   ';\n      const expected = '-----------a--b--#                   ';\n\n      const observableLookup: Record<string, Observable<string>> = { x: x, y: y };\n\n      const result = e1.pipe(switchMap((value) => observableLookup[value]));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(x.subscriptions).toBe(xsubs);\n      expectSubscriptions(y.subscriptions).toBe(ysubs);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should switch inner hot observables', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const x = hot('   -----a--b--c--d--e--|                 ');\n      const xsubs = '   ---------^---------!                  ';\n      const y = hot('   --p-o-o-p-------------f---g---h---i--|');\n      const ysubs = '   -------------------^-----------------!';\n      const e1 = hot('  ---------x---------y---------|        ');\n      const e1subs = '  ^----------------------------!        ';\n      const expected = '-----------c--d--e----f---g---h---i--|';\n\n      const observableLookup: Record<string, Observable<string>> = { x: x, y: y };\n\n      const result = e1.pipe(switchMap((value) => observableLookup[value]));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(x.subscriptions).toBe(xsubs);\n      expectSubscriptions(y.subscriptions).toBe(ysubs);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should switch inner empty and empty', () => {\n    testScheduler.run(({ hot, cold, expectObservable, expectSubscriptions }) => {\n      const x = cold('           |                    ');\n      const y = cold('                     |          ');\n      const xsubs = '   ---------(^!)                 ';\n      const ysubs = '   -------------------(^!)       ';\n      const e1 = hot('  ---------x---------y---------|');\n      const e1subs = '  ^----------------------------!';\n      const expected = '-----------------------------|';\n\n      const observableLookup: Record<string, Observable<string>> = { x: x, y: y };\n\n      const result = e1.pipe(switchMap((value) => observableLookup[value]));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(x.subscriptions).toBe(xsubs);\n      expectSubscriptions(y.subscriptions).toBe(ysubs);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should switch inner empty and never', () => {\n    testScheduler.run(({ hot, cold, expectObservable, expectSubscriptions }) => {\n      const x = cold('           |                    ');\n      const y = cold('                     -          ');\n      const xsubs = '   ---------(^!)                 ';\n      const ysubs = '   -------------------^          ';\n      const e1 = hot('  ---------x---------y---------|');\n      const e1subs = '  ^----------------------------!';\n      const expected = '------------------------------';\n\n      const observableLookup: Record<string, Observable<string>> = { x: x, y: y };\n\n      const result = e1.pipe(switchMap((value) => observableLookup[value]));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(x.subscriptions).toBe(xsubs);\n      expectSubscriptions(y.subscriptions).toBe(ysubs);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should switch inner never and empty', () => {\n    testScheduler.run(({ hot, cold, expectObservable, expectSubscriptions }) => {\n      const x = cold('           -                    ');\n      const y = cold('                     |          ');\n      const xsubs = '   ---------^---------!          ';\n      const ysubs = '   -------------------(^!)       ';\n      const e1 = hot('  ---------x---------y---------|');\n      const e1subs = '  ^----------------------------!';\n      const expected = '-----------------------------|';\n\n      const observableLookup: Record<string, Observable<string>> = { x: x, y: y };\n\n      const result = e1.pipe(switchMap((value) => observableLookup[value]));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(x.subscriptions).toBe(xsubs);\n      expectSubscriptions(y.subscriptions).toBe(ysubs);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should switch inner never and throw', () => {\n    testScheduler.run(({ hot, cold, expectObservable, expectSubscriptions }) => {\n      const x = cold('           -                    ');\n      const y = cold('                     #          ', undefined, 'sad');\n      const xsubs = '   ---------^---------!          ';\n      const ysubs = '   -------------------(^!)       ';\n      const e1 = hot('  ---------x---------y---------|');\n      const e1subs = '  ^------------------!          ';\n      const expected = '-------------------#          ';\n\n      const observableLookup: Record<string, Observable<string>> = { x: x, y: y };\n\n      const result = e1.pipe(switchMap((value) => observableLookup[value]));\n\n      expectObservable(result).toBe(expected, undefined, 'sad');\n      expectSubscriptions(x.subscriptions).toBe(xsubs);\n      expectSubscriptions(y.subscriptions).toBe(ysubs);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should switch inner empty and throw', () => {\n    testScheduler.run(({ hot, cold, expectObservable, expectSubscriptions }) => {\n      const x = cold('           |                    ');\n      const y = cold('                     #          ', undefined, 'sad');\n      const xsubs = '   ---------(^!)                 ';\n      const ysubs = '   -------------------(^!)       ';\n      const e1 = hot('  ---------x---------y---------|');\n      const e1subs = '  ^------------------!          ';\n      const expected = '-------------------#          ';\n\n      const observableLookup: Record<string, Observable<string>> = { x: x, y: y };\n\n      const result = e1.pipe(switchMap((value) => observableLookup[value]));\n\n      expectObservable(result).toBe(expected, undefined, 'sad');\n      expectSubscriptions(x.subscriptions).toBe(xsubs);\n      expectSubscriptions(y.subscriptions).toBe(ysubs);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should handle outer empty', () => {\n    testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' |   ');\n      const e1subs = '  (^!)';\n      const expected = '|   ';\n\n      const result = e1.pipe(switchMap((value) => of(value)));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should handle outer never', () => {\n    testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' -');\n      const e1subs = '  ^';\n      const expected = '-';\n\n      const result = e1.pipe(switchMap((value) => of(value)));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should handle outer throw', () => {\n    testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' #   ');\n      const e1subs = '  (^!)';\n      const expected = '#   ';\n\n      const result = e1.pipe(switchMap((value) => of(value)));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should handle outer error', () => {\n    testScheduler.run(({ hot, cold, expectObservable, expectSubscriptions }) => {\n      const x = cold('           --a--b--c--d--e--|');\n      const xsubs = '   ---------^---------!       ';\n      const e1 = hot('  ---------x---------#       ');\n      const e1subs = '  ^------------------!       ';\n      const expected = '-----------a--b--c-#       ';\n\n      const observableLookup: Record<string, Observable<string>> = { x: x };\n\n      const result = e1.pipe(switchMap((value) => observableLookup[value]));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(x.subscriptions).toBe(xsubs);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should stop listening to a synchronous observable when unsubscribed', () => {\n    const sideEffects: number[] = [];\n    const synchronousObservable = new Observable<number>((subscriber) => {\n      // This will check to see if the subscriber was closed on each loop\n      // when the unsubscribe hits (from the `take`), it should be closed\n      for (let i = 0; !subscriber.closed && i < 10; i++) {\n        sideEffects.push(i);\n        subscriber.next(i);\n      }\n    });\n\n    synchronousObservable\n      .pipe(\n        switchMap((value) => of(value)),\n        take(3)\n      )\n      .subscribe(() => {\n        /* noop */\n      });\n\n    expect(sideEffects).to.deep.equal([0, 1, 2]);\n  });\n\n  it('should unsubscribe previous inner sub when getting synchronously reentrance during subscribing the inner sub', () => {\n    const e = new BehaviorSubject(1);\n    const results: Array<number> = [];\n\n    e.pipe(\n      take(3),\n      switchMap(\n        (value) =>\n          new Observable<number>((subscriber) => {\n            e.next(value + 1);\n            subscriber.next(value);\n          })\n      )\n    ).subscribe((value) => results.push(value));\n\n    expect(results).to.deep.equal([3]);\n  });\n});\n"
  },
  {
    "path": "packages/rxjs/spec/operators/switchMapTo-spec.ts",
    "content": "import { expect } from 'chai';\nimport { Observable, of } from 'rxjs';\nimport { switchMapTo, mergeMap, take } from 'rxjs/operators';\nimport { TestScheduler } from 'rxjs/testing';\nimport { observableMatcher } from '../helpers/observableMatcher';\n\n/** @test {switchMapTo} */\ndescribe('switchMapTo', () => {\n  let testScheduler: TestScheduler;\n\n  beforeEach(() => {\n    testScheduler = new TestScheduler(observableMatcher);\n  });\n\n  it('should map-and-flatten each item to an Observable', () => {\n    testScheduler.run(({ hot, cold, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  --1-----3--5-------|');\n      const e1subs = '  ^------------------!';\n      const e2 = cold('   x-x-x|            ', { x: 10 });\n      //                        x-x-x|\n      //                           x-x-x|\n      const expected = '--x-x-x-x-xx-x-x---|';\n      const values = { x: 10 };\n\n      const result = e1.pipe(switchMapTo(e2));\n\n      expectObservable(result).toBe(expected, values);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should switch a synchronous many outer to a synchronous many inner', (done) => {\n    const a = of(1, 2, 3);\n    const expected = ['a', 'b', 'c', 'a', 'b', 'c', 'a', 'b', 'c'];\n    a.pipe(switchMapTo(of('a', 'b', 'c'))).subscribe({\n      next(x) {\n        expect(x).to.equal(expected.shift());\n      },\n      complete: done,\n    });\n  });\n\n  it('should unsub inner observables', () => {\n    let unsubbed = 0;\n\n    of('a', 'b')\n      .pipe(\n        switchMapTo(\n          new Observable<string>((subscriber) => {\n            subscriber.complete();\n            return () => {\n              unsubbed++;\n            };\n          })\n        )\n      )\n      .subscribe();\n\n    expect(unsubbed).to.equal(2);\n  });\n\n  it('should switch to an inner cold observable', () => {\n    testScheduler.run(({ hot, cold, expectObservable, expectSubscriptions }) => {\n      const x = cold('           --a--b--c--d--e--|          ');\n      const xsubs = [\n        '               ---------^---------!                 ',\n        //                                 --a--b--c--d--e--|\n        '               -------------------^----------------!',\n      ];\n      const e1 = hot('  ---------x---------x---------|       ');\n      const e1subs = '  ^----------------------------!       ';\n      const expected = '-----------a--b--c---a--b--c--d--e--|';\n\n      expectObservable(e1.pipe(switchMapTo(x))).toBe(expected);\n      expectSubscriptions(x.subscriptions).toBe(xsubs);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should switch to an inner cold observable, outer eventually throws', () => {\n    testScheduler.run(({ hot, cold, expectObservable, expectSubscriptions }) => {\n      const x = cold('           --a--b--c--d--e--|');\n      const xsubs = '   ---------^---------!       ';\n      const e1 = hot('  ---------x---------#       ');\n      const e1subs = '  ^------------------!       ';\n      const expected = '-----------a--b--c-#       ';\n\n      expectObservable(e1.pipe(switchMapTo(x))).toBe(expected);\n      expectSubscriptions(x.subscriptions).toBe(xsubs);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should switch to an inner cold observable, outer is unsubscribed early', () => {\n    testScheduler.run(({ hot, cold, expectObservable, expectSubscriptions }) => {\n      const x = cold('           --a--b--c--d--e--|   ');\n      const xsubs = [\n        '               ---------^---------!          ',\n        //                                 --a--b--c--d--e--|\n        '               -------------------^--!       ',\n      ];\n      const e1 = hot('  ---------x---------x---------|');\n      const unsub = '   ----------------------!       ';\n      const e1subs = '  ^---------------------!       ';\n      const expected = '-----------a--b--c---a-       ';\n\n      expectObservable(e1.pipe(switchMapTo(x)), unsub).toBe(expected);\n      expectSubscriptions(x.subscriptions).toBe(xsubs);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should not break unsubscription chains when result is unsubscribed explicitly', () => {\n    testScheduler.run(({ hot, cold, expectObservable, expectSubscriptions }) => {\n      const x = cold('--a--b--c--d--e--|   ');\n      const xsubs = [\n        '               ---------^---------!          ',\n        //                                 --a--b--c--d--e--|\n        '               -------------------^--!       ',\n      ];\n      const e1 = hot('  ---------x---------x---------|');\n      const e1subs = '  ^---------------------!       ';\n      const expected = '-----------a--b--c---a-       ';\n      const unsub = '   ----------------------!       ';\n\n      const result = e1.pipe(\n        mergeMap((x) => of(x)),\n        switchMapTo(x),\n        mergeMap((x) => of(x))\n      );\n\n      expectObservable(result, unsub).toBe(expected);\n      expectSubscriptions(x.subscriptions).toBe(xsubs);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should switch to an inner cold observable, inner never completes', () => {\n    testScheduler.run(({ hot, cold, expectObservable, expectSubscriptions }) => {\n      const x = cold('           --a--b--c--d--e-          ');\n      const xsubs = [\n        '               ---------^---------!               ',\n        //                                 --a--b--c--d--e-\n        '               -------------------^               ',\n      ];\n      const e1 = hot('  ---------x---------y---------|     ');\n      const e1subs = '  ^----------------------------!     ';\n      const expected = '-----------a--b--c---a--b--c--d--e-';\n\n      expectObservable(e1.pipe(switchMapTo(x))).toBe(expected);\n      expectSubscriptions(x.subscriptions).toBe(xsubs);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should handle a synchronous switch to the inner observable', () => {\n    testScheduler.run(({ hot, cold, expectObservable, expectSubscriptions }) => {\n      const x = cold('           --a--b--c--d--e--|   ');\n      // prettier-ignore\n      const xsubs = [\n        '               ---------(^!)                 ',\n        '               ---------^----------------!   '\n      ];\n      const e1 = hot('  ---------(xx)----------------|');\n      const e1subs = '  ^----------------------------!';\n      const expected = '-----------a--b--c--d--e-----|';\n\n      expectObservable(e1.pipe(switchMapTo(x))).toBe(expected);\n      expectSubscriptions(x.subscriptions).toBe(xsubs);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should switch to an inner cold observable, inner raises an error', () => {\n    testScheduler.run(({ hot, cold, expectObservable, expectSubscriptions }) => {\n      const x = cold('           --a--b--#            ');\n      const xsubs = '   ---------^-------!            ';\n      const e1 = hot('  ---------x---------x---------|');\n      const e1subs = '  ^----------------!            ';\n      const expected = '-----------a--b--#            ';\n\n      expectObservable(e1.pipe(switchMapTo(x))).toBe(expected);\n      expectSubscriptions(x.subscriptions).toBe(xsubs);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should switch an inner hot observable', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const x = hot('   --p-o-o-p---a--b--c--d-|      ');\n      // prettier-ignore\n      const xsubs = [\n        '               ---------^---------!          ',\n        '               -------------------^---!      '\n      ];\n      const e1 = hot('  ---------x---------x---------|');\n      const e1subs = '  ^----------------------------!';\n      const expected = '------------a--b--c--d-------|';\n\n      expectObservable(e1.pipe(switchMapTo(x))).toBe(expected);\n      expectSubscriptions(x.subscriptions).toBe(xsubs);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should switch to an inner empty', () => {\n    testScheduler.run(({ hot, cold, expectObservable, expectSubscriptions }) => {\n      const x = cold('           |                    ');\n      const xsubs = [\n        '               ---------(^!)                 ',\n        //                                 |\n        '               -------------------(^!)       ',\n      ];\n      const e1 = hot('  ---------x---------x---------|');\n      const e1subs = '  ^----------------------------!';\n      const expected = '-----------------------------|';\n\n      expectObservable(e1.pipe(switchMapTo(x))).toBe(expected);\n      expectSubscriptions(x.subscriptions).toBe(xsubs);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should switch to an inner never', () => {\n    testScheduler.run(({ hot, cold, expectObservable, expectSubscriptions }) => {\n      const x = cold('           -                    ');\n      const xsubs = [\n        '               ---------^---------!          ',\n        //                                 -\n        '               -------------------^          ',\n      ];\n      const e1 = hot('  ---------x---------x---------|');\n      const e1subs = '  ^----------------------------!';\n      const expected = '------------------------------';\n\n      expectObservable(e1.pipe(switchMapTo(x))).toBe(expected);\n      expectSubscriptions(x.subscriptions).toBe(xsubs);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should switch to an inner that just raises an error', () => {\n    testScheduler.run(({ hot, cold, expectObservable, expectSubscriptions }) => {\n      const x = cold('           #                    ');\n      const xsubs = '   ---------(^!)                 ';\n      const e1 = hot('  ---------x---------x---------|');\n      const e1subs = '  ^--------!                    ';\n      const expected = '---------#                    ';\n\n      expectObservable(e1.pipe(switchMapTo(x))).toBe(expected);\n      expectSubscriptions(x.subscriptions).toBe(xsubs);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should handle an empty outer', () => {\n    testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' |   ');\n      const e1subs = '  (^!)';\n      const expected = '|   ';\n\n      expectObservable(e1.pipe(switchMapTo(of('foo')))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should handle a never outer', () => {\n    testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' -');\n      const e1subs = '  ^';\n      const expected = '-';\n\n      expectObservable(e1.pipe(switchMapTo(of('foo')))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should handle an outer that just raises and error', () => {\n    testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' #   ');\n      const e1subs = '  (^!)';\n      const expected = '#   ';\n\n      expectObservable(e1.pipe(switchMapTo(of('foo')))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should stop listening to a synchronous observable when unsubscribed', () => {\n    const sideEffects: number[] = [];\n    const synchronousObservable = new Observable<number>((subscriber) => {\n      // This will check to see if the subscriber was closed on each loop\n      // when the unsubscribe hits (from the `take`), it should be closed\n      for (let i = 0; !subscriber.closed && i < 10; i++) {\n        sideEffects.push(i);\n        subscriber.next(i);\n      }\n    });\n\n    synchronousObservable.pipe(switchMapTo(of(0)), take(3)).subscribe(() => {\n      /* noop */\n    });\n\n    expect(sideEffects).to.deep.equal([0, 1, 2]);\n  });\n});\n"
  },
  {
    "path": "packages/rxjs/spec/operators/switchScan-spec.ts",
    "content": "import { expect } from 'chai';\nimport { concat, defer, Observable, of } from 'rxjs';\nimport { switchScan, map, mergeMap, takeWhile } from 'rxjs/operators';\nimport { TestScheduler } from 'rxjs/testing';\nimport { observableMatcher } from '../helpers/observableMatcher';\n\n/** @test {switchScan} */\ndescribe('switchScan', () => {\n  let testScheduler: TestScheduler;\n\n  beforeEach(() => {\n    testScheduler = new TestScheduler(observableMatcher);\n  });\n\n  it('should map-and-flatten each item to an Observable while passing the accumulated value', () => {\n    testScheduler.run(({ hot, cold, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  --1-----3--5-------|');\n      const e1subs = '  ^------------------!';\n      const e2 = cold('    x-x-x|           ', { x: 10 });\n      //                        x-x-x|\n      //                           x-x-x|\n      const expected = '--x-x-x-y-yz-z-z---|';\n      const values = { x: 10, y: 40, z: 90 };\n\n      const result = e1.pipe(switchScan((acc, x) => e2.pipe(map((i) => i * Number(x) + acc)), 0));\n\n      expectObservable(result).toBe(expected, values);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should provide the proper accumulated values', () => {\n    const accs: number[] = [];\n\n    of(1, 3, 5)\n      .pipe(\n        switchScan((acc, x) => {\n          accs.push(acc);\n          return of(acc + x);\n        }, 100)\n      )\n      .subscribe();\n\n    expect(accs).to.deep.equal([100, 101, 104]);\n  });\n\n  it('should unsub inner observables', () => {\n    const unsubbed: string[] = [];\n\n    of('a', 'b')\n      .pipe(\n        switchScan(\n          (_acc, x) =>\n            new Observable<string>((subscriber) => {\n              subscriber.complete();\n              return () => {\n                unsubbed.push(x);\n              };\n            }),\n          null\n        )\n      )\n      .subscribe();\n\n    expect(unsubbed).to.deep.equal(['a', 'b']);\n  });\n\n  it('should switch inner cold observables', () => {\n    testScheduler.run(({ hot, cold, expectObservable, expectSubscriptions }) => {\n      const x = cold('           --a--b--c--d--e--|           ');\n      const xsubs = '   ---------^---------!                  ';\n      const y = cold('                     ---f---g---h---i--|');\n      const ysubs = '   -------------------^-----------------!';\n      const e1 = hot('  ---------x---------y---------|        ');\n      const e1subs = '  ^----------------------------!        ';\n      const expected = '-----------a--b--c----f---g---h---i--|';\n\n      const observableLookup: Record<string, Observable<string>> = { x, y };\n\n      const result = e1.pipe(switchScan((_acc, value) => observableLookup[value], null));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(x.subscriptions).toBe(xsubs);\n      expectSubscriptions(y.subscriptions).toBe(ysubs);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should raise error when projection throws', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  -------x-----y---|');\n      const e1subs = '  ^------!          ';\n      const expected = '-------#          ';\n\n      function project(): any[] {\n        throw 'error';\n      }\n\n      expectObservable(e1.pipe(switchScan(project, null))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should switch inner cold observables, outer is unsubscribed early', () => {\n    testScheduler.run(({ hot, cold, expectObservable, expectSubscriptions }) => {\n      const x = cold('           --a--b--c--d--e--|           ');\n      const xsubs = '   ---------^---------!                  ';\n      const y = cold('                     ---f---g---h---i--|');\n      const ysubs = '   -------------------^-!                ';\n      const e1 = hot('  ---------x---------y---------|        ');\n      const e1subs = '  ^--------------------!                ';\n      const unsub = '   ---------------------!                ';\n      const expected = '-----------a--b--c----                ';\n\n      const observableLookup: Record<string, Observable<string>> = { x, y };\n\n      const result = e1.pipe(switchScan((_acc, value) => observableLookup[value], null));\n\n      expectObservable(result, unsub).toBe(expected);\n      expectSubscriptions(x.subscriptions).toBe(xsubs);\n      expectSubscriptions(y.subscriptions).toBe(ysubs);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should not break unsubscription chains when result is unsubscribed explicitly', () => {\n    testScheduler.run(({ hot, cold, expectObservable, expectSubscriptions }) => {\n      const x = cold('           --a--b--c--d--e--|           ');\n      const xsubs = '   ---------^---------!                  ';\n      const y = cold('                     ---f---g---h---i--|');\n      const ysubs = '   -------------------^-!                ';\n      const e1 = hot('  ---------x---------y---------|        ');\n      const e1subs = '  ^--------------------!                ';\n      const expected = '-----------a--b--c----                ';\n      const unsub = '   ---------------------!                ';\n\n      const observableLookup: Record<string, Observable<string>> = { x, y };\n\n      const result = e1.pipe(\n        mergeMap((x) => of(x)),\n        switchScan((_acc, value) => observableLookup[value], null),\n        mergeMap((x) => of(x))\n      );\n\n      expectObservable(result, unsub).toBe(expected);\n      expectSubscriptions(x.subscriptions).toBe(xsubs);\n      expectSubscriptions(y.subscriptions).toBe(ysubs);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should stop listening to a synchronous observable when unsubscribed', () => {\n    const sideEffects: number[] = [];\n    const synchronousObservable = concat(\n      defer(() => {\n        sideEffects.push(1);\n        return of(1);\n      }),\n      defer(() => {\n        sideEffects.push(2);\n        return of(2);\n      }),\n      defer(() => {\n        sideEffects.push(3);\n        return of(3);\n      })\n    );\n\n    of(null)\n      .pipe(\n        switchScan(() => synchronousObservable, null),\n        takeWhile((x) => x != 2) // unsubscribe at the second side-effect\n      )\n      .subscribe(() => {\n        /* noop */\n      });\n\n    expect(sideEffects).to.deep.equal([1, 2]);\n  });\n\n  it('should switch inner cold observables, inner never completes', () => {\n    testScheduler.run(({ hot, cold, expectObservable, expectSubscriptions }) => {\n      const x = cold('           --a--b--c--d--e--|          ');\n      const xsubs = '   ---------^---------!                 ';\n      const y = cold('                     ---f---g---h---i--');\n      const ysubs = '   -------------------^                 ';\n      const e1 = hot('  ---------x---------y---------|       ');\n      const e1subs = '  ^----------------------------!       ';\n      const expected = '-----------a--b--c----f---g---h---i--';\n\n      const observableLookup: Record<string, Observable<string>> = { x, y };\n\n      const result = e1.pipe(switchScan((_acc, value) => observableLookup[value], null));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(x.subscriptions).toBe(xsubs);\n      expectSubscriptions(y.subscriptions).toBe(ysubs);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should handle a synchronous switch to the second inner observable', () => {\n    testScheduler.run(({ hot, cold, expectObservable, expectSubscriptions }) => {\n      const x = cold('           --a--b--c--d--e--|   ');\n      const xsubs = '   ---------(^!)                 ';\n      const y = cold('           ---f---g---h---i--|  ');\n      const ysubs = '   ---------^-----------------!  ';\n      const e1 = hot('  ---------(xy)----------------|');\n      const e1subs = '  ^----------------------------!';\n      const expected = '------------f---g---h---i----|';\n\n      const observableLookup: Record<string, Observable<string>> = { x, y };\n\n      const result = e1.pipe(switchScan((_acc, value) => observableLookup[value], null));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(x.subscriptions).toBe(xsubs);\n      expectSubscriptions(y.subscriptions).toBe(ysubs);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should switch inner cold observables, one inner throws', () => {\n    testScheduler.run(({ hot, cold, expectObservable, expectSubscriptions }) => {\n      const x = cold('           --a--b--#--d--e--|          ');\n      const xsubs = '   ---------^-------!                   ';\n      const y = cold('                     ---f---g---h---i--');\n      const ysubs = '                                        ';\n      const e1 = hot('  ---------x---------y---------|       ');\n      const e1subs = '  ^----------------!                   ';\n      const expected = '-----------a--b--#                   ';\n\n      const observableLookup: Record<string, Observable<string>> = { x, y };\n\n      const result = e1.pipe(switchScan((_acc, value) => observableLookup[value], null));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(x.subscriptions).toBe(xsubs);\n      expectSubscriptions(y.subscriptions).toBe(ysubs);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should switch inner hot observables', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const x = hot('   -----a--b--c--d--e--|                 ');\n      const xsubs = '   ---------^---------!                  ';\n      const y = hot('   --p-o-o-p-------------f---g---h---i--|');\n      const ysubs = '   -------------------^-----------------!';\n      const e1 = hot('  ---------x---------y---------|        ');\n      const e1subs = '  ^----------------------------!        ';\n      const expected = '-----------c--d--e----f---g---h---i--|';\n\n      const observableLookup: Record<string, Observable<string>> = { x, y };\n\n      const result = e1.pipe(switchScan((_acc, value) => observableLookup[value], null));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(x.subscriptions).toBe(xsubs);\n      expectSubscriptions(y.subscriptions).toBe(ysubs);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should switch inner empty and empty', () => {\n    testScheduler.run(({ hot, cold, expectObservable, expectSubscriptions }) => {\n      const x = cold('           |                    ');\n      const y = cold('                     |          ');\n      const xsubs = '   ---------(^!)                 ';\n      const ysubs = '   -------------------(^!)       ';\n      const e1 = hot('  ---------x---------y---------|');\n      const e1subs = '  ^----------------------------!';\n      const expected = '-----------------------------|';\n\n      const observableLookup: Record<string, Observable<string>> = { x, y };\n\n      const result = e1.pipe(switchScan((_acc, value) => observableLookup[value], null));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(x.subscriptions).toBe(xsubs);\n      expectSubscriptions(y.subscriptions).toBe(ysubs);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should switch inner empty and never', () => {\n    testScheduler.run(({ hot, cold, expectObservable, expectSubscriptions }) => {\n      const x = cold('           |                    ');\n      const y = cold('                     -----------');\n      const xsubs = '   ---------(^!)                 ';\n      const ysubs = '   -------------------^          ';\n      const e1 = hot('  ---------x---------y---------|');\n      const e1subs = '  ^----------------------------!';\n      const expected = '------------------------------';\n\n      const observableLookup: Record<string, Observable<string>> = { x, y };\n\n      const result = e1.pipe(switchScan((_acc, value) => observableLookup[value], null));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(x.subscriptions).toBe(xsubs);\n      expectSubscriptions(y.subscriptions).toBe(ysubs);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should switch inner never and empty', () => {\n    testScheduler.run(({ hot, cold, expectObservable, expectSubscriptions }) => {\n      const x = cold('           -----------          ');\n      const y = cold('                     |          ');\n      const xsubs = '   ---------^---------!          ';\n      const ysubs = '   -------------------(^!)       ';\n      const e1 = hot('  ---------x---------y---------|');\n      const e1subs = '  ^----------------------------!';\n      const expected = '-----------------------------|';\n\n      const observableLookup: Record<string, Observable<string>> = { x, y };\n\n      const result = e1.pipe(switchScan((_acc, value) => observableLookup[value], null));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(x.subscriptions).toBe(xsubs);\n      expectSubscriptions(y.subscriptions).toBe(ysubs);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should switch inner never and throw', () => {\n    testScheduler.run(({ hot, cold, expectObservable, expectSubscriptions }) => {\n      const x = cold('           -----------          ');\n      const y = cold('                     #          ', undefined, 'sad');\n      const xsubs = '   ---------^---------!          ';\n      const ysubs = '   -------------------(^!)       ';\n      const e1 = hot('  ---------x---------y---------|');\n      const e1subs = '  ^------------------!          ';\n      const expected = '-------------------#          ';\n\n      const observableLookup: Record<string, Observable<string>> = { x, y };\n\n      const result = e1.pipe(switchScan((_acc, value) => observableLookup[value], null));\n\n      expectObservable(result).toBe(expected, undefined, 'sad');\n      expectSubscriptions(x.subscriptions).toBe(xsubs);\n      expectSubscriptions(y.subscriptions).toBe(ysubs);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should switch inner empty and throw', () => {\n    testScheduler.run(({ hot, cold, expectObservable, expectSubscriptions }) => {\n      const x = cold('           |                    ');\n      const y = cold('                     #          ', undefined, 'sad');\n      const xsubs = '   ---------(^!)                 ';\n      const ysubs = '   -------------------(^!)       ';\n      const e1 = hot('  ---------x---------y---------|');\n      const e1subs = '  ^------------------!          ';\n      const expected = '-------------------#          ';\n\n      const observableLookup: Record<string, Observable<string>> = { x, y };\n\n      const result = e1.pipe(switchScan((_acc, value) => observableLookup[value], null));\n\n      expectObservable(result).toBe(expected, undefined, 'sad');\n      expectSubscriptions(x.subscriptions).toBe(xsubs);\n      expectSubscriptions(y.subscriptions).toBe(ysubs);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should handle outer empty', () => {\n    testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' |   ');\n      const e1subs = '  (^!)';\n      const expected = '|   ';\n\n      const result = e1.pipe(switchScan((_acc, value) => of(value), ''));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should handle outer never', () => {\n    testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' -');\n      const e1subs = '  ^';\n      const expected = '-';\n\n      const result = e1.pipe(switchScan((_acc, value) => of(value), ''));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should handle outer throw', () => {\n    testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' #   ');\n      const e1subs = '  (^!)';\n      const expected = '#   ';\n\n      const result = e1.pipe(switchScan((_acc, value) => of(value), ''));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should handle outer error', () => {\n    testScheduler.run(({ hot, cold, expectObservable, expectSubscriptions }) => {\n      const x = cold('           --a--b--c--d--e--|');\n      const xsubs = '   ---------^---------!       ';\n      const e1 = hot('  ---------x---------#       ');\n      const e1subs = '  ^------------------!       ';\n      const expected = '-----------a--b--c-#       ';\n\n      const observableLookup: Record<string, Observable<string>> = { x: x };\n\n      const result = e1.pipe(switchScan((_acc, value) => observableLookup[value], null));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(x.subscriptions).toBe(xsubs);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should create a new seed for each subscriber', () => {\n    const seeds: string[] = [];\n    const observer = (value: string) => seeds.push(value);\n\n    const source = of('a', 'b').pipe(switchScan((acc, x) => of(acc + x), ''));\n\n    source.subscribe(observer);\n    source.subscribe(observer);\n\n    expect(seeds).to.deep.equal(['a', 'ab', 'a', 'ab']);\n  });\n\n  it('should pass index to the accumulator function', () => {\n    const indices: number[] = [];\n\n    of('a', 'b', 'c', 'd')\n      .pipe(\n        switchScan((_acc, _x, index) => {\n          indices.push(index);\n          return of();\n        }, '')\n      )\n      .subscribe();\n\n    expect(indices).to.deep.equal([0, 1, 2, 3]);\n  });\n});\n"
  },
  {
    "path": "packages/rxjs/spec/operators/take-spec.ts",
    "content": "import { expect } from 'chai';\nimport { config, merge, Observable, of, Subject } from 'rxjs';\nimport { finalize, mergeMap, take, tap } from 'rxjs/operators';\nimport { TestScheduler } from 'rxjs/testing';\nimport { observableMatcher } from '../helpers/observableMatcher';\n\n/** @test {take} */\ndescribe('take', () => {\n  let testScheduler: TestScheduler;\n\n  beforeEach(() => {\n    testScheduler = new TestScheduler(observableMatcher);\n  });\n\n  it('should take two values of an observable with many values', () => {\n    testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' --a-----b----c---d--|');\n      const e1subs = '  ^-------!------------';\n      const expected = '--a-----(b|)         ';\n\n      expectObservable(e1.pipe(take(2))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should work with empty', () => {\n    testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' |');\n      const e1subs = '  (^!)';\n      const expected = '|';\n\n      expectObservable(e1.pipe(take(42))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should go on forever on never', () => {\n    testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' -');\n      const e1subs = '  ^';\n      const expected = '-';\n\n      expectObservable(e1.pipe(take(42))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should be empty on take(0)', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('--a--^--b----c---d--|');\n      const e1subs: string[] = []; // Don't subscribe at all\n      const expected = '   |';\n\n      expectObservable(e1.pipe(take(0))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should be empty if provided with negative value', () => {\n    testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' --a-----b----c---d--|');\n      const expected = '|';\n      const e1subs: string[] = []; // Don't subscribe at all\n\n      expectObservable(e1.pipe(take(-42))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should take one value of an observable with one value', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  ---(a|)');\n      const e1subs = '  ^--!---';\n      const expected = '---(a|)';\n\n      expectObservable(e1.pipe(take(1))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should take one values of an observable with many values', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('--a--^--b----c---d--|');\n      const e1subs = '     ^--!------------';\n      const expected = '   ---(b|)         ';\n\n      expectObservable(e1.pipe(take(1))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should error on empty', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('--a--^----|');\n      const e1subs = '     ^----!';\n      const expected = '   -----|';\n\n      expectObservable(e1.pipe(take(42))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should propagate error from the source observable', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('---^---#', undefined, 'too bad');\n      const e1subs = '   ^---!';\n      const expected = ' ----#';\n\n      expectObservable(e1.pipe(take(42))).toBe(expected, null, 'too bad');\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should propagate error from an observable with values', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('---^--a--b--#');\n      const e1subs = '   ^--------!';\n      const expected = ' ---a--b--#';\n\n      expectObservable(e1.pipe(take(42))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should allow unsubscribing explicitly and early', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('---^--a--b-----c--d--e--|');\n      const unsub = '    ---------!------------';\n      const e1subs = '   ^--------!------------';\n      const expected = ' ---a--b---            ';\n\n      expectObservable(e1.pipe(take(42)), unsub).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should work with throw', () => {\n    testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' #');\n      const e1subs = '  (^!)';\n      const expected = '#';\n\n      expectObservable(e1.pipe(take(42))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should not break unsubscription chain when unsubscribed explicitly', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('---^--a--b-----c--d--e--|');\n      const unsub = '    ---------!            ';\n      const e1subs = '   ^--------!            ';\n      const expected = ' ---a--b---            ';\n\n      const result = e1.pipe(\n        mergeMap((x: string) => of(x)),\n        take(42),\n        mergeMap((x: string) => of(x))\n      );\n\n      expectObservable(result, unsub).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should unsubscribe from the source when it reaches the limit', () => {\n    const source = new Observable<number>((observer) => {\n      expect(observer.closed).to.be.false;\n      observer.next(42);\n      expect(observer.closed).to.be.true;\n    }).pipe(take(1));\n\n    source.subscribe();\n  });\n\n  it('should complete when the source is reentrant', () => {\n    let completed = false;\n    const source = new Subject<void>();\n    source.pipe(take(5)).subscribe({\n      next() {\n        source.next();\n      },\n      complete() {\n        completed = true;\n      },\n    });\n    source.next();\n    expect(completed).to.be.true;\n  });\n\n  it('should stop listening to a synchronous observable when unsubscribed', () => {\n    const sideEffects: number[] = [];\n    const synchronousObservable = new Observable<number>((subscriber) => {\n      // This will check to see if the subscriber was closed on each loop\n      // when the unsubscribe hits (from the `take`), it should be closed\n      for (let i = 0; !subscriber.closed && i < 10; i++) {\n        sideEffects.push(i);\n        subscriber.next(i);\n      }\n    });\n\n    synchronousObservable.pipe(take(3)).subscribe(() => {\n      /* noop */\n    });\n\n    expect(sideEffects).to.deep.equal([0, 1, 2]);\n  });\n\n  it('should complete even if the parameter is a string', () => {\n    testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' --a-----b----c---d--|');\n      const e1subs = '  ^-------!------------';\n      const expected = '--a-----(b|)         ';\n\n      expectObservable(e1.pipe(take('2' as any))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should unsubscribe from the source when it reaches the limit before a recursive synchronous upstream error is notified', () => {\n    testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const subject = new Subject();\n      const e1 = cold(' (a|)');\n      const e1subs = '  (^!)';\n      const expected = '(a|)';\n\n      const result = merge(e1, subject).pipe(\n        take(1),\n        tap(() => subject.error('error'))\n      );\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should unsubscribe from the source when it reaches the limit before a recursive synchronous upstream completion is notified', () => {\n    testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const subject = new Subject();\n      const e1 = cold(' (a|)');\n      const e1subs = '  (^!)';\n      const expected = '(a|)';\n\n      const result = merge(e1, subject).pipe(\n        take(1),\n        tap(() => subject.complete())\n      );\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should properly handle reentrancy when taking many values', () => {\n    const results: any[] = [];\n    const subject = new Subject<number>();\n\n    config.onStoppedNotification = (x) => results.push(x);\n\n    merge(subject, of(1))\n      .pipe(\n        finalize(() => results.push('finalize source')),\n        take(5),\n        tap((n) => subject.next(n + 1)),\n        finalize(() => results.push('finalize result'))\n      )\n      .subscribe({\n        next: (n) => results.push(n),\n        complete: () => results.push('done'),\n      });\n\n    // Because this is reentrant, the last \"taken\" value of 5 is followed by `complete()`\n    // which shuts off all value emissions. Otherwise, this would be\n    // [5, 'done', 4, 3, 2, 1, 'finalize source', 'finalize result']\n    expect(results).to.deep.equal([5, 'done', 'finalize source', 'finalize result']);\n  });\n\n  afterEach(() => (config.onStoppedNotification = null));\n});\n"
  },
  {
    "path": "packages/rxjs/spec/operators/takeLast-spec.ts",
    "content": "import { takeLast, mergeMap } from 'rxjs/operators';\nimport { of } from 'rxjs';\nimport { TestScheduler } from 'rxjs/testing';\nimport { observableMatcher } from '../helpers/observableMatcher';\n\n/** @test {takeLast} */\ndescribe('takeLast operator', () => {\n  let rxTest: TestScheduler;\n\n  beforeEach(() => {\n    rxTest = new TestScheduler(observableMatcher);\n  });\n\n  it('should take two values of an observable with many values', () => {\n    rxTest.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold('--a-----b----c---d--|    ');\n      const e1subs = ' ^-------------------!    ';\n      const expected = '--------------------(cd|)';\n\n      expectObservable(e1.pipe(takeLast(2))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should take last three values', () => {\n    rxTest.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' --a-----b----c---d--|    ');\n      const e1subs = '  ^-------------------!    ';\n      const expected = '--------------------(bcd|)';\n\n      expectObservable(e1.pipe(takeLast(3))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should take all element when try to take larger then source', () => {\n    rxTest.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' --a-----b----c---d--|    ');\n      const e1subs = '  ^-------------------!    ';\n      const expected = '--------------------(abcd|)';\n\n      expectObservable(e1.pipe(takeLast(5))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should take all element when try to take exact', () => {\n    rxTest.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' --a-----b----c---d--|    ');\n      const e1subs = '  ^-------------------!    ';\n      const expected = '--------------------(abcd|)';\n\n      expectObservable(e1.pipe(takeLast(4))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should not take any values', () => {\n    rxTest.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' --a-----b----c---d--|');\n      const expected = '|';\n      const e1subs: string[] = [];\n\n      expectObservable(e1.pipe(takeLast(0))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should not take any values if provided with negative value', () => {\n    rxTest.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' --a-----b----c---d--|');\n      const expected = '|';\n      const e1subs: string[] = [];\n\n      expectObservable(e1.pipe(takeLast(-42))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should work with empty', () => {\n    rxTest.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' |');\n      const e1subs = '  (^!)';\n      const expected = '|';\n\n      expectObservable(e1.pipe(takeLast(42))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should go on forever on never', () => {\n    rxTest.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' -');\n      const e1subs = '  ^';\n      const expected = '-';\n\n      expectObservable(e1.pipe(takeLast(42))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should be empty on takeLast(0)', () => {\n    rxTest.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('--a--^--b----c---d--|');\n      const expected = '   |';\n      const e1subs: string[] = []; // Don't subscribe at all\n\n      expectObservable(e1.pipe(takeLast(0))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should take one value from an observable with one value', () => {\n    rxTest.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  ---(a|)');\n      const e1subs = '  ^--!   ';\n      const expected = '---(a|)';\n\n      expectObservable(e1.pipe(takeLast(1))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should take one value from an observable with many values', () => {\n    rxTest.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('--a--^--b----c---d--|   ');\n      const e1subs = '     ^--------------!   ';\n      const expected = '   ---------------(d|)';\n\n      expectObservable(e1.pipe(takeLast(1))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should error on empty', () => {\n    rxTest.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('--a--^----|');\n      const e1subs = '     ^----!';\n      const expected = '   -----|';\n\n      expectObservable(e1.pipe(takeLast(42))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should propagate error from the source observable', () => {\n    rxTest.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('---^---#', undefined, 'too bad');\n      const e1subs = '   ^---!';\n      const expected = ' ----#';\n\n      expectObservable(e1.pipe(takeLast(42))).toBe(expected, null, 'too bad');\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should propagate error from an observable with values', () => {\n    rxTest.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('---^--a--b--#');\n      const e1subs = '   ^--------!';\n      const expected = ' ---------#';\n\n      expectObservable(e1.pipe(takeLast(42))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should allow unsubscribing explicitly and early', () => {\n    rxTest.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('---^--a--b-----c--d--e--|');\n      const unsub = '    ---------!            ';\n      const e1subs = '   ^--------!            ';\n      const expected = ' ----------------------';\n\n      expectObservable(e1.pipe(takeLast(42)), unsub).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should work with throw', () => {\n    rxTest.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' #');\n      const e1subs = '  (^!)';\n      const expected = '#';\n\n      expectObservable(e1.pipe(takeLast(42))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should not break unsubscription chain when unsubscribed explicitly', () => {\n    rxTest.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('---^--a--b-----c--d--e--|');\n      const unsub = '    ---------!            ';\n      const e1subs = '   ^--------!            ';\n      const expected = ' ----------------------';\n\n      const result = e1.pipe(\n        mergeMap((x: string) => of(x)),\n        takeLast(42),\n        mergeMap((x: string) => of(x))\n      );\n\n      expectObservable(result, unsub).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n});\n"
  },
  {
    "path": "packages/rxjs/spec/operators/takeUntil-spec.ts",
    "content": "/** @prettier */\nimport { takeUntil, mergeMap, tap } from 'rxjs/operators';\nimport { of, EMPTY, Subject, merge } from 'rxjs';\nimport { TestScheduler } from 'rxjs/testing';\nimport { observableMatcher } from '../helpers/observableMatcher';\n\n/** @test {takeUntil} */\ndescribe('takeUntil operator', () => {\n  let testScheduler: TestScheduler;\n\n  beforeEach(() => {\n    testScheduler = new TestScheduler(observableMatcher);\n  });\n\n  it('should take values until notifier emits', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  --a--b--c--d--e--f--g--|');\n      const e1subs = '  ^------------!          ';\n      const e2 = hot('  -------------z--|       ');\n      const e2subs = '  ^------------!          ';\n      const expected = '--a--b--c--d-|          ';\n\n      expectObservable(e1.pipe(takeUntil(e2))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should take values and raises error when notifier raises error', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  --a--b--c--d--e--f--g--|');\n      const e1subs = '  ^------------!          ';\n      const e2 = hot('  -------------#          ');\n      const e2subs = '  ^------------!          ';\n      const expected = '--a--b--c--d-#          ';\n\n      expectObservable(e1.pipe(takeUntil(e2))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should take all values when notifier is empty', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  --a--b--c--d--e--f--g--|');\n      const e1subs = '  ^----------------------!';\n      const e2 = hot('  -------------|          ');\n      const e2subs = '  ^------------!          ';\n      const expected = '--a--b--c--d--e--f--g--|';\n\n      expectObservable(e1.pipe(takeUntil(e2))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should take all values when notifier does not complete', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  --a--b--c--d--e--f--g--|');\n      const e1subs = '  ^----------------------!';\n      const e2 = hot('  -                       ');\n      const e2subs = '  ^----------------------!';\n      const expected = '--a--b--c--d--e--f--g--|';\n\n      expectObservable(e1.pipe(takeUntil(e2))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should complete without subscribing to the source when notifier synchronously emits', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  ----a--|');\n      const e2 = of(1, 2, 3);\n      const expected = '(|)     ';\n\n      expectObservable(e1.pipe(takeUntil(e2))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe([]);\n    });\n  });\n\n  it('should subscribe to the source when notifier synchronously completes without emitting', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  ----a--|');\n      const e1subs = '  ^------!';\n      const e2 = EMPTY;\n      const expected = '----a--|';\n\n      expectObservable(e1.pipe(takeUntil(e2))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should allow unsubscribing explicitly and early', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  --a--b--c--d--e--f--g--|');\n      const e1subs = '  ^------!                ';\n      const e2 = hot('  -------------z--|       ');\n      const e2subs = '  ^------!                ';\n      const unsub = '   -------!                ';\n      const expected = '--a--b--                ';\n\n      expectObservable(e1.pipe(takeUntil(e2)), unsub).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should complete when notifier emits if source observable does not complete', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  -        ');\n      const e1subs = '  ^-!      ';\n      const e2 = hot('  --a--b--|');\n      const e2subs = '  ^-!      ';\n      const expected = '--|      ';\n\n      expectObservable(e1.pipe(takeUntil(e2))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should raise error when notifier raises error if source observable does not complete', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  -  ');\n      const e1subs = '  ^-!';\n      const e2 = hot('  --#');\n      const e2subs = '  ^-!';\n      const expected = '--#';\n\n      expectObservable(e1.pipe(takeUntil(e2))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should not complete when notifier is empty if source observable does not complete', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  -  ');\n      const e1subs = '  ^  ';\n      const e2 = hot('  --|');\n      const e2subs = '  ^-!';\n      const expected = '---';\n\n      expectObservable(e1.pipe(takeUntil(e2))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should not complete when source and notifier do not complete', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  -');\n      const e1subs = '  ^';\n      const e2 = hot('  -');\n      const e2subs = '  ^';\n      const expected = '-';\n\n      expectObservable(e1.pipe(takeUntil(e2))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should complete when notifier emits before source observable emits', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  ----a--|');\n      const e1subs = '  ^-!     ';\n      const e2 = hot('  --x     ');\n      const e2subs = '  ^-!     ';\n      const expected = '--|     ';\n\n      expectObservable(e1.pipe(takeUntil(e2))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should raise error if source raises error before notifier emits', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  --a--b--c--d--#     ');\n      const e1subs = '  ^-------------!     ';\n      const e2 = hot('  ----------------a--|');\n      const e2subs = '  ^-------------!     ';\n      const expected = '--a--b--c--d--#     ';\n\n      expectObservable(e1.pipe(takeUntil(e2))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should raise error immediately if source throws', () => {\n    testScheduler.run(({ hot, cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' #   ');\n      const e1subs = '  (^!)';\n      const e2 = hot('  --x ');\n      const e2subs = '  (^!)';\n      const expected = '#   ';\n\n      expectObservable(e1.pipe(takeUntil(e2))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should dispose source observable if notifier emits before source emits', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  ---a---|');\n      const e1subs = '  ^-!     ';\n      const e2 = hot('  --x-|   ');\n      const e2subs = '  ^-!     ';\n      const expected = '--|     ';\n\n      expectObservable(e1.pipe(takeUntil(e2))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should dispose notifier if source observable completes', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  --a--|     ');\n      const e1subs = '  ^----!     ';\n      const e2 = hot('  -------x--|');\n      const e2subs = '  ^----!     ';\n      const expected = '--a--|     ';\n\n      expectObservable(e1.pipe(takeUntil(e2))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should not break unsubscription chain when unsubscribed explicitly', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  --a--b--c--d--e--f--g--|');\n      const e1subs = '  ^------!                ';\n      const e2 = hot('  -------------z--|       ');\n      const e2subs = '  ^------!                ';\n      const unsub = '   -------!                ';\n      const expected = '--a--b--                ';\n\n      const result = e1.pipe(\n        mergeMap((x: string) => of(x)),\n        takeUntil(e2),\n        mergeMap((x: string) => of(x))\n      );\n\n      expectObservable(result, unsub).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should not emit errors sent from the source *after* it found the first value in reentrant scenarios', () => {\n    testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const subject = new Subject();\n      const source = cold('  -------a----b----c---|');\n      const notifier = cold('--------------x--');\n      const expected = '     -------a----b-|';\n      const subs = '         ^-------------!';\n\n      const result = merge(source, subject).pipe(\n        takeUntil(notifier),\n        tap({\n          complete: () => {\n            subject.error(new Error('reentrant shennanigans'));\n          },\n        })\n      );\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(source.subscriptions).toBe(subs);\n      expectSubscriptions(notifier.subscriptions).toBe(subs);\n    });\n  });\n});\n"
  },
  {
    "path": "packages/rxjs/spec/operators/takeWhile-spec.ts",
    "content": "import { expect } from 'chai';\nimport { takeWhile, tap, mergeMap } from 'rxjs/operators';\nimport { of, Observable, from, Subject, merge } from 'rxjs';\nimport { TestScheduler } from 'rxjs/testing';\nimport { observableMatcher } from '../helpers/observableMatcher';\n\n/** @test {takeWhile} */\ndescribe('takeWhile', () => {\n  let testScheduler: TestScheduler;\n\n  beforeEach(() => {\n    testScheduler = new TestScheduler(observableMatcher);\n  });\n\n  it('should take all elements until predicate is false', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('-1-^2--3--4--5--6--|');\n      const e1subs = '   ^------!         ';\n      const expected = ' -2--3--|         ';\n\n      const result = e1.pipe(takeWhile((v) => +v < 4));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should take all elements with predicate returns true', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('--a-^-b--c--d--e--|');\n      const e1subs = '    ^-------------!';\n      const expected = '  --b--c--d--e--|';\n\n      const result = e1.pipe(takeWhile(() => true));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should take all elements with truthy predicate', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('--a-^-b--c--d--e--|');\n      const e1subs = '    ^-------------!';\n      const expected = '  --b--c--d--e--|';\n\n      const result = e1.pipe(\n        takeWhile(<any>(() => {\n          return {};\n        }))\n      );\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should skip all elements with predicate returns false', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('--a-^-b--c--d--e--|');\n      const e1subs = '    ^-!            ';\n      const expected = '  --|            ';\n\n      const result = e1.pipe(takeWhile(() => false));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should skip all elements with falsy predicate', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('--a-^-b--c--d--e--|');\n      const e1subs = '    ^-!            ';\n      const expected = '  --|            ';\n\n      const result = e1.pipe(takeWhile(() => null as any));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should take all elements until predicate return false', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('--a-^-b--c--d--e--|');\n      const e1subs = '    ^-------!      ';\n      const expected = '  --b--c--|      ';\n\n      function predicate(value: string) {\n        return value !== 'd';\n      }\n\n      const result = e1.pipe(takeWhile(predicate));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should take all elements up to and including the element that made the predicate return false', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('--a-^-b--c--d--e--|');\n      const e1subs = '    ^-------!      ';\n      const expected = '  --b--c--(d|)   ';\n\n      function predicate(value: string) {\n        return value !== 'd';\n      }\n      const inclusive = true;\n\n      const result = e1.pipe(takeWhile(predicate, inclusive));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should take elements with predicate when source does not complete', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('--a-^-b--c--d--e--');\n      const e1subs = '    ^-------------';\n      const expected = '  --b--c--d--e--';\n\n      const result = e1.pipe(takeWhile(() => true));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should not complete when source never completes', () => {\n    testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' -');\n      const e1subs = '  ^';\n      const expected = '-';\n\n      const result = e1.pipe(takeWhile(() => true));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should complete when source does not emit', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('--a-^------------|');\n      const e1subs = '    ^------------!';\n      const expected = '  -------------|';\n\n      const result = e1.pipe(takeWhile(() => true));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should complete when source is empty', () => {\n    testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' |   ');\n      const e1subs = '  (^!)';\n      const expected = '|   ';\n\n      const result = e1.pipe(takeWhile(() => true));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should pass element index to predicate', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('--a-^-b--c--d--e--|');\n      const e1subs = '    ^-------!      ';\n      const expected = '  --b--c--|      ';\n\n      function predicate(value: string, index: number) {\n        return index < 2;\n      }\n\n      const result = e1.pipe(takeWhile(predicate));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should raise error when source raises error', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('--a-^-b--c--d--e--#');\n      const e1subs = '    ^-------------!';\n      const expected = '  --b--c--d--e--#';\n\n      const result = e1.pipe(takeWhile(() => true));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should raise error when source throws', () => {\n    testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' #   ');\n      const e1subs = '  (^!)';\n      const expected = '#   ';\n\n      const result = e1.pipe(takeWhile(() => true));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should invoke predicate until return false', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('--a-^-b--c--d--e--|');\n      const e1subs = '    ^-------!      ';\n      const expected = '  --b--c--|      ';\n\n      let invoked = 0;\n      function predicate(value: string) {\n        invoked++;\n        return value !== 'd';\n      }\n\n      const result = e1.pipe(\n        takeWhile(predicate),\n        tap({\n          complete: () => {\n            expect(invoked).to.equal(3);\n          },\n        })\n      );\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should raise error if predicate throws', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('--a-^-b--c--d--e--|');\n      const e1subs = '    ^-!            ';\n      const expected = '  --#            ';\n\n      function predicate(value: string) {\n        throw 'error';\n      }\n\n      const result = e1.pipe(takeWhile(<any>predicate));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should take elements until unsubscribed', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('--a-^-b--c--d--e--|');\n      const unsub = '     -----!         ';\n      const e1subs = '    ^----!         ';\n      const expected = '  --b---         ';\n\n      function predicate(value: string) {\n        return value !== 'd';\n      }\n\n      const result = e1.pipe(takeWhile(predicate));\n\n      expectObservable(result, unsub).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should not break unsubscription chain when unsubscribed explicitly', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('--a-^-b--c--d--e--|');\n      const unsub = '     -----!         ';\n      const e1subs = '    ^----!         ';\n      const expected = '  --b---         ';\n\n      function predicate(value: string) {\n        return value !== 'd';\n      }\n\n      const result = e1.pipe(\n        mergeMap((x: string) => of(x)),\n        takeWhile(predicate),\n        mergeMap((x: string) => of(x))\n      );\n\n      expectObservable(result, unsub).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should support type guards without breaking previous behavior', () => {\n    // type guards with interfaces and classes\n    {\n      interface Bar {\n        bar?: string;\n      }\n      interface Baz {\n        baz?: number;\n      }\n      class Foo implements Bar, Baz {\n        constructor(public bar: string = 'name', public baz: number = 42) {}\n      }\n\n      const isBar = (x: any): x is Bar => x && (<Bar>x).bar !== undefined;\n\n      const foo: Foo = new Foo();\n      of(foo)\n        .pipe(takeWhile((foo) => foo.baz === 42))\n        .subscribe((x) => x.baz); // x is still Foo\n      of(foo)\n        .pipe(takeWhile(isBar))\n        .subscribe((x) => x.bar); // x is Bar!\n\n      const foobar: Bar = new Foo(); // type is interface, not the class\n      of(foobar)\n        .pipe(takeWhile((foobar) => foobar.bar === 'name'))\n        .subscribe((x) => x.bar); // <-- x is still Bar\n      of(foobar)\n        .pipe(takeWhile(isBar))\n        .subscribe((x) => x.bar); // <--- x is Bar!\n\n      const barish = { bar: 'quack', baz: 42 }; // type can quack like a Bar\n      of(barish)\n        .pipe(takeWhile((x) => x.bar === 'quack'))\n        .subscribe((x) => x.bar); // x is still { bar: string; baz: number; }\n      of(barish)\n        .pipe(takeWhile(isBar))\n        .subscribe((bar) => bar.bar); // x is Bar!\n    }\n\n    // type guards with primitive types\n    {\n      const xs: Observable<string | number> = from([1, 'aaa', 3, 'bb']);\n\n      // This type guard will narrow a `string | number` to a string in the examples below\n      const isString = (x: string | number): x is string => typeof x === 'string';\n\n      xs.pipe(takeWhile(isString)).subscribe((s) => s.length); // s is string\n\n      // In contrast, this type of regular boolean predicate still maintains the original type\n      xs.pipe(takeWhile((x) => typeof x === 'number')).subscribe((x) => x); // x is still string | number\n      xs.pipe(takeWhile((x, i) => typeof x === 'number' && x > i)).subscribe((x) => x); // x is still string | number\n    }\n  });\n\n  it('should stop listening to a synchronous observable when unsubscribed', () => {\n    const sideEffects: number[] = [];\n    const synchronousObservable = new Observable<number>((subscriber) => {\n      // This will check to see if the subscriber was closed on each loop\n      // when the unsubscribe hits (from the `take`), it should be closed\n      for (let i = 0; !subscriber.closed && i < 10; i++) {\n        sideEffects.push(i);\n        subscriber.next(i);\n      }\n    });\n\n    synchronousObservable.pipe(takeWhile((value) => value < 2)).subscribe(() => {\n      /* noop */\n    });\n\n    expect(sideEffects).to.deep.equal([0, 1, 2]);\n  });\n\n  it('should not emit errors sent from the source *after* it found the first value in reentrant scenarios', () => {\n    testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const subject = new Subject();\n      const source = cold('-------a----b----c---|');\n      const expected = '   -------a----(b|)';\n      const subs = '       ^-----------!';\n\n      const result = merge(source, subject).pipe(\n        takeWhile((x) => x !== 'b', true),\n        tap({\n          complete: () => {\n            subject.error(new Error('reentrant shennanigans'));\n          },\n        })\n      );\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(source.subscriptions).toBe(subs);\n    });\n  });\n\n  it('should not emit errors sent from the source *after* it found the first value in reentrant scenarios in next', () => {\n    testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const subject = new Subject();\n      const source = cold('-------a----b----c---|');\n      const expected = '   -------a----(b|)';\n      const subs = '       ^-----------!';\n\n      const result = merge(source, subject).pipe(\n        takeWhile((x) => x !== 'b', true),\n        tap((x) => {\n          if (x === 'b') {\n            subject.error(new Error('reentrant shennanigans'));\n          }\n        })\n      );\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(source.subscriptions).toBe(subs);\n    });\n  });\n\n  it('should not emit completes sent from the source *after* it found the first value in reentrant scenarios', () => {\n    testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const subject = new Subject();\n      const source = cold('-------a----b----c---|');\n      const expected = '   -------a----(b|)';\n      const subs = '       ^-----------!';\n\n      const result = merge(source, subject).pipe(\n        takeWhile((x) => x !== 'b', true),\n        tap((x) => {\n          if (x === 'b') {\n            subject.complete();\n          }\n        })\n      );\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(source.subscriptions).toBe(subs);\n    });\n  });\n\n  it('should not emit errors sent from the source *after* it found the first value in reentrant scenarios', () => {\n    testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const subject = new Subject();\n      const source = cold('-------a----b----c---|');\n      const expected = '   -------a----|';\n      const subs = '       ^-----------!';\n\n      const result = merge(source, subject).pipe(\n        takeWhile((x) => x !== 'b'),\n        tap({\n          complete: () => {\n            subject.error(new Error('reentrant shennanigans'));\n          },\n        })\n      );\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(source.subscriptions).toBe(subs);\n    });\n  });\n\n  it('should not emit completions sent from the source *after* it found the first value in reentrant scenarios', () => {\n    testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const subject = new Subject();\n      const source = cold('-------a----b----c---|');\n      const expected = '   -------a----(b|)';\n      const subs = '       ^-----------!';\n\n      const result = merge(source, subject).pipe(\n        takeWhile((x) => x !== 'b', true),\n        tap({\n          complete: () => {\n            subject.complete();\n          },\n        })\n      );\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(source.subscriptions).toBe(subs);\n    });\n  });\n\n  it('should not emit completions sent from the source *after* it found the first value in reentrant scenarios', () => {\n    testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const subject = new Subject();\n      const source = cold('-------a----b----c---|');\n      const expected = '   -------a----|';\n      const subs = '       ^-----------!';\n\n      const result = merge(source, subject).pipe(\n        takeWhile((x) => x !== 'b'),\n        tap({\n          complete: () => {\n            subject.complete();\n          },\n        })\n      );\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(source.subscriptions).toBe(subs);\n    });\n  });\n});\n"
  },
  {
    "path": "packages/rxjs/spec/operators/tap-spec.ts",
    "content": "import { expect } from 'chai';\nimport { tap, mergeMap, take } from 'rxjs/operators';\nimport type { Observer} from 'rxjs';\nimport { Subject, of, throwError, EMPTY, Observable, noop } from 'rxjs';\nimport { TestScheduler } from 'rxjs/testing';\nimport { observableMatcher } from '../helpers/observableMatcher';\n\n/** @test {tap} */\ndescribe('tap', () => {\n  let testScheduler: TestScheduler;\n\n  beforeEach(() => {\n    testScheduler = new TestScheduler(observableMatcher);\n  });\n\n  it('should mirror multiple values and complete', () => {\n    testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' --1--2--3--|');\n      const e1subs = '  ^----------!';\n      const expected = '--1--2--3--|';\n\n      const result = e1.pipe(\n        tap(() => {\n          //noop\n        })\n      );\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should next with a callback', () => {\n    let value = null;\n    of(42)\n      .pipe(\n        tap(function (x) {\n          value = x;\n        })\n      )\n      .subscribe();\n\n    expect(value).to.equal(42);\n  });\n\n  it('should error with a callback', () => {\n    let err = null;\n    throwError(() => 'bad')\n      .pipe(\n        tap({\n          error: function (x) {\n            err = x;\n          },\n        })\n      )\n      .subscribe({\n        error(ex) {\n          expect(ex).to.equal('bad');\n        },\n      });\n\n    expect(err).to.equal('bad');\n  });\n\n  it('should handle everything with an observer', (done) => {\n    const expected = [1, 2, 3];\n    const results: number[] = [];\n\n    of(1, 2, 3)\n      .pipe(\n        tap(<Observer<number>>{\n          next: (x: number) => {\n            results.push(x);\n          },\n          error: () => {\n            done(new Error('should not be called'));\n          },\n          complete: () => {\n            expect(results).to.deep.equal(expected);\n            done();\n          },\n        })\n      )\n      .subscribe();\n  });\n\n  it('should handle everything with a Subject', (done) => {\n    const expected = [1, 2, 3];\n    const results: number[] = [];\n    const subject = new Subject<number>();\n\n    subject.subscribe({\n      next: (x: any) => {\n        results.push(x);\n      },\n      error: () => {\n        done(new Error('should not be called'));\n      },\n      complete: () => {\n        expect(results).to.deep.equal(expected);\n        done();\n      },\n    });\n\n    of(1, 2, 3).pipe(tap(subject)).subscribe();\n  });\n\n  it('should handle an error with a callback', () => {\n    let errored = false;\n    throwError(() => 'bad')\n      .pipe(\n        tap({\n          error: (err: any) => {\n            expect(err).to.equal('bad');\n          },\n        })\n      )\n      .subscribe({\n        error(err: any) {\n          errored = true;\n          expect(err).to.equal('bad');\n        },\n      });\n\n    expect(errored).to.be.true;\n  });\n\n  it('should handle an error with observer', () => {\n    let errored = false;\n    throwError(() => 'bad')\n      .pipe(\n        tap(<any>{\n          error: function (err: string) {\n            expect(err).to.equal('bad');\n          },\n        })\n      )\n      .subscribe({\n        error(err) {\n          errored = true;\n          expect(err).to.equal('bad');\n        },\n      });\n\n    expect(errored).to.be.true;\n  });\n\n  it('should handle complete with observer', () => {\n    let completed = false;\n\n    EMPTY.pipe(\n      tap(<any>{\n        complete: () => {\n          completed = true;\n        },\n      })\n    ).subscribe();\n\n    expect(completed).to.be.true;\n  });\n\n  it('should handle next with observer', () => {\n    let value = null;\n\n    of('hi')\n      .pipe(\n        tap(<any>{\n          next: (x: string) => {\n            value = x;\n          },\n        })\n      )\n      .subscribe();\n\n    expect(value).to.equal('hi');\n  });\n\n  it('should raise error if next handler raises error', () => {\n    of('hi')\n      .pipe(\n        tap(<any>{\n          next: () => {\n            throw new Error('bad');\n          },\n        })\n      )\n      .subscribe({\n        error(err: any) {\n          expect(err.message).to.equal('bad');\n        },\n      });\n  });\n\n  it('should raise error if error handler raises error', () => {\n    throwError(() => 'ops')\n      .pipe(\n        tap(<any>{\n          error: () => {\n            throw new Error('bad');\n          },\n        })\n      )\n      .subscribe({\n        error(err: any) {\n          expect(err.message).to.equal('bad');\n        },\n      });\n  });\n\n  it('should raise error if complete handler raises error', () => {\n    EMPTY.pipe(\n      tap(<any>{\n        complete: () => {\n          throw new Error('bad');\n        },\n      })\n    ).subscribe({\n      error(err: any) {\n        expect(err.message).to.equal('bad');\n      },\n    });\n  });\n\n  it('should allow unsubscribing explicitly and early', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  --1--2--3--#');\n      const unsub = '   -------!    ';\n      const e1subs = '  ^------!    ';\n      const expected = '--1--2--    ';\n\n      const result = e1.pipe(\n        tap(() => {\n          //noop\n        })\n      );\n      expectObservable(result, unsub).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should not break unsubscription chains when result is unsubscribed explicitly', () => {\n    testScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  --1--2--3--#');\n      const e1subs = '  ^------!    ';\n      const expected = '--1--2--    ';\n      const unsub = '   -------!    ';\n\n      const result = e1.pipe(\n        mergeMap((x: any) => of(x)),\n        tap(() => {\n          //noop\n        }),\n        mergeMap((x: any) => of(x))\n      );\n\n      expectObservable(result, unsub).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should mirror multiple values and complete', () => {\n    testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' --1--2--3--|');\n      const e1subs = '  ^----------!';\n      const expected = '--1--2--3--|';\n\n      const result = e1.pipe(\n        tap(() => {\n          //noop\n        })\n      );\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should mirror multiple values and terminate with error', () => {\n    testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' --1--2--3--#');\n      const e1subs = '  ^----------!';\n      const expected = '--1--2--3--#';\n\n      const result = e1.pipe(\n        tap(() => {\n          //noop\n        })\n      );\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should stop listening to a synchronous observable when unsubscribed', () => {\n    const sideEffects: number[] = [];\n    const synchronousObservable = new Observable<number>((subscriber) => {\n      // This will check to see if the subscriber was closed on each loop\n      // when the unsubscribe hits (from the `take`), it should be closed\n      for (let i = 0; !subscriber.closed && i < 10; i++) {\n        sideEffects.push(i);\n        subscriber.next(i);\n      }\n    });\n\n    synchronousObservable\n      .pipe(\n        tap(() => {\n          /* noop */\n        }),\n        take(3)\n      )\n      .subscribe(() => {\n        /* noop */\n      });\n\n    expect(sideEffects).to.deep.equal([0, 1, 2]);\n  });\n\n  describe('lifecycle handlers', () => {\n    it('should support an unsubscribe event that fires before finalize', () => {\n      const results: any[] = [];\n      const subject = new Subject<number>();\n\n      const subscription = subject\n        .pipe(\n          tap({\n            subscribe: () => results.push('subscribe'),\n            next: (value) => results.push(`next ${value}`),\n            error: (err) => results.push(`error: ${err.message}`),\n            complete: () => results.push('complete'),\n            unsubscribe: () => results.push('unsubscribe'),\n            finalize: () => results.push('finalize'),\n          })\n        )\n        .subscribe();\n\n      subject.next(1);\n      subject.next(2);\n      expect(results).to.deep.equal(['subscribe', 'next 1', 'next 2']);\n\n      subscription.unsubscribe();\n\n      expect(results).to.deep.equal(['subscribe', 'next 1', 'next 2', 'unsubscribe', 'finalize']);\n    });\n\n    it('should not call unsubscribe if source completes', () => {\n      const results: any[] = [];\n      const subject = new Subject<number>();\n\n      const subscription = subject\n        .pipe(\n          tap({\n            subscribe: () => results.push('subscribe'),\n            next: (value) => results.push(`next ${value}`),\n            error: (err) => results.push(`error: ${err.message}`),\n            complete: () => results.push('complete'),\n            unsubscribe: () => results.push('unsubscribe'),\n            finalize: () => results.push('finalize'),\n          })\n        )\n        .subscribe();\n\n      subject.next(1);\n      subject.next(2);\n      expect(results).to.deep.equal(['subscribe', 'next 1', 'next 2']);\n      subject.complete();\n      // should have no effect\n      subscription.unsubscribe();\n\n      expect(results).to.deep.equal(['subscribe', 'next 1', 'next 2', 'complete', 'finalize']);\n    });\n\n    it('should not call unsubscribe if source errors', () => {\n      const results: any[] = [];\n      const subject = new Subject<number>();\n\n      const subscription = subject\n        .pipe(\n          tap({\n            subscribe: () => results.push('subscribe'),\n            next: (value) => results.push(`next ${value}`),\n            error: (err) => results.push(`error: ${err.message}`),\n            complete: () => results.push('complete'),\n            unsubscribe: () => results.push('unsubscribe'),\n            finalize: () => results.push('finalize'),\n          })\n        )\n        .subscribe({\n          error: noop,\n        });\n\n      subject.next(1);\n      subject.next(2);\n      expect(results).to.deep.equal(['subscribe', 'next 1', 'next 2']);\n      subject.error(new Error('bad'));\n      // should have no effect\n      subscription.unsubscribe();\n\n      expect(results).to.deep.equal(['subscribe', 'next 1', 'next 2', 'error: bad', 'finalize']);\n    });\n  });\n});\n"
  },
  {
    "path": "packages/rxjs/spec/operators/throttle-spec.ts",
    "content": "import { expect } from 'chai';\nimport { TestScheduler } from 'rxjs/internal/testing/TestScheduler';\nimport { observableMatcher } from '../helpers/observableMatcher';\nimport { throttle, mergeMap, take } from 'rxjs/operators';\nimport { of, Observable } from 'rxjs';\n\n/** @test {throttle} */\ndescribe('throttle', () => {\n  let testScheduler: TestScheduler;\n\n  beforeEach(() => {\n    testScheduler = new TestScheduler(observableMatcher);\n  });\n\n  it('should immediately emit the first value in each time window', () => {\n    testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  -a-xy-----b--x--cxyz-|');\n      const e1subs = '  ^--------------------!';\n      const e2 = cold('  ----i                ');\n      //                          ----i\n      //                                ----i\n      const e2subs = [\n        '               -^---!                ',\n        '               ----------^---!       ',\n        '               ----------------^---! ',\n      ];\n      const expected = '-a--------b-----c----|';\n\n      const result = e1.pipe(throttle(() => e2));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should handle sync source with sync notifier and trailing appropriately', () => {\n    const results: any[] = [];\n    const source = of(1).pipe(throttle(() => of(1), { leading: false, trailing: true }));\n\n    source.subscribe({\n      next: (value) => results.push(value),\n      complete: () => results.push('done'),\n    });\n\n    expect(results).to.deep.equal([1, 'done']);\n  });\n\n  it('should simply mirror the source if values are not emitted often enough', () => {\n    testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  ^a--------b-----c----|');\n      const e1subs = '  ^--------------------!';\n      const e2 = cold('  ----|                ');\n      const e2subs = [\n        '               -^---!                ',\n        '               ----------^---!       ',\n        '               ----------------^---! ',\n      ];\n      const expected = '-a--------b-----c----|';\n\n      const result = e1.pipe(throttle(() => e2));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should throttle with duration Observable using next to close the duration', () => {\n    testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  ^a-xy-----b--x--cxxx-|');\n      const e1subs = '  ^--------------------!';\n      const e2 = cold('  ----x-y-z            ');\n      const e2subs = [\n        '               -^---!                ',\n        '               ----------^---!       ',\n        '               ----------------^---! ',\n      ];\n      const expected = '-a--------b-----c----|';\n\n      const result = e1.pipe(throttle(() => e2));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should interrupt source and duration when result is unsubscribed early', () => {\n    testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  -a-x-y-z-xyz-x-y-z----b--x-x-|');\n      const unsub = '   --------------!               ';\n      const e1subs = '  ^-------------!               ';\n      const e2 = cold('  ---------------------|       ');\n      const e2subs = '  -^------------!               ';\n      const expected = '-a-------------               ';\n\n      const result = e1.pipe(throttle(() => e2));\n\n      expectObservable(result, unsub).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should not break unsubscription chains when result is unsubscribed explicitly', () => {\n    testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  -a-x-y-z-xyz-x-y-z----b--x-x-|');\n      const e1subs = '  ^-------------!               ';\n      const e2 = cold('  ------------------|           ');\n      const e2subs = '  -^------------!               ';\n      const expected = '-a-------------               ';\n      const unsub = '   --------------!               ';\n\n      const result = e1.pipe(\n        mergeMap((x: string) => of(x)),\n        throttle(() => e2),\n        mergeMap((x: string) => of(x))\n      );\n\n      expectObservable(result, unsub).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should handle a busy producer emitting a regular repeating sequence', () => {\n    testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  abcdefabcdefabcdefabcdefa|');\n      const e1subs = '  ^------------------------!';\n      const e2 = cold(' -----|                    ');\n      const e2subs = [\n        '               ^----!                    ',\n        '               ------^----!              ',\n        '               ------------^----!        ',\n        '               ------------------^----!  ',\n        '               ------------------------^!',\n      ];\n      const expected = 'a-----a-----a-----a-----a|';\n\n      const result = e1.pipe(throttle(() => e2));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should mirror source if durations are immediate', () => {\n    testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  abcdefabcdefabcdefabcdefa|');\n      const e1subs = '  ^------------------------!';\n      const e2 = cold(' x                         ');\n      const expected = 'abcdefabcdefabcdefabcdefa|';\n\n      const result = e1.pipe(throttle(() => e2));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should mirror source if durations are empty', () => {\n    testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  abcdefabcdefabcdefabcdefa|');\n      const e1subs = '  ^------------------------!';\n      const e2 = cold(' |                         ');\n      const expected = 'abcdefabcdefabcdefabcdefa|';\n\n      const result = e1.pipe(throttle(() => e2));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should take only the first value emitted if duration is a never', () => {\n    testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  ----abcdefabcdefabcdefabcdefa|');\n      const e1subs = '  ^----------------------------!';\n      const e2 = cold(' -                             ');\n      const e2subs = '  ----^------------------------!';\n      const expected = '----a------------------------|';\n\n      const result = e1.pipe(throttle(() => e2));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should unsubscribe duration Observable when source raise error', () => {\n    testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  ----abcdefabcdefabcdefabcdefa#');\n      const e1subs = '  ^----------------------------!';\n      const e2 = cold(' -                             ');\n      const e2subs = '  ----^------------------------!';\n      const expected = '----a------------------------#';\n\n      const result = e1.pipe(throttle(() => e2));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should raise error as soon as just-throw duration is used', () => {\n    testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  ----abcdefabcdefabcdefabcdefa|');\n      const e1subs = '  ^---!-------------------------';\n      const e2 = cold(' #                             ');\n      const e2subs = '  ----(^!)                      ';\n      const expected = '----(a#)                      ';\n\n      const result = e1.pipe(throttle(() => e2));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should throttle using durations of varying lengths', () => {\n    testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  abcdefabcdabcdefghabca|   ');\n      const e1subs = '  ^---------------------!   ';\n      const e2 = [\n        cold('          -----|                    '),\n        cold('                ---|                '),\n        cold('                    -------|        '),\n        cold('                            --|     '),\n        cold('                               ----|'),\n      ];\n      const e2subs = [\n        '               ^----!                    ',\n        '               ------^--!                ',\n        '               ----------^------!        ',\n        '               ------------------^-!     ',\n        '               ---------------------^!   ',\n      ];\n      const expected = 'a-----a---a-------a--a|   ';\n\n      let i = 0;\n      const result = e1.pipe(throttle(() => e2[i++]));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      for (let j = 0; j < e2.length; j++) {\n        expectSubscriptions(e2[j].subscriptions).toBe(e2subs[j]);\n      }\n    });\n  });\n\n  it('should propagate error from duration Observable', () => {\n    testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  abcdefabcdabcdefghabca|   ');\n      const e1subs = '  ^----------------!        ';\n      const e2 = [\n        cold('          -----|                    '),\n        cold('                ---|                '),\n        cold('                    -------#        '),\n      ];\n      const e2subs = [\n        '               ^----!                    ',\n        '               ------^--!                ',\n        '               ----------^------!        ',\n      ];\n      const expected = 'a-----a---a------#        ';\n\n      let i = 0;\n      const result = e1.pipe(throttle(() => e2[i++]));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      for (let j = 0; j < e2.length; j++) {\n        expectSubscriptions(e2[j].subscriptions).toBe(e2subs[j]);\n      }\n    });\n  });\n\n  it('should propagate error thrown from durationSelector function', () => {\n    testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => {\n      const s1 = hot(' --^--x--x--x--x--x--x--e--x--x--x--|');\n      const s1Subs = ' ^--------------------!              ';\n      const n1 = cold('----|                               ');\n      const n1Subs = [\n        '              ---^---!                            ',\n        '              ---------^---!                      ',\n        '              ---------------^---!                ',\n      ];\n      const exp = '    ---x-----x-----x-----(e#)           ';\n\n      let i = 0;\n      const result = s1.pipe(\n        throttle(() => {\n          if (i++ === 3) {\n            throw new Error('lol');\n          }\n          return n1;\n        })\n      );\n      expectObservable(result).toBe(exp, undefined, new Error('lol'));\n      expectSubscriptions(s1.subscriptions).toBe(s1Subs);\n      expectSubscriptions(n1.subscriptions).toBe(n1Subs);\n    });\n  });\n\n  it('should complete when source does not emit', () => {\n    testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  -----|');\n      const subs = '    ^----!';\n      const expected = '-----|';\n\n      function durationSelector() {\n        return cold('-----|');\n      }\n\n      expectObservable(e1.pipe(throttle(durationSelector))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(subs);\n    });\n  });\n\n  it('should raise error when source does not emit and raises error', () => {\n    testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  -----#');\n      const subs = '    ^----!';\n      const expected = '-----#';\n\n      function durationSelector() {\n        return cold('-----|');\n      }\n\n      expectObservable(e1.pipe(throttle(durationSelector))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(subs);\n    });\n  });\n\n  it('should handle an empty source', () => {\n    testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' |     ');\n      const subs = '    (^!)  ';\n      const expected = '|     ';\n\n      function durationSelector() {\n        return cold('-----|');\n      }\n\n      expectObservable(e1.pipe(throttle(durationSelector))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(subs);\n    });\n  });\n\n  it('should handle a never source', () => {\n    testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' -     ');\n      const subs = '    ^     ';\n      const expected = '-     ';\n\n      function durationSelector() {\n        return cold('-----|');\n      }\n\n      expectObservable(e1.pipe(throttle(durationSelector))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(subs);\n    });\n  });\n\n  it('should handle a throw source', () => {\n    testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' #     ');\n      const subs = '    (^!)  ';\n      const expected = '#     ';\n\n      function durationSelector() {\n        return cold('-----|');\n      }\n\n      expectObservable(e1.pipe(throttle(durationSelector))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(subs);\n    });\n  });\n\n  describe('throttle(fn, { leading: true, trailing: true })', () => {\n    it('should immediately emit the first value in each time window', () => {\n      testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => {\n        const e1 = hot('  -a-xy-----b--x--cxxx------|');\n        const e1subs = '  ^-------------------------!';\n        const e2 = cold('  ----x                     ');\n        const e2subs = [\n          '               -^---!                     ',\n          '               -----^---!                 ',\n          '               ----------^---!            ',\n          '               --------------^---!        ',\n          '               ------------------^---!    ',\n          '               ----------------------^---!',\n        ];\n        const expected = '-a---y----b---x---x---x---|';\n\n        const result = e1.pipe(throttle(() => e2, { trailing: true }));\n\n        expectObservable(result).toBe(expected);\n        expectSubscriptions(e1.subscriptions).toBe(e1subs);\n        expectSubscriptions(e2.subscriptions).toBe(e2subs);\n      });\n    });\n\n    it('should work for individual values', () => {\n      testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => {\n        const s1 = hot('-^-x------------------|     ');\n        const s1Subs = ' ^--------------------!     ';\n        const n1 = cold('  ------------------------|');\n        const n1Subs = ['--^------------------!     '];\n        const exp = '    --x------------------|     ';\n\n        const result = s1.pipe(throttle(() => n1, { trailing: true }));\n        expectObservable(result).toBe(exp);\n        expectSubscriptions(s1.subscriptions).toBe(s1Subs);\n        expectSubscriptions(n1.subscriptions).toBe(n1Subs);\n      });\n    });\n\n    it('should emit trailing value after throttle duration when source completes', () => {\n      testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => {\n        const e1 = hot('  -a--------xy|     ');\n        const e1subs = '  ^-----------!     ';\n        const e2 = cold('  ----x            ');\n        const e2subs = [\n          // because prettier\n          '               -^---!            ',\n          '               ----------^---!   ',\n        ];\n        const expected = '-a--------x---(y|)';\n\n        const result = e1.pipe(throttle(() => e2, { trailing: true }));\n\n        expectObservable(result).toBe(expected);\n        expectSubscriptions(e1.subscriptions).toBe(e1subs);\n        expectSubscriptions(e2.subscriptions).toBe(e2subs);\n      });\n    });\n  });\n\n  describe('throttle(fn, { leading: false, trailing: true })', () => {\n    it('should immediately emit the first value in each time window', () => {\n      testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => {\n        const e1 = hot('  -a-xy-----b--x--cxxx------|');\n        const e1subs = '  ^-------------------------!';\n        const e2 = cold('  ----x                     ');\n        const e2subs = [\n          '               -^---!                     ',\n          '               -----^---!                 ',\n          '               ----------^---!            ',\n          '               --------------^---!        ',\n          '               ------------------^---!    ',\n          '               ----------------------^---!',\n        ];\n        const expected = '-----y--------x---x---x---|';\n\n        const result = e1.pipe(throttle(() => e2, { leading: false, trailing: true }));\n\n        expectObservable(result).toBe(expected);\n        expectSubscriptions(e1.subscriptions).toBe(e1subs);\n        expectSubscriptions(e2.subscriptions).toBe(e2subs);\n      });\n    });\n\n    it('should work for individual values', () => {\n      testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => {\n        const s1 = hot('-^-x------------------|        ');\n        const s1Subs = ' ^--------------------!        ';\n        const n1 = cold('  ------------------------x   ');\n        const n1Subs = ['--^-----------------------!   '];\n        const exp = '    --------------------------(x|)';\n\n        const result = s1.pipe(throttle(() => n1, { leading: false, trailing: true }));\n        expectObservable(result).toBe(exp);\n        expectSubscriptions(s1.subscriptions).toBe(s1Subs);\n        expectSubscriptions(n1.subscriptions).toBe(n1Subs);\n      });\n    });\n\n    it('should wait for trailing throttle before completing, even if source completes', () => {\n      testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => {\n        const source = hot('  -^--x--------y---------|        ');\n        const sourceSubs = '   ^---------------------!        ';\n        const duration = cold('   ------------------------x   ');\n        const durationSubs = ' ---^-----------------------!   ';\n        const exp = '          ---------------------------(y|)';\n\n        const result = source.pipe(throttle(() => duration, { leading: false, trailing: true }));\n        expectObservable(result).toBe(exp);\n        expectSubscriptions(source.subscriptions).toBe(sourceSubs);\n        expectSubscriptions(duration.subscriptions).toBe(durationSubs);\n      });\n    });\n\n    it('should emit trailing value after throttle duration when source completes', () => {\n      testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => {\n        const e1 = hot('  -a--------x|   ');\n        const e1subs = '  ^----------!   ';\n        const e2 = cold('  ----x         ');\n        const e2subs = [\n          // because prettier\n          '               -^---!         ',\n          '               -----^---!     ',\n          '               ----------^---!',\n        ];\n        const expected = '-----a--------(x|)';\n\n        const result = e1.pipe(throttle(() => e2, { leading: false, trailing: true }));\n\n        expectObservable(result).toBe(expected);\n        expectSubscriptions(e1.subscriptions).toBe(e1subs);\n        expectSubscriptions(e2.subscriptions).toBe(e2subs);\n      });\n    });\n\n    it('should emit the last trailing value after throttle duration when source completes', () => {\n      testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => {\n        const e1 = hot('  -a--------xy|  ');\n        const e1subs = '  ^-----------!  ';\n        const e2 = cold('  ----x         ');\n        const e2subs = [\n          // because prettier\n          '               -^---!         ',\n          '               -----^---!     ',\n          '               ----------^---!',\n        ];\n        const expected = '-----a--------(y|)';\n\n        const result = e1.pipe(throttle(() => e2, { leading: false, trailing: true }));\n\n        expectObservable(result).toBe(expected);\n        expectSubscriptions(e1.subscriptions).toBe(e1subs);\n        expectSubscriptions(e2.subscriptions).toBe(e2subs);\n      });\n    });\n\n    it('should complete when source completes if no value is available', () => {\n      testScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => {\n        const e1 = hot('  -a-----|');\n        const e1subs = '  ^------!';\n        const e2 = cold('  ----x  ');\n        const e2subs = [\n          // because prettier\n          '               -^---!  ',\n          '               -----^-!',\n        ];\n        const expected = '-----a-|';\n\n        const result = e1.pipe(throttle(() => e2, { leading: false, trailing: true }));\n\n        expectObservable(result).toBe(expected);\n        expectSubscriptions(e1.subscriptions).toBe(e1subs);\n        expectSubscriptions(e2.subscriptions).toBe(e2subs);\n      });\n    });\n  });\n\n  it('should stop listening to a synchronous observable when unsubscribed', () => {\n    const sideEffects: number[] = [];\n    const synchronousObservable = new Observable<number>((subscriber) => {\n      // This will check to see if the subscriber was closed on each loop\n      // when the unsubscribe hits (from the `take`), it should be closed\n      for (let i = 0; !subscriber.closed && i < 10; i++) {\n        sideEffects.push(i);\n        subscriber.next(i);\n      }\n    });\n\n    synchronousObservable\n      .pipe(\n        throttle(() => of(0)),\n        take(3)\n      )\n      .subscribe(() => {\n        /* noop */\n      });\n\n    expect(sideEffects).to.deep.equal([0, 1, 2]);\n  });\n});\n"
  },
  {
    "path": "packages/rxjs/spec/operators/throttleTime-spec.ts",
    "content": "import { expect } from 'chai';\nimport { throttleTime, take, map, mergeMap } from 'rxjs/operators';\nimport { TestScheduler } from 'rxjs/testing';\nimport { of, concat, timer } from 'rxjs';\nimport { observableMatcher } from '../helpers/observableMatcher';\n\n/** @test {throttleTime} */\ndescribe('throttleTime operator', () => {\n  let rxTest: TestScheduler;\n\n  beforeEach(() => {\n    rxTest = new TestScheduler(observableMatcher);\n  });\n\n  describe('default behavior { leading: true, trailing: false }', () => {\n    it('should immediately emit the first value in each time window', () => {\n      rxTest.run(({ hot, expectObservable, expectSubscriptions }) => {\n        const e1 = hot('  -a-x-y----b---x-cx---|');\n        //                 ----|    ----| ----|\n        const expected = '-a--------b-----c----|';\n        const subs = '    ^--------------------!';\n\n        const result = e1.pipe(throttleTime(5));\n\n        expectObservable(result).toBe(expected);\n        expectSubscriptions(e1.subscriptions).toBe(subs);\n      });\n    });\n\n    it('should throttle events by 5 time units', (done) => {\n      of(1, 2, 3)\n        .pipe(throttleTime(5))\n        .subscribe({\n          next: (x) => {\n            expect(x).to.equal(1);\n          },\n          complete: done,\n        });\n    });\n\n    it('should throttle events multiple times', () => {\n      const expected = ['1-0', '2-0'];\n      concat(\n        timer(0, 1).pipe(\n          take(3),\n          map((x) => '1-' + x)\n        ),\n        timer(8, 1).pipe(\n          take(5),\n          map((x) => '2-' + x)\n        )\n      )\n        .pipe(throttleTime(5, rxTest))\n        .subscribe((x) => {\n          expect(x).to.equal(expected.shift());\n        });\n\n      rxTest.flush();\n    });\n\n    it('should simply mirror the source if values are not emitted often enough', () => {\n      rxTest.run(({ hot, expectObservable, expectSubscriptions }) => {\n        const e1 = hot('  -a--------b-----c----|');\n        const subs = '    ^--------------------!';\n        const expected = '-a--------b-----c----|';\n\n        expectObservable(e1.pipe(throttleTime(5))).toBe(expected);\n        expectSubscriptions(e1.subscriptions).toBe(subs);\n      });\n    });\n\n    it('should handle a busy producer emitting a regular repeating sequence', () => {\n      rxTest.run(({ hot, expectObservable, expectSubscriptions }) => {\n        const e1 = hot('  abcdefabcdefabcdefabcdefa|');\n        const subs = '    ^------------------------!';\n        const expected = 'a-----a-----a-----a-----a|';\n\n        expectObservable(e1.pipe(throttleTime(5))).toBe(expected);\n        expectSubscriptions(e1.subscriptions).toBe(subs);\n      });\n    });\n\n    it('should complete when source does not emit', () => {\n      rxTest.run(({ hot, expectObservable, expectSubscriptions }) => {\n        const e1 = hot('  -----|');\n        const subs = '    ^----!';\n        const expected = '-----|';\n\n        expectObservable(e1.pipe(throttleTime(5))).toBe(expected);\n        expectSubscriptions(e1.subscriptions).toBe(subs);\n      });\n    });\n\n    it('should raise error when source does not emit and raises error', () => {\n      rxTest.run(({ hot, expectObservable, expectSubscriptions }) => {\n        const e1 = hot('  -----#');\n        const subs = '    ^----!';\n        const expected = '-----#';\n\n        expectObservable(e1.pipe(throttleTime(10))).toBe(expected);\n        expectSubscriptions(e1.subscriptions).toBe(subs);\n      });\n    });\n\n    it('should handle an empty source', () => {\n      rxTest.run(({ cold, expectObservable, expectSubscriptions }) => {\n        const e1 = cold(' |');\n        const subs = '    (^!)';\n        const expected = '|';\n\n        expectObservable(e1.pipe(throttleTime(30))).toBe(expected);\n        expectSubscriptions(e1.subscriptions).toBe(subs);\n      });\n    });\n\n    it('should handle a never source', () => {\n      rxTest.run(({ cold, expectObservable, expectSubscriptions }) => {\n        const e1 = cold(' -');\n        const subs = '    ^';\n        const expected = '-';\n\n        expectObservable(e1.pipe(throttleTime(30))).toBe(expected);\n        expectSubscriptions(e1.subscriptions).toBe(subs);\n      });\n    });\n\n    it('should handle a throw source', () => {\n      rxTest.run(({ cold, expectObservable, expectSubscriptions }) => {\n        const e1 = cold(' #');\n        const subs = '    (^!)';\n        const expected = '#';\n\n        expectObservable(e1.pipe(throttleTime(30))).toBe(expected);\n        expectSubscriptions(e1.subscriptions).toBe(subs);\n      });\n    });\n\n    it('should throttle and does not complete when source does not completes', () => {\n      rxTest.run(({ hot, expectObservable, expectSubscriptions }) => {\n        const e1 = hot('  -a--(bc)-------d----------------');\n        const unsub = '   -------------------------------!';\n        const subs = '    ^------------------------------!';\n        const expected = '-a-------------d----------------';\n\n        expectObservable(e1.pipe(throttleTime(5)), unsub).toBe(expected);\n        expectSubscriptions(e1.subscriptions).toBe(subs);\n      });\n    });\n\n    it('should not break unsubscription chains when result is unsubscribed explicitly', () => {\n      rxTest.run(({ hot, expectObservable, expectSubscriptions }) => {\n        const e1 = hot('  -a--(bc)-------d----------------');\n        const subs = '    ^------------------------------!';\n        const expected = '-a-------------d----------------';\n        const unsub = '   -------------------------------!';\n\n        const result = e1.pipe(\n          mergeMap((x) => of(x)),\n          throttleTime(5),\n          mergeMap((x) => of(x))\n        );\n\n        expectObservable(result, unsub).toBe(expected);\n        expectSubscriptions(e1.subscriptions).toBe(subs);\n      });\n    });\n\n    it('should throttle values until source raises error', () => {\n      rxTest.run(({ hot, expectObservable, expectSubscriptions }) => {\n        const e1 = hot('  -a--(bc)-------d---------------#');\n        const subs = '    ^------------------------------!';\n        const expected = '-a-------------d---------------#';\n\n        expectObservable(e1.pipe(throttleTime(5))).toBe(expected);\n        expectSubscriptions(e1.subscriptions).toBe(subs);\n      });\n    });\n  });\n\n  describe('throttleTime(fn, { leading: true, trailing: true })', () => {\n    it('should immediately emit the first and last values in each time window', () => {\n      rxTest.run(({ hot, time, expectObservable, expectSubscriptions }) => {\n        const e1 = hot('  -a-xy-----b--x--cxxx--|');\n        const e1subs = '  ^---------------------!';\n        const t = time('   ----|                 ');\n        //                     ----|----|---|---|\n        const expected = '-a---y----b---x---x---(x|)';\n\n        const result = e1.pipe(throttleTime(t, rxTest, { trailing: true }));\n\n        expectObservable(result).toBe(expected);\n        expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      });\n    });\n\n    it('should emit the value if only a single one is given', () => {\n      rxTest.run(({ hot, time, expectObservable }) => {\n        const e1 = hot('  -a--------------------|');\n        const t = time('   ----|                 ');\n        const expected = '-a--------------------|';\n\n        const result = e1.pipe(throttleTime(t, rxTest, { trailing: true }));\n\n        expectObservable(result).toBe(expected);\n      });\n    });\n  });\n\n  describe('throttleTime(fn, { leading: false, trailing: true })', () => {\n    it('should immediately emit the last value in each time window', () => {\n      rxTest.run(({ hot, time, expectObservable, expectSubscriptions }) => {\n        const e1 = hot('  -a-xy-----b--x--cxxx--|');\n        const e1subs = '  ^---------------------!';\n        const t = time('   ----|                 ');\n        //                 ----|---|----|---|---|\n        const expected = '-----y--------x---x---(x|)';\n\n        const result = e1.pipe(throttleTime(t, rxTest, { leading: false, trailing: true }));\n\n        expectObservable(result).toBe(expected);\n        expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      });\n    });\n\n    it('should emit the last throttled value when complete', () => {\n      rxTest.run(({ hot, time, expectObservable, expectSubscriptions }) => {\n        const e1 = hot('  -a-xy-----b--x--cxx-|');\n        const e1subs = '  ^-------------------!';\n        const t = time('   ----|               ');\n        //                 ----|---|----|---|---|\n        const expected = '-----y--------x---x-|';\n\n        const result = e1.pipe(throttleTime(t, rxTest, { leading: false, trailing: true }));\n\n        expectObservable(result).toBe(expected);\n        expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      });\n    });\n\n    it('should emit the value if only a single one is given', () => {\n      rxTest.run(({ hot, time, expectObservable }) => {\n        const e1 = hot('  -a--------------------|');\n        const t = time('   ----|                 ');\n        const expected = '-----a----------------|';\n\n        const result = e1.pipe(throttleTime(t, rxTest, { leading: false, trailing: true }));\n\n        expectObservable(result).toBe(expected);\n      });\n    });\n  });\n});\n"
  },
  {
    "path": "packages/rxjs/spec/operators/throwIfEmpty-spec.ts",
    "content": "import { expect } from 'chai';\nimport { EMPTY, of, EmptyError, defer, throwError, Observable } from 'rxjs';\nimport { throwIfEmpty, mergeMap, retry, take } from 'rxjs/operators';\nimport { TestScheduler } from 'rxjs/testing';\nimport { observableMatcher } from '../helpers/observableMatcher';\n\n/** @test {throwIfEmpty} */\ndescribe('throwIfEmpty', () => {\n  let rxTestScheduler: TestScheduler;\n\n  beforeEach(() => {\n    rxTestScheduler = new TestScheduler(observableMatcher);\n  });\n\n  describe('with errorFactory', () => {\n    it('should error when empty', () => {\n      rxTestScheduler.run(({ cold, expectObservable }) => {\n        const source = cold('----|');\n        const expected = '   ----#';\n\n        const result = source.pipe(throwIfEmpty(() => new Error('test')));\n\n        expectObservable(result).toBe(expected, undefined, new Error('test'));\n      });\n    });\n\n    it('should throw if empty', () => {\n      const error = new Error('So empty inside');\n      let thrown: any;\n\n      EMPTY.pipe(throwIfEmpty(() => error)).subscribe({\n        error(err) {\n          thrown = err;\n        },\n      });\n\n      expect(thrown).to.equal(error);\n    });\n\n    it('should NOT throw if NOT empty', () => {\n      const error = new Error('So empty inside');\n      let thrown: any;\n\n      of('test')\n        .pipe(throwIfEmpty(() => error))\n        .subscribe({\n          error(err) {\n            thrown = err;\n          },\n        });\n\n      expect(thrown).to.be.undefined;\n    });\n\n    it('should pass values through', () => {\n      rxTestScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n        const source = cold('----a---b---c---|');\n        const sub1 = '       ^---------------!';\n        const expected = '   ----a---b---c---|';\n\n        const result = source.pipe(throwIfEmpty(() => new Error('test')));\n\n        expectObservable(result).toBe(expected);\n        expectSubscriptions(source.subscriptions).toBe([sub1]);\n      });\n    });\n\n    it('should never when never', () => {\n      rxTestScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n        const source = cold('-');\n        const sub1 = '       ^';\n        const expected = '   -';\n\n        const result = source.pipe(throwIfEmpty(() => new Error('test')));\n\n        expectObservable(result).toBe(expected);\n        expectSubscriptions(source.subscriptions).toBe([sub1]);\n      });\n    });\n\n    it('should error when empty', () => {\n      rxTestScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n        const source = cold('----|');\n        const sub1 = '       ^---!';\n        const expected = '   ----#';\n\n        const result = source.pipe(throwIfEmpty(() => new Error('test')));\n\n        expectObservable(result).toBe(expected, undefined, new Error('test'));\n        expectSubscriptions(source.subscriptions).toBe([sub1]);\n      });\n    });\n\n    it('should throw if empty after retry', () => {\n      const error = new Error('So empty inside');\n      let thrown: any;\n      let sourceIsEmpty = false;\n\n      const source = defer(() => {\n        if (sourceIsEmpty) {\n          return EMPTY;\n        }\n        sourceIsEmpty = true;\n        return of(1, 2);\n      });\n\n      source\n        .pipe(\n          throwIfEmpty(() => error),\n          mergeMap((value) => {\n            if (value > 1) {\n              return throwError(() => new Error());\n            }\n\n            return of(value);\n          }),\n          retry(1)\n        )\n        .subscribe({\n          error(err) {\n            thrown = err;\n          },\n        });\n\n      expect(thrown).to.equal(error);\n    });\n  });\n\n  describe('without errorFactory', () => {\n    it('should throw EmptyError if empty', () => {\n      let thrown: any;\n\n      EMPTY.pipe(throwIfEmpty()).subscribe({\n        error(err) {\n          thrown = err;\n        },\n      });\n\n      expect(thrown).to.be.instanceof(EmptyError);\n    });\n\n    it('should NOT throw if NOT empty', () => {\n      let thrown: any;\n\n      of('test')\n        .pipe(throwIfEmpty())\n        .subscribe({\n          error(err) {\n            thrown = err;\n          },\n        });\n\n      expect(thrown).to.be.undefined;\n    });\n\n    it('should pass values through', () => {\n      rxTestScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n        const source = cold('----a---b---c---|');\n        const sub1 = '       ^---------------!';\n        const expected = '   ----a---b---c---|';\n\n        const result = source.pipe(throwIfEmpty());\n\n        expectObservable(result).toBe(expected);\n        expectSubscriptions(source.subscriptions).toBe([sub1]);\n      });\n    });\n\n    it('should never when never', () => {\n      rxTestScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n        const source = cold('-');\n        const sub1 = '       ^';\n        const expected = '   -';\n\n        const result = source.pipe(throwIfEmpty());\n\n        expectObservable(result).toBe(expected);\n        expectSubscriptions(source.subscriptions).toBe([sub1]);\n      });\n    });\n\n    it('should error when empty', () => {\n      rxTestScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n        const source = cold('----|');\n        const sub1 = '       ^---!';\n        const expected = '   ----#';\n\n        const result = source.pipe(throwIfEmpty());\n\n        expectObservable(result).toBe(expected, undefined, new EmptyError());\n        expectSubscriptions(source.subscriptions).toBe([sub1]);\n      });\n    });\n\n    it('should throw if empty after retry', () => {\n      let thrown: any;\n      let sourceIsEmpty = false;\n\n      const source = defer(() => {\n        if (sourceIsEmpty) {\n          return EMPTY;\n        }\n        sourceIsEmpty = true;\n        return of(1, 2);\n      });\n\n      source\n        .pipe(\n          throwIfEmpty(),\n          mergeMap((value) => {\n            if (value > 1) {\n              return throwError(() => new Error());\n            }\n\n            return of(value);\n          }),\n          retry(1)\n        )\n        .subscribe({\n          error(err) {\n            thrown = err;\n          },\n        });\n\n      expect(thrown).to.be.instanceof(EmptyError);\n    });\n  });\n\n  it('should stop listening to a synchronous observable when unsubscribed', () => {\n    const sideEffects: number[] = [];\n    const synchronousObservable = new Observable<number>((subscriber) => {\n      // This will check to see if the subscriber was closed on each loop\n      // when the unsubscribe hits (from the `take`), it should be closed\n      for (let i = 0; !subscriber.closed && i < 10; i++) {\n        sideEffects.push(i);\n        subscriber.next(i);\n      }\n    });\n\n    synchronousObservable.pipe(throwIfEmpty(), take(3)).subscribe(() => {\n      /* noop */\n    });\n\n    expect(sideEffects).to.deep.equal([0, 1, 2]);\n  });\n});\n"
  },
  {
    "path": "packages/rxjs/spec/operators/timeInterval-spec.ts",
    "content": "import { expect } from 'chai';\nimport { timeInterval, map, mergeMap, take } from 'rxjs/operators';\nimport { TestScheduler } from 'rxjs/testing';\nimport { of, Observable } from 'rxjs';\nimport { TimeInterval } from 'rxjs/internal/operators/timeInterval';\nimport { observableMatcher } from '../helpers/observableMatcher';\n\n/** @test {timeInterval} */\ndescribe('timeInterval', () => {\n  let rxTestScheduler: TestScheduler;\n\n  beforeEach(() => {\n    rxTestScheduler = new TestScheduler(observableMatcher);\n  });\n\n  it('should record the time interval between source elements', () => {\n    rxTestScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('--a--^b-c-----d--e--|');\n      const e1subs = '     ^--------------!';\n      const expected = '   -w-x-----y--z--|';\n      const expectedValue = { w: 1, x: 2, y: 6, z: 3 };\n\n      const result = e1.pipe(\n        timeInterval(rxTestScheduler),\n        map((x) => x.interval)\n      );\n\n      expectObservable(result).toBe(expected, expectedValue);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should record interval if source emit elements', () => {\n    rxTestScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('--a--^b--c----d---e--|');\n      const e1subs = '     ^---------------!';\n      const expected = '   -w--x----y---z--|';\n\n      const expectedValue = {\n        w: new TimeInterval('b', 1),\n        x: new TimeInterval('c', 3),\n        y: new TimeInterval('d', 5),\n        z: new TimeInterval('e', 4),\n      };\n\n      expectObservable(e1.pipe(timeInterval(rxTestScheduler))).toBe(expected, expectedValue);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should completes without record interval if source does not emits', () => {\n    rxTestScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  ---------|');\n      const e1subs = '  ^--------!';\n      const expected = '---------|';\n\n      expectObservable(e1.pipe(timeInterval(rxTestScheduler))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should complete immediately if source is empty', () => {\n    rxTestScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' |   ');\n      const e1subs = '  (^!)';\n      const expected = '|   ';\n\n      expectObservable(e1.pipe(timeInterval(rxTestScheduler))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should record interval then does not completes if source emits but not completes', () => {\n    rxTestScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  -a--b--');\n      const e1subs = '  ^------';\n      const expected = '-y--z--';\n\n      const expectedValue = {\n        y: new TimeInterval('a', 1),\n        z: new TimeInterval('b', 3),\n      };\n\n      expectObservable(e1.pipe(timeInterval(rxTestScheduler))).toBe(expected, expectedValue);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should allow unsubscribing explicitly and early', () => {\n    rxTestScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  -a--b-----c---d---|');\n      const unsub = '   -------!           ';\n      const e1subs = '  ^------!           ';\n      const expected = '-y--z---           ';\n\n      const expectedValue = {\n        y: new TimeInterval('a', 1),\n        z: new TimeInterval('b', 3),\n      };\n\n      const result = e1.pipe(timeInterval(rxTestScheduler));\n\n      expectObservable(result, unsub).toBe(expected, expectedValue);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should not break unsubscription chains when result is unsubscribed explicitly', () => {\n    rxTestScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  -a--b-----c---d---|');\n      const e1subs = '  ^------!           ';\n      const expected = '-y--z---           ';\n      const unsub = '   -------!           ';\n\n      const expectedValue = {\n        y: new TimeInterval('a', 1),\n        z: new TimeInterval('b', 3),\n      };\n\n      const result = e1.pipe(\n        mergeMap((x: string) => of(x)),\n        timeInterval(rxTestScheduler),\n        mergeMap((x) => of(x))\n      );\n\n      expectObservable(result, unsub).toBe(expected, expectedValue);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should not completes if source never completes', () => {\n    rxTestScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' -');\n      const e1subs = '  ^';\n      const expected = '-';\n\n      expectObservable(e1.pipe(timeInterval(rxTestScheduler))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('raise error if source raises error', () => {\n    rxTestScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  ---#');\n      const e1subs = '  ^--!';\n      const expected = '---#';\n\n      expectObservable(e1.pipe(timeInterval(rxTestScheduler))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should record interval then raise error if source raises error after emit', () => {\n    rxTestScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  -a--b--#');\n      const e1subs = '  ^------!';\n      const expected = '-y--z--#';\n\n      const expectedValue = {\n        y: new TimeInterval('a', 1),\n        z: new TimeInterval('b', 3),\n      };\n\n      expectObservable(e1.pipe(timeInterval(rxTestScheduler))).toBe(expected, expectedValue);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should raise error if source immediately throws', () => {\n    rxTestScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' #   ');\n      const e1subs = '  (^!)';\n      const expected = '#   ';\n\n      expectObservable(e1.pipe(timeInterval(rxTestScheduler))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should stop listening to a synchronous observable when unsubscribed', () => {\n    const sideEffects: number[] = [];\n    const synchronousObservable = new Observable<number>((subscriber) => {\n      // This will check to see if the subscriber was closed on each loop\n      // when the unsubscribe hits (from the `take`), it should be closed\n      for (let i = 0; !subscriber.closed && i < 10; i++) {\n        sideEffects.push(i);\n        subscriber.next(i);\n      }\n    });\n\n    synchronousObservable.pipe(timeInterval(), take(3)).subscribe(() => {\n      /* noop */\n    });\n\n    expect(sideEffects).to.deep.equal([0, 1, 2]);\n  });\n});\n"
  },
  {
    "path": "packages/rxjs/spec/operators/timeout-spec.ts",
    "content": "import { expect } from 'chai';\nimport { timeout, mergeMap, take, concatWith } from 'rxjs/operators';\nimport { TestScheduler } from 'rxjs/testing';\nimport { TimeoutError, of, Observable, NEVER } from 'rxjs';\nimport { observableMatcher } from '../helpers/observableMatcher';\n\n/** @test {timeout} */\ndescribe('timeout operator', () => {\n  let rxTestScheduler: TestScheduler;\n\n  beforeEach(() => {\n    rxTestScheduler = new TestScheduler(observableMatcher);\n  });\n\n  const defaultTimeoutError = new TimeoutError();\n\n  it('should timeout after a specified timeout period', () => {\n    rxTestScheduler.run(({ cold, expectObservable, expectSubscriptions, time }) => {\n      const e1 = cold(' -------a--b--|');\n      const t = time('  -----|        ');\n      const e1subs = '  ^----!        ';\n      const expected = '-----#        ';\n\n      const result = e1.pipe(timeout(t, rxTestScheduler));\n\n      expectObservable(result).toBe(expected, null, defaultTimeoutError);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should emit and TimeoutError on timeout with appropriate due as number', () => {\n    rxTestScheduler.run(({ cold, time }) => {\n      const e1 = cold('-------a--b--|');\n      const t = time(' -----|');\n      const result = e1.pipe(timeout(t, rxTestScheduler));\n      let error: any;\n      result.subscribe({\n        next: () => {\n          throw new Error('this should not next');\n        },\n        error: (err) => {\n          error = err;\n        },\n        complete: () => {\n          throw new Error('this should not complete');\n        },\n      });\n      rxTestScheduler.flush();\n      expect(error).to.be.an.instanceof(TimeoutError);\n      expect(error).to.have.property('name', 'TimeoutError');\n      expect(error!.info).to.deep.equal({\n        seen: 0,\n        meta: null,\n        lastValue: null,\n      });\n    });\n  });\n\n  it('should emit and TimeoutError on timeout with appropriate due as Date', () => {\n    rxTestScheduler.run(({ cold, time }) => {\n      const e1 = cold('-------a--b--|');\n      const t = time(' ----|');\n\n      // 4ms from \"now\", considering \"now\" with the rxTestScheduler is currently frame 0.\n      const dueDate = new Date(t);\n\n      const result = e1.pipe(timeout(dueDate, rxTestScheduler));\n      let error: any;\n      result.subscribe({\n        next: () => {\n          throw new Error('this should not next');\n        },\n        error: (err) => {\n          error = err;\n        },\n        complete: () => {\n          throw new Error('this should not complete');\n        },\n      });\n      rxTestScheduler.flush();\n      expect(error).to.be.an.instanceof(TimeoutError);\n      expect(error).to.have.property('name', 'TimeoutError');\n      expect(error!.info).to.deep.equal({\n        seen: 0,\n        meta: null,\n        lastValue: null,\n      });\n    });\n  });\n\n  it('should not timeout if source completes within absolute timeout period', () => {\n    rxTestScheduler.run(({ hot, expectObservable, expectSubscriptions, time }) => {\n      const e1 = hot('  --a--b--c--d--e--|');\n      const t = time('  --------------------|');\n      const e1subs = '  ^----------------!';\n      const expected = '--a--b--c--d--e--|';\n\n      // Start frame is zero.\n      const timeoutValue = new Date(t);\n\n      expectObservable(e1.pipe(timeout(timeoutValue, rxTestScheduler))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should not timeout if source emits within timeout period', () => {\n    rxTestScheduler.run(({ hot, expectObservable, expectSubscriptions, time }) => {\n      const e1 = hot('  --a--b--c--d--e--|');\n      const t = time('  -----|            ');\n      const e1subs = '  ^----------------!';\n      const expected = '--a--b--c--d--e--|';\n\n      expectObservable(e1.pipe(timeout(t, rxTestScheduler))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should allow unsubscribing explicitly and early', () => {\n    rxTestScheduler.run(({ hot, expectObservable, expectSubscriptions, time }) => {\n      const e1 = hot('  --a--b--c---d--e--|');\n      const t = time('  -----|             ');\n      const unsub = '   ----------!        ';\n      const e1subs = '  ^---------!        ';\n      const expected = '--a--b--c--        ';\n\n      const result = e1.pipe(timeout(t, rxTestScheduler));\n\n      expectObservable(result, unsub).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should not break unsubscription chains when result is unsubscribed explicitly', () => {\n    rxTestScheduler.run(({ hot, expectObservable, expectSubscriptions, time }) => {\n      const e1 = hot('  --a--b--c---d--e--|');\n      const t = time('  -----|             ');\n      const e1subs = '  ^---------!        ';\n      const expected = '--a--b--c--        ';\n      const unsub = '   ----------!        ';\n\n      const result = e1.pipe(\n        mergeMap((x) => of(x)),\n        timeout(t, rxTestScheduler),\n        mergeMap((x) => of(x))\n      );\n\n      expectObservable(result, unsub).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should timeout after a specified timeout period between emit with default error while source emits', () => {\n    rxTestScheduler.run(({ hot, expectObservable, expectSubscriptions, time }) => {\n      const e1 = hot('  ---a---b---c------d---e---|');\n      const t = time('             -----|');\n      const e1subs = '  ^---------------!          ';\n      const expected = '---a---b---c----#          ';\n\n      const result = e1.pipe(timeout(t, rxTestScheduler));\n\n      expectObservable(result).toBe(expected, undefined, defaultTimeoutError);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should timeout at a specified Date', () => {\n    rxTestScheduler.run(({ cold, expectObservable, expectSubscriptions, time }) => {\n      const e1 = cold(' -');\n      const t = time('  ----------|');\n      const e1subs = '  ^---------!';\n      const expected = '----------#';\n\n      // Start time is zero\n      const result = e1.pipe(timeout(new Date(t), rxTestScheduler));\n\n      expectObservable(result).toBe(expected, null, defaultTimeoutError);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should work with synchronous observable', () => {\n    expect(() => {\n      of(1).pipe(timeout(10)).subscribe();\n    }).to.not.throw();\n  });\n\n  describe('config', () => {\n    it('should timeout after a specified timeout period', () => {\n      rxTestScheduler.run(({ cold, expectObservable, expectSubscriptions, time }) => {\n        const e1 = cold(' -------a--b--|');\n        const t = time('  -----|        ');\n        const e1subs = '  ^----!        ';\n        const expected = '-----#        ';\n\n        const result = e1.pipe(\n          timeout({\n            each: t,\n          })\n        );\n\n        expectObservable(result).toBe(expected, null, defaultTimeoutError);\n        expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      });\n    });\n\n    it('should emit and TimeoutError on timeout with appropriate due as number', () => {\n      rxTestScheduler.run(({ cold, time }) => {\n        const e1 = cold('-------a--b--|');\n        const t = time(' -----|');\n        const result = e1.pipe(timeout({ each: t }));\n        let error: any;\n        result.subscribe({\n          next: () => {\n            throw new Error('this should not next');\n          },\n          error: (err) => {\n            error = err;\n          },\n          complete: () => {\n            throw new Error('this should not complete');\n          },\n        });\n        rxTestScheduler.flush();\n        expect(error).to.be.an.instanceof(TimeoutError);\n        expect(error).to.have.property('name', 'TimeoutError');\n        expect(error!.info).to.deep.equal({\n          seen: 0,\n          meta: null,\n          lastValue: null,\n        });\n      });\n    });\n\n    it('should emit and TimeoutError on timeout with appropriate due as Date', () => {\n      rxTestScheduler.run(({ cold, time }) => {\n        const e1 = cold('-------a--b--|');\n        const t = time(' ----|');\n\n        // 4ms from \"now\", considering \"now\" with the rxTestScheduler is currently frame 0.\n        const dueDate = new Date(t);\n\n        const result = e1.pipe(timeout({ first: dueDate }));\n        let error: any;\n        result.subscribe({\n          next: () => {\n            throw new Error('this should not next');\n          },\n          error: (err) => {\n            error = err;\n          },\n          complete: () => {\n            throw new Error('this should not complete');\n          },\n        });\n        rxTestScheduler.flush();\n        expect(error).to.be.an.instanceof(TimeoutError);\n        expect(error).to.have.property('name', 'TimeoutError');\n        expect(error!.info).to.deep.equal({\n          seen: 0,\n          meta: null,\n          lastValue: null,\n        });\n      });\n    });\n\n    it('should not timeout if source completes within absolute timeout period', () => {\n      rxTestScheduler.run(({ hot, expectObservable, expectSubscriptions, time }) => {\n        const e1 = hot('  --a--b--c--d--e--|');\n        const t = time('  --------------------|');\n        const e1subs = '  ^----------------!';\n        const expected = '--a--b--c--d--e--|';\n\n        expectObservable(e1.pipe(timeout({ first: new Date(t) }))).toBe(expected);\n        expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      });\n    });\n\n    it('should not timeout if source emits within timeout period', () => {\n      rxTestScheduler.run(({ hot, expectObservable, expectSubscriptions, time }) => {\n        const e1 = hot('  --a--b--c--d--e--|');\n        const t = time('  -----|            ');\n        const e1subs = '  ^----------------!';\n        const expected = '--a--b--c--d--e--|';\n\n        expectObservable(e1.pipe(timeout({ each: t }))).toBe(expected);\n        expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      });\n    });\n\n    it('should allow unsubscribing explicitly and early', () => {\n      rxTestScheduler.run(({ hot, expectObservable, expectSubscriptions, time }) => {\n        const e1 = hot('  --a--b--c---d--e--|');\n        const t = time('  -----|             ');\n        const unsub = '   ----------!        ';\n        const e1subs = '  ^---------!        ';\n        const expected = '--a--b--c--        ';\n\n        const result = e1.pipe(timeout({ each: t }));\n\n        expectObservable(result, unsub).toBe(expected);\n        expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      });\n    });\n\n    it('should not break unsubscription chains when result is unsubscribed explicitly', () => {\n      rxTestScheduler.run(({ hot, expectObservable, expectSubscriptions, time }) => {\n        const e1 = hot('  --a--b--c---d--e--|');\n        const t = time('  -----|             ');\n        const e1subs = '  ^---------!        ';\n        const expected = '--a--b--c--        ';\n        const unsub = '   ----------!        ';\n\n        const result = e1.pipe(\n          mergeMap((x) => of(x)),\n          timeout({ each: t }),\n          mergeMap((x) => of(x))\n        );\n\n        expectObservable(result, unsub).toBe(expected);\n        expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      });\n    });\n\n    it('should timeout after a specified timeout period between emit with default error while source emits', () => {\n      rxTestScheduler.run(({ hot, expectObservable, expectSubscriptions, time }) => {\n        const e1 = hot('  ---a---b---c------d---e---|');\n        const t = time('             -----|');\n        const e1subs = '  ^---------------!          ';\n        const expected = '---a---b---c----#          ';\n\n        const result = e1.pipe(timeout({ each: t }));\n\n        expectObservable(result).toBe(expected, undefined, defaultTimeoutError);\n        expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      });\n    });\n\n    it('should timeout at a specified Date', () => {\n      rxTestScheduler.run(({ cold, expectObservable, expectSubscriptions, time }) => {\n        const e1 = cold(' -');\n        const t = time('  ----------|');\n        const e1subs = '  ^---------!';\n        const expected = '----------#';\n\n        // Start time is zero\n        const result = e1.pipe(timeout({ first: new Date(t) }));\n\n        expectObservable(result).toBe(expected, null, defaultTimeoutError);\n        expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      });\n    });\n\n    it('should timeout at a specified time for first value only', () => {\n      rxTestScheduler.run(({ cold, expectObservable, expectSubscriptions, time }) => {\n        const e1 = cold(' -');\n        const t = time('  ----------|');\n        const e1subs = '  ^---------!';\n        const expected = '----------#';\n\n        // Start time is zero\n        const result = e1.pipe(timeout({ first: t }));\n\n        expectObservable(result).toBe(expected, undefined, defaultTimeoutError);\n        expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      });\n    });\n\n    it('should not timeout for long delays if only first is specified', () => {\n      rxTestScheduler.run(({ cold, expectObservable, expectSubscriptions, time }) => {\n        const e1 = cold(' ---a-----------------------b---|');\n        const t = time('     ----------|');\n        const e1subs = '  ^------------------------------!';\n        const expected = '---a-----------------------b---|';\n\n        // Start time is zero\n        const result = e1.pipe(timeout({ first: t }));\n\n        expectObservable(result).toBe(expected, undefined, defaultTimeoutError);\n        expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      });\n    });\n\n    it('should not timeout for long delays if only first is specified as Date', () => {\n      rxTestScheduler.run(({ cold, expectObservable, expectSubscriptions, time }) => {\n        const e1 = cold(' ---a-----------------------b---|');\n        const t = time('  ----------|');\n        const e1subs = '  ^------------------------------!';\n        const expected = '---a-----------------------b---|';\n\n        // Start time is zero\n        const result = e1.pipe(timeout({ first: new Date(t) }));\n\n        expectObservable(result).toBe(expected, undefined, defaultTimeoutError);\n        expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      });\n    });\n\n    it('should timeout for long delays if first is specified as Date AND each is specified', () => {\n      rxTestScheduler.run(({ cold, expectObservable, expectSubscriptions, time }) => {\n        const e1 = cold('   ---a-----------------------b---|');\n        const first = time('-------------|');\n        const each = time('    ------|');\n        const e1subs = '    ^--------!';\n        const expected = '  ---a-----#';\n\n        // Start time is zero\n        const result = e1.pipe(timeout({ first: new Date(first), each }));\n\n        expectObservable(result).toBe(expected, undefined, defaultTimeoutError);\n        expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      });\n    });\n  });\n\n  describe('using with', () => {\n    it('should timeout after a specified period then subscribe to the passed observable', () => {\n      rxTestScheduler.run(({ hot, cold, time, expectObservable, expectSubscriptions }) => {\n        const source = cold('  -------a--b--|');\n        const sourceSubs = '   ^----!        ';\n        const t = time('       -----|');\n        const inner = cold('        x-y-z-|  ');\n        const innerSubs = '    -----^-----!  ';\n        const expected = '     -----x-y-z-|  ';\n\n        const result = source.pipe(\n          timeout({\n            each: t,\n            with: () => inner,\n          })\n        );\n\n        expectObservable(result).toBe(expected);\n        expectSubscriptions(source.subscriptions).toBe(sourceSubs);\n        expectSubscriptions(inner.subscriptions).toBe(innerSubs);\n      });\n    });\n\n    it('should timeout at a specified date then subscribe to the passed observable', () => {\n      rxTestScheduler.run(({ hot, cold, time, expectObservable, expectSubscriptions }) => {\n        const source = cold('  -');\n        const sourceSubs = '   ^---------!           ';\n        const t = time('       ----------|');\n        const inner = cold('             --x--y--z--|');\n        const innerSubs = '    ----------^----------!';\n        const expected = '     ------------x--y--z--|';\n\n        // The current frame is zero.\n        const result = source.pipe(\n          timeout({\n            first: new Date(t),\n            with: () => inner,\n          })\n        );\n\n        expectObservable(result).toBe(expected);\n        expectSubscriptions(source.subscriptions).toBe(sourceSubs);\n        expectSubscriptions(inner.subscriptions).toBe(innerSubs);\n      });\n    });\n\n    it('should timeout after a specified period between emit then subscribe to the passed observable when source emits', () => {\n      rxTestScheduler.run(({ hot, cold, time, expectObservable, expectSubscriptions }) => {\n        const source = hot('  ---a---b------c---|');\n        const t = time('             ----|       ');\n        const sourceSubs = '  ^----------!       ';\n        const inner = cold('             -x-y-|  ');\n        const innerSubs = '   -----------^----!  ';\n        const expected = '    ---a---b----x-y-|  ';\n\n        const result = source.pipe(\n          timeout({\n            each: t,\n            with: () => inner,\n          })\n        );\n\n        expectObservable(result).toBe(expected);\n        expectSubscriptions(source.subscriptions).toBe(sourceSubs);\n        expectSubscriptions(inner.subscriptions).toBe(innerSubs);\n      });\n    });\n\n    it('should allow unsubscribing explicitly and early', () => {\n      rxTestScheduler.run(({ hot, cold, time, expectObservable, expectSubscriptions }) => {\n        const source = hot('  ---a---b-----c----|');\n        const t = time('             ----|       ');\n        const sourceSubs = '  ^----------!       ';\n        const inner = cold('             -x---y| ');\n        const innerSubs = '   -----------^--!    ';\n        const expected = '    ---a---b----x--    ';\n        const unsub = '       --------------!    ';\n\n        const result = source.pipe(timeout({ each: t, with: () => inner }));\n\n        expectObservable(result, unsub).toBe(expected);\n        expectSubscriptions(source.subscriptions).toBe(sourceSubs);\n        expectSubscriptions(inner.subscriptions).toBe(innerSubs);\n      });\n    });\n\n    it('should not break unsubscription chain when unsubscribed explicitly', () => {\n      rxTestScheduler.run(({ hot, cold, time, expectObservable, expectSubscriptions }) => {\n        const source = hot('  ---a---b-----c----|');\n        const t = time('      ----|              ');\n        const sourceSubs = '  ^----------!       ';\n        const inner = cold('             -x---y| ');\n        const innerSubs = '   -----------^--!    ';\n        const expected = '    ---a---b----x--    ';\n        const unsub = '       --------------!    ';\n\n        const result = source.pipe(\n          mergeMap((x) => of(x)),\n          timeout({ each: t, with: () => inner }),\n          mergeMap((x) => of(x))\n        );\n\n        expectObservable(result, unsub).toBe(expected);\n        expectSubscriptions(source.subscriptions).toBe(sourceSubs);\n        expectSubscriptions(inner.subscriptions).toBe(innerSubs);\n      });\n    });\n\n    it('should not subscribe to withObservable after explicit unsubscription', () => {\n      rxTestScheduler.run(({ hot, cold, time, expectObservable, expectSubscriptions }) => {\n        const source = cold('---a------b------');\n        const t = time('     -----|           ');\n        const sourceSubs = ' ^----!           ';\n        const inner = cold('      i---j---|   ');\n        const expected = '   ---a--           ';\n        const unsub = '      -----!           ';\n\n        const result = source.pipe(\n          mergeMap((x) => of(x)),\n          timeout({ each: t, with: () => inner }),\n          mergeMap((x) => of(x))\n        );\n\n        expectObservable(result, unsub).toBe(expected);\n        expectSubscriptions(source.subscriptions).toBe(sourceSubs);\n        expectSubscriptions(inner.subscriptions).toBe([]);\n      });\n    });\n\n    it('should timeout after a specified period then subscribe to the passed observable when source is empty', () => {\n      rxTestScheduler.run(({ hot, cold, time, expectObservable, expectSubscriptions }) => {\n        const source = hot('  -------------|      ');\n        const t = time('      ----------|         ');\n        const sourceSubs = '  ^---------!         ';\n        const inner = cold('            ----x----|');\n        const innerSubs = '   ----------^--------!';\n        const expected = '    --------------x----|';\n\n        const result = source.pipe(timeout({ each: t, with: () => inner }));\n\n        expectObservable(result).toBe(expected);\n        expectSubscriptions(source.subscriptions).toBe(sourceSubs);\n        expectSubscriptions(inner.subscriptions).toBe(innerSubs);\n      });\n    });\n\n    it('should timeout after a specified period between emit then never completes if other source does not complete', () => {\n      rxTestScheduler.run(({ hot, cold, time, expectObservable, expectSubscriptions }) => {\n        const source = hot('  --a--b--------c--d--|');\n        const t = time('           ----|           ');\n        const sourceSubs = '  ^--------!           ';\n        const inner = cold('           ------------');\n        const innerSubs = '   ---------^-----------';\n        const expected = '    --a--b---------------';\n\n        const result = source.pipe(timeout({ each: t, with: () => inner }));\n\n        expectObservable(result).toBe(expected);\n        expectSubscriptions(source.subscriptions).toBe(sourceSubs);\n        expectSubscriptions(inner.subscriptions).toBe(innerSubs);\n      });\n    });\n\n    it('should timeout after a specified period then subscribe to the passed observable when source raises error after timeout', () => {\n      rxTestScheduler.run(({ hot, cold, time, expectObservable, expectSubscriptions }) => {\n        const source = hot('  -------------#      ');\n        const t = time('      ----------|         ');\n        const sourceSubs = '  ^---------!         ';\n        const inner = cold('            ----x----|');\n        const innerSubs = '   ----------^--------!';\n        const expected = '    --------------x----|';\n\n        const result = source.pipe(timeout({ each: t, with: () => inner }));\n\n        expectObservable(result).toBe(expected);\n        expectSubscriptions(source.subscriptions).toBe(sourceSubs);\n        expectSubscriptions(inner.subscriptions).toBe(innerSubs);\n      });\n    });\n\n    it('should timeout after a specified period between emit then never completes if other source emits but not complete', () => {\n      rxTestScheduler.run(({ hot, cold, time, expectObservable, expectSubscriptions }) => {\n        const source = hot('  -------------|      ');\n        const t = time('      -----------|        ');\n        const sourceSubs = '  ^----------!        ';\n        const inner = cold('             ----x----');\n        const innerSubs = '   -----------^--------';\n        const expected = '    ---------------x----';\n\n        const result = source.pipe(timeout({ each: t, with: () => inner }));\n\n        expectObservable(result).toBe(expected);\n        expectSubscriptions(source.subscriptions).toBe(sourceSubs);\n        expectSubscriptions(inner.subscriptions).toBe(innerSubs);\n      });\n    });\n\n    it('should not timeout if source completes within timeout period', () => {\n      rxTestScheduler.run(({ hot, cold, time, expectObservable, expectSubscriptions }) => {\n        const source = hot('  -----|        ');\n        const t = time('      ----------|   ');\n        const sourceSubs = '  ^----!        ';\n        const inner = cold('            ----x----');\n        const expected = '    -----|        ';\n\n        const result = source.pipe(timeout({ each: t, with: () => inner }));\n\n        expectObservable(result).toBe(expected);\n        expectSubscriptions(source.subscriptions).toBe(sourceSubs);\n        expectSubscriptions(inner.subscriptions).toBe([]);\n      });\n    });\n\n    it('should not timeout if source raises error within timeout period', () => {\n      rxTestScheduler.run(({ hot, cold, time, expectObservable, expectSubscriptions }) => {\n        const source = hot('-----#              ');\n        const t = time('    ----------|         ');\n        const sourceSubs = '^----!              ';\n        const inner = cold('       ----x----|');\n        const expected = '  -----#              ';\n\n        const result = source.pipe(timeout({ each: t, with: () => inner }));\n\n        expectObservable(result).toBe(expected);\n        expectSubscriptions(source.subscriptions).toBe(sourceSubs);\n        expectSubscriptions(inner.subscriptions).toBe([]);\n      });\n    });\n\n    it('should not timeout if source emits within timeout period', () => {\n      rxTestScheduler.run(({ hot, cold, time, expectObservable, expectSubscriptions }) => {\n        const source = hot('   --a--b--c--d--e--|');\n        const t = time('       -----|            ');\n        const sourceSubs = '   ^----------------!';\n        const inner = cold('        ----x----|   ');\n        const expected = '     --a--b--c--d--e--|';\n\n        const result = source.pipe(timeout({ each: t, with: () => inner }));\n\n        expectObservable(result).toBe(expected);\n        expectSubscriptions(source.subscriptions).toBe(sourceSubs);\n        expectSubscriptions(inner.subscriptions).toBe([]);\n      });\n    });\n\n    it('should not timeout if source completes within specified Date', () => {\n      rxTestScheduler.run(({ hot, cold, time, expectObservable, expectSubscriptions }) => {\n        const source = hot('--a--b--c--d--e--|   ');\n        const t = time('    --------------------|');\n        const sourceSubs = '^----------------!   ';\n        const inner = cold('--x--|            ');\n        const expected = '  --a--b--c--d--e--|   ';\n\n        // Start frame is zero.\n        const result = source.pipe(timeout({ first: new Date(t), with: () => inner }));\n\n        expectObservable(result).toBe(expected);\n        expectSubscriptions(source.subscriptions).toBe(sourceSubs);\n        expectSubscriptions(inner.subscriptions).toBe([]);\n      });\n    });\n\n    it('should not timeout if source raises error within specified Date', () => {\n      rxTestScheduler.run(({ hot, cold, time, expectObservable, expectSubscriptions }) => {\n        const source = hot('---a---#           ');\n        const t = time('       ----------|     ');\n        const sourceSubs = '^------!           ';\n        const inner = cold('             --x--|');\n        const expected = '  ---a---#           ';\n\n        // Start frame is zero.\n        const result = source.pipe(timeout({ first: new Date(t), with: () => inner }));\n\n        expectObservable(result).toBe(expected);\n        expectSubscriptions(source.subscriptions).toBe(sourceSubs);\n        expectSubscriptions(inner.subscriptions).toBe([]);\n      });\n    });\n\n    it('should not timeout if source emits synchronously when subscribed', () => {\n      rxTestScheduler.run(({ expectObservable, time }) => {\n        const source = of('a').pipe(concatWith(NEVER));\n        const t = time('  ---|');\n        const expected = 'a---';\n        expectObservable(source.pipe(timeout({ first: new Date(t) }))).toBe(expected);\n      });\n    });\n  });\n\n  it('should stop listening to a synchronous observable when unsubscribed', () => {\n    const sideEffects: number[] = [];\n    const synchronousObservable = new Observable<number>((subscriber) => {\n      // This will check to see if the subscriber was closed on each loop\n      // when the unsubscribe hits (from the `take`), it should be closed\n      for (let i = 0; !subscriber.closed && i < 10; i++) {\n        sideEffects.push(i);\n        subscriber.next(i);\n      }\n    });\n\n    synchronousObservable.pipe(timeout(0), take(3)).subscribe(() => {\n      /* noop */\n    });\n\n    expect(sideEffects).to.deep.equal([0, 1, 2]);\n  });\n});\n"
  },
  {
    "path": "packages/rxjs/spec/operators/timeoutWith-spec.ts",
    "content": "import { expect } from 'chai';\nimport { timeoutWith, mergeMap, take } from 'rxjs/operators';\nimport { TestScheduler } from 'rxjs/testing';\nimport { of, Observable, EMPTY } from 'rxjs';\nimport { observableMatcher } from '../helpers/observableMatcher';\n\n/** @test {timeoutWith} */\ndescribe('timeoutWith operator', () => {\n  let rxTestScheduler: TestScheduler;\n\n  beforeEach(() => {\n    rxTestScheduler = new TestScheduler(observableMatcher);\n  });\n\n  it('should timeout after a specified period then subscribe to the passed observable', () => {\n    rxTestScheduler.run(({ cold, time, expectObservable, expectSubscriptions }) => {\n      const source = cold('  -------a--b--|');\n      const sourceSubs = '   ^----!        ';\n      const t = time('       -----|');\n      const switchTo = cold('     x-y-z-|  ');\n      const switchToSubs = ' -----^-----!  ';\n      const expected = '     -----x-y-z-|  ';\n\n      const result = source.pipe(timeoutWith(t, switchTo, rxTestScheduler));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(source.subscriptions).toBe(sourceSubs);\n      expectSubscriptions(switchTo.subscriptions).toBe(switchToSubs);\n    });\n  });\n\n  it('should timeout at a specified date then subscribe to the passed observable', () => {\n    rxTestScheduler.run(({ cold, time, expectObservable, expectSubscriptions }) => {\n      const source = cold('  -');\n      const sourceSubs = '   ^---------!           ';\n      const t = time('       ----------|');\n      const switchTo = cold('          --x--y--z--|');\n      const switchToSubs = ' ----------^----------!';\n      const expected = '     ------------x--y--z--|';\n\n      // The the current frame is zero.\n      const result = source.pipe(timeoutWith(new Date(t), switchTo, rxTestScheduler));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(source.subscriptions).toBe(sourceSubs);\n      expectSubscriptions(switchTo.subscriptions).toBe(switchToSubs);\n    });\n  });\n\n  it('should timeout after a specified period between emit then subscribe to the passed observable when source emits', () => {\n    rxTestScheduler.run(({ hot, cold, time, expectObservable, expectSubscriptions }) => {\n      const source = hot('  ---a---b------c---|');\n      const t = time('             ----|       ');\n      const sourceSubs = '  ^----------!       ';\n      const switchTo = cold('          -x-y-|  ');\n      const switchToSubs = '-----------^----!  ';\n      const expected = '    ---a---b----x-y-|  ';\n\n      const result = source.pipe(timeoutWith(t, switchTo, rxTestScheduler));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(source.subscriptions).toBe(sourceSubs);\n      expectSubscriptions(switchTo.subscriptions).toBe(switchToSubs);\n    });\n  });\n\n  it('should allow unsubscribing explicitly and early', () => {\n    rxTestScheduler.run(({ hot, cold, time, expectObservable, expectSubscriptions }) => {\n      const source = hot('  ---a---b-----c----|');\n      const t = time('             ----|       ');\n      const sourceSubs = '  ^----------!       ';\n      const switchTo = cold('          -x---y| ');\n      const switchToSubs = '-----------^--!    ';\n      const expected = '    ---a---b----x--    ';\n      const unsub = '       --------------!    ';\n\n      const result = source.pipe(timeoutWith(t, switchTo, rxTestScheduler));\n\n      expectObservable(result, unsub).toBe(expected);\n      expectSubscriptions(source.subscriptions).toBe(sourceSubs);\n      expectSubscriptions(switchTo.subscriptions).toBe(switchToSubs);\n    });\n  });\n\n  it('should not break unsubscription chain when unsubscribed explicitly', () => {\n    rxTestScheduler.run(({ hot, cold, time, expectObservable, expectSubscriptions }) => {\n      const source = hot('  ---a---b-----c----|');\n      const t = time('      ----|              ');\n      const sourceSubs = '  ^----------!       ';\n      const switchTo = cold('          -x---y| ');\n      const switchToSubs = '-----------^--!    ';\n      const expected = '    ---a---b----x--    ';\n      const unsub = '       --------------!    ';\n\n      const result = source.pipe(\n        mergeMap((x) => of(x)),\n        timeoutWith(t, switchTo, rxTestScheduler),\n        mergeMap((x) => of(x))\n      );\n\n      expectObservable(result, unsub).toBe(expected);\n      expectSubscriptions(source.subscriptions).toBe(sourceSubs);\n      expectSubscriptions(switchTo.subscriptions).toBe(switchToSubs);\n    });\n  });\n\n  it('should not subscribe to withObservable after explicit unsubscription', () => {\n    rxTestScheduler.run(({ cold, time, expectObservable, expectSubscriptions }) => {\n      const source = cold('---a------b------');\n      const t = time('     -----|           ');\n      const sourceSubs = ' ^----!           ';\n      const switchTo = cold('   i---j---|   ');\n      const expected = '   ---a--           ';\n      const unsub = '      -----!           ';\n\n      const result = source.pipe(\n        mergeMap((x: string) => of(x)),\n        timeoutWith(t, switchTo, rxTestScheduler),\n        mergeMap((x: string) => of(x))\n      );\n\n      expectObservable(result, unsub).toBe(expected);\n      expectSubscriptions(source.subscriptions).toBe(sourceSubs);\n      expectSubscriptions(switchTo.subscriptions).toBe([]);\n    });\n  });\n\n  it('should timeout after a specified period then subscribe to the passed observable when source is empty', () => {\n    rxTestScheduler.run(({ hot, cold, time, expectObservable, expectSubscriptions }) => {\n      const source = hot('  -------------|      ');\n      const t = time('      ----------|         ');\n      const sourceSubs = '  ^---------!         ';\n      const switchTo = cold('         ----x----|');\n      const switchToSubs = '----------^--------!';\n      const expected = '    --------------x----|';\n\n      const result = source.pipe(timeoutWith(t, switchTo, rxTestScheduler));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(source.subscriptions).toBe(sourceSubs);\n      expectSubscriptions(switchTo.subscriptions).toBe(switchToSubs);\n    });\n  });\n\n  it('should timeout after a specified period between emit then never completes if other source does not complete', () => {\n    rxTestScheduler.run(({ hot, cold, time, expectObservable, expectSubscriptions }) => {\n      const source = hot('  --a--b--------c--d--|');\n      const t = time('           ----|           ');\n      const sourceSubs = '  ^--------!           ';\n      const switchTo = cold('        ------------');\n      const switchToSubs = '---------^-----------';\n      const expected = '    --a--b---------------';\n\n      const result = source.pipe(timeoutWith(t, switchTo, rxTestScheduler));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(source.subscriptions).toBe(sourceSubs);\n      expectSubscriptions(switchTo.subscriptions).toBe(switchToSubs);\n    });\n  });\n\n  it('should timeout after a specified period then subscribe to the passed observable when source raises error after timeout', () => {\n    rxTestScheduler.run(({ hot, cold, time, expectObservable, expectSubscriptions }) => {\n      const source = hot('  -------------#      ');\n      const t = time('      ----------|         ');\n      const sourceSubs = '  ^---------!         ';\n      const switchTo = cold('         ----x----|');\n      const switchToSubs = '----------^--------!';\n      const expected = '    --------------x----|';\n\n      const result = source.pipe(timeoutWith(t, switchTo, rxTestScheduler));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(source.subscriptions).toBe(sourceSubs);\n      expectSubscriptions(switchTo.subscriptions).toBe(switchToSubs);\n    });\n  });\n\n  it('should timeout after a specified period between emit then never completes if other source emits but not complete', () => {\n    rxTestScheduler.run(({ hot, cold, time, expectObservable, expectSubscriptions }) => {\n      const source = hot('  -------------|      ');\n      const t = time('      -----------|        ');\n      const sourceSubs = '  ^----------!        ';\n      const switchTo = cold('          ----x----');\n      const switchToSubs = '-----------^--------';\n      const expected = '    ---------------x----';\n\n      const result = source.pipe(timeoutWith(t, switchTo, rxTestScheduler));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(source.subscriptions).toBe(sourceSubs);\n      expectSubscriptions(switchTo.subscriptions).toBe(switchToSubs);\n    });\n  });\n\n  it('should not timeout if source completes within timeout period', () => {\n    rxTestScheduler.run(({ hot, cold, time, expectObservable, expectSubscriptions }) => {\n      const source = hot('  -----|        ');\n      const t = time('      ----------|   ');\n      const sourceSubs = '  ^----!        ';\n      const switchTo = cold('    ----x----');\n      const expected = '    -----|        ';\n\n      const result = source.pipe(timeoutWith(t, switchTo, rxTestScheduler));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(source.subscriptions).toBe(sourceSubs);\n      expectSubscriptions(switchTo.subscriptions).toBe([]);\n    });\n  });\n\n  it('should not timeout if source raises error within timeout period', () => {\n    rxTestScheduler.run(({ hot, cold, time, expectObservable, expectSubscriptions }) => {\n      const source = hot('-----#              ');\n      const t = time('    ----------|         ');\n      const sourceSubs = '^----!              ';\n      const switchTo = cold('       ----x----|');\n      const expected = '  -----#              ';\n\n      const result = source.pipe(timeoutWith(t, switchTo, rxTestScheduler));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(source.subscriptions).toBe(sourceSubs);\n      expectSubscriptions(switchTo.subscriptions).toBe([]);\n    });\n  });\n\n  it('should not timeout if source emits within timeout period', () => {\n    rxTestScheduler.run(({ hot, cold, time, expectObservable, expectSubscriptions }) => {\n      const source = hot('   --a--b--c--d--e--|');\n      const t = time('       -----|            ');\n      const sourceSubs = '   ^----------------!';\n      const switchTo = cold('----x----|        ');\n      const expected = '     --a--b--c--d--e--|';\n\n      const result = source.pipe(timeoutWith(t, switchTo, rxTestScheduler));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(source.subscriptions).toBe(sourceSubs);\n      expectSubscriptions(switchTo.subscriptions).toBe([]);\n    });\n  });\n\n  it('should not timeout if source completes within specified Date', () => {\n    rxTestScheduler.run(({ hot, cold, time, expectObservable, expectSubscriptions }) => {\n      const source = hot('--a--b--c--d--e--|   ');\n      const t = time('    --------------------|');\n      const sourceSubs = '^----------------!   ';\n      const switchTo = cold('--x--|            ');\n      const expected = '  --a--b--c--d--e--|   ';\n\n      // Start frame is zero.\n      const result = source.pipe(timeoutWith(new Date(t), switchTo, rxTestScheduler));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(source.subscriptions).toBe(sourceSubs);\n      expectSubscriptions(switchTo.subscriptions).toBe([]);\n    });\n  });\n\n  it('should not timeout if source raises error within specified Date', () => {\n    rxTestScheduler.run(({ hot, cold, time, expectObservable, expectSubscriptions }) => {\n      const source = hot('---a---#           ');\n      const t = time('       ----------|     ');\n      const sourceSubs = '^------!           ';\n      const switchTo = cold('          --x--|');\n      const expected = '  ---a---#           ';\n\n      // Start frame is zero.\n      const result = source.pipe(timeoutWith(new Date(t), switchTo, rxTestScheduler));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(source.subscriptions).toBe(sourceSubs);\n      expectSubscriptions(switchTo.subscriptions).toBe([]);\n    });\n  });\n\n  it('should stop listening to a synchronous observable when unsubscribed', () => {\n    const sideEffects: number[] = [];\n    const synchronousObservable = new Observable<number>((subscriber) => {\n      // This will check to see if the subscriber was closed on each loop\n      // when the unsubscribe hits (from the `take`), it should be closed\n      for (let i = 0; !subscriber.closed && i < 10; i++) {\n        sideEffects.push(i);\n        subscriber.next(i);\n      }\n    });\n\n    synchronousObservable.pipe(timeoutWith(0, EMPTY), take(3)).subscribe(() => {\n      /* noop */\n    });\n\n    expect(sideEffects).to.deep.equal([0, 1, 2]);\n  });\n});\n"
  },
  {
    "path": "packages/rxjs/spec/operators/timestamp-spec.ts",
    "content": "import { expect } from 'chai';\nimport { timestamp, map, mergeMap, take } from 'rxjs/operators';\nimport { TestScheduler } from 'rxjs/testing';\nimport { of, Observable } from 'rxjs';\nimport { observableMatcher } from '../helpers/observableMatcher';\n\n/** @test {timestamp} */\ndescribe('timestamp', () => {\n  let rxTestScheduler: TestScheduler;\n\n  beforeEach(() => {\n    rxTestScheduler = new TestScheduler(observableMatcher);\n  });\n\n  it('should record the time stamp per each source elements', () => {\n    rxTestScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  -b-c-----d--e--|');\n      const e1subs = '  ^--------------!';\n      const expected = '-w-x-----y--z--|';\n      const expectedValue = { w: 1, x: 3, y: 9, z: 12 };\n\n      const result = e1.pipe(\n        timestamp(rxTestScheduler),\n        map((x) => x.timestamp)\n      );\n\n      expectObservable(result).toBe(expected, expectedValue);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should record stamp if source emit elements', () => {\n    rxTestScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('--a--^b--c----d---e--|');\n      const e1subs = '     ^---------------!';\n      const expected = '   -w--x----y---z--|';\n\n      const expectedValue = {\n        w: { value: 'b', timestamp: 1 },\n        x: { value: 'c', timestamp: 4 },\n        y: { value: 'd', timestamp: 9 },\n        z: { value: 'e', timestamp: 13 },\n      };\n\n      expectObservable(e1.pipe(timestamp(rxTestScheduler))).toBe(expected, expectedValue);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should completes without record stamp if source does not emits', () => {\n    rxTestScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  ---------|');\n      const e1subs = '  ^--------!';\n      const expected = '---------|';\n\n      expectObservable(e1.pipe(timestamp(rxTestScheduler))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should complete immediately if source is empty', () => {\n    rxTestScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' |   ');\n      const e1subs = '  (^!)';\n      const expected = '|   ';\n\n      expectObservable(e1.pipe(timestamp(rxTestScheduler))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should record stamp then does not completes if source emits but not completes', () => {\n    rxTestScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  -a--b--');\n      const e1subs = '  ^------';\n      const expected = '-y--z--';\n\n      const expectedValue = {\n        y: { value: 'a', timestamp: 1 },\n        z: { value: 'b', timestamp: 4 },\n      };\n\n      expectObservable(e1.pipe(timestamp(rxTestScheduler))).toBe(expected, expectedValue);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should allow unsubscribing explicitly and early', () => {\n    rxTestScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  -a--b-----c---d---|');\n      const unsub = '   -------!           ';\n      const e1subs = '  ^------!           ';\n      const expected = '-y--z---           ';\n\n      const expectedValue = {\n        y: { value: 'a', timestamp: 1 },\n        z: { value: 'b', timestamp: 4 },\n      };\n\n      const result = e1.pipe(timestamp(rxTestScheduler));\n\n      expectObservable(result, unsub).toBe(expected, expectedValue);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should not break unsubscription chains when result is unsubscribed explicitly', () => {\n    rxTestScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  -a--b-----c---d---|');\n      const e1subs = '  ^------!           ';\n      const expected = '-y--z---           ';\n      const unsub = '   -------!           ';\n\n      const expectedValue = {\n        y: { value: 'a', timestamp: 1 },\n        z: { value: 'b', timestamp: 4 },\n      };\n\n      const result = e1.pipe(\n        mergeMap((x) => of(x)),\n        timestamp(rxTestScheduler),\n        mergeMap((x) => of(x))\n      );\n\n      expectObservable(result, unsub).toBe(expected, expectedValue);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should not completes if source never completes', () => {\n    rxTestScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' -');\n      const e1subs = '  ^';\n      const expected = '-';\n\n      expectObservable(e1.pipe(timestamp(rxTestScheduler))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('raise error if source raises error', () => {\n    rxTestScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  ---#');\n      const e1subs = '  ^--!';\n      const expected = '---#';\n\n      expectObservable(e1.pipe(timestamp(rxTestScheduler))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should record stamp then raise error if source raises error after emit', () => {\n    rxTestScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  -a--b--#');\n      const e1subs = '  ^------!';\n      const expected = '-y--z--#';\n\n      const expectedValue = {\n        y: { value: 'a', timestamp: 1 },\n        z: { value: 'b', timestamp: 4 },\n      };\n\n      expectObservable(e1.pipe(timestamp(rxTestScheduler))).toBe(expected, expectedValue);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should raise error if source immediately throws', () => {\n    rxTestScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' #   ');\n      const e1subs = '  (^!)';\n      const expected = '#   ';\n\n      expectObservable(e1.pipe(timestamp(rxTestScheduler))).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should stop listening to a synchronous observable when unsubscribed', () => {\n    const sideEffects: number[] = [];\n    const synchronousObservable = new Observable<number>((subscriber) => {\n      // This will check to see if the subscriber was closed on each loop\n      // when the unsubscribe hits (from the `take`), it should be closed\n      for (let i = 0; !subscriber.closed && i < 10; i++) {\n        sideEffects.push(i);\n        subscriber.next(i);\n      }\n    });\n\n    synchronousObservable.pipe(timestamp(), take(3)).subscribe(() => {\n      /* noop */\n    });\n\n    expect(sideEffects).to.deep.equal([0, 1, 2]);\n  });\n});\n"
  },
  {
    "path": "packages/rxjs/spec/operators/toArray-spec.ts",
    "content": "import { toArray, mergeMap } from 'rxjs/operators';\nimport { of } from 'rxjs';\nimport { TestScheduler } from 'rxjs/testing';\nimport { observableMatcher } from '../helpers/observableMatcher';\n\n/** @test {toArray} */\ndescribe('toArray', () => {\n  let rxTestScheduler: TestScheduler;\n\n  beforeEach(() => {\n    rxTestScheduler = new TestScheduler(observableMatcher);\n  });\n\n  it('should reduce the values of an observable into an array', () => {\n    rxTestScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  ---a--b--|   ');\n      const e1subs = '  ^--------!   ';\n      const expected = '---------(w|)';\n\n      expectObservable(e1.pipe(toArray())).toBe(expected, { w: ['a', 'b'] });\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should be never when source is never', () => {\n    rxTestScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' -');\n      const e1subs = '  ^';\n      const expected = '-';\n\n      expectObservable(e1.pipe(toArray())).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should be empty when source is empty', () => {\n    rxTestScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' |   ');\n      const e1subs = '  (^!)';\n      const expected = '(w|)';\n\n      expectObservable(e1.pipe(toArray())).toBe(expected, { w: [] });\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it(\"should be never when source doesn't complete\", () => {\n    rxTestScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('--x--^--y--');\n      const e1subs = '     ^-----';\n      const expected = '   ------';\n\n      expectObservable(e1.pipe(toArray())).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should reduce observable without values into an array of length zero', () => {\n    rxTestScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('-x-^---|   ');\n      const e1subs = '   ^---!   ';\n      const expected = ' ----(w|)';\n\n      expectObservable(e1.pipe(toArray())).toBe(expected, { w: [] });\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should reduce the a single value of an observable into an array', () => {\n    rxTestScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('-x-^--y--|  ');\n      const e1subs = '   ^-----!  ';\n      const expected = ' ------(w|)';\n\n      expectObservable(e1.pipe(toArray())).toBe(expected, { w: ['y'] });\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should allow multiple subscriptions', () => {\n    rxTestScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('-x-^--y--|   ');\n      const e1subs = '   ^-----!   ';\n      const expected = ' ------(w|)';\n\n      const result = e1.pipe(toArray());\n      expectObservable(result).toBe(expected, { w: ['y'] });\n      expectObservable(result).toBe(expected, { w: ['y'] });\n      expectSubscriptions(e1.subscriptions).toBe([e1subs, e1subs]);\n    });\n  });\n\n  it('should allow unsubscribing explicitly and early', () => {\n    rxTestScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  --a--b----c-----d----e---|');\n      const e1subs = '  ^-------!                 ';\n      const expected = '---------                 ';\n      const unsub = '   --------!                 ';\n\n      expectObservable(e1.pipe(toArray()), unsub).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should not break unsubscription chains when result is unsubscribed explicitly', () => {\n    rxTestScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  --a--b----c-----d----e---|');\n      const e1subs = '  ^-------!                 ';\n      const expected = '---------                 ';\n      const unsub = '   --------!                 ';\n\n      const result = e1.pipe(\n        mergeMap((x: string) => of(x)),\n        toArray(),\n        mergeMap((x: Array<string>) => of(x))\n      );\n\n      expectObservable(result, unsub).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should work with error', () => {\n    rxTestScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('-x-^--y--z--#', { x: 1, y: 2, z: 3 }, 'too bad');\n      const e1subs = '   ^--------!';\n      const expected = ' ---------#';\n\n      expectObservable(e1.pipe(toArray())).toBe(expected, null, 'too bad');\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should work with throw', () => {\n    rxTestScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e1 = cold(' #   ');\n      const e1subs = '  (^!)';\n      const expected = '#   ';\n\n      expectObservable(e1.pipe(toArray())).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n});\n"
  },
  {
    "path": "packages/rxjs/spec/operators/window-spec.ts",
    "content": "import { window, mergeMap, take } from 'rxjs/operators';\nimport { TestScheduler } from 'rxjs/testing';\nimport type { Observable} from 'rxjs';\nimport { EMPTY, of, interval } from 'rxjs';\nimport { observableMatcher } from '../helpers/observableMatcher';\nimport { expect } from 'chai';\n\n/** @test {window} */\ndescribe('window', () => {\n  let rxTestScheduler: TestScheduler;\n\n  beforeEach(() => {\n    rxTestScheduler = new TestScheduler(observableMatcher);\n  });\n\n  it('should emit windows that close and reopen', () => {\n    rxTestScheduler.run(({ hot, cold, expectObservable, expectSubscriptions }) => {\n      const source = hot('  ---a---b---c---d---e---f---g---h---i---|    ');\n      const sourceSubs = '  ^--------------------------------------!    ';\n      const closings = hot('-------------w------------w----------------|');\n      const closingSubs = ' ^--------------------------------------!    ';\n      const expected = '    x------------y------------z------------|    ';\n      const x = cold('      ---a---b---c-|                              ');\n      const y = cold('                   --d---e---f--|                 ');\n      const z = cold('                                -g---h---i---|    ');\n      const expectedValues = { x: x, y: y, z: z };\n\n      const result = source.pipe(window(closings));\n\n      expectObservable(result).toBe(expected, expectedValues);\n      expectSubscriptions(source.subscriptions).toBe(sourceSubs);\n      expectSubscriptions(closings.subscriptions).toBe(closingSubs);\n    });\n  });\n\n  it('should return a single empty window if source is empty and closings are basic', () => {\n    rxTestScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const source = cold('  |        ');\n      const sourceSubs = '   (^!)     ';\n      const closings = cold('--x--x--|');\n      const closingSubs = '  (^!)     ';\n      const expected = '     (w|)     ';\n      const w = cold('       |        ');\n      const expectedValues = { w: w };\n\n      const result = source.pipe(window(closings));\n\n      expectObservable(result).toBe(expected, expectedValues);\n      expectSubscriptions(source.subscriptions).toBe(sourceSubs);\n      expectSubscriptions(closings.subscriptions).toBe(closingSubs);\n    });\n  });\n\n  it('should return a single empty window if source is empty and closing is empty', () => {\n    rxTestScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const source = cold('  |   ');\n      const sourceSubs = '   (^!)';\n      const closings = cold('|   ');\n      const closingSubs = '  (^!)';\n      const expected = '     (w|)';\n      const w = cold('       |   ');\n      const expectedValues = { w: w };\n\n      const result = source.pipe(window(closings));\n\n      expectObservable(result).toBe(expected, expectedValues);\n      expectSubscriptions(source.subscriptions).toBe(sourceSubs);\n      expectSubscriptions(closings.subscriptions).toBe(closingSubs);\n    });\n  });\n\n  it('should return a single empty window if source is sync empty and closing is sync empty', () => {\n    rxTestScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const source = cold('  (|) ');\n      const sourceSubs = '   (^!)';\n      const expected = '     (w|)';\n      const w = cold('       |   ');\n      const expectedValues = { w: w };\n\n      const result = source.pipe(window(EMPTY));\n\n      expectObservable(result).toBe(expected, expectedValues);\n      expectSubscriptions(source.subscriptions).toBe(sourceSubs);\n      // expectSubscriptions(closings.subscriptions).toBe(closingSubs);\n    });\n  });\n\n  it('should split a Just source into a single window identical to source, using a Never closing', () => {\n    rxTestScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const source = cold('  (a|)');\n      const sourceSubs = '   (^!)';\n      const closings = cold('-   ');\n      const closingSubs = '  (^!)';\n      const expected = '     (w|)';\n      const w = cold('       (a|)');\n      const expectedValues = { w: w };\n\n      const result = source.pipe(window(closings));\n\n      expectObservable(result).toBe(expected, expectedValues);\n      expectSubscriptions(source.subscriptions).toBe(sourceSubs);\n      expectSubscriptions(closings.subscriptions).toBe(closingSubs);\n    });\n  });\n\n  it('should return a single Never window if source is Never', () => {\n    rxTestScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const source = cold('  ------');\n      const sourceSubs = '   ^-----';\n      const closings = cold('------');\n      const closingSubs = '  ^-----';\n      const expected = '     w-----';\n      const w = cold('       ------');\n      const expectedValues = { w: w };\n\n      const result = source.pipe(window(closings));\n\n      expectObservable(result).toBe(expected, expectedValues);\n      expectSubscriptions(source.subscriptions).toBe(sourceSubs);\n      expectSubscriptions(closings.subscriptions).toBe(closingSubs);\n    });\n  });\n\n  it('should be able to split a never Observable into timely empty windows', () => {\n    rxTestScheduler.run(({ hot, cold, expectObservable, expectSubscriptions }) => {\n      const source = hot('   ^--------');\n      const sourceSubs = '   ^--------';\n      const closings = cold('--x--x--|');\n      const closingSubs = '  ^-------!';\n      const expected = '     a-b--c---';\n      const a = cold('       --|      ');\n      const b = cold('         ---|   ');\n      const c = cold('            ----');\n      const expectedValues = { a: a, b: b, c: c };\n\n      const result = source.pipe(window(closings));\n\n      expectObservable(result).toBe(expected, expectedValues);\n      expectSubscriptions(source.subscriptions).toBe(sourceSubs);\n      expectSubscriptions(closings.subscriptions).toBe(closingSubs);\n    });\n  });\n\n  it('should emit an error-only window if outer is a simple throw-Observable', () => {\n    rxTestScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const source = cold('  #        ');\n      const sourceSubs = '   (^!)     ';\n      const closings = cold('--x--x--|');\n      const closingSubs = '  (^!)     ';\n      const expected = '     (w#)     ';\n      const w = cold('       #        ');\n      const expectedValues = { w: w };\n\n      const result = source.pipe(window(closings));\n\n      expectObservable(result).toBe(expected, expectedValues);\n      expectSubscriptions(source.subscriptions).toBe(sourceSubs);\n      expectSubscriptions(closings.subscriptions).toBe(closingSubs);\n    });\n  });\n\n  it('should handle basic case with window closings', () => {\n    rxTestScheduler.run(({ hot, cold, expectObservable, expectSubscriptions }) => {\n      const source = hot('-1-2-^3-4-5-6-7-8-9-|         ');\n      const subs = '           ^--------------!         ';\n      const closings = hot('---^---x---x---x---x---x---|');\n      const closingSubs = '    ^--------------!         ';\n      const expected = '       a---b---c---d--|         ';\n      const a = cold('         -3-4|                    ');\n      const b = cold('             -5-6|                ');\n      const c = cold('                 -7-8|            ');\n      const d = cold('                     -9-|         ');\n      const expectedValues = { a: a, b: b, c: c, d: d };\n\n      const result = source.pipe(window(closings));\n\n      expectObservable(result).toBe(expected, expectedValues);\n      expectSubscriptions(source.subscriptions).toBe(subs);\n      expectSubscriptions(closings.subscriptions).toBe(closingSubs);\n    });\n  });\n\n  it('should handle basic case with window closings, but outer throws', () => {\n    rxTestScheduler.run(({ hot, cold, expectObservable, expectSubscriptions }) => {\n      const source = hot('-1-2-^3-4-5-6-7-8-9-#         ');\n      const subs = '           ^--------------!         ';\n      const closings = hot('---^---x---x---x---x---x---|');\n      const closingSubs = '    ^--------------!         ';\n      const expected = '       a---b---c---d--#         ';\n      const a = cold('         -3-4|                    ');\n      const b = cold('             -5-6|                ');\n      const c = cold('                 -7-8|            ');\n      const d = cold('                     -9-#         ');\n      const expectedValues = { a: a, b: b, c: c, d: d };\n\n      const result = source.pipe(window(closings));\n\n      expectObservable(result).toBe(expected, expectedValues);\n      expectSubscriptions(source.subscriptions).toBe(subs);\n      expectSubscriptions(closings.subscriptions).toBe(closingSubs);\n    });\n  });\n\n  it('should stop emitting windows when outer is unsubscribed early', () => {\n    rxTestScheduler.run(({ hot, cold, expectObservable, expectSubscriptions }) => {\n      const source = hot('-1-2-^3-4-5-6-7-8-9-|         ');\n      const subs = '           ^-------!                ';\n      const closings = hot('---^---x---x---x---x---x---|');\n      const closingSubs = '    ^-------!                ';\n      const expected = '       a---b----                ';\n      const a = cold('         -3-4|                    ');\n      const b = cold('             -5-6                 ');\n      const unsub = '          --------!                ';\n      const expectedValues = { a: a, b: b };\n\n      const result = source.pipe(window(closings));\n\n      expectObservable(result, unsub).toBe(expected, expectedValues);\n      expectSubscriptions(source.subscriptions).toBe(subs);\n      expectSubscriptions(closings.subscriptions).toBe(closingSubs);\n    });\n  });\n\n  it('should not break unsubscription chains when result is unsubscribed explicitly', () => {\n    rxTestScheduler.run(({ hot, cold, expectObservable, expectSubscriptions }) => {\n      const source = hot('-1-2-^3-4-5-6-7-8-9-|         ');\n      const subs = '           ^-------!                ';\n      const closings = hot('---^---x---x---x---x---x---|');\n      const closingSubs = '    ^-------!                ';\n      const expected = '       a---b----                ';\n      const a = cold('         -3-4|                    ');\n      const b = cold('             -5-6-                ');\n      const unsub = '          --------!                ';\n      const expectedValues = { a: a, b: b };\n\n      const result = source.pipe(\n        mergeMap((x: string) => of(x)),\n        window(closings),\n        mergeMap((x: Observable<string>) => of(x))\n      );\n\n      expectObservable(result, unsub).toBe(expected, expectedValues);\n      expectSubscriptions(source.subscriptions).toBe(subs);\n      expectSubscriptions(closings.subscriptions).toBe(closingSubs);\n    });\n  });\n\n  it('should make outer emit error when closing throws', () => {\n    rxTestScheduler.run(({ hot, cold, expectObservable, expectSubscriptions }) => {\n      const source = hot('-1-2-^3-4-5-6-7-8-9-#');\n      const subs = '           ^---!           ';\n      const closings = hot('---^---#           ');\n      const closingSubs = '    ^---!           ';\n      const expected = '       a---#           ';\n      const a = cold('         -3-4#           ');\n      const expectedValues = { a: a };\n\n      const result = source.pipe(window(closings));\n\n      expectObservable(result).toBe(expected, expectedValues);\n      expectSubscriptions(source.subscriptions).toBe(subs);\n      expectSubscriptions(closings.subscriptions).toBe(closingSubs);\n    });\n  });\n\n  it('should complete the resulting Observable when window closings completes', () => {\n    rxTestScheduler.run(({ hot, cold, expectObservable, expectSubscriptions }) => {\n      const source = hot('-1-2-^3-4-5-6-7-8-9-|');\n      const subs = '           ^--------------!';\n      const closings = hot('---^---x---x---|   ');\n      const closingSubs = '    ^-----------!   ';\n      const expected = '       a---b---c------|';\n      const a = cold('         -3-4|           ');\n      const b = cold('             -5-6|       ');\n      const c = cold('                 -7-8-9-|');\n      const expectedValues = { a: a, b: b, c: c };\n\n      const result = source.pipe(window(closings));\n\n      expectObservable(result).toBe(expected, expectedValues);\n      expectSubscriptions(source.subscriptions).toBe(subs);\n      expectSubscriptions(closings.subscriptions).toBe(closingSubs);\n    });\n  });\n\n  it('should window when Promise resolves', (done) => {\n    const e1 = interval(3).pipe(take(5));\n    let pos = 0;\n    const result: number[][] = [[], []];\n    const expected = [\n      [0, 1],\n      [2, 3, 4],\n    ];\n\n    e1.pipe(window(new Promise<void>((resolve) => setTimeout(() => resolve(), 8)))).subscribe({\n      next: (x) => {\n        x.subscribe({\n          next: (v) => result[pos].push(v),\n          complete: () => pos++,\n        });\n      },\n      error: () => done(new Error('should not be called')),\n      complete: () => {\n        expect(result).to.deep.equal(expected);\n        done();\n      },\n    });\n  });\n\n  it('should raise error when Promise rejects', (done) => {\n    const e1 = interval(1).pipe(take(5));\n    const error = new Error('err');\n\n    e1.pipe(window(Promise.reject(error))).subscribe({\n      error: (err) => {\n        expect(err).to.be.an('error');\n        done();\n      },\n      complete: () => {\n        done(new Error('should not be called'));\n      },\n    });\n  });\n});\n"
  },
  {
    "path": "packages/rxjs/spec/operators/windowCount-spec.ts",
    "content": "import { expect } from 'chai';\nimport { windowCount, mergeMap, mergeAll, take } from 'rxjs/operators';\nimport { of, Observable } from 'rxjs';\nimport { TestScheduler } from 'rxjs/testing';\nimport { observableMatcher } from '../helpers/observableMatcher';\n\n/** @test {windowCount} */\ndescribe('windowCount', () => {\n  let rxTestScheduler: TestScheduler;\n\n  beforeEach(() => {\n    rxTestScheduler = new TestScheduler(observableMatcher);\n  });\n\n  it('should emit windows with count 3, no skip specified', () => {\n    rxTestScheduler.run(({ hot, cold, expectObservable, expectSubscriptions }) => {\n      const source = hot('---a---b---c---d---e---f---g---h---i---|');\n      const sourceSubs = '^--------------------------------------!';\n      const expected = '  x----------y-----------z-----------w---|';\n      const x = cold('    ---a---b---(c|)                         ');\n      const y = cold('               ----d---e---(f|)             ');\n      const z = cold('                           ----g---h---(i|) ');\n      const w = cold('                                       ----|');\n      const expectedValues = { x: x, y: y, z: z, w: w };\n\n      const result = source.pipe(windowCount(3));\n\n      expectObservable(result).toBe(expected, expectedValues);\n      expectSubscriptions(source.subscriptions).toBe(sourceSubs);\n    });\n  });\n\n  it('should emit windows with count 2 and skip 1', () => {\n    rxTestScheduler.run(({ hot, cold, expectObservable, expectSubscriptions }) => {\n      const source = hot('^-a--b--c--d--|');\n      const subs = '      ^-------------!';\n      const expected = '  u-v--x--y--z--|';\n      const u = cold('    --a--(b|)      ');\n      const v = cold('      ---b--(c|)   ');\n      const x = cold('         ---c--(d|)');\n      const y = cold('            ---d--|');\n      const z = cold('               ---|');\n      const values = { u: u, v: v, x: x, y: y, z: z };\n\n      const result = source.pipe(windowCount(2, 1));\n\n      expectObservable(result).toBe(expected, values);\n      expectSubscriptions(source.subscriptions).toBe(subs);\n    });\n  });\n\n  it('should emit windows with count 2, and skip unspecified', () => {\n    rxTestScheduler.run(({ hot, cold, expectObservable, expectSubscriptions }) => {\n      const source = hot('--a--b--c--d--e--f--|');\n      const subs = '      ^-------------------!';\n      const expected = '  x----y-----z-----w--|';\n      const x = cold('    --a--(b|)            ');\n      const y = cold('         ---c--(d|)      ');\n      const z = cold('               ---e--(f|)');\n      const w = cold('                     ---|');\n      const values = { x: x, y: y, z: z, w: w };\n\n      const result = source.pipe(windowCount(2));\n\n      expectObservable(result).toBe(expected, values);\n      expectSubscriptions(source.subscriptions).toBe(subs);\n    });\n  });\n\n  it('should return empty if source is empty', () => {\n    rxTestScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const source = cold('|');\n      const subs = '       (^!)';\n      const expected = '   (w|)';\n      const w = cold('     |');\n      const values = { w: w };\n\n      const result = source.pipe(windowCount(2, 1));\n\n      expectObservable(result).toBe(expected, values);\n      expectSubscriptions(source.subscriptions).toBe(subs);\n    });\n  });\n\n  it('should return Never if source if Never', () => {\n    rxTestScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const source = cold('-');\n      const subs = '       ^';\n      const expected = '   w';\n      const w = cold('     -');\n      const expectedValues = { w: w };\n\n      const result = source.pipe(windowCount(2, 1));\n\n      expectObservable(result).toBe(expected, expectedValues);\n      expectSubscriptions(source.subscriptions).toBe(subs);\n    });\n  });\n\n  it('should propagate error from a just-throw source', () => {\n    rxTestScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const source = cold('  #');\n      const subs = '         (^!)';\n      const expected = '     (w#)';\n      const w = cold('       #');\n      const expectedValues = { w: w };\n\n      const result = source.pipe(windowCount(2, 1));\n\n      expectObservable(result).toBe(expected, expectedValues);\n      expectSubscriptions(source.subscriptions).toBe(subs);\n    });\n  });\n\n  it('should raise error if source raises error', () => {\n    rxTestScheduler.run(({ hot, cold, expectObservable, expectSubscriptions }) => {\n      const source = hot('--a--b--c--d--e--f--#');\n      const subs = '      ^-------------------!';\n      const expected = '  u-v--w--x--y--z--q--#';\n      const u = cold('    --a--b--(c|)         ');\n      const v = cold('      ---b--c--(d|)      ');\n      const w = cold('         ---c--d--(e|)   ');\n      const x = cold('            ---d--e--(f|)');\n      const y = cold('               ---e--f--#');\n      const z = cold('                  ---f--#');\n      const q = cold('                     ---#');\n      const values = { u: u, v: v, w: w, x: x, y: y, z: z, q: q };\n\n      const result = source.pipe(windowCount(3, 1));\n\n      expectObservable(result).toBe(expected, values);\n      expectSubscriptions(source.subscriptions).toBe(subs);\n    });\n  });\n\n  it('should dispose of inner windows once outer is unsubscribed early', () => {\n    rxTestScheduler.run(({ hot, cold, expectObservable, expectSubscriptions }) => {\n      const source = hot('^-a--b--c--d--|');\n      const subs = '      ^--------!     ';\n      const expected = '  w-x--y--z-     ';\n      const w = cold('    --a--(b|)      ');\n      const x = cold('      ---b--(c|)   ');\n      const y = cold('         ---c-     ');\n      const z = cold('            --     ');\n      const unsub = '     ---------!     ';\n      const values = { w: w, x: x, y: y, z: z };\n\n      const result = source.pipe(windowCount(2, 1));\n\n      expectObservable(result, unsub).toBe(expected, values);\n      expectSubscriptions(source.subscriptions).toBe(subs);\n    });\n  });\n\n  it('should not break unsubscription chains when result is unsubscribed explicitly', () => {\n    rxTestScheduler.run(({ hot, cold, expectObservable, expectSubscriptions }) => {\n      const source = hot('^-a--b--c--d--|');\n      const subs = '      ^--------!     ';\n      const expected = '  w-x--y--z-     ';\n      const w = cold('    --a--(b|)      ');\n      const x = cold('      ---b--(c|)   ');\n      const y = cold('         ---c-     ');\n      const z = cold('            --     ');\n      const unsub = '     ---------!     ';\n      const values = { w: w, x: x, y: y, z: z };\n\n      const result = source.pipe(\n        mergeMap((x: string) => of(x)),\n        windowCount(2, 1),\n        mergeMap((x: Observable<string>) => of(x))\n      );\n\n      expectObservable(result, unsub).toBe(expected, values);\n      expectSubscriptions(source.subscriptions).toBe(subs);\n    });\n  });\n\n  it('should stop listening to a synchronous observable when unsubscribed', () => {\n    const sideEffects: number[] = [];\n    const synchronousObservable = new Observable<number>((subscriber) => {\n      // This will check to see if the subscriber was closed on each loop\n      // when the unsubscribe hits (from the `take`), it should be closed\n      for (let i = 0; !subscriber.closed && i < 10; i++) {\n        sideEffects.push(i);\n        subscriber.next(i);\n      }\n    });\n\n    synchronousObservable.pipe(windowCount(3), mergeAll(), take(3)).subscribe(() => {\n      /* noop */\n    });\n\n    expect(sideEffects).to.deep.equal([0, 1, 2]);\n  });\n});\n"
  },
  {
    "path": "packages/rxjs/spec/operators/windowTime-spec.ts",
    "content": "import { windowTime, mergeMap } from 'rxjs/operators';\nimport { TestScheduler } from 'rxjs/testing';\nimport type { Observable } from 'rxjs';\nimport { of } from 'rxjs';\nimport { observableMatcher } from '../helpers/observableMatcher';\n\n/** @test {windowTime} */\ndescribe('windowTime', () => {\n  let rxTestScheduler: TestScheduler;\n\n  beforeEach(() => {\n    rxTestScheduler = new TestScheduler(observableMatcher);\n  });\n\n  it('should emit windows given windowTimeSpan and windowCreationInterval', () => {\n    rxTestScheduler.run(({ hot, cold, expectObservable, expectSubscriptions }) => {\n      const source = hot('--1--2--^-a--b--c--d--e---f--g--h-|');\n      const subs = '              ^-------------------------!';\n      //  10 frames               0---------1---------2-----|\n      //  5                       -----|\n      //  5                                 -----|\n      //  5                                           -----|\n      const expected = '          x---------y---------z-----|';\n      const x = cold('            --a--(b|)                  ');\n      const y = cold('                      -d--e|           ');\n      const z = cold('                                -g--h| ');\n      const values = { x, y, z };\n\n      const result = source.pipe(windowTime(5, 10, rxTestScheduler));\n\n      expectObservable(result).toBe(expected, values);\n      expectSubscriptions(source.subscriptions).toBe(subs);\n    });\n  });\n\n  // NOTE: This test and behavior were broken in 5.x and 6.x, to where\n  // Not passing a creationInterval would not cause new windows to open\n  // when old ones closed.\n  it('should close windows after max count is reached', () => {\n    rxTestScheduler.run(({ hot, time, cold, expectObservable, expectSubscriptions }) => {\n      const source = hot('--1--2--^--a--b--c--d--e--f--g-----|');\n      const subs = '              ^--------------------------!';\n      const timeSpan = time('     ----------|                 ');\n      //                                 ----------|\n      //                                       ----------|\n      //                                             ---------\n      const expected = '          w-----x-----y-----z--------|';\n      const w = cold('            ---a--(b|)                  ');\n      const x = cold('                  ---c--(d|)            ');\n      const y = cold('                        ---e--(f|)      ');\n      const z = cold('                              ---g-----|');\n      const values = { w, x, y, z };\n\n      const result = source.pipe(windowTime(timeSpan, null, 2, rxTestScheduler));\n\n      expectObservable(result).toBe(expected, values);\n      expectSubscriptions(source.subscriptions).toBe(subs);\n    });\n  });\n\n  it('should close window after max count is reached with windowCreationInterval', () => {\n    rxTestScheduler.run(({ hot, cold, expectSubscriptions, expectObservable }) => {\n      const source = hot('--1--2--^-a--b--c--de-f---g--h--i-|');\n      const subs = '              ^-------------------------!';\n      //  10 frames               0---------1---------2-----|\n      //  5                       -----|\n      //  5                                 -----|\n      //  5                                           -----|\n      const expected = '          x---------y---------z-----|';\n      const x = cold('            --a--(b|)                  ');\n      const y = cold('                      -de-(f|)         ');\n      const z = cold('                                -h--i| ');\n      const values = { x, y, z };\n\n      const result = source.pipe(windowTime(5, 10, 3, rxTestScheduler));\n\n      expectObservable(result).toBe(expected, values);\n      expectSubscriptions(source.subscriptions).toBe(subs);\n    });\n  });\n\n  it('should emit windows given windowTimeSpan', () => {\n    rxTestScheduler.run(({ hot, cold, time, expectSubscriptions, expectObservable }) => {\n      const source = hot('--1--2--^--a--b--c--d--e--f--g--h--|');\n      const subs = '              ^--------------------------!';\n      const timeSpan = time('     ----------|                 ');\n      //  10 frames               0---------1---------2------|\n      //                                    ----------|\n      //                                              ----------|\n      const expected = '          x---------y---------z------|';\n      const x = cold('            ---a--b--c|                 ');\n      const y = cold('                      --d--e--f-|       ');\n      const z = cold('                                -g--h--|');\n      const values = { x, y, z };\n\n      const result = source.pipe(windowTime(timeSpan, rxTestScheduler));\n\n      expectObservable(result).toBe(expected, values);\n      expectSubscriptions(source.subscriptions).toBe(subs);\n    });\n  });\n\n  it('should emit windows given windowTimeSpan and windowCreationInterval', () => {\n    rxTestScheduler.run(({ hot, time, cold, expectSubscriptions, expectObservable }) => {\n      const source = hot('--1--2--^--a--b--c--d--e--f--g--h--|');\n      const subs = '              ^--------------------------!';\n      //  10 frames               0---------1---------2------|\n      const interval = time('     ----------|                 ');\n      //  10                                ----------|\n      //  10                                          ----------|\n      const timeSpan = time('     -----|                      ');\n      //  5                                 ----|\n      //  5                                           ----|\n      const expected = '          x---------y---------z------|';\n      const x = cold('            ---a-|                      ');\n      const y = cold('                      --d--(e|)         ');\n      const z = cold('                                -g--h|  ');\n      const values = { x, y, z };\n\n      const result = source.pipe(windowTime(timeSpan, interval, rxTestScheduler));\n\n      expectObservable(result).toBe(expected, values);\n      expectSubscriptions(source.subscriptions).toBe(subs);\n    });\n  });\n\n  it('should return a single empty window if source is empty', () => {\n    rxTestScheduler.run(({ cold, time, expectSubscriptions, expectObservable }) => {\n      const source = cold('|');\n      const subs = '       (^!)';\n      const expected = '   (w|)';\n      const w = cold('     |');\n      const expectedValues = { w };\n      const timeSpan = time('-----|');\n      const interval = time('----------|');\n\n      const result = source.pipe(windowTime(timeSpan, interval, rxTestScheduler));\n\n      expectObservable(result).toBe(expected, expectedValues);\n      expectSubscriptions(source.subscriptions).toBe(subs);\n    });\n  });\n\n  it('should split a Just source into a single window identical to source', () => {\n    rxTestScheduler.run(({ cold, time, expectSubscriptions, expectObservable }) => {\n      const source = cold('(a|)');\n      const subs = '       (^!)';\n      const expected = '   (w|)';\n      const w = cold('     (a|)');\n      const expectedValues = { w };\n      const timeSpan = time('-----|');\n      const interval = time('----------|');\n\n      const result = source.pipe(windowTime(timeSpan, interval, rxTestScheduler));\n\n      expectObservable(result).toBe(expected, expectedValues);\n      expectSubscriptions(source.subscriptions).toBe(subs);\n    });\n  });\n\n  it('should be able to split a never Observable into timely empty windows', () => {\n    rxTestScheduler.run(({ hot, cold, time, expectSubscriptions, expectObservable }) => {\n      const source = hot('   ^----------');\n      const subs = '         ^---------!';\n      const timeSpan = time('---|');\n      const interval = time('---|');\n      //                        ---|\n      //                           ---|\n      //                              ---|\n      const expected = '     a--b--c--d-';\n      const a = cold('       ---|       ');\n      const b = cold('          ---|    ');\n      const c = cold('             ---| ');\n      const d = cold('                --');\n      const unsub = '        ----------!';\n      const expectedValues = { a, b, c, d };\n\n      const result = source.pipe(windowTime(timeSpan, interval, rxTestScheduler));\n\n      expectObservable(result, unsub).toBe(expected, expectedValues);\n      expectSubscriptions(source.subscriptions).toBe(subs);\n    });\n  });\n\n  it('should emit an error-only window if outer is a simple throw-Observable', () => {\n    rxTestScheduler.run(({ cold, time, expectSubscriptions, expectObservable }) => {\n      const source = cold('#   ');\n      const subs = '       (^!)';\n      const expected = '   (w#)';\n      const w = cold('     #   ');\n      const expectedValues = { w };\n      const timeSpan = time('-----|');\n      const interval = time('----------|');\n\n      const result = source.pipe(windowTime(timeSpan, interval, rxTestScheduler));\n\n      expectObservable(result).toBe(expected, expectedValues);\n      expectSubscriptions(source.subscriptions).toBe(subs);\n    });\n  });\n\n  it('should handle source Observable which eventually emits an error', () => {\n    rxTestScheduler.run(({ hot, cold, time, expectSubscriptions, expectObservable }) => {\n      const source = hot('--1--2--^--a--b--c--d--e--f--g--h--#');\n      const subs = '              ^--------------------------!';\n      const timeSpan = time('     -----|                      ');\n      const interval = time('     ----------|                 ');\n      //  10 frames               0---------1---------2------|\n      //  5                       ----|\n      //  5                                 ----|\n      //  5                                           ----|\n      const expected = '          x---------y---------z------#';\n      const x = cold('            ---a-|                      ');\n      const y = cold('                      --d--(e|)         ');\n      const z = cold('                                -g--h|  ');\n      const values = { x, y, z };\n\n      const result = source.pipe(windowTime(timeSpan, interval, rxTestScheduler));\n\n      expectObservable(result).toBe(expected, values);\n      expectSubscriptions(source.subscriptions).toBe(subs);\n    });\n  });\n\n  it('should emit windows given windowTimeSpan and windowCreationInterval, but outer is unsubscribed early', () => {\n    rxTestScheduler.run(({ hot, cold, time, expectSubscriptions, expectObservable }) => {\n      const source = hot('--1--2--^--a--b--c--d--e--f--g--h--|');\n      const subs = '              ^----------!                ';\n      const timeSpan = time('     -----|                      ');\n      const interval = time('     ----------|                 ');\n      //  10 frames               0---------1---------2------|\n      //  5                       ----|\n      //  5                                 ----|\n      //  5                                           ----|\n      const expected = '          x---------y-                ';\n      const x = cold('            ---a-|                      ');\n      const y = cold('                      --                ');\n      const unsub = '             -----------!                ';\n      const values = { x, y };\n\n      const result = source.pipe(windowTime(timeSpan, interval, rxTestScheduler));\n\n      expectObservable(result, unsub).toBe(expected, values);\n      expectSubscriptions(source.subscriptions).toBe(subs);\n    });\n  });\n\n  it('should not break unsubscription chains when result is unsubscribed explicitly', () => {\n    rxTestScheduler.run(({ hot, cold, time, expectSubscriptions, expectObservable }) => {\n      const source = hot('--1--2--^--a--b--c--d--e--f--g--h--|');\n      const sourcesubs = '        ^-------------!             ';\n      const timeSpan = time('     -----|                      ');\n      const interval = time('     ----------|                 ');\n      //  10 frames               0---------1---------2------|\n      //  5                       ----|\n      //  5                                 ----|\n      //  5                                           ----|\n      const expected = '          x---------y----             ';\n      const x = cold('            ---a-|                      ');\n      const y = cold('                      --d--             ');\n      const unsub = '             --------------!             ';\n      const values = { x, y };\n\n      const result = source.pipe(\n        mergeMap((x: string) => of(x)),\n        windowTime(timeSpan, interval, rxTestScheduler),\n        mergeMap((x: Observable<string>) => of(x))\n      );\n\n      expectObservable(result, unsub).toBe(expected, values);\n      expectSubscriptions(source.subscriptions).toBe(sourcesubs);\n    });\n  });\n\n  it('should not error if maxWindowSize is hit while nexting to other windows.', () => {\n    rxTestScheduler.run(({ cold, time, expectObservable }) => {\n      const source = cold('                ----a---b---c---d---e---f---g---h---i---j---');\n      const windowTimeSpan = time('        ------------|                               ');\n      const windowCreationInterval = time('--------|                                   ');\n      const maxWindowSize = 4;\n      const a = cold('                     ----a---b---|                               ');\n      //                                   ------------|\n      const b = cold('                             b---c---d---(e|)');\n      const c = cold('                                     ----e---f---(g|)');\n      const d = cold('                                             ----g---h---(i|)    ');\n      const e = cold('                                                     ----i---j---');\n      const f = cold('                                                             ----');\n      const expected = '                   a-------b-------c-------d-------e-------f---';\n      const killSub = '                    ------------------------------------------! ';\n      const values = { a, b, c, d, e, f };\n      const result = source.pipe(windowTime(windowTimeSpan, windowCreationInterval, maxWindowSize, rxTestScheduler));\n      expectObservable(result, killSub).toBe(expected, values);\n    });\n  });\n});\n"
  },
  {
    "path": "packages/rxjs/spec/operators/windowToggle-spec.ts",
    "content": "import { expect } from 'chai';\nimport type { Observable} from 'rxjs';\nimport { NEVER, of, EMPTY } from 'rxjs';\nimport { windowToggle, tap, mergeMap } from 'rxjs/operators';\nimport { TestScheduler } from 'rxjs/testing';\nimport { observableMatcher } from '../helpers/observableMatcher';\n\n/** @test {windowToggle} */\ndescribe('windowToggle', () => {\n  let rxTestScheduler: TestScheduler;\n\n  beforeEach(() => {\n    rxTestScheduler = new TestScheduler(observableMatcher);\n  });\n\n  it('should emit windows governed by openings and closings', () => {\n    rxTestScheduler.run(({ hot, cold, expectObservable, expectSubscriptions }) => {\n      const e2 = cold('         ----w--------w--------w--|');\n      const e2subs = '          ^------------------------!';\n      const e3 = cold('             -----x                ');\n      //                                     -----x\n      //                                              -----x\n      const e3subs = [\n        '                       ----^----!                ',\n        '                       -------------^----!       ',\n        '                       ----------------------^--!',\n      ];\n      const e1 = hot('  --1--2--^-a--b--c--d--e--f--g--h-|');\n      const e1subs = '          ^------------------------!';\n      const expected = '        ----x--------y--------z--|';\n      const x = cold('              -b--c|                ');\n      const y = cold('                       -e--f|       ');\n      const z = cold('                                -h-|');\n      const values = { x, y, z };\n\n      const result = e1.pipe(windowToggle(e2, () => e3));\n\n      expectObservable(result).toBe(expected, values);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n      expectSubscriptions(e3.subscriptions).toBe(e3subs);\n    });\n  });\n\n  it('should emit windows that are opened by an observable from the first argument and closed by an observable returned by the function in the second argument', () => {\n    rxTestScheduler.run(({ hot, cold, expectObservable, expectSubscriptions }) => {\n      const e2 = cold('       --------x-------x-------x--|');\n      const e2subs = '        ^--------------------------!';\n      const e3 = cold('               ----------(x|)      ');\n      //                                      ----------(x|)\n      //                                              ----------(x|)\n      const e3subs = [\n        '                     --------^---------!         ',\n        '                     ----------------^---------! ',\n        '                     ------------------------^--!',\n      ];\n\n      const e1 = hot('--1--2--^--a--b--c--d--e--f--g--h--|');\n      const e1subs = '        ^--------------------------!';\n      const expected = '      --------x-------y-------z--|';\n      const x = cold('                -c--d--e--(f|)      ');\n      const y = cold('                        --f--g--h-| ');\n      const z = cold('                                ---|');\n      const values = { x, y, z };\n\n      const source = e1.pipe(\n        windowToggle(e2, (value: string) => {\n          expect(value).to.equal('x');\n          return e3;\n        })\n      );\n\n      expectObservable(source).toBe(expected, values);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n      expectSubscriptions(e3.subscriptions).toBe(e3subs);\n    });\n  });\n\n  it('should emit windows using varying cold closings', () => {\n    rxTestScheduler.run(({ hot, cold, expectObservable, expectSubscriptions }) => {\n      const e2 = cold('    --x-----------y--------z---|            ');\n      const e2subs = '     ^--------------------------!            ';\n      const close = [\n        cold('               ---------------s--|                   '),\n        cold('                           ----(s|)                  '),\n        cold('                                  ---------------(s|)'),\n      ];\n      const closeSubs = [\n        '                  --^--------------!                      ',\n        '                  --------------^---!                     ',\n        '                  -----------------------^-----------!    ',\n      ];\n\n      const e1 = hot('--a--^---b---c---d---e---f---g---h------|    ');\n      const e1subs = '     ^----------------------------------!    ';\n      const expected = '   --x-----------y--------z-----------|    ';\n      const x = cold('       --b---c---d---e|                      ');\n      const y = cold('                   --e-|                     ');\n      const z = cold('                            -g---h------|    ');\n      const values = { x, y, z };\n\n      let i = 0;\n      const result = e1.pipe(windowToggle(e2, () => close[i++]));\n\n      expectObservable(result).toBe(expected, values);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n      expectSubscriptions(close[0].subscriptions).toBe(closeSubs[0]);\n      expectSubscriptions(close[1].subscriptions).toBe(closeSubs[1]);\n      expectSubscriptions(close[2].subscriptions).toBe(closeSubs[2]);\n    });\n  });\n\n  it('should emit windows using varying hot closings', () => {\n    rxTestScheduler.run(({ hot, cold, expectObservable, expectSubscriptions }) => {\n      const e2 = cold('    --x-----------y--------z---|           ');\n      const e2subs = '     ^--------------------------!           ';\n      const closings = [\n        hot('          -1--^----------------s-|                   '),\n        hot('              -----3----4-------(s|)                 '),\n        hot('              -------3----4-------5----------------s|'),\n      ];\n      const closingSubs = [\n        '                  --^--------------!                     ',\n        '                  --------------^---!                    ',\n        '                  -----------------------^-----------!   ',\n      ];\n\n      const e1 = hot('--a--^---b---c---d---e---f---g---h------|   ');\n      const e1subs = '     ^----------------------------------!   ';\n      const expected = '   --x-----------y--------z-----------|   ';\n      const x = cold('       --b---c---d---e|                     ');\n      const y = cold('                   --e-|                    ');\n      const z = cold('                            -g---h------|   ');\n      const values = { x, y, z };\n\n      let i = 0;\n      const result = e1.pipe(windowToggle(e2, () => closings[i++]));\n\n      expectObservable(result).toBe(expected, values);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n      expectSubscriptions(closings[0].subscriptions).toBe(closingSubs[0]);\n      expectSubscriptions(closings[1].subscriptions).toBe(closingSubs[1]);\n      expectSubscriptions(closings[2].subscriptions).toBe(closingSubs[2]);\n    });\n  });\n\n  it('should emit windows using varying empty delayed closings', () => {\n    rxTestScheduler.run(({ hot, cold, expectObservable, expectSubscriptions }) => {\n      const e2 = cold('    --x-----------y--------z---|           ');\n      const e2subs = '     ^--------------------------!           ';\n      const close = [\n        cold('               ---------------|                     '),\n        cold('                           ----|                    '),\n        cold('                                    ---------------|'),\n      ];\n\n      const e1 = hot('--a--^---b---c---d---e---f---g---h------|   ');\n      const e1subs = '     ^----------------------------------!   ';\n      const expected = '   --x-----------y--------z-----------|   ';\n      const x = cold('       --b---c---d---e---f---g---h------|   ');\n      const y = cold('                   --e---f---g---h------|   ');\n      const z = cold('                            -g---h------|   ');\n      const values = { x, y, z };\n\n      let i = 0;\n      const result = e1.pipe(windowToggle(e2, () => close[i++]));\n\n      expectObservable(result).toBe(expected, values);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should emit windows using varying cold closings, outer unsubscribed early', () => {\n    rxTestScheduler.run(({ hot, cold, expectObservable, expectSubscriptions }) => {\n      const e2 = cold('    --x-----------y--------z---|              ');\n      const e2subs = '     ^----------------!                        ';\n      const close = [\n        cold('               -------------s---|                      '),\n        cold('                           -----(s|)                   '),\n        cold('                                    ---------------(s|)'),\n      ];\n      const closeSubs = [\n        '                  --^------------!                          ',\n        '                  --------------^--!                        ',\n      ];\n\n      const e1 = hot('--a--^---b---c---d---e---f---g---h------|      ');\n      const e1subs = '     ^----------------!                        ';\n      const expected = '   --x-----------y---                        ';\n      const x = cold('       --b---c---d--|                          ');\n      const y = cold('                   --e-                        ');\n      const unsub = '      -----------------!                        ';\n      const values = { x, y };\n\n      let i = 0;\n      const result = e1.pipe(windowToggle(e2, () => close[i++]));\n\n      expectObservable(result, unsub).toBe(expected, values);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n      expectSubscriptions(close[0].subscriptions).toBe(closeSubs[0]);\n      expectSubscriptions(close[1].subscriptions).toBe(closeSubs[1]);\n      expectSubscriptions(close[2].subscriptions).toBe([]);\n    });\n  });\n\n  it('should not break unsubscription chains when result is unsubscribed explicitly', () => {\n    rxTestScheduler.run(({ hot, cold, expectObservable, expectSubscriptions }) => {\n      const e2 = cold('    --x-----------y--------z---|              ');\n      const e2subs = '     ^--------------!                          ';\n      const close = [\n        cold('               ---------------s--|                     '),\n        cold('                           ----(s|)                    '),\n        cold('                                    ---------------(s|)'),\n      ];\n      const closeSubs = [\n        '                  --^------------!                          ',\n        '                  --------------^!                          ',\n      ];\n      const e1 = hot('--a--^---b---c---d---e---f---g---h------|      ');\n      const e1subs = '     ^--------------!                          ';\n      const expected = '   --x-----------y-                          ';\n      const x = cold('       --b---c---d---                          ');\n      const y = cold('                   --                          ');\n      const unsub = '      ---------------!                          ';\n      const values = { x, y };\n\n      let i = 0;\n      const result = e1.pipe(\n        mergeMap((x) => of(x)),\n        windowToggle(e2, () => close[i++]),\n        mergeMap((x) => of(x))\n      );\n\n      expectObservable(result, unsub).toBe(expected, values);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n      expectSubscriptions(close[0].subscriptions).toBe(closeSubs[0]);\n      expectSubscriptions(close[1].subscriptions).toBe(closeSubs[1]);\n    });\n  });\n\n  it('should close window Subjects if the outer is unsubscribed early', () => {\n    rxTestScheduler.run(({ hot, cold, expectObservable, expectSubscriptions, time }) => {\n      const open = cold(' o-------------------------|');\n      const e1 = hot('    --a--b--c--d--e--f--g--h--|');\n      const e1subs = '    ^--------!                 ';\n      const expected = '  x---------                 ';\n      const x = cold('    --a--b--c-                 ');\n      const unsub = '     ---------!                 ';\n      const late = time(' ---------------|           ');\n      const values = { x };\n\n      let window: Observable<string>;\n      const result = e1.pipe(\n        windowToggle(open, () => NEVER),\n        tap((w) => {\n          window = w;\n        })\n      );\n\n      expectObservable(result, unsub).toBe(expected, values);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      rxTestScheduler.schedule(() => {\n        const subscription = window.subscribe();\n        expect(subscription.closed).to.be.true;\n      }, late);\n    });\n  });\n\n  it('should propagate error thrown from closingSelector', () => {\n    rxTestScheduler.run(({ hot, cold, expectObservable, expectSubscriptions }) => {\n      const e2 = cold('    --x-----------y--------z---|              ');\n      const e2subs = '     ^-------------!                           ';\n      const close = [\n        cold('               ---------------s--|                     '),\n        cold('                           ----(s|)                    '),\n        cold('                                    ---------------(s|)'),\n      ];\n\n      const e1 = hot('--a--^---b---c---d---e---f---g---h------|      ');\n      const e1subs = '     ^-------------!                           ';\n      const expected = '   --x-----------#----                       ';\n      const x = cold('       --b---c---d-#                           ');\n      const values = { x: x };\n\n      let i = 0;\n      const result = e1.pipe(\n        windowToggle(e2, () => {\n          if (i === 1) {\n            throw 'error';\n          }\n          return close[i++];\n        })\n      );\n\n      expectObservable(result).toBe(expected, values);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should propagate error emitted from a closing', () => {\n    rxTestScheduler.run(({ hot, cold, expectObservable, expectSubscriptions }) => {\n      const e2 = cold('    --x-----------y--------z---|        ');\n      const e2subs = '     ^-------------!                     ';\n      // prettier-ignore\n      const close = [\n        cold('               ---------------s--|               '),\n        cold('                           #                     ')\n      ];\n\n      const e1 = hot('--a--^---b---c---d---e---f---g---h------|');\n      const e1subs = '     ^-------------!                     ';\n      const expected = '   --x-----------(y#)                  ';\n      const x = cold('       --b---c---d-#                     ');\n      const y = cold('                   #                     ');\n      const values = { x, y };\n\n      let i = 0;\n      const result = e1.pipe(windowToggle(e2, () => close[i++]));\n\n      expectObservable(result).toBe(expected, values);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should propagate error emitted late from a closing', () => {\n    rxTestScheduler.run(({ hot, cold, expectObservable, expectSubscriptions }) => {\n      const e2 = cold('    --x-----------y--------z---|        ');\n      const e2subs = '     ^------------------!                ';\n      // prettier-ignore\n      const close = [\n        cold('               ---------------s--|               '),\n        cold('                           -----#                ')\n      ];\n\n      const e1 = hot('--a--^---b---c---d---e---f---g---h------|');\n      const e1subs = '     ^------------------!                ';\n      const expected = '   --x-----------y----#                ';\n      const x = cold('       --b---c---d---e|                  ');\n      const y = cold('                   --e--#                ');\n      const values = { x, y };\n\n      let i = 0;\n      const result = e1.pipe(windowToggle(e2, () => close[i++]));\n\n      expectObservable(result).toBe(expected, values);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should handle errors', () => {\n    rxTestScheduler.run(({ hot, cold, expectObservable, expectSubscriptions }) => {\n      const e2 = cold('    --x-----------y--------z---|        ');\n      const e2subs = '     ^------------------!                ';\n      // prettier-ignore\n      const close = [\n        cold('               ---------------s--|               '),\n        cold('                           -------s|             ')\n      ];\n\n      const e1 = hot('--a--^---b---c---d---e--#                ');\n      const e1subs = '     ^------------------!                ';\n      const expected = '   --x-----------y----#                ';\n      const x = cold('       --b---c---d---e|                  ');\n      const y = cold('                   --e--#                ');\n      const values = { x, y };\n\n      let i = 0;\n      const result = e1.pipe(windowToggle(e2, () => close[i++]));\n\n      expectObservable(result).toBe(expected, values);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should handle empty source', () => {\n    rxTestScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e2 = cold('--o-----|');\n      const e2subs = '   (^!)';\n      const e3 = cold('  -----c--|');\n\n      const e1 = cold('  |');\n      const e1subs = '   (^!)';\n      const expected = ' |';\n\n      const result = e1.pipe(windowToggle(e2, () => e3));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should handle throw', () => {\n    rxTestScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e2 = cold(' --o-----|');\n      const e2subs = '  (^!)';\n      const e3 = cold(' -----c--|');\n\n      const e1 = cold(' #');\n      const e1subs = '  (^!)';\n      const expected = '#';\n\n      const result = e1.pipe(windowToggle(e2, () => e3));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should handle never', () => {\n    rxTestScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => {\n      const e2 = cold(' --o-----o------o-----o---o-----|             ');\n      const e2subs = '  ^------------------------------!             ';\n      const e3 = cold('   --c-|                                      ');\n\n      const e1 = hot('  -                                            ');\n      const e1subs = '  ^-------------------------------------------!';\n      const expected = '--u-----v------x-----y---z-------------------';\n      const u = cold('    --|                                        ');\n      const v = cold('          --|                                  ');\n      const x = cold('                 --|                           ');\n      const y = cold('                       --|                     ');\n      const z = cold('                           --|                 ');\n      const unsub = '   --------------------------------------------!';\n      const values = { u: u, v: v, x, y, z };\n\n      const result = e1.pipe(windowToggle(e2, () => e3));\n\n      expectObservable(result, unsub).toBe(expected, values);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should handle a never opening Observable', () => {\n    rxTestScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => {\n      const e2 = cold('    -                                   ');\n      const e2subs = '     ^----------------------------------!';\n      const e3 = cold('    --c-|                               ');\n\n      const e1 = hot('--a--^---b---c---d---e---f---g---h------|');\n      const e1subs = '     ^----------------------------------!';\n      const expected = '   -----------------------------------|';\n\n      const result = e1.pipe(windowToggle(e2, () => e3));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should handle a never closing Observable', () => {\n    rxTestScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => {\n      const e2 = cold('    ---o---------------o-----------|    ');\n      const e2subs = '     ^------------------------------!    ';\n      const e3 = cold('       -                                ');\n      //                                      -\n\n      const e1 = hot('--a--^---b---c---d---e---f---g---h------|');\n      const e1subs = '     ^----------------------------------!';\n      const expected = '   ---x---------------y---------------|';\n      const x = cold('        -b---c---d---e---f---g---h------|');\n      const y = cold('                        -f---g---h------|');\n      const values = { x, y };\n\n      const result = e1.pipe(windowToggle(e2, () => e3));\n\n      expectObservable(result).toBe(expected, values);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should handle opening Observable that just throws', () => {\n    rxTestScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => {\n      const e2 = cold('    #                                   ');\n      const e2subs = '     (^!)                                ';\n      const e3 = cold('    --c-|                               ');\n      const subs = '       (^!)                                ';\n\n      const e1 = hot('--a--^---b---c---d---e---f---g---h------|');\n      const e1subs = '     (^!)                                ';\n      const expected = '   #                                   ';\n\n      const result = e1.pipe(windowToggle(e2, () => e3));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(subs);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should handle empty closing observable', () => {\n    rxTestScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => {\n      const e2 = cold('    ---o---------------o-----------|    ');\n      const e2subs = '     ^------------------------------!    ';\n      const e3 = EMPTY;\n\n      const e1 = hot('--a--^---b---c---d---e---f---g---h------|');\n      const e1subs = '     ^----------------------------------!';\n      const expected = '   ---x---------------y---------------|';\n      const x = cold('        -b---c---d---e---f---g---h------|');\n      const y = cold('                        -f---g---h------|');\n      const values = { x, y };\n\n      const result = e1.pipe(windowToggle(e2, () => e3));\n\n      expectObservable(result).toBe(expected, values);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n});\n"
  },
  {
    "path": "packages/rxjs/spec/operators/windowWhen-spec.ts",
    "content": "import { windowWhen, mergeMap } from 'rxjs/operators';\nimport type { Observable} from 'rxjs';\nimport { of } from 'rxjs';\nimport { TestScheduler } from 'rxjs/testing';\nimport { observableMatcher } from '../helpers/observableMatcher';\n\n/** @test {windowWhen} */\ndescribe('windowWhen', () => {\n  let rxTestScheduler: TestScheduler;\n\n  beforeEach(() => {\n    rxTestScheduler = new TestScheduler(observableMatcher);\n  });\n\n  it('should emit windows that close and reopen', () => {\n    rxTestScheduler.run(({ hot, cold, expectObservable, expectSubscriptions }) => {\n      const e2 = cold('    -----------x|               ');\n      //                              -----------x|\n      //                                         -----------x|\n      const e2subs = [\n        '                  ^----------!                ',\n        '                  -----------^----------!     ',\n        '                  ----------------------^----!',\n      ];\n      const e1 = hot('--a--^--b--c--d--e--f--g--h--i--|');\n      const e1subs = '     ^--------------------------!';\n      const expected = '   a----------b----------c----|';\n\n      const a = cold('     ---b--c--d-|                ');\n      const b = cold('                -e--f--g--h|     ');\n      const c = cold('                           --i--|');\n      const values = { a: a, b: b, c: c };\n\n      const source = e1.pipe(windowWhen(() => e2));\n\n      expectObservable(source).toBe(expected, values);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should emit windows using varying cold closings', () => {\n    rxTestScheduler.run(({ hot, cold, expectObservable, expectSubscriptions }) => {\n      const closings = [\n        cold('               -----------------s--|                    '),\n        cold('                                -----(s|)               '),\n        cold('                                     ---------------(s|)'),\n      ];\n      const closeSubs = [\n        '                    ^----------------!                       ',\n        '                    -----------------^----!                  ',\n        '                    ----------------------^------------!     ',\n      ];\n      const e1 = hot('  --a--^---b---c---d---e---f---g---h------|     ');\n      const e1subs = '       ^----------------------------------!     ';\n      const expected = '     x----------------y----z------------|     ';\n\n      const x = cold('       ----b---c---d---e|                       ');\n      const y = cold('                        ---f-|                  ');\n      const z = cold('                             --g---h------|     ');\n      const values = { x: x, y: y, z: z };\n\n      let i = 0;\n      const result = e1.pipe(windowWhen(() => closings[i++]));\n\n      expectObservable(result).toBe(expected, values);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(closings[0].subscriptions).toBe(closeSubs[0]);\n      expectSubscriptions(closings[1].subscriptions).toBe(closeSubs[1]);\n      expectSubscriptions(closings[2].subscriptions).toBe(closeSubs[2]);\n    });\n  });\n\n  it('should emit windows using varying hot closings', () => {\n    rxTestScheduler.run(({ hot, cold, expectObservable, expectSubscriptions }) => {\n      const closings = [\n        hot('            -1--^----------------s-|                   '),\n        hot('                -----3----4-----------(s|)             '),\n        hot('                -------3----4-------5----------------s|'),\n      ];\n      const closeSubs = [\n        '                    ^----------------!                     ',\n        '                    -----------------^----!                ',\n        '                    ----------------------^------------!   ',\n      ];\n      const e1 = hot('  --a--^---b---c---d---e---f---g---h------|   ');\n      const subs = '         ^----------------------------------!   ';\n      const expected = '     x----------------y----z------------|   ';\n\n      const x = cold('       ----b---c---d---e|                     ');\n      const y = cold('                        ---f-|                ');\n      const z = cold('                             --g---h------|   ');\n      const values = { x: x, y: y, z: z };\n\n      let i = 0;\n      const result = e1.pipe(windowWhen(() => closings[i++]));\n\n      expectObservable(result).toBe(expected, values);\n      expectSubscriptions(e1.subscriptions).toBe(subs);\n      expectSubscriptions(closings[0].subscriptions).toBe(closeSubs[0]);\n      expectSubscriptions(closings[1].subscriptions).toBe(closeSubs[1]);\n      expectSubscriptions(closings[2].subscriptions).toBe(closeSubs[2]);\n    });\n  });\n\n  it('should not emit windows using varying empty delayed closings', () => {\n    rxTestScheduler.run(({ hot, cold, expectObservable, expectSubscriptions }) => {\n      const closings = [\n        cold('             -----------------|                    '),\n        cold('                              -----|               '),\n        cold('                                   ---------------|'),\n      ];\n      const closeSubs = [\n        '                  ^----------------!                    ',\n        '                                                        ',\n        '                                                        ',\n      ];\n      const e1 = hot('--a--^---b---c---d---e---f---g---h------|  ');\n      const e1subs = '     ^----------------------------------!  ';\n      const expected = '   x----------------------------------|  ';\n\n      const x = cold('     ----b---c---d---e---f---g---h------|  ');\n      const values = { x: x };\n\n      let i = 0;\n      const result = e1.pipe(windowWhen(() => closings[i++]));\n\n      expectObservable(result).toBe(expected, values);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(closings[0].subscriptions).toBe(closeSubs[0]);\n      expectSubscriptions(closings[1].subscriptions).toBe(closeSubs[1]);\n      expectSubscriptions(closings[2].subscriptions).toBe(closeSubs[2]);\n    });\n  });\n\n  it('should emit windows using varying cold closings, outer unsubscribed early', () => {\n    rxTestScheduler.run(({ hot, cold, expectObservable, expectSubscriptions }) => {\n      const closings = [\n        cold('               -----------------s--|               '),\n        cold('                                ---------(s|)      '),\n      ];\n      const closeSubs = [\n        '                    ^----------------!                  ',\n        '                    -----------------^---!              ',\n      ];\n      const e1 = hot('  --a--^---b---c---d---e---f---g---h------|');\n      const e1subs = '       ^--------------------!              ';\n      const expected = '     x----------------y----              ';\n      const unsub = '        ---------------------!              ';\n\n      const x = cold('       ----b---c---d---e|                  ');\n      const y = cold('                        ---f-              ');\n      const values = { x: x, y: y };\n\n      let i = 0;\n      const result = e1.pipe(windowWhen(() => closings[i++]));\n\n      expectObservable(result, unsub).toBe(expected, values);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(closings[0].subscriptions).toBe(closeSubs[0]);\n      expectSubscriptions(closings[1].subscriptions).toBe(closeSubs[1]);\n    });\n  });\n\n  it('should not break unsubscription chain when unsubscribed explicitly', () => {\n    rxTestScheduler.run(({ hot, cold, expectObservable, expectSubscriptions }) => {\n      const closings = [\n        cold('               -----------------s--|               '),\n        cold('                                ---------(s|)      '),\n      ];\n      const closeSubs = [\n        '                    ^----------------!                  ',\n        '                    -----------------^---!              ',\n      ];\n      const e1 = hot('  --a--^---b---c---d---e---f---g---h------|');\n      const e1subs = '       ^--------------------!              ';\n      const expected = '     x----------------y----              ';\n      const unsub = '        ---------------------!              ';\n\n      const x = cold('       ----b---c---d---e|                  ');\n      const y = cold('                        ---f-              ');\n      const values = { x: x, y: y };\n\n      let i = 0;\n      const result = e1.pipe(\n        mergeMap((x: string) => of(x)),\n        windowWhen(() => closings[i++]),\n        mergeMap((x: Observable<string>) => of(x))\n      );\n\n      expectObservable(result, unsub).toBe(expected, values);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(closings[0].subscriptions).toBe(closeSubs[0]);\n      expectSubscriptions(closings[1].subscriptions).toBe(closeSubs[1]);\n    });\n  });\n\n  it('should propagate error thrown from closingSelector', () => {\n    rxTestScheduler.run(({ hot, cold, expectObservable, expectSubscriptions }) => {\n      const closings = [\n        cold('                 -----------------s--|                    '),\n        cold('                                  -----(s|)               '),\n        cold('                                       ---------------(s|)'),\n      ];\n      const closeSubs = ['     ^----------------!                       '];\n      const e1 = hot('    --a--^---b---c---d---e---f---g---h------|     ');\n      const e1subs = '         ^----------------!                       ';\n      const expected = '       x----------------(y#)                    ';\n\n      const x = cold('         ----b---c---d---e|                       ');\n      const y = cold('                          #                       ');\n      const values = { x: x, y: y };\n\n      let i = 0;\n      const result = e1.pipe(\n        windowWhen(() => {\n          if (i === 1) {\n            throw 'error';\n          }\n          return closings[i++];\n        })\n      );\n\n      expectObservable(result).toBe(expected, values);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(closings[0].subscriptions).toBe(closeSubs[0]);\n    });\n  });\n\n  it('should propagate error emitted from a closing', () => {\n    rxTestScheduler.run(({ hot, cold, expectObservable, expectSubscriptions }) => {\n      const closings = [\n        cold('               -----------------s--|               '),\n        cold('                                #                  '),\n      ];\n      const closeSubs = [\n        '                    ^----------------!                  ',\n        '                    -----------------(^!)               ',\n      ];\n      const e1 = hot('  --a--^---b---c---d---e---f---g---h------|');\n      const e1subs = '       ^----------------!                  ';\n      const expected = '     x----------------(y#)               ';\n\n      const x = cold('       ----b---c---d---e|                  ');\n      const y = cold('                        #                  ');\n      const values = { x: x, y: y };\n\n      let i = 0;\n      const result = e1.pipe(windowWhen(() => closings[i++]));\n\n      expectObservable(result).toBe(expected, values);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(closings[0].subscriptions).toBe(closeSubs[0]);\n      expectSubscriptions(closings[1].subscriptions).toBe(closeSubs[1]);\n    });\n  });\n\n  it('should propagate error emitted late from a closing', () => {\n    rxTestScheduler.run(({ hot, cold, expectObservable, expectSubscriptions }) => {\n      const closings = [\n        cold('               -----------------s--|               '),\n        cold('                                -----#             '),\n      ];\n      const closeSubs = [\n        '                    ^----------------!                  ',\n        '                    -----------------^----!             ',\n      ];\n      const e1 = hot('  --a--^---b---c---d---e---f---g---h------|');\n      const e1subs = '       ^---------------------!             ';\n      const expected = '     x----------------y----#             ';\n\n      const x = cold('       ----b---c---d---e|                  ');\n      const y = cold('                        ---f-#             ');\n      const values = { x: x, y: y };\n\n      let i = 0;\n      const result = e1.pipe(windowWhen(() => closings[i++]));\n\n      expectObservable(result).toBe(expected, values);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(closings[0].subscriptions).toBe(closeSubs[0]);\n      expectSubscriptions(closings[1].subscriptions).toBe(closeSubs[1]);\n    });\n  });\n\n  it('should propagate errors emitted from the source', () => {\n    rxTestScheduler.run(({ hot, cold, expectObservable, expectSubscriptions }) => {\n      // prettier-ignore\n      const closings = [\n        cold('               -----------------s--|       '),\n        cold('                                -------(s|)'),\n      ];\n      // prettier-ignore\n      const closeSubs = [\n        '                    ^----------------!          ',\n        '                    -----------------^----!     ',\n      ];\n      const e1 = hot('  --a--^---b---c---d---e---f-#     ');\n      const e1subs = '       ^---------------------!     ';\n      const expected = '     x----------------y----#     ';\n\n      const x = cold('       ----b---c---d---e|          ');\n      const y = cold('                        ---f-#     ');\n      const values = { x: x, y: y };\n\n      let i = 0;\n      const result = e1.pipe(windowWhen(() => closings[i++]));\n\n      expectObservable(result).toBe(expected, values);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(closings[0].subscriptions).toBe(closeSubs[0]);\n      expectSubscriptions(closings[1].subscriptions).toBe(closeSubs[1]);\n    });\n  });\n\n  it('should handle empty source', () => {\n    rxTestScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e2 = cold(' -----c--|');\n      const e2subs = '  (^!)     ';\n      const e1 = cold(' |        ');\n      const e1subs = '  (^!)     ';\n      const expected = '(w|)     ';\n      const win = cold('|        ');\n      const values = { w: win };\n\n      const result = e1.pipe(windowWhen(() => e2));\n\n      expectObservable(result).toBe(expected, values);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should handle a never source', () => {\n    rxTestScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e2 = cold(' -----c--|         ');\n      //                     -----c--|\n      //                        -----c--|\n      //                             -----\n      const e2subs = [\n        '               ^----!            ',\n        '               -----^----!       ',\n        '               ----------^----!  ',\n        '               ---------------^-!',\n      ];\n      const e1 = cold(' -                 ');\n      const e1subs = '  ^----------------!';\n      const expected = 'a----b----c----d--';\n      const unsub = '   -----------------!';\n\n      const win = cold('-----|');\n      //                     -----|\n      //                          -----|\n      const d = cold('                 ---');\n      const values = { a: win, b: win, c: win, d: d };\n\n      const result = e1.pipe(windowWhen(() => e2));\n\n      expectObservable(result, unsub).toBe(expected, values);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should handle throw', () => {\n    rxTestScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e2 = cold(' -----c--|');\n      const e2subs = '  (^!)     ';\n      const e1 = cold(' #        ');\n      const e1subs = '  (^!)     ';\n      const expected = '(w#)     ';\n      const win = cold('#        ');\n      const values = { w: win };\n\n      const result = e1.pipe(windowWhen(() => e2));\n\n      expectObservable(result).toBe(expected, values);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should handle a never closing Observable', () => {\n    rxTestScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => {\n      const e2 = cold('      -                                  ');\n      const e2subs = '       ^----------------------------------!';\n      const e1 = hot('  --a--^---b---c---d---e---f---g---h------|');\n      const e1subs = '       ^----------------------------------!';\n      const expected = '     x----------------------------------|';\n\n      const x = cold('       ----b---c---d---e---f---g---h------|');\n      const values = { x: x };\n\n      const result = e1.pipe(windowWhen(() => e2));\n\n      expectObservable(result).toBe(expected, values);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should handle a throw closing Observable', () => {\n    rxTestScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => {\n      const e2 = cold('      #                                   ');\n      const e2subs = '       (^!)                                ';\n      const e1 = hot('  --a--^---b---c---d---e---f---g---h------|');\n      const e1subs = '       (^!)                                ';\n      const expected = '     (x#)                                ';\n\n      const x = cold('       #                                   ');\n      const values = { x: x };\n\n      const result = e1.pipe(windowWhen(() => e2));\n\n      expectObservable(result).toBe(expected, values);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n});\n"
  },
  {
    "path": "packages/rxjs/spec/operators/withLatestFrom-spec.ts",
    "content": "import { expect } from 'chai';\nimport { lowerCaseO } from '../helpers/test-helper';\nimport { withLatestFrom, mergeMap, delay } from 'rxjs/operators';\nimport { of } from 'rxjs';\nimport { TestScheduler } from 'rxjs/testing';\nimport { observableMatcher } from '../helpers/observableMatcher';\n\n/** @test {withLatestFrom} */\ndescribe('withLatestFrom', () => {\n  let rxTestScheduler: TestScheduler;\n\n  beforeEach(() => {\n    rxTestScheduler = new TestScheduler(observableMatcher);\n  });\n\n  it('should combine events from cold observables', () => {\n    rxTestScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const e2 = cold(' --1--2-3-4---|   ');\n      const e2subs = '  ^------------!   ';\n      const e1 = cold(' -a--b-----c-d-e-|');\n      const e1subs = '  ^---------------!';\n      const expected = '----B-----C-D-E-|';\n\n      const result = e1.pipe(withLatestFrom(e2, (a: string, b: string) => String(a) + String(b)));\n\n      expectObservable(result).toBe(expected, { B: 'b1', C: 'c4', D: 'd4', E: 'e4' });\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n    });\n  });\n\n  it('should merge the value with the latest values from the other observables into arrays', () => {\n    rxTestScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e2 = hot('  --e--^-f---g---h------|');\n      const e2subs = '       ^-------------!   ';\n      const e3 = hot('  --i--^-j---k---l------|');\n      const e3subs = '       ^-------------!   ';\n      const e1 = hot('  --a--^---b---c---d-|   ');\n      const e1subs = '       ^-------------!   ';\n      const expected = '     ----x---y---z-|   ';\n      const values = {\n        x: ['b', 'f', 'j'],\n        y: ['c', 'g', 'k'],\n        z: ['d', 'h', 'l'],\n      };\n\n      const result = e1.pipe(withLatestFrom(e2, e3));\n\n      expectObservable(result).toBe(expected, values);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n      expectSubscriptions(e3.subscriptions).toBe(e3subs);\n    });\n  });\n\n  it('should merge the value with the latest values from the other observables into arrays and a project argument', () => {\n    rxTestScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e2 = hot('  --e--^-f---g---h------|');\n      const e2subs = '       ^-------------!   ';\n      const e3 = hot('  --i--^-j---k---l------|');\n      const e3subs = '       ^-------------!   ';\n      const e1 = hot('  --a--^---b---c---d-|   ');\n      const e1subs = '       ^-------------!   ';\n      const expected = '     ----x---y---z-|   ';\n      const values = {\n        x: 'bfj',\n        y: 'cgk',\n        z: 'dhl',\n      };\n      const project = (a: string, b: string, c: string) => a + b + c;\n\n      const result = e1.pipe(withLatestFrom(e2, e3, project));\n\n      expectObservable(result).toBe(expected, values);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n      expectSubscriptions(e3.subscriptions).toBe(e3subs);\n    });\n  });\n\n  it('should allow unsubscribing early and explicitly', () => {\n    rxTestScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e2 = hot('  --e--^-f---g---h------|');\n      const e2subs = '       ^----------!      ';\n      const e3 = hot('  --i--^-j---k---l------|');\n      const e3subs = '       ^----------!      ';\n      const e1 = hot('  --a--^---b---c---d-|   ');\n      const e1subs = '       ^----------!      ';\n      const expected = '     ----x---y---      ';\n      const unsub = '        -----------!      ';\n      const values = {\n        x: 'bfj',\n        y: 'cgk',\n        z: 'dhl',\n      };\n      const project = (a: string, b: string, c: string) => a + b + c;\n\n      const result = e1.pipe(withLatestFrom(e2, e3, project));\n\n      expectObservable(result, unsub).toBe(expected, values);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n      expectSubscriptions(e3.subscriptions).toBe(e3subs);\n    });\n  });\n\n  it('should not break unsubscription chains when result is unsubscribed explicitly', () => {\n    rxTestScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e2 = hot('  --e--^-f---g---h------|');\n      const e2subs = '       ^----------!      ';\n      const e3 = hot('  --i--^-j---k---l------|');\n      const e3subs = '       ^----------!      ';\n      const e1 = hot('  --a--^---b---c---d-|   ');\n      const e1subs = '       ^----------!      ';\n      const expected = '     ----x---y---      ';\n      const unsub = '        -----------!      ';\n      const values = {\n        x: 'bfj',\n        y: 'cgk',\n        z: 'dhl',\n      };\n      const project = (a: string, b: string, c: string) => a + b + c;\n\n      const result = e1.pipe(\n        mergeMap((x: string) => of(x)),\n        withLatestFrom(e2, e3, project),\n        mergeMap((x: string) => of(x))\n      );\n\n      expectObservable(result, unsub).toBe(expected, values);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n      expectSubscriptions(e3.subscriptions).toBe(e3subs);\n    });\n  });\n\n  it('should handle empty', () => {\n    rxTestScheduler.run(({ hot, cold, expectObservable, expectSubscriptions }) => {\n      const e2 = hot('  --e--^-f---g---h----|');\n      const e2subs = '       (^!)            ';\n      const e3 = hot('  --i--^-j---k---l----|');\n      const e3subs = '       (^!)            ';\n      const e1 = cold('      |               ');\n      const e1subs = '       (^!)            ';\n      const expected = '     |               '; // empty\n\n      const result = e1.pipe(withLatestFrom(e2, e3));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n      expectSubscriptions(e3.subscriptions).toBe(e3subs);\n    });\n  });\n\n  it('should handle never', () => {\n    rxTestScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => {\n      const e2 = hot('   --e--^-f---g---h----|  ');\n      const e2subs = '        ^--------------!  ';\n      const e3 = hot('   --i--^-j---k---l----|  ');\n      const e3subs = '        ^--------------!  ';\n      const e1 = cold('        -                ');\n      const e1subs = '         ^----------------';\n      const expected = '    --------------------'; // never\n\n      const result = e1.pipe(withLatestFrom(e2, e3));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n      expectSubscriptions(e3.subscriptions).toBe(e3subs);\n    });\n  });\n\n  it('should handle throw', () => {\n    rxTestScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => {\n      const e2 = hot('  --e--^-f---g---h----|');\n      const e2subs = '       (^!)            ';\n      const e3 = hot('  --i--^-j---k---l----|');\n      const e3subs = '       (^!)            ';\n      const e1 = cold('      #               ');\n      const e1subs = '       (^!)            ';\n      const expected = '     #               '; // throw\n\n      const result = e1.pipe(withLatestFrom(e2, e3));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n      expectSubscriptions(e3.subscriptions).toBe(e3subs);\n    });\n  });\n\n  it('should handle error', () => {\n    rxTestScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e2 = hot('  --e--^-f---g---h----|');\n      const e2subs = '       ^-------!       ';\n      const e3 = hot('  --i--^-j---k---l----|');\n      const e3subs = '       ^-------!       ';\n      const e1 = hot('  --a--^---b---#       ', undefined, new Error('boo-hoo'));\n      const e1subs = '       ^-------!       ';\n      const expected = '     ----x---#       '; // throw\n      const values = {\n        x: ['b', 'f', 'j'],\n      };\n\n      const result = e1.pipe(withLatestFrom(e2, e3));\n\n      expectObservable(result).toBe(expected, values, new Error('boo-hoo'));\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n      expectSubscriptions(e3.subscriptions).toBe(e3subs);\n    });\n  });\n\n  it('should handle error with project argument', () => {\n    rxTestScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e2 = hot('  --e--^-f---g---h----|');\n      const e2subs = '       ^-------!       ';\n      const e3 = hot('  --i--^-j---k---l----|');\n      const e3subs = '       ^-------!       ';\n      const e1 = hot('  --a--^---b---#       ', undefined, new Error('boo-hoo'));\n      const e1subs = '       ^-------!       ';\n      const expected = '     ----x---#       '; // throw\n      const values = {\n        x: 'bfj',\n      };\n      const project = (a: string, b: string, c: string) => a + b + c;\n\n      const result = e1.pipe(withLatestFrom(e2, e3, project));\n\n      expectObservable(result).toBe(expected, values, new Error('boo-hoo'));\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n      expectSubscriptions(e3.subscriptions).toBe(e3subs);\n    });\n  });\n\n  it('should handle merging with empty', () => {\n    rxTestScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => {\n      const e2 = cold('      |                 ');\n      const e2subs = '       (^!)              ';\n      const e3 = hot('  --i--^-j---k---l------|');\n      const e3subs = '       ^-------------!   ';\n      const e1 = hot('  --a--^---b---c---d-|   ');\n      const e1subs = '       ^-------------!   ';\n      const expected = '     --------------|   ';\n\n      const result = e1.pipe(withLatestFrom(e2, e3));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n      expectSubscriptions(e3.subscriptions).toBe(e3subs);\n    });\n  });\n\n  it('should handle merging with never', () => {\n    rxTestScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => {\n      const e2 = cold('      -                 ');\n      const e2subs = '       ^-------------!   ';\n      const e3 = hot('  --i--^-j---k---l------|');\n      const e3subs = '       ^-------------!   ';\n      const e1 = hot('  --a--^---b---c---d-|   ');\n      const e1subs = '       ^-------------!   ';\n      const expected = '     --------------|   ';\n\n      const result = e1.pipe(withLatestFrom(e2, e3));\n\n      expectObservable(result).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n      expectSubscriptions(e3.subscriptions).toBe(e3subs);\n    });\n  });\n\n  it('should handle promises', (done) => {\n    of(1)\n      .pipe(delay(1), withLatestFrom(Promise.resolve(2), Promise.resolve(3)))\n      .subscribe({\n        next(x: any) {\n          expect(x).to.deep.equal([1, 2, 3]);\n        },\n        complete: done,\n      });\n  });\n\n  it('should handle arrays', () => {\n    of(1)\n      .pipe(delay(1), withLatestFrom([2, 3, 4], [4, 5, 6]))\n      .subscribe((x: any) => {\n        expect(x).to.deep.equal([1, 4, 6]);\n      });\n  });\n\n  it('should handle lowercase-o observables', () => {\n    of(1)\n      .pipe(delay(1), withLatestFrom(lowerCaseO(2, 3, 4), lowerCaseO(4, 5, 6)))\n      .subscribe((x: any) => {\n        expect(x).to.deep.equal([1, 4, 6]);\n      });\n  });\n\n  it('should work with synchronous observables', () => {\n    const result: Array<Array<number>> = [];\n    of(1, 2, 3)\n      .pipe(withLatestFrom(of(4, 5)))\n      .subscribe((x) => {\n        result.push(x);\n      });\n\n    expect(result.length).to.equal(3);\n    expect(result[0]).to.deep.equal([1, 5]);\n    expect(result[1]).to.deep.equal([2, 5]);\n    expect(result[2]).to.deep.equal([3, 5]);\n  });\n});\n"
  },
  {
    "path": "packages/rxjs/spec/operators/zipAll-spec.ts",
    "content": "import { expect } from 'chai';\nimport { zipAll, mergeMap } from 'rxjs/operators';\nimport { queueScheduler, of, zip, scheduled } from 'rxjs';\nimport { TestScheduler } from 'rxjs/testing';\nimport { observableMatcher } from '../helpers/observableMatcher';\n\n/** @test {zipAll} */\ndescribe('zipAll operator', () => {\n  let rxTestScheduler: TestScheduler;\n\n  beforeEach(() => {\n    rxTestScheduler = new TestScheduler(observableMatcher);\n  });\n\n  it('should combine paired events from two observables', () => {\n    rxTestScheduler.run(({ hot, cold, expectObservable }) => {\n      const x = cold('                  -a-----b-|');\n      const y = cold('                  --1-2-----');\n      const outer = hot('-x----y--------|         ', { x: x, y: y });\n      const expected = ' -----------------A----B-|';\n\n      const result = outer.pipe(zipAll((a, b) => a + b));\n\n      expectObservable(result).toBe(expected, { A: 'a1', B: 'b2' });\n    });\n  });\n\n  it('should combine two observables', () => {\n    rxTestScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const a = hot('   ---1---2---3---');\n      const asubs = '   ^';\n      const b = hot('   --4--5--6--7--8--');\n      const bsubs = '   ^';\n      const expected = '---x---y---z';\n      const values = { x: ['1', '4'], y: ['2', '5'], z: ['3', '6'] };\n\n      expectObservable(of(a, b).pipe(zipAll())).toBe(expected, values);\n      expectSubscriptions(a.subscriptions).toBe(asubs);\n      expectSubscriptions(b.subscriptions).toBe(bsubs);\n    });\n  });\n\n  it('should take all observables from the source and zip them', (done) => {\n    const expected = ['a1', 'b2', 'c3'];\n    let i = 0;\n    of(of('a', 'b', 'c'), of(1, 2, 3))\n      .pipe(zipAll((a: string, b: number) => a + b))\n      .subscribe({\n        next(x) {\n          expect(x).to.equal(expected[i++]);\n        },\n        complete: done,\n      });\n  });\n\n  it('should end once one observable completes and its buffer is empty', () => {\n    rxTestScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  ---a--b--c--|               ');\n      const e1subs = '  ^-----------!               ';\n      const e2 = hot('  ------d----e----f--------|  ');\n      const e2subs = '  ^-----------------!         ';\n      const e3 = hot('  --------h----i----j---------'); // doesn't complete\n      const e3subs = '  ^-----------------!         ';\n      const expected = '--------x----y----(z|)      '; // e1 complete and buffer empty\n      const values = {\n        x: ['a', 'd', 'h'],\n        y: ['b', 'e', 'i'],\n        z: ['c', 'f', 'j'],\n      };\n\n      expectObservable(of(e1, e2, e3).pipe(zipAll())).toBe(expected, values);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n      expectSubscriptions(e3.subscriptions).toBe(e3subs);\n    });\n  });\n\n  it('should end once one observable nexts and zips value from completed other observable whose buffer is empty', () => {\n    rxTestScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  ---a--b--c--|             ');\n      const e1subs = '  ^-----------!             ';\n      const e2 = hot('  ------d----e----f|        ');\n      const e2subs = '  ^----------------!        ';\n      const e3 = hot('  --------h----i----j-------'); // doesn't complete\n      const e3subs = '  ^-----------------!       ';\n      const expected = '--------x----y----(z|)    '; // e2 buffer empty and signaled complete\n      const values = {\n        x: ['a', 'd', 'h'],\n        y: ['b', 'e', 'i'],\n        z: ['c', 'f', 'j'],\n      };\n\n      expectObservable(of(e1, e2, e3).pipe(zipAll())).toBe(expected, values);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n      expectSubscriptions(e3.subscriptions).toBe(e3subs);\n    });\n  });\n\n  describe('with iterables', () => {\n    it('should zip them with values', () => {\n      rxTestScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n        const myIterator = (function* () {\n          for (let i = 0; i < 4; i++) {\n            yield i;\n          }\n        })();\n\n        const e1 = hot('  ---a---b---c---d---|');\n        const e1subs = '  ^--------------!';\n        const expected = '---w---x---y---(z|)';\n\n        const values = {\n          w: ['a', 0],\n          x: ['b', 1],\n          y: ['c', 2],\n          z: ['d', 3],\n        };\n\n        expectObservable(of(e1, myIterator).pipe(zipAll<string | number>())).toBe(expected, values);\n        expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      });\n    });\n\n    it('should complete instantly with never observable and empty iterable', () => {\n      rxTestScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n        const a = cold('  -');\n        const asubs = '   (^!)';\n        const b: string[] = [];\n        const expected = '|';\n\n        expectObservable(of(a, b).pipe(zipAll())).toBe(expected);\n        expectSubscriptions(a.subscriptions).toBe(asubs);\n      });\n    });\n\n    it('should work with empty observable and empty iterable', () => {\n      rxTestScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n        const a = cold('  |');\n        const asubs = '   (^!)';\n        const b: string[] = [];\n        const expected = '|';\n\n        expectObservable(of(a, b).pipe(zipAll())).toBe(expected);\n        expectSubscriptions(a.subscriptions).toBe(asubs);\n      });\n    });\n\n    it('should work with empty observable and non-empty iterable', () => {\n      rxTestScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n        const a = cold('  |');\n        const asubs = '   (^!)';\n        const b = [1];\n        const expected = '|';\n\n        expectObservable(of(a, b).pipe(zipAll<string | number>())).toBe(expected);\n        expectSubscriptions(a.subscriptions).toBe(asubs);\n      });\n    });\n\n    it('should work with non-empty observable and empty iterable', () => {\n      rxTestScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n        const a = hot('---^----a--|');\n        const asubs = '   (^!)';\n        const b: string[] = [];\n        const expected = '|';\n\n        expectObservable(of(a, b).pipe(zipAll())).toBe(expected);\n        expectSubscriptions(a.subscriptions).toBe(asubs);\n      });\n    });\n\n    it('should work with never observable and non-empty iterable', () => {\n      rxTestScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n        const a = cold('  -');\n        const asubs = '   ^';\n        const b = [1];\n        const expected = '-';\n\n        expectObservable(of(a, b).pipe(zipAll<string | number>())).toBe(expected);\n        expectSubscriptions(a.subscriptions).toBe(asubs);\n      });\n    });\n\n    it('should work with non-empty observable and non-empty iterable', () => {\n      rxTestScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n        const a = hot('---^----1--|');\n        const asubs = '   ^----!   ';\n        const b = [2];\n        const expected = '-----(x|)';\n\n        expectObservable(of(a, b).pipe(zipAll<string | number>())).toBe(expected, { x: ['1', 2] });\n        expectSubscriptions(a.subscriptions).toBe(asubs);\n      });\n    });\n\n    it('should work with observable which raises error and non-empty iterable', () => {\n      rxTestScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n        const a = hot('---^----#');\n        const asubs = '   ^----!';\n        const b = [1];\n        const expected = '-----#';\n\n        expectObservable(of(a, b).pipe(zipAll<string | number>())).toBe(expected);\n        expectSubscriptions(a.subscriptions).toBe(asubs);\n      });\n    });\n\n    it('should work with non-empty many observable and non-empty many iterable', () => {\n      rxTestScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n        const a = hot('---^--1--2--3--|');\n        const asubs = '   ^--------!   ';\n        const b = [4, 5, 6];\n        const expected = '---x--y--(z|)';\n\n        expectObservable(of(a, b).pipe(zipAll<string | number>())).toBe(expected, { x: ['1', 4], y: ['2', 5], z: ['3', 6] });\n        expectSubscriptions(a.subscriptions).toBe(asubs);\n      });\n    });\n\n    it('should work with non-empty observable and non-empty iterable selector that throws', () => {\n      rxTestScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n        const a = hot('---^--1--2--3--|');\n        const asubs = '   ^-----!';\n        const b = [4, 5, 6];\n        const expected = '---x--#';\n\n        const selector = function (x: string, y: number) {\n          if (y === 5) {\n            throw new Error('too bad');\n          } else {\n            return x + y;\n          }\n        };\n        expectObservable(of(a, b).pipe(zipAll(selector))).toBe(expected, { x: '14' }, new Error('too bad'));\n        expectSubscriptions(a.subscriptions).toBe(asubs);\n      });\n    });\n  });\n\n  it('should combine two observables and selector', () => {\n    rxTestScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const a = hot('   ---1---2---3---');\n      const asubs = '   ^';\n      const b = hot('   --4--5--6--7--8--');\n      const bsubs = '   ^';\n      const expected = '---x---y---z';\n\n      expectObservable(of(a, b).pipe(zipAll((e1, e2) => e1 + e2))).toBe(expected, { x: '14', y: '25', z: '36' });\n      expectSubscriptions(a.subscriptions).toBe(asubs);\n      expectSubscriptions(b.subscriptions).toBe(bsubs);\n    });\n  });\n\n  it('should work with n-ary symmetric', () => {\n    rxTestScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const a = hot('   ---1-^-1----4----|');\n      const asubs = '        ^---------!  ';\n      const b = hot('   ---1-^--2--5----| ');\n      const bsubs = '        ^---------!  ';\n      const c = hot('   ---1-^---3---6-|  ');\n      const expected = '     ----x---y-|  ';\n\n      expectObservable(of(a, b, c).pipe(zipAll())).toBe(expected, { x: ['1', '2', '3'], y: ['4', '5', '6'] });\n      expectSubscriptions(a.subscriptions).toBe(asubs);\n      expectSubscriptions(b.subscriptions).toBe(bsubs);\n    });\n  });\n\n  it('should work with n-ary symmetric selector', () => {\n    rxTestScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const a = hot('---1-^-1----4----|');\n      const asubs = '     ^---------!  ';\n      const b = hot('---1-^--2--5----| ');\n      const bsubs = '     ^---------!  ';\n      const c = hot('---1-^---3---6-|  ');\n      const expected = '  ----x---y-|  ';\n\n      const observable = of(a, b, c).pipe(zipAll((r0, r1, r2) => [r0, r1, r2]));\n      expectObservable(observable).toBe(expected, { x: ['1', '2', '3'], y: ['4', '5', '6'] });\n      expectSubscriptions(a.subscriptions).toBe(asubs);\n      expectSubscriptions(b.subscriptions).toBe(bsubs);\n    });\n  });\n\n  it('should work with n-ary symmetric array selector', () => {\n    rxTestScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const a = hot('   ---1-^-1----4----|');\n      const asubs = '        ^---------!  ';\n      const b = hot('   ---1-^--2--5----| ');\n      const bsubs = '        ^---------!  ';\n      const c = hot('   ---1-^---3---6-|  ');\n      const expected = '     ----x---y-|  ';\n\n      const observable = of(a, b, c).pipe(zipAll((r0, r1, r2) => [r0, r1, r2]));\n      expectObservable(observable).toBe(expected, { x: ['1', '2', '3'], y: ['4', '5', '6'] });\n      expectSubscriptions(a.subscriptions).toBe(asubs);\n      expectSubscriptions(b.subscriptions).toBe(bsubs);\n    });\n  });\n\n  it('should work with some data asymmetric 1', () => {\n    rxTestScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const a = hot('---1-^-1-3-5-7-9-x-y-z-w-u-|');\n      const asubs = '     ^-----------------!    ';\n      const b = hot('---1-^--2--4--6--8--0--|    ');\n      const bsubs = '     ^-----------------!    ';\n      const expected = '  ---a--b--c--d--e--|    ';\n\n      expectObservable(of(a, b).pipe(zipAll((r1, r2) => r1 + r2))).toBe(expected, { a: '12', b: '34', c: '56', d: '78', e: '90' });\n      expectSubscriptions(a.subscriptions).toBe(asubs);\n      expectSubscriptions(b.subscriptions).toBe(bsubs);\n    });\n  });\n\n  it('should work with some data asymmetric 2', () => {\n    rxTestScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const a = hot('---1-^--2--4--6--8--0--|    ');\n      const asubs = '     ^-----------------!    ';\n      const b = hot('---1-^-1-3-5-7-9-x-y-z-w-u-|');\n      const bsubs = '     ^-----------------!    ';\n      const expected = '  ---a--b--c--d--e--|    ';\n\n      expectObservable(of(a, b).pipe(zipAll((r1, r2) => r1 + r2))).toBe(expected, { a: '21', b: '43', c: '65', d: '87', e: '09' });\n      expectSubscriptions(a.subscriptions).toBe(asubs);\n      expectSubscriptions(b.subscriptions).toBe(bsubs);\n    });\n  });\n\n  it('should work with some data symmetric', () => {\n    rxTestScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const a = hot('---1-^-1-3-5-7-9------| ');\n      const asubs = '     ^----------------! ';\n      const b = hot('---1-^--2--4--6--8--0--|');\n      const bsubs = '     ^----------------! ';\n      const expected = '  ---a--b--c--d--e-| ';\n\n      expectObservable(of(a, b).pipe(zipAll((r1, r2) => r1 + r2))).toBe(expected, { a: '12', b: '34', c: '56', d: '78', e: '90' });\n      expectSubscriptions(a.subscriptions).toBe(asubs);\n      expectSubscriptions(b.subscriptions).toBe(bsubs);\n    });\n  });\n\n  it('should work with selector throws', () => {\n    rxTestScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const a = hot('---1-^-2---4----|  ');\n      const asubs = '     ^-------!     ';\n      const b = hot('---1-^--3----5----|');\n      const bsubs = '     ^-------!     ';\n      const expected = '  ---x----#     ';\n\n      const selector = function (x: string, y: string) {\n        if (y === '5') {\n          throw new Error('too bad');\n        } else {\n          return x + y;\n        }\n      };\n      const observable = of(a, b).pipe(zipAll(selector));\n      expectObservable(observable).toBe(expected, { x: '23' }, new Error('too bad'));\n      expectSubscriptions(a.subscriptions).toBe(asubs);\n      expectSubscriptions(b.subscriptions).toBe(bsubs);\n    });\n  });\n\n  // TODO: This does not seem to belong in this battery of tests.\n  it('should work with right completes first', () => {\n    rxTestScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const a = hot('---1-^-2-----|');\n      const asubs = '     ^-----!';\n      const b = hot('---1-^--3--|');\n      const bsubs = '     ^-----!';\n      const expected = '  ---x--|';\n\n      expectObservable(zip(a, b)).toBe(expected, { x: ['2', '3'] });\n      expectSubscriptions(a.subscriptions).toBe(asubs);\n      expectSubscriptions(b.subscriptions).toBe(bsubs);\n    });\n  });\n\n  it('should zip until one child terminates', (done) => {\n    const expected = ['a1', 'b2'];\n    let i = 0;\n    of(of('a', 'b', 'c'), of(1, 2))\n      .pipe(zipAll((a: string, b: number) => a + b))\n      .subscribe({\n        next: (x) => {\n          expect(x).to.equal(expected[i++]);\n        },\n        complete: done,\n      });\n  });\n\n  it('should handle a hot observable of observables', () => {\n    rxTestScheduler.run(({ hot, cold, expectObservable, expectSubscriptions }) => {\n      const x = cold('          a---b---c---|      ');\n      const xsubs = '   --------^-----------!';\n      const y = cold('          d---e---f---|   ');\n      const ysubs = '   --------^-----------!';\n      const e1 = hot('  --x--y--|            ', { x: x, y: y });\n      const e1subs = '  ^-------!            ';\n      const expected = '--------u---v---w---|';\n      const values = {\n        u: ['a', 'd'],\n        v: ['b', 'e'],\n        w: ['c', 'f'],\n      };\n\n      expectObservable(e1.pipe(zipAll())).toBe(expected, values);\n      expectSubscriptions(x.subscriptions).toBe(xsubs);\n      expectSubscriptions(y.subscriptions).toBe(ysubs);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should handle merging a hot observable of non-overlapped observables', () => {\n    rxTestScheduler.run(({ hot, cold, expectObservable, expectSubscriptions }) => {\n      const x = cold('                             a-b---------|');\n      const xsubs = '   ---------------------------^-----------!';\n      const y = cold('                             c-d-e-f-|');\n      const ysubs = '   ---------------------------^-------!';\n      const z = cold('                             g-h-i-j-k-|');\n      const zsubs = '   ---------------------------^---------!';\n      const e1 = hot('  --x------y--------z--------|            ', { x: x, y: y, z: z });\n      const e1subs = '  ^--------------------------!            ';\n      const expected = '---------------------------u-v---------|';\n      const values = {\n        u: ['a', 'c', 'g'],\n        v: ['b', 'd', 'h'],\n      };\n\n      expectObservable(e1.pipe(zipAll())).toBe(expected, values);\n      expectSubscriptions(x.subscriptions).toBe(xsubs);\n      expectSubscriptions(y.subscriptions).toBe(ysubs);\n      expectSubscriptions(z.subscriptions).toBe(zsubs);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should raise error if inner observable raises error', () => {\n    rxTestScheduler.run(({ hot, cold, expectObservable, expectSubscriptions }) => {\n      const x = cold('                                a-b---------|');\n      const xsubs = '   ------------------------------^-------!';\n      const y = cold('                                c-d-e-f-#');\n      const ysubs = '   ------------------------------^-------!';\n      const z = cold('                                g-h-i-j-k-|');\n      const zsubs = '   ------------------------------^-------!';\n      const e1 = hot('  --x---------y--------z--------|        ', { x: x, y: y, z: z });\n      const e1subs = '  ^-----------------------------!        ';\n      const expected = '------------------------------u-v-----#';\n\n      const expectedValues = {\n        u: ['a', 'c', 'g'],\n        v: ['b', 'd', 'h'],\n      };\n\n      expectObservable(e1.pipe(zipAll())).toBe(expected, expectedValues);\n      expectSubscriptions(x.subscriptions).toBe(xsubs);\n      expectSubscriptions(y.subscriptions).toBe(ysubs);\n      expectSubscriptions(z.subscriptions).toBe(zsubs);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should raise error if outer observable raises error', () => {\n    rxTestScheduler.run(({ hot, cold, expectObservable, expectSubscriptions }) => {\n      const y = cold('  a-b---------|');\n      const z = cold('  c-d-e-f-|');\n      const e1 = hot('  --y---------z---#', { y: y, z: z });\n      const e1subs = '  ^---------------!';\n      const expected = '----------------#';\n\n      expectObservable(e1.pipe(zipAll())).toBe(expected);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n    });\n  });\n\n  it('should work with two nevers', () => {\n    rxTestScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const a = cold('  -');\n      const asubs = '   ^';\n      const b = cold('  -');\n      const bsubs = '   ^';\n      const expected = '-';\n\n      expectObservable(of(a, b).pipe(zipAll())).toBe(expected);\n      expectSubscriptions(a.subscriptions).toBe(asubs);\n      expectSubscriptions(b.subscriptions).toBe(bsubs);\n    });\n  });\n\n  it('should work with never and empty', () => {\n    rxTestScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const a = cold('  -');\n      const asubs = '   (^!)';\n      const b = cold('  |');\n      const bsubs = '   (^!)';\n      const expected = '|';\n\n      expectObservable(of(a, b).pipe(zipAll())).toBe(expected);\n      expectSubscriptions(a.subscriptions).toBe(asubs);\n      expectSubscriptions(b.subscriptions).toBe(bsubs);\n    });\n  });\n\n  it('should work with empty and never', () => {\n    rxTestScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const a = cold('  |');\n      const asubs = '   (^!)';\n      const b = cold('  -');\n      const bsubs = '   (^!)';\n      const expected = '|';\n\n      expectObservable(of(a, b).pipe(zipAll())).toBe(expected);\n      expectSubscriptions(a.subscriptions).toBe(asubs);\n      expectSubscriptions(b.subscriptions).toBe(bsubs);\n    });\n  });\n\n  it('should work with empty and empty', () => {\n    rxTestScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const a = cold('  |');\n      const asubs = '   (^!)';\n      const b = cold('  |');\n      const bsubs = '   (^!)';\n      const expected = '|';\n\n      expectObservable(of(a, b).pipe(zipAll())).toBe(expected);\n      expectSubscriptions(a.subscriptions).toBe(asubs);\n      expectSubscriptions(b.subscriptions).toBe(bsubs);\n    });\n  });\n\n  it('should work with empty and non-empty', () => {\n    rxTestScheduler.run(({ hot, cold, expectObservable, expectSubscriptions }) => {\n      const a = cold('  |');\n      const asubs = '   (^!)';\n      const b = hot('   ---1--|');\n      const bsubs = '   (^!)';\n      const expected = '|';\n\n      expectObservable(of(a, b).pipe(zipAll())).toBe(expected);\n      expectSubscriptions(a.subscriptions).toBe(asubs);\n      expectSubscriptions(b.subscriptions).toBe(bsubs);\n    });\n  });\n\n  it('should work with non-empty and empty', () => {\n    rxTestScheduler.run(({ hot, cold, expectObservable, expectSubscriptions }) => {\n      const a = hot('   ---1--|');\n      const asubs = '   (^!)';\n      const b = cold('  |');\n      const bsubs = '   (^!)';\n      const expected = '|';\n\n      expectObservable(of(a, b).pipe(zipAll())).toBe(expected);\n      expectSubscriptions(a.subscriptions).toBe(asubs);\n      expectSubscriptions(b.subscriptions).toBe(bsubs);\n    });\n  });\n\n  it('should work with never and non-empty', () => {\n    rxTestScheduler.run(({ hot, cold, expectObservable, expectSubscriptions }) => {\n      const a = cold('  -');\n      const asubs = '   ^';\n      const b = hot('   ---1--|');\n      const bsubs = '   ^-----!';\n      const expected = '-';\n\n      expectObservable(of(a, b).pipe(zipAll())).toBe(expected);\n      expectSubscriptions(a.subscriptions).toBe(asubs);\n      expectSubscriptions(b.subscriptions).toBe(bsubs);\n    });\n  });\n\n  it('should work with non-empty and never', () => {\n    rxTestScheduler.run(({ hot, cold, expectObservable, expectSubscriptions }) => {\n      const a = hot('   ---1--|');\n      const asubs = '   ^-----!';\n      const b = cold('  -');\n      const bsubs = '   ^';\n      const expected = '-';\n\n      expectObservable(of(a, b).pipe(zipAll())).toBe(expected);\n      expectSubscriptions(a.subscriptions).toBe(asubs);\n      expectSubscriptions(b.subscriptions).toBe(bsubs);\n    });\n  });\n\n  it('should combine a source with a second', () => {\n    rxTestScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const a = hot('   ---1---2---3---');\n      const asubs = '   ^';\n      const b = hot('   --4--5--6--7--8--');\n      const bsubs = '   ^';\n      const expected = '---x---y---z';\n\n      expectObservable(of(a, b).pipe(zipAll())).toBe(expected, { x: ['1', '4'], y: ['2', '5'], z: ['3', '6'] });\n      expectSubscriptions(a.subscriptions).toBe(asubs);\n      expectSubscriptions(b.subscriptions).toBe(bsubs);\n    });\n  });\n\n  it('should work with empty and error', () => {\n    rxTestScheduler.run(({ hot, cold, expectObservable, expectSubscriptions }) => {\n      const a = cold('  |');\n      const asubs = '   (^!)';\n      const b = hot('   ------#', undefined, 'too bad');\n      const bsubs = '   (^!)';\n      const expected = '|';\n\n      expectObservable(of(a, b).pipe(zipAll())).toBe(expected);\n      expectSubscriptions(a.subscriptions).toBe(asubs);\n      expectSubscriptions(b.subscriptions).toBe(bsubs);\n    });\n  });\n\n  it('should work with error and empty', () => {\n    rxTestScheduler.run(({ hot, cold, expectObservable, expectSubscriptions }) => {\n      const a = hot('   ------#', undefined, 'too bad');\n      const asubs = '   (^!)';\n      const b = cold('  |');\n      const bsubs = '   (^!)';\n      const expected = '|';\n\n      expectObservable(of(a, b).pipe(zipAll())).toBe(expected);\n      expectSubscriptions(a.subscriptions).toBe(asubs);\n      expectSubscriptions(b.subscriptions).toBe(bsubs);\n    });\n  });\n\n  it('should work with error', () => {\n    rxTestScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const a = hot('   ----------|');\n      const asubs = '   ^-----!    ';\n      const b = hot('   ------#    ');\n      const bsubs = '   ^-----!    ';\n      const expected = '------#    ';\n\n      expectObservable(of(a, b).pipe(zipAll())).toBe(expected);\n      expectSubscriptions(a.subscriptions).toBe(asubs);\n      expectSubscriptions(b.subscriptions).toBe(bsubs);\n    });\n  });\n\n  it('should work with never and error', () => {\n    rxTestScheduler.run(({ hot, cold, expectObservable, expectSubscriptions }) => {\n      const a = cold('  -');\n      const asubs = '   ^-----!';\n      const b = hot('   ------#');\n      const bsubs = '   ^-----!';\n      const expected = '------#';\n\n      expectObservable(of(a, b).pipe(zipAll())).toBe(expected);\n      expectSubscriptions(a.subscriptions).toBe(asubs);\n      expectSubscriptions(b.subscriptions).toBe(bsubs);\n    });\n  });\n\n  it('should work with error and never', () => {\n    rxTestScheduler.run(({ hot, cold, expectObservable, expectSubscriptions }) => {\n      const a = hot('   ------#');\n      const asubs = '   ^-----!';\n      const b = cold('  -');\n      const bsubs = '   ^-----!';\n      const expected = '------#';\n\n      expectObservable(of(a, b).pipe(zipAll())).toBe(expected);\n      expectSubscriptions(a.subscriptions).toBe(asubs);\n      expectSubscriptions(b.subscriptions).toBe(bsubs);\n    });\n  });\n\n  it('should work with error and error', () => {\n    rxTestScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const a = hot('   ------#', undefined, 'too bad');\n      const asubs = '   ^-----!';\n      const b = hot('   ----------#', undefined, 'too bad 2');\n      const bsubs = '   ^-----!';\n      const expected = '------#';\n\n      expectObservable(of(a, b).pipe(zipAll())).toBe(expected, null, 'too bad');\n      expectSubscriptions(a.subscriptions).toBe(asubs);\n      expectSubscriptions(b.subscriptions).toBe(bsubs);\n    });\n  });\n\n  it('should work with two sources that eventually raise errors', () => {\n    rxTestScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const a = hot('   --w-----#----', { w: 1 }, 'too bad');\n      const asubs = '   ^-------!';\n      const b = hot('   -----z-----#-', { z: 2 }, 'too bad 2');\n      const bsubs = '   ^-------!';\n      const expected = '-----x--#';\n\n      expectObservable(of(a, b).pipe(zipAll())).toBe(expected, { x: [1, 2] }, 'too bad');\n      expectSubscriptions(a.subscriptions).toBe(asubs);\n      expectSubscriptions(b.subscriptions).toBe(bsubs);\n    });\n  });\n\n  it('should work with two sources that eventually raise errors (swapped)', () => {\n    rxTestScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const a = hot('   -----z-----#-', { z: 2 }, 'too bad 2');\n      const asubs = '   ^-------!';\n      const b = hot('   --w-----#', { w: 1 }, 'too bad');\n      const bsubs = '   ^-------!';\n      const expected = '-----x--#';\n\n      expectObservable(of(a, b).pipe(zipAll())).toBe(expected, { x: [2, 1] }, 'too bad');\n      expectSubscriptions(a.subscriptions).toBe(asubs);\n      expectSubscriptions(b.subscriptions).toBe(bsubs);\n    });\n  });\n\n  it('should work with error and some', () => {\n    rxTestScheduler.run(({ hot, cold, expectObservable, expectSubscriptions }) => {\n      const a = cold('  #');\n      const asubs = '   (^!)';\n      const b = hot('   --1--2--3--');\n      const bsubs = '   (^!)';\n      const expected = '#';\n\n      expectObservable(of(a, b).pipe(zipAll())).toBe(expected);\n      expectSubscriptions(a.subscriptions).toBe(asubs);\n      expectSubscriptions(b.subscriptions).toBe(bsubs);\n    });\n  });\n\n  it('should combine two immediately-scheduled observables', (done) => {\n    rxTestScheduler.run(() => {\n      const a = scheduled([1, 2, 3], queueScheduler);\n      const b = scheduled([4, 5, 6, 7, 8], queueScheduler);\n      const r = [\n        [1, 4],\n        [2, 5],\n        [3, 6],\n      ];\n      let i = 0;\n\n      const result = scheduled([a, b], queueScheduler).pipe(zipAll());\n\n      result.subscribe({\n        next(vals) {\n          expect(vals).to.deep.equal(r[i++]);\n        },\n        complete: done,\n      });\n    });\n  });\n\n  it('should combine a source with an immediately-scheduled source', (done) => {\n    const a = scheduled([1, 2, 3], queueScheduler);\n    const b = of(4, 5, 6, 7, 8);\n    const r = [\n      [1, 4],\n      [2, 5],\n      [3, 6],\n    ];\n    let i = 0;\n\n    const result = scheduled([a, b], queueScheduler).pipe(zipAll());\n\n    result.subscribe({\n      next(vals) {\n        expect(vals).to.deep.equal(r[i++]);\n      },\n      complete: done,\n    });\n  });\n\n  it('should not break unsubscription chain when unsubscribed explicitly', () => {\n    rxTestScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const a = hot('   ---1---2---3---|');\n      const unsub = '   ---------!';\n      const asubs = '   ^--------!';\n      const b = hot('   --4--5--6--7--8--|');\n      const bsubs = '   ^--------!';\n      const expected = '---x---y--';\n      const values = { x: ['1', '4'], y: ['2', '5'] };\n\n      const r = of(a, b).pipe(\n        mergeMap((x) => of(x)),\n        zipAll(),\n        mergeMap((x) => of(x))\n      );\n\n      expectObservable(r, unsub).toBe(expected, values);\n      expectSubscriptions(a.subscriptions).toBe(asubs);\n      expectSubscriptions(b.subscriptions).toBe(bsubs);\n    });\n  });\n\n  it('should complete when empty source', () => {\n    rxTestScheduler.run(({ hot, expectObservable }) => {\n      const source = hot('|');\n      const expected = '  |';\n\n      expectObservable(source.pipe(zipAll())).toBe(expected);\n    });\n  });\n});\n"
  },
  {
    "path": "packages/rxjs/spec/operators/zipWith-spec.ts",
    "content": "import { expect } from 'chai';\nimport { zipWith, mergeMap } from 'rxjs/operators';\nimport { queueScheduler, of, scheduled } from 'rxjs';\nimport { TestScheduler } from 'rxjs/testing';\nimport { observableMatcher } from '../helpers/observableMatcher';\n\n/** @test {zipWith} */\ndescribe('zipWith', () => {\n  let rxTestScheduler: TestScheduler;\n\n  beforeEach(() => {\n    rxTestScheduler = new TestScheduler(observableMatcher);\n  });\n\n  it('should combine a source with a second', () => {\n    rxTestScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const a = hot('   ---1---2---3-----');\n      const asubs = '   ^';\n      const b = hot('   --4--5--6--7--8--');\n      const bsubs = '   ^';\n      const expected = '---x---y---z-----';\n      expectObservable(a.pipe(zipWith(b))).toBe(expected, { x: ['1', '4'], y: ['2', '5'], z: ['3', '6'] });\n      expectSubscriptions(a.subscriptions).toBe(asubs);\n      expectSubscriptions(b.subscriptions).toBe(bsubs);\n    });\n  });\n\n  it('should end once one observable completes and its buffer is empty', () => {\n    rxTestScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  ---a--b--c--|               ');\n      const e1subs = '  ^-----------!               ';\n      const e2 = hot('  ------d----e----f--------|  ');\n      const e2subs = '  ^-----------------!         ';\n      const e3 = hot('  --------h----i----j---------'); // doesn't complete\n      const e3subs = '  ^-----------------!         ';\n      const expected = '--------x----y----(z|)      '; // e1 complete and buffer empty\n      const values = {\n        x: ['a', 'd', 'h'],\n        y: ['b', 'e', 'i'],\n        z: ['c', 'f', 'j'],\n      };\n\n      expectObservable(e1.pipe(zipWith(e2, e3))).toBe(expected, values);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n      expectSubscriptions(e3.subscriptions).toBe(e3subs);\n    });\n  });\n\n  it('should end once one observable nexts and zips value from completed other observable whose buffer is empty', () => {\n    rxTestScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const e1 = hot('  ---a--b--c--|             ');\n      const e1subs = '  ^-----------!             ';\n      const e2 = hot('  ------d----e----f|        ');\n      const e2subs = '  ^----------------!        ';\n      const e3 = hot('  --------h----i----j-------'); // doesn't complete\n      const e3subs = '  ^-----------------!       ';\n      const expected = '--------x----y----(z|)    '; // e2 buffer empty and signaled complete\n      const values = {\n        x: ['a', 'd', 'h'],\n        y: ['b', 'e', 'i'],\n        z: ['c', 'f', 'j'],\n      };\n\n      expectObservable(e1.pipe(zipWith(e2, e3))).toBe(expected, values);\n      expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      expectSubscriptions(e2.subscriptions).toBe(e2subs);\n      expectSubscriptions(e3.subscriptions).toBe(e3subs);\n    });\n  });\n\n  describe('with iterables', () => {\n    it('should zip them with values', () => {\n      rxTestScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n        const myIterator = (function* () {\n          for (let i = 0; i < 4; i++) {\n            yield i;\n          }\n        })();\n\n        const e1 = hot('  ---a---b---c---d---|');\n        const e1subs = '  ^--------------!';\n        const expected = '---w---x---y---(z|)';\n\n        const values = {\n          w: ['a', 0],\n          x: ['b', 1],\n          y: ['c', 2],\n          z: ['d', 3],\n        };\n\n        expectObservable(e1.pipe(zipWith(myIterator))).toBe(expected, values);\n        expectSubscriptions(e1.subscriptions).toBe(e1subs);\n      });\n    });\n\n    it('should complete instantly for an empty iterable', () => {\n      rxTestScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n        const a = cold('  -');\n        const asubs = '   (^!)';\n        const expected = '|';\n        const b: string[] = [];\n\n        expectObservable(a.pipe(zipWith(b))).toBe(expected);\n        expectSubscriptions(a.subscriptions).toBe(asubs);\n      });\n    });\n\n    it('should work with empty observable and empty iterable', () => {\n      rxTestScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n        const a = cold('  |');\n        const asubs = '   (^!)';\n        const expected = '|';\n        const b: string[] = [];\n\n        expectObservable(a.pipe(zipWith(b))).toBe(expected);\n        expectSubscriptions(a.subscriptions).toBe(asubs);\n      });\n    });\n\n    it('should work with empty observable and non-empty iterable', () => {\n      rxTestScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n        const a = cold('  |');\n        const asubs = '   (^!)';\n        const expected = '|';\n        const b = [1];\n\n        expectObservable(a.pipe(zipWith(b))).toBe(expected);\n        expectSubscriptions(a.subscriptions).toBe(asubs);\n      });\n    });\n\n    it('should complete instantly with non-empty observable and empty iterable', () => {\n      rxTestScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n        const a = hot('   ---^----a--|');\n        const asubs = '      (^!)';\n        const b: string[] = [];\n        const expected = '   |';\n\n        expectObservable(a.pipe(zipWith(b))).toBe(expected);\n        expectSubscriptions(a.subscriptions).toBe(asubs);\n      });\n    });\n\n    it('should work with never observable and non-empty iterable', () => {\n      rxTestScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n        const a = cold('  -');\n        const asubs = '   ^';\n        const expected = '-';\n        const b = [1];\n\n        expectObservable(a.pipe(zipWith(b))).toBe(expected);\n        expectSubscriptions(a.subscriptions).toBe(asubs);\n      });\n    });\n\n    it('should work with non-empty observable and non-empty iterable', () => {\n      rxTestScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n        const a = hot('---^----1--|');\n        const asubs = '   ^----!   ';\n        const expected = '-----(x|)';\n        const b = [2];\n\n        expectObservable(a.pipe(zipWith(b))).toBe(expected, { x: ['1', 2] });\n        expectSubscriptions(a.subscriptions).toBe(asubs);\n      });\n    });\n\n    it('should work with observable which raises error and non-empty iterable', () => {\n      rxTestScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n        const a = hot('---^----#');\n        const asubs = '   ^----!';\n        const expected = '-----#';\n        const b = [1];\n\n        expectObservable(a.pipe(zipWith(b))).toBe(expected);\n        expectSubscriptions(a.subscriptions).toBe(asubs);\n      });\n    });\n\n    it('should work with non-empty many observable and non-empty many iterable', () => {\n      rxTestScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n        const a = hot('---^--1--2--3--|');\n        const asubs = '   ^--------!   ';\n        const expected = '---x--y--(z|)';\n        const b = [4, 5, 6];\n\n        expectObservable(a.pipe(zipWith(b))).toBe(expected, { x: ['1', 4], y: ['2', 5], z: ['3', 6] });\n        expectSubscriptions(a.subscriptions).toBe(asubs);\n      });\n    });\n  });\n\n  it('should work with n-ary symmetric', () => {\n    rxTestScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const a = hot('---1-^-1----4----|');\n      const asubs = '     ^---------!  ';\n      const b = hot('---1-^--2--5----| ');\n      const bsubs = '     ^---------!  ';\n      const c = hot('---1-^---3---6-|  ');\n      const expected = '  ----x---y-|  ';\n\n      expectObservable(a.pipe(zipWith(b, c))).toBe(expected, { x: ['1', '2', '3'], y: ['4', '5', '6'] });\n      expectSubscriptions(a.subscriptions).toBe(asubs);\n      expectSubscriptions(b.subscriptions).toBe(bsubs);\n    });\n  });\n\n  it('should work with right completes first', () => {\n    rxTestScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const a = hot('---1-^-2-----|');\n      const asubs = '     ^-----!';\n      const b = hot('---1-^--3--|');\n      const bsubs = '     ^-----!';\n      const expected = '  ---x--|';\n\n      expectObservable(a.pipe(zipWith(b))).toBe(expected, { x: ['2', '3'] });\n      expectSubscriptions(a.subscriptions).toBe(asubs);\n      expectSubscriptions(b.subscriptions).toBe(bsubs);\n    });\n  });\n\n  it('should work with two nevers', () => {\n    rxTestScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const a = cold('  -');\n      const asubs = '   ^';\n      const b = cold('  -');\n      const bsubs = '   ^';\n      const expected = '-';\n\n      expectObservable(a.pipe(zipWith(b))).toBe(expected);\n      expectSubscriptions(a.subscriptions).toBe(asubs);\n      expectSubscriptions(b.subscriptions).toBe(bsubs);\n    });\n  });\n\n  it('should work with never and empty', () => {\n    rxTestScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const a = cold('  -');\n      const asubs = '   (^!)';\n      const b = cold('  |');\n      const bsubs = '   (^!)';\n      const expected = '|';\n\n      expectObservable(a.pipe(zipWith(b))).toBe(expected);\n      expectSubscriptions(a.subscriptions).toBe(asubs);\n      expectSubscriptions(b.subscriptions).toBe(bsubs);\n    });\n  });\n\n  it('should work with empty and never', () => {\n    rxTestScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const a = cold('  |');\n      const asubs = '   (^!)';\n      const b = cold('  -');\n      const bsubs = '   (^!)';\n      const expected = '|';\n\n      expectObservable(a.pipe(zipWith(b))).toBe(expected);\n      expectSubscriptions(a.subscriptions).toBe(asubs);\n      expectSubscriptions(b.subscriptions).toBe(bsubs);\n    });\n  });\n\n  it('should work with empty and empty', () => {\n    rxTestScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n      const a = cold('  |');\n      const asubs = '   (^!)';\n      const b = cold('  |');\n      const bsubs = '   (^!)';\n      const expected = '|';\n\n      expectObservable(a.pipe(zipWith(b))).toBe(expected);\n      expectSubscriptions(a.subscriptions).toBe(asubs);\n      expectSubscriptions(b.subscriptions).toBe(bsubs);\n    });\n  });\n\n  it('should work with empty and non-empty', () => {\n    rxTestScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => {\n      const a = cold('  |');\n      const asubs = '   (^!)';\n      const b = hot('   ---1--|');\n      const bsubs = '   (^!)';\n      const expected = '|';\n\n      expectObservable(a.pipe(zipWith(b))).toBe(expected);\n      expectSubscriptions(a.subscriptions).toBe(asubs);\n      expectSubscriptions(b.subscriptions).toBe(bsubs);\n    });\n  });\n\n  it('should work with non-empty and empty', () => {\n    rxTestScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => {\n      const a = hot('   ---1--|');\n      const asubs = '   (^!)';\n      const b = cold('  |');\n      const bsubs = '   (^!)';\n      const expected = '|';\n\n      expectObservable(a.pipe(zipWith(b))).toBe(expected);\n      expectSubscriptions(a.subscriptions).toBe(asubs);\n      expectSubscriptions(b.subscriptions).toBe(bsubs);\n    });\n  });\n\n  it('should work with never and non-empty', () => {\n    rxTestScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => {\n      const a = cold('  -');\n      const asubs = '   ^';\n      const b = hot('   ---1--|');\n      const bsubs = '   ^-----!';\n      const expected = '-';\n\n      expectObservable(a.pipe(zipWith(b))).toBe(expected);\n      expectSubscriptions(a.subscriptions).toBe(asubs);\n      expectSubscriptions(b.subscriptions).toBe(bsubs);\n    });\n  });\n\n  it('should work with non-empty and never', () => {\n    rxTestScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => {\n      const a = hot('   ---1--|');\n      const asubs = '   ^-----!';\n      const b = cold('  -');\n      const bsubs = '   ^';\n      const expected = '-';\n\n      expectObservable(a.pipe(zipWith(b))).toBe(expected);\n      expectSubscriptions(a.subscriptions).toBe(asubs);\n      expectSubscriptions(b.subscriptions).toBe(bsubs);\n    });\n  });\n\n  it('should work with empty and error', () => {\n    rxTestScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => {\n      const a = cold('  |');\n      const asubs = '   (^!)';\n      const b = hot('   ------#', undefined, 'too bad');\n      const bsubs = '   (^!)';\n      const expected = '|';\n\n      expectObservable(a.pipe(zipWith(b))).toBe(expected);\n      expectSubscriptions(a.subscriptions).toBe(asubs);\n      expectSubscriptions(b.subscriptions).toBe(bsubs);\n    });\n  });\n\n  it('should work with error and empty', () => {\n    rxTestScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => {\n      const a = hot('   ------#', undefined, 'too bad');\n      const asubs = '   (^!)';\n      const b = cold('  |');\n      const bsubs = '   (^!)';\n      const expected = '|';\n\n      expectObservable(a.pipe(zipWith(b))).toBe(expected);\n      expectSubscriptions(a.subscriptions).toBe(asubs);\n      expectSubscriptions(b.subscriptions).toBe(bsubs);\n    });\n  });\n\n  it('should work with error', () => {\n    rxTestScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const a = hot('   ----------|');\n      const asubs = '   ^-----!    ';\n      const b = hot('   ------#    ');\n      const bsubs = '   ^-----!    ';\n      const expected = '------#    ';\n\n      expectObservable(a.pipe(zipWith(b))).toBe(expected);\n      expectSubscriptions(a.subscriptions).toBe(asubs);\n      expectSubscriptions(b.subscriptions).toBe(bsubs);\n    });\n  });\n\n  it('should work with never and error', () => {\n    rxTestScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => {\n      const a = cold('  -------');\n      const asubs = '   ^-----!';\n      const b = hot('   ------#');\n      const bsubs = '   ^-----!';\n      const expected = '------#';\n\n      expectObservable(a.pipe(zipWith(b))).toBe(expected);\n      expectSubscriptions(a.subscriptions).toBe(asubs);\n      expectSubscriptions(b.subscriptions).toBe(bsubs);\n    });\n  });\n\n  it('should work with error and never', () => {\n    rxTestScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => {\n      const a = hot('   ------#');\n      const asubs = '   ^-----!';\n      const b = cold('  -------');\n      const bsubs = '   ^-----!';\n      const expected = '------#';\n\n      expectObservable(a.pipe(zipWith(b))).toBe(expected);\n      expectSubscriptions(a.subscriptions).toBe(asubs);\n      expectSubscriptions(b.subscriptions).toBe(bsubs);\n    });\n  });\n\n  it('should work with error and error', () => {\n    rxTestScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const a = hot('   ------#', undefined, 'too bad');\n      const asubs = '   ^-----!';\n      const b = hot('   ----------#', undefined, 'too bad 2');\n      const bsubs = '   ^-----!';\n      const expected = '------#';\n\n      expectObservable(a.pipe(zipWith(b))).toBe(expected, null, 'too bad');\n      expectSubscriptions(a.subscriptions).toBe(asubs);\n      expectSubscriptions(b.subscriptions).toBe(bsubs);\n    });\n  });\n\n  it('should work with two sources that eventually raise errors', () => {\n    rxTestScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const a = hot('   --w-----#----', { w: 1 }, 'too bad');\n      const asubs = '   ^-------!';\n      const b = hot('   -----z-----#-', { z: 2 }, 'too bad 2');\n      const bsubs = '   ^-------!';\n      const expected = '-----x--#';\n\n      expectObservable(a.pipe(zipWith(b))).toBe(expected, { x: [1, 2] }, 'too bad');\n      expectSubscriptions(a.subscriptions).toBe(asubs);\n      expectSubscriptions(b.subscriptions).toBe(bsubs);\n    });\n  });\n\n  it('should work with two sources that eventually raise errors (swapped)', () => {\n    rxTestScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const a = hot('   -----z-----#-', { z: 2 }, 'too bad 2');\n      const asubs = '   ^-------!';\n      const b = hot('   --w-----#----', { w: 1 }, 'too bad');\n      const bsubs = '   ^-------!';\n      const expected = '-----x--#';\n\n      expectObservable(a.pipe(zipWith(b))).toBe(expected, { x: [2, 1] }, 'too bad');\n      expectSubscriptions(a.subscriptions).toBe(asubs);\n      expectSubscriptions(b.subscriptions).toBe(bsubs);\n    });\n  });\n\n  it('should work with error and some', () => {\n    rxTestScheduler.run(({ cold, hot, expectObservable, expectSubscriptions }) => {\n      const a = cold('  #');\n      const asubs = '   (^!)';\n      const b = hot('   --1--2--3--');\n      const bsubs = '   (^!)';\n      const expected = '#';\n\n      expectObservable(a.pipe(zipWith(b))).toBe(expected);\n      expectSubscriptions(a.subscriptions).toBe(asubs);\n      expectSubscriptions(b.subscriptions).toBe(bsubs);\n    });\n  });\n\n  it('should combine an immediately-scheduled source with an immediately-scheduled second', (done) => {\n    const a = scheduled([1, 2, 3], queueScheduler);\n    const b = scheduled([4, 5, 6, 7, 8], queueScheduler);\n    const r = [\n      [1, 4],\n      [2, 5],\n      [3, 6],\n    ];\n    let i = 0;\n\n    a.pipe(zipWith(b)).subscribe({\n      next(vals) {\n        expect(vals).to.deep.equal(r[i++]);\n      },\n      complete: done,\n    });\n  });\n\n  it('should not break unsubscription chain when unsubscribed explicitly', () => {\n    rxTestScheduler.run(({ hot, expectObservable, expectSubscriptions }) => {\n      const a = hot('   ---1---2---3---|');\n      const unsub = '   ---------!';\n      const asubs = '   ^--------!';\n      const b = hot('   --4--5--6--7--8--|');\n      const bsubs = '   ^--------!';\n      const expected = '---x---y--';\n\n      const r = a.pipe(\n        mergeMap((x) => of(x)),\n        zipWith(b),\n        mergeMap((x) => of(x))\n      );\n\n      expectObservable(r, unsub).toBe(expected, { x: ['1', '4'], y: ['2', '5'] });\n      expectSubscriptions(a.subscriptions).toBe(asubs);\n      expectSubscriptions(b.subscriptions).toBe(bsubs);\n    });\n  });\n});\n"
  },
  {
    "path": "packages/rxjs/spec/scheduled/scheduled-spec.ts",
    "content": "import { scheduled, of } from 'rxjs';\nimport { TestScheduler } from 'rxjs/testing';\nimport { lowerCaseO } from '../helpers/test-helper';\nimport { observableMatcher } from '../helpers/observableMatcher';\nimport { expect } from 'chai';\n\ndescribe('scheduled', () => {\n  let testScheduler: TestScheduler;\n\n  beforeEach(() => {\n    testScheduler = new TestScheduler(observableMatcher);\n  });\n\n  it('should schedule a sync observable', () => {\n    const input = of('a', 'b', 'c');\n    testScheduler.run(({ expectObservable }) => {\n      expectObservable(scheduled(input, testScheduler)).toBe('(abc|)');\n    });\n  });\n\n  it('should schedule an array', () => {\n    const input = ['a', 'b', 'c'];\n    testScheduler.run(({ expectObservable }) => {\n      expectObservable(scheduled(input, testScheduler)).toBe('(abc|)');\n    });\n  });\n\n  it('should schedule an iterable', () => {\n    const input = 'abc'; // strings are iterables\n    testScheduler.run(({ expectObservable }) => {\n      expectObservable(scheduled(input, testScheduler)).toBe('(abc|)');\n    });\n  });\n\n  it('should schedule an observable-like', () => {\n    const input = lowerCaseO('a', 'b', 'c'); // strings are iterables\n    testScheduler.run(({ expectObservable }) => {\n      expectObservable(scheduled(input, testScheduler)).toBe('(abc|)');\n    });\n  });\n\n  it('should schedule a promise', (done) => {\n    const results: any[] = [];\n    const input = Promise.resolve('x'); // strings are iterables\n    scheduled(input, testScheduler).subscribe({\n      next(value) {\n        results.push(value);\n      },\n      complete() {\n        results.push('done');\n      },\n    });\n\n    expect(results).to.deep.equal([]);\n\n    // Promises force async, so we can't schedule synchronously, no matter what.\n    testScheduler.flush();\n    expect(results).to.deep.equal([]);\n\n    Promise.resolve().then(() => {\n      // NOW it should work, as the other promise should have resolved.\n      testScheduler.flush();\n      expect(results).to.deep.equal(['x', 'done']);\n      done();\n    });\n  });\n\n  it('should handle scheduling a promise that unsubscribes prior to complete', (done) => {\n    const results: any[] = [];\n    const input = Promise.resolve('x'); // strings are iterables\n    const subscription = scheduled(input, testScheduler).subscribe({\n      next(value) { \n        results.push(value); \n        subscription.unsubscribe();\n      },\n      complete() { results.push('done'); },\n    });\n\n    expect(results).to.deep.equal([]);\n\n    // Promises force async, so we can't schedule synchronously, no matter what.\n    testScheduler.flush();\n    expect(results).to.deep.equal([]);\n\n    Promise.resolve().then(() => {\n      // NOW it should work, as the other promise should have resolved.\n      testScheduler.flush();\n      expect(results).to.deep.equal(['x']);\n      done();\n    });\n  });\n});\n"
  },
  {
    "path": "packages/rxjs/spec/schedulers/AnimationFrameScheduler-spec.ts",
    "content": "/** @prettier */\nimport { expect } from 'chai';\nimport * as sinon from 'sinon';\nimport type { Subscription} from 'rxjs';\nimport { animationFrameScheduler, merge } from 'rxjs';\nimport { delay } from 'rxjs/operators';\nimport { TestScheduler } from 'rxjs/testing';\nimport { observableMatcher } from '../helpers/observableMatcher';\nimport { animationFrameProvider } from 'rxjs/internal/scheduler/animationFrameProvider';\nimport { intervalProvider } from 'rxjs/internal/scheduler/intervalProvider';\n\nconst animationFrame = animationFrameScheduler;\n\n/** @test {Scheduler} */\ndescribe('Scheduler.animationFrame', () => {\n  let testScheduler: TestScheduler;\n\n  beforeEach(() => {\n    testScheduler = new TestScheduler(observableMatcher);\n  });\n\n  it('should exist', () => {\n    expect(animationFrame).exist;\n  });\n\n  it('should act like the async scheduler if delay > 0', () => {\n    testScheduler.run(({ animate, cold, expectObservable, time }) => {\n      animate('         ----------x--');\n      const a = cold('  a            ');\n      const ta = time(' ----|        ');\n      const b = cold('  b            ');\n      const tb = time(' --------|    ');\n      const expected = '----a---b----';\n\n      const result = merge(a.pipe(delay(ta, animationFrame)), b.pipe(delay(tb, animationFrame)));\n      expectObservable(result).toBe(expected);\n    });\n  });\n\n  it('should cancel animationFrame actions when delay > 0', () => {\n    testScheduler.run(({ animate, cold, expectObservable, flush, time }) => {\n      const requestSpy = sinon.spy(animationFrameProvider, 'requestAnimationFrame');\n      const setSpy = sinon.spy(intervalProvider, 'setInterval');\n      const clearSpy = sinon.spy(intervalProvider, 'clearInterval');\n\n      animate('         ----------x--');\n      const a = cold('  a            ');\n      const ta = time(' ----|        ');\n      const subs = '    ^-!          ';\n      const expected = '-------------';\n\n      const result = merge(a.pipe(delay(ta, animationFrame)));\n      expectObservable(result, subs).toBe(expected);\n\n      flush();\n      expect(requestSpy).to.have.not.been.called;\n      expect(setSpy).to.have.been.calledOnce;\n      expect(clearSpy).to.have.been.calledOnce;\n      requestSpy.restore();\n      setSpy.restore();\n      clearSpy.restore();\n    });\n  });\n\n  it('should schedule an action to happen later', (done) => {\n    let actionHappened = false;\n    animationFrame.schedule(() => {\n      actionHappened = true;\n      done();\n    });\n    if (actionHappened) {\n      done(new Error('Scheduled action happened synchronously'));\n    }\n  });\n\n  it('should execute recursively scheduled actions in separate asynchronous contexts', (done) => {\n    let syncExec1 = true;\n    let syncExec2 = true;\n    animationFrame.schedule(\n      function (index) {\n        if (index === 0) {\n          this.schedule(1);\n          animationFrame.schedule(() => {\n            syncExec1 = false;\n          });\n        } else if (index === 1) {\n          this.schedule(2);\n          animationFrame.schedule(() => {\n            syncExec2 = false;\n          });\n        } else if (index === 2) {\n          this.schedule(3);\n        } else if (index === 3) {\n          if (!syncExec1 && !syncExec2) {\n            done();\n          } else {\n            done(new Error('Execution happened synchronously.'));\n          }\n        }\n      },\n      0,\n      0\n    );\n  });\n\n  it('should cancel the animation frame if all scheduled actions unsubscribe before it executes', (done) => {\n    let animationFrameExec1 = false;\n    let animationFrameExec2 = false;\n    const action1 = animationFrame.schedule(() => {\n      animationFrameExec1 = true;\n    });\n    const action2 = animationFrame.schedule(() => {\n      animationFrameExec2 = true;\n    });\n    expect(animationFrame._scheduled).to.exist;\n    expect(animationFrame.actions.length).to.equal(2);\n    action1.unsubscribe();\n    action2.unsubscribe();\n    expect(animationFrame.actions.length).to.equal(0);\n    expect(animationFrame._scheduled).to.equal(undefined);\n    animationFrame.schedule(() => {\n      expect(animationFrameExec1).to.equal(false);\n      expect(animationFrameExec2).to.equal(false);\n      done();\n    });\n  });\n\n  it('should execute the rest of the scheduled actions if the first action is canceled', (done) => {\n    let actionHappened = false;\n    let secondSubscription: Subscription | null = null;\n\n    const firstSubscription = animationFrame.schedule(() => {\n      actionHappened = true;\n      if (secondSubscription) {\n        secondSubscription.unsubscribe();\n      }\n      done(new Error('The first action should not have executed.'));\n    });\n\n    secondSubscription = animationFrame.schedule(() => {\n      if (!actionHappened) {\n        done();\n      }\n    });\n\n    if (actionHappened) {\n      done(new Error('Scheduled action happened synchronously'));\n    } else {\n      firstSubscription.unsubscribe();\n    }\n  });\n\n  it('should not execute rescheduled actions when flushing', (done) => {\n    let flushCount = 0;\n    const scheduledIndices: number[] = [];\n\n    const originalFlush = animationFrame.flush;\n    animationFrame.flush = (...args) => {\n      ++flushCount;\n      originalFlush.apply(animationFrame, args);\n      if (flushCount === 2) {\n        animationFrame.flush = originalFlush;\n        try {\n          expect(scheduledIndices).to.deep.equal([0, 1]);\n          done();\n        } catch (error) {\n          done(error);\n        }\n      }\n    };\n\n    animationFrame.schedule(\n      function (index) {\n        if (flushCount < 2) {\n          this.schedule(index! + 1);\n          scheduledIndices.push(index! + 1);\n        }\n      },\n      0,\n      0\n    );\n    scheduledIndices.push(0);\n  });\n\n  it('should execute actions scheduled when flushing in a subsequent flush', (done) => {\n    const sandbox = sinon.createSandbox();\n    const stubFlush = sandbox.stub(animationFrameScheduler, 'flush').callThrough();\n\n    animationFrameScheduler.schedule(() => {\n      expect(stubFlush).to.have.callCount(1);\n      animationFrameScheduler.schedule(() => {\n        expect(stubFlush).to.have.callCount(2);\n        sandbox.restore();\n        done();\n      });\n    });\n    animationFrameScheduler.schedule(() => {\n      expect(stubFlush).to.have.callCount(1);\n    });\n  });\n\n  it('should execute actions scheduled when flushing in a subsequent flush when some actions are unsubscribed', (done) => {\n    const sandbox = sinon.createSandbox();\n    const stubFlush = sandbox.stub(animationFrameScheduler, 'flush').callThrough();\n\n    // eslint-disable-next-line prefer-const\n    let b: Subscription;\n\n    animationFrameScheduler.schedule(() => {\n      expect(stubFlush).to.have.callCount(1);\n      animationFrameScheduler.schedule(() => {\n        expect(stubFlush).to.have.callCount(2);\n        sandbox.restore();\n        done();\n      });\n      b.unsubscribe();\n    });\n    b = animationFrameScheduler.schedule(() => {\n      done(new Error('Unexpected execution of b'));\n    });\n  });\n\n  it('should properly cancel an unnecessary flush', (done) => {\n    const sandbox = sinon.createSandbox();\n    const cancelAnimationFrameStub = sandbox.stub(animationFrameProvider, 'cancelAnimationFrame').callThrough();\n\n    animationFrameScheduler.schedule(() => {\n      expect(animationFrameScheduler.actions).to.have.length(1);\n      const c = animationFrameScheduler.schedule(() => {\n        done(new Error('Unexpected execution of c'));\n      });\n      expect(animationFrameScheduler.actions).to.have.length(2);\n      // What we're testing here is that the unsubscription of action c effects\n      // the cancellation of the animation frame in a scenario in which the\n      // actions queue is not empty - it contains action b.\n      c.unsubscribe();\n      expect(animationFrameScheduler.actions).to.have.length(1);\n      expect(cancelAnimationFrameStub).to.have.callCount(1);\n    });\n    animationFrameScheduler.schedule(() => {\n      sandbox.restore();\n      done();\n    });\n  });\n});\n"
  },
  {
    "path": "packages/rxjs/spec/schedulers/AsapScheduler-spec.ts",
    "content": "/** @prettier  */\nimport { expect } from 'chai';\nimport * as sinon from 'sinon';\nimport type { Subscription, SchedulerAction} from 'rxjs';\nimport { asapScheduler, merge } from 'rxjs';\nimport { delay } from 'rxjs/operators';\nimport { TestScheduler } from 'rxjs/testing';\nimport { observableMatcher } from '../helpers/observableMatcher';\nimport { immediateProvider } from 'rxjs/internal/scheduler/immediateProvider';\nimport { intervalProvider } from 'rxjs/internal/scheduler/intervalProvider';\n\nconst asap = asapScheduler;\n\n/** @test {Scheduler} */\ndescribe('Scheduler.asap', () => {\n  let testScheduler: TestScheduler;\n\n  beforeEach(() => {\n    testScheduler = new TestScheduler(observableMatcher);\n  });\n\n  it('should exist', () => {\n    expect(asap).exist;\n  });\n\n  it('should act like the async scheduler if delay > 0', () => {\n    testScheduler.run(({ cold, expectObservable, time }) => {\n      const a = cold('  a            ');\n      const ta = time(' ----|        ');\n      const b = cold('  b            ');\n      const tb = time(' --------|    ');\n      const expected = '----a---b----';\n\n      const result = merge(a.pipe(delay(ta, asap)), b.pipe(delay(tb, asap)));\n      expectObservable(result).toBe(expected);\n    });\n  });\n\n  it('should cancel asap actions when delay > 0', () => {\n    testScheduler.run(({ cold, expectObservable, flush, time }) => {\n      const sandbox = sinon.createSandbox();\n      const setImmediateSpy = sandbox.spy(immediateProvider, 'setImmediate');\n      const setSpy = sandbox.spy(intervalProvider, 'setInterval');\n      const clearSpy = sandbox.spy(intervalProvider, 'clearInterval');\n\n      const a = cold('  a            ');\n      const ta = time(' ----|        ');\n      const subs = '    ^-!          ';\n      const expected = '-------------';\n\n      const result = merge(a.pipe(delay(ta, asap)));\n      expectObservable(result, subs).toBe(expected);\n\n      flush();\n      expect(setImmediateSpy).to.have.not.been.called;\n      expect(setSpy).to.have.been.calledOnce;\n      expect(clearSpy).to.have.been.calledOnce;\n      sandbox.restore();\n    });\n  });\n\n  it('should reuse the interval for recursively scheduled actions with the same delay', () => {\n    const sandbox = sinon.createSandbox();\n    const fakeTimer = sandbox.useFakeTimers();\n    // callThrough is missing from the declarations installed by the typings tool in stable\n    const stubSetInterval = (<any>sandbox.stub(global, 'setInterval')).callThrough();\n    const period = 50;\n    const state = { index: 0, period };\n    type State = typeof state;\n    function dispatch(this: SchedulerAction<State>, state: State): void {\n      state.index += 1;\n      if (state.index < 3) {\n        this.schedule(state, state.period);\n      }\n    }\n    asap.schedule(dispatch as any, period, state);\n    expect(state).to.have.property('index', 0);\n    expect(stubSetInterval).to.have.property('callCount', 1);\n    fakeTimer.tick(period);\n    expect(state).to.have.property('index', 1);\n    expect(stubSetInterval).to.have.property('callCount', 1);\n    fakeTimer.tick(period);\n    expect(state).to.have.property('index', 2);\n    expect(stubSetInterval).to.have.property('callCount', 1);\n    sandbox.restore();\n  });\n\n  it('should not reuse the interval for recursively scheduled actions with a different delay', () => {\n    const sandbox = sinon.createSandbox();\n    const fakeTimer = sandbox.useFakeTimers();\n    // callThrough is missing from the declarations installed by the typings tool in stable\n    const stubSetInterval = (<any>sandbox.stub(global, 'setInterval')).callThrough();\n    const period = 50;\n    const state = { index: 0, period };\n    type State = typeof state;\n    function dispatch(this: SchedulerAction<State>, state: State): void {\n      state.index += 1;\n      state.period -= 1;\n      if (state.index < 3) {\n        this.schedule(state, state.period);\n      }\n    }\n    asap.schedule(dispatch as any, period, state);\n    expect(state).to.have.property('index', 0);\n    expect(stubSetInterval).to.have.property('callCount', 1);\n    fakeTimer.tick(period);\n    expect(state).to.have.property('index', 1);\n    expect(stubSetInterval).to.have.property('callCount', 2);\n    fakeTimer.tick(period);\n    expect(state).to.have.property('index', 2);\n    expect(stubSetInterval).to.have.property('callCount', 3);\n    sandbox.restore();\n  });\n\n  it('should schedule an action to happen later', (done) => {\n    let actionHappened = false;\n    asap.schedule(() => {\n      actionHappened = true;\n      done();\n    });\n    if (actionHappened) {\n      done(new Error('Scheduled action happened synchronously'));\n    }\n  });\n\n  it('should execute recursively scheduled actions in separate asynchronous contexts', (done) => {\n    let syncExec1 = true;\n    let syncExec2 = true;\n    asap.schedule(\n      function (index) {\n        if (index === 0) {\n          this.schedule(1);\n          asap.schedule(() => {\n            syncExec1 = false;\n          });\n        } else if (index === 1) {\n          this.schedule(2);\n          asap.schedule(() => {\n            syncExec2 = false;\n          });\n        } else if (index === 2) {\n          this.schedule(3);\n        } else if (index === 3) {\n          if (!syncExec1 && !syncExec2) {\n            done();\n          } else {\n            done(new Error('Execution happened synchronously.'));\n          }\n        }\n      },\n      0,\n      0\n    );\n  });\n\n  it('should cancel the setImmediate if all scheduled actions unsubscribe before it executes', (done) => {\n    let asapExec1 = false;\n    let asapExec2 = false;\n    const action1 = asap.schedule(() => {\n      asapExec1 = true;\n    });\n    const action2 = asap.schedule(() => {\n      asapExec2 = true;\n    });\n    expect(asap._scheduled).to.exist;\n    expect(asap.actions.length).to.equal(2);\n    action1.unsubscribe();\n    action2.unsubscribe();\n    expect(asap.actions.length).to.equal(0);\n    expect(asap._scheduled).to.equal(undefined);\n    asap.schedule(() => {\n      expect(asapExec1).to.equal(false);\n      expect(asapExec2).to.equal(false);\n      done();\n    });\n  });\n\n  it('should execute the rest of the scheduled actions if the first action is canceled', (done) => {\n    let actionHappened = false;\n    let secondSubscription: Subscription | null = null;\n\n    const firstSubscription = asap.schedule(() => {\n      actionHappened = true;\n      if (secondSubscription) {\n        secondSubscription.unsubscribe();\n      }\n      done(new Error('The first action should not have executed.'));\n    });\n\n    secondSubscription = asap.schedule(() => {\n      if (!actionHappened) {\n        done();\n      }\n    });\n\n    if (actionHappened) {\n      done(new Error('Scheduled action happened synchronously'));\n    } else {\n      firstSubscription.unsubscribe();\n    }\n  });\n\n  it('should not execute rescheduled actions when flushing', (done) => {\n    let flushCount = 0;\n    const scheduledIndices: number[] = [];\n\n    const originalFlush = asap.flush;\n    asap.flush = (...args) => {\n      ++flushCount;\n      originalFlush.apply(asap, args);\n      if (flushCount === 2) {\n        asap.flush = originalFlush;\n        try {\n          expect(scheduledIndices).to.deep.equal([0, 1]);\n          done();\n        } catch (error) {\n          done(error);\n        }\n      }\n    };\n\n    asap.schedule(\n      function (index) {\n        if (flushCount < 2) {\n          this.schedule(index! + 1);\n          scheduledIndices.push(index! + 1);\n        }\n      },\n      0,\n      0\n    );\n    scheduledIndices.push(0);\n  });\n\n  it('should execute actions scheduled when flushing in a subsequent flush', (done) => {\n    const sandbox = sinon.createSandbox();\n    const stubFlush = sandbox.stub(asapScheduler, 'flush').callThrough();\n\n    asapScheduler.schedule(() => {\n      expect(stubFlush).to.have.callCount(1);\n      asapScheduler.schedule(() => {\n        expect(stubFlush).to.have.callCount(2);\n        sandbox.restore();\n        done();\n      });\n    });\n    asapScheduler.schedule(() => {\n      expect(stubFlush).to.have.callCount(1);\n    });\n  });\n\n  it('should execute actions scheduled when flushing in a subsequent flush when some actions are unsubscribed', (done) => {\n    const sandbox = sinon.createSandbox();\n    const stubFlush = sandbox.stub(asapScheduler, 'flush').callThrough();\n\n    // eslint-disable-next-line prefer-const\n    let b: Subscription;\n\n    asapScheduler.schedule(() => {\n      expect(stubFlush).to.have.callCount(1);\n      asapScheduler.schedule(() => {\n        expect(stubFlush).to.have.callCount(2);\n        sandbox.restore();\n        done();\n      });\n      b.unsubscribe();\n    });\n    b = asapScheduler.schedule(() => {\n      done(new Error('Unexpected execution of b'));\n    });\n  });\n\n  it('should properly cancel an unnecessary flush', (done) => {\n    const sandbox = sinon.createSandbox();\n    const clearImmediateStub = sandbox.stub(immediateProvider, 'clearImmediate').callThrough();\n\n    let c: Subscription;\n\n    asapScheduler.schedule(() => {\n      expect(asapScheduler.actions).to.have.length(1);\n      c = asapScheduler.schedule(() => {\n        done(new Error('Unexpected execution of c'));\n      });\n      expect(asapScheduler.actions).to.have.length(2);\n      // What we're testing here is that the unsubscription of action c effects\n      // the cancellation of the microtask in a scenario in which the actions\n      // queue is not empty - it contains action b.\n      c.unsubscribe();\n      expect(asapScheduler.actions).to.have.length(1);\n      expect(clearImmediateStub).to.have.callCount(1);\n    });\n    asapScheduler.schedule(() => {\n      sandbox.restore();\n      done();\n    });\n  });\n\n  it('scheduling inside of an executing action more than once should work', (done) => {\n    const results: any[] = [];\n\n    let resolve: () => void;\n    const promise = new Promise<void>((r) => (resolve = r));\n\n    asapScheduler.schedule(() => {\n      results.push(1);\n      asapScheduler.schedule(() => {\n        results.push(2);\n      });\n      asapScheduler.schedule(() => {\n        results.push(3);\n        resolve();\n      });\n    });\n\n    promise.then(() => {\n      // This should always fire after two recursively scheduled microtasks.\n      expect(results).to.deep.equal([1, 2, 3]);\n      done();\n    });\n  });\n});\n"
  },
  {
    "path": "packages/rxjs/spec/schedulers/QueueScheduler-spec.ts",
    "content": "/** @prettier */\nimport { expect } from 'chai';\nimport * as sinon from 'sinon';\nimport type { Subscription} from 'rxjs';\nimport { queueScheduler, merge } from 'rxjs';\nimport { delay } from 'rxjs/operators';\nimport { TestScheduler } from 'rxjs/testing';\nimport { observableMatcher } from '../helpers/observableMatcher';\n\nconst queue = queueScheduler;\n\n/** @test {Scheduler} */\ndescribe('Scheduler.queue', () => {\n  let testScheduler: TestScheduler;\n\n  beforeEach(() => {\n    testScheduler = new TestScheduler(observableMatcher);\n  });\n\n  it('should act like the async scheduler if delay > 0', () => {\n    testScheduler.run(({ cold, expectObservable, time }) => {\n      const a = cold('  a            ');\n      const ta = time(' ----|        ');\n      const b = cold('  b            ');\n      const tb = time(' --------|    ');\n      const expected = '----a---b----';\n\n      const result = merge(a.pipe(delay(ta, queue)), b.pipe(delay(tb, queue)));\n      expectObservable(result).toBe(expected);\n    });\n  });\n\n  it('should switch from synchronous to asynchronous at will', () => {\n    const sandbox = sinon.createSandbox();\n    const fakeTimer = sandbox.useFakeTimers();\n\n    let asyncExec = false;\n    const state: Array<number> = [];\n\n    queue.schedule(\n      function (index) {\n        state.push(index!);\n        if (index === 0) {\n          this.schedule(1, 100);\n        } else if (index === 1) {\n          asyncExec = true;\n          this.schedule(2, 0);\n        }\n      },\n      0,\n      0\n    );\n\n    expect(asyncExec).to.be.false;\n    expect(state).to.be.deep.equal([0]);\n\n    fakeTimer.tick(100);\n\n    expect(asyncExec).to.be.true;\n    expect(state).to.be.deep.equal([0, 1, 2]);\n\n    sandbox.restore();\n  });\n\n  it('should unsubscribe the rest of the scheduled actions if an action throws an error', () => {\n    const actions: Subscription[] = [];\n    let action2Exec = false;\n    let action3Exec = false;\n    let errorValue: any = undefined;\n    try {\n      queue.schedule(() => {\n        actions.push(\n          queue.schedule(() => {\n            throw new Error('oops');\n          }),\n          queue.schedule(() => {\n            action2Exec = true;\n          }),\n          queue.schedule(() => {\n            action3Exec = true;\n          })\n        );\n      });\n    } catch (e) {\n      errorValue = e;\n    }\n    expect(actions.every((action) => action.closed)).to.be.true;\n    expect(action2Exec).to.be.false;\n    expect(action3Exec).to.be.false;\n    expect(errorValue).exist;\n    expect(errorValue.message).to.equal('oops');\n  });\n});\n"
  },
  {
    "path": "packages/rxjs/spec/schedulers/TestScheduler-spec.ts",
    "content": "/** @prettier */\nimport { expect } from 'chai';\nimport { TestScheduler } from 'rxjs/testing';\nimport { Observable, Subject, of, merge, animationFrameScheduler, asapScheduler, asyncScheduler, interval } from 'rxjs';\nimport { delay, debounceTime, concatMap, mergeMap, mapTo, take } from 'rxjs/operators';\nimport { nextNotification, COMPLETE_NOTIFICATION, errorNotification } from '@rxjs/observable';\nimport { animationFrameProvider } from 'rxjs/internal/scheduler/animationFrameProvider';\nimport { immediateProvider } from 'rxjs/internal/scheduler/immediateProvider';\nimport { intervalProvider } from 'rxjs/internal/scheduler/intervalProvider';\nimport { timeoutProvider } from 'rxjs/internal/scheduler/timeoutProvider';\nimport { observableMatcher } from '../helpers/observableMatcher';\n\n/** @test {TestScheduler} */\ndescribe('TestScheduler', () => {\n  it('should exist', () => {\n    expect(TestScheduler).exist;\n    expect(TestScheduler).to.be.a('function');\n  });\n\n  it('should have frameTimeFactor set initially', () => {\n    expect(TestScheduler.frameTimeFactor).to.equal(10);\n  });\n\n  describe('parseMarbles()', () => {\n    it('should parse a marble string into a series of notifications and types', () => {\n      const result = TestScheduler.parseMarbles('-------a---b---|', { a: 'A', b: 'B' });\n      expect(result).deep.equal([\n        { frame: 70, notification: nextNotification('A') },\n        { frame: 110, notification: nextNotification('B') },\n        { frame: 150, notification: COMPLETE_NOTIFICATION },\n      ]);\n    });\n\n    it('should parse a marble string, allowing spaces too', () => {\n      const result = TestScheduler.parseMarbles('--a--b--|   ', { a: 'A', b: 'B' });\n      expect(result).deep.equal([\n        { frame: 20, notification: nextNotification('A') },\n        { frame: 50, notification: nextNotification('B') },\n        { frame: 80, notification: COMPLETE_NOTIFICATION },\n      ]);\n    });\n\n    it('should parse a marble string with a subscription point', () => {\n      const result = TestScheduler.parseMarbles('---^---a---b---|', { a: 'A', b: 'B' });\n      expect(result).deep.equal([\n        { frame: 40, notification: nextNotification('A') },\n        { frame: 80, notification: nextNotification('B') },\n        { frame: 120, notification: COMPLETE_NOTIFICATION },\n      ]);\n    });\n\n    it('should parse a marble string with an error', () => {\n      const result = TestScheduler.parseMarbles('-------a---b---#', { a: 'A', b: 'B' }, 'omg error!');\n      expect(result).deep.equal([\n        { frame: 70, notification: nextNotification('A') },\n        { frame: 110, notification: nextNotification('B') },\n        { frame: 150, notification: errorNotification('omg error!') },\n      ]);\n    });\n\n    it('should default in the letter for the value if no value hash was passed', () => {\n      const result = TestScheduler.parseMarbles('--a--b--c--');\n      expect(result).deep.equal([\n        { frame: 20, notification: nextNotification('a') },\n        { frame: 50, notification: nextNotification('b') },\n        { frame: 80, notification: nextNotification('c') },\n      ]);\n    });\n\n    it('should handle grouped values', () => {\n      const result = TestScheduler.parseMarbles('---(abc)---');\n      expect(result).deep.equal([\n        { frame: 30, notification: nextNotification('a') },\n        { frame: 30, notification: nextNotification('b') },\n        { frame: 30, notification: nextNotification('c') },\n      ]);\n    });\n\n    it('should ignore whitespace when runMode=true', () => {\n      const runMode = true;\n      const result = TestScheduler.parseMarbles('  -a - b -    c |       ', { a: 'A', b: 'B', c: 'C' }, undefined, undefined, runMode);\n      expect(result).deep.equal([\n        { frame: 10, notification: nextNotification('A') },\n        { frame: 30, notification: nextNotification('B') },\n        { frame: 50, notification: nextNotification('C') },\n        { frame: 60, notification: COMPLETE_NOTIFICATION },\n      ]);\n    });\n\n    it('should support time progression syntax when runMode=true', () => {\n      const runMode = true;\n      const result = TestScheduler.parseMarbles('10.2ms a 1.2s b 1m c|', { a: 'A', b: 'B', c: 'C' }, undefined, undefined, runMode);\n      expect(result).deep.equal([\n        { frame: 10.2, notification: nextNotification('A') },\n        { frame: 10.2 + 10 + 1.2 * 1000, notification: nextNotification('B') },\n        { frame: 10.2 + 10 + 1.2 * 1000 + 10 + 1000 * 60, notification: nextNotification('C') },\n        { frame: 10.2 + 10 + 1.2 * 1000 + 10 + 1000 * 60 + 10, notification: COMPLETE_NOTIFICATION },\n      ]);\n    });\n\n    it('should support emoji characters', () => {\n      const result = TestScheduler.parseMarbles('--🙈--🙉--🙊--|');\n      expect(result).deep.equal([\n        { frame: 20, notification: nextNotification('🙈') },\n        { frame: 50, notification: nextNotification('🙉') },\n        { frame: 80, notification: nextNotification('🙊') },\n        { frame: 110, notification: COMPLETE_NOTIFICATION },\n      ]);\n    });\n  });\n\n  describe('parseMarblesAsSubscriptions()', () => {\n    it('should parse a subscription marble string into a subscriptionLog', () => {\n      const result = TestScheduler.parseMarblesAsSubscriptions('---^---!-');\n      expect(result.subscribedFrame).to.equal(30);\n      expect(result.unsubscribedFrame).to.equal(70);\n    });\n\n    it('should parse a subscription marble string with an unsubscription', () => {\n      const result = TestScheduler.parseMarblesAsSubscriptions('---^-');\n      expect(result.subscribedFrame).to.equal(30);\n      expect(result.unsubscribedFrame).to.equal(Infinity);\n    });\n\n    it('should parse a subscription marble string with a synchronous unsubscription', () => {\n      const result = TestScheduler.parseMarblesAsSubscriptions('---(^!)-');\n      expect(result.subscribedFrame).to.equal(30);\n      expect(result.unsubscribedFrame).to.equal(30);\n    });\n\n    it('should ignore whitespace when runMode=true', () => {\n      const runMode = true;\n      const result = TestScheduler.parseMarblesAsSubscriptions('  - -  - -  ^ -   - !  -- -      ', runMode);\n      expect(result.subscribedFrame).to.equal(40);\n      expect(result.unsubscribedFrame).to.equal(70);\n    });\n\n    it('should support time progression syntax when runMode=true', () => {\n      const runMode = true;\n      const result = TestScheduler.parseMarblesAsSubscriptions('10.2ms ^ 1.2s - 1m !', runMode);\n      expect(result.subscribedFrame).to.equal(10.2);\n      expect(result.unsubscribedFrame).to.equal(10.2 + 10 + 1.2 * 1000 + 10 + 1000 * 60);\n    });\n\n    it('should throw if found more than one subscription point', () => {\n      expect(() => TestScheduler.parseMarblesAsSubscriptions('---^-^-!-')).to.throw();\n    });\n\n    it('should throw if found more than one unsubscription point', () => {\n      expect(() => TestScheduler.parseMarblesAsSubscriptions('---^---!-!')).to.throw();\n    });\n  });\n\n  describe('createTime()', () => {\n    it('should parse a simple time marble string to a number', () => {\n      const scheduler = new TestScheduler(null!);\n      const time = scheduler.createTime('-----|');\n      expect(time).to.equal(50);\n    });\n\n    it('should progress time with whitespace', () => {\n      const scheduler = new TestScheduler(null!);\n      const time = scheduler.createTime('     |');\n      //                                 -----|\n      expect(time).to.equal(50);\n    });\n\n    it('should progress time with mix of whitespace and dashes', () => {\n      const scheduler = new TestScheduler(null!);\n      const time = scheduler.createTime('  --|');\n      expect(time).to.equal(40);\n    });\n\n    it('should throw if not given good marble input', () => {\n      const scheduler = new TestScheduler(null!);\n      expect(() => {\n        scheduler.createTime('-a-b-#');\n      }).to.throw();\n    });\n  });\n\n  describe('createColdObservable()', () => {\n    it('should create a cold observable', () => {\n      const expected = ['A', 'B'];\n      const scheduler = new TestScheduler(null!);\n      const source = scheduler.createColdObservable('--a---b--|', { a: 'A', b: 'B' });\n      expect(source).to.be.an.instanceOf(Observable);\n      source.subscribe((x) => {\n        expect(x).to.equal(expected.shift());\n      });\n      scheduler.flush();\n      expect(expected.length).to.equal(0);\n    });\n  });\n\n  describe('createHotObservable()', () => {\n    it('should create a hot observable', () => {\n      const expected = ['A', 'B'];\n      const scheduler = new TestScheduler(null!);\n      const source = scheduler.createHotObservable('--a---b--|', { a: 'A', b: 'B' });\n      expect(source).to.be.an.instanceof(Subject);\n      source.subscribe((x) => {\n        expect(x).to.equal(expected.shift());\n      });\n      scheduler.flush();\n      expect(expected.length).to.equal(0);\n    });\n  });\n\n  describe('end-to-end helper tests', () => {\n    let testScheduler: TestScheduler;\n\n    beforeEach(() => {\n      testScheduler = new TestScheduler(observableMatcher);\n    });\n\n    it('should be awesome', () => {\n      testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n        const values = { a: 1, b: 2 };\n        const myObservable = cold('---a---b--|', values);\n        const subs = '             ^---------!';\n        const expected = '         ---a---b--|';\n        expectObservable(myObservable).toBe(expected, values);\n        expectSubscriptions(myObservable.subscriptions).toBe(subs);\n      });\n    });\n\n    it('should support testing metastreams', () => {\n      testScheduler.run(({ cold, hot, expectObservable }) => {\n        const x = cold('-a-b|');\n        const y = cold('-c-d|');\n        const myObservable = hot('---x---y----|', { x: x, y: y });\n        const expected = '        ---x---y----|';\n        const expectedx = cold('-a-b|');\n        const expectedy = cold('-c-d|');\n        expectObservable(myObservable).toBe(expected, { x: expectedx, y: expectedy });\n      });\n    });\n  });\n\n  describe('TestScheduler.run()', () => {\n    const assertDeepEquals = (actual: any, expected: any) => {\n      expect(actual).deep.equal(expected);\n    };\n\n    describe('marble diagrams', () => {\n      it('should ignore whitespace', () => {\n        const testScheduler = new TestScheduler(assertDeepEquals);\n\n        testScheduler.run(({ cold, expectObservable, expectSubscriptions }) => {\n          const input = cold('-a-b-c|                 ');\n          const subs = '      ^-----!                 ';\n          const expected = '  -- 9ms a 9ms b 9ms (c|) ';\n\n          const output = input.pipe(concatMap((d) => of(d).pipe(delay(10))));\n\n          expectObservable(output).toBe(expected);\n          expectSubscriptions(input.subscriptions).toBe(subs);\n        });\n      });\n\n      it('should support time progression syntax', () => {\n        const testScheduler = new TestScheduler(assertDeepEquals);\n\n        testScheduler.run(({ cold, expectObservable }) => {\n          const output = cold('10.2ms a 1.2s b 1m c|');\n          const expected = '   10.2ms a 1.2s b 1m c|';\n\n          expectObservable(output).toBe(expected);\n        });\n      });\n    });\n\n    it('should provide the correct helpers', () => {\n      const testScheduler = new TestScheduler(assertDeepEquals);\n\n      testScheduler.run(({ cold, hot, flush, expectObservable, expectSubscriptions }) => {\n        expect(cold).to.be.a('function');\n        expect(hot).to.be.a('function');\n        expect(flush).to.be.a('function');\n        expect(expectObservable).to.be.a('function');\n        expect(expectSubscriptions).to.be.a('function');\n\n        const obs1 = cold('-a-c-e|');\n        const obs2 = hot(' ^-b-d-f|');\n        const output = merge(obs1, obs2);\n        const expected = ' -abcdef|';\n\n        expectObservable(output).toBe(expected);\n        expectObservable(output).toEqual(cold(expected));\n        // There are two subscriptions to each of these, because we merged\n        // them together, then we subscribed to the merged result once\n        // to check `toBe` and another time to check `toEqual`.\n        expectSubscriptions(obs1.subscriptions).toBe(['^-----!', '^-----!']);\n        expectSubscriptions(obs2.subscriptions).toBe(['^------!', '^------!']);\n      });\n    });\n\n    it('should have each frame represent a single virtual millisecond', () => {\n      const testScheduler = new TestScheduler(assertDeepEquals);\n\n      testScheduler.run(({ cold, expectObservable }) => {\n        const output = cold('-a-b-c--------|').pipe(debounceTime(5));\n        const expected = '   ------ 4ms c---|';\n        expectObservable(output).toBe(expected);\n      });\n    });\n\n    it('should have no maximum frame count', () => {\n      const testScheduler = new TestScheduler(assertDeepEquals);\n\n      testScheduler.run(({ cold, expectObservable }) => {\n        const output = cold('-a|').pipe(delay(1000 * 10));\n        const expected = '   - 10s (a|)';\n        expectObservable(output).toBe(expected);\n      });\n    });\n\n    it('should make operators that use AsyncScheduler automatically use TestScheduler for actual scheduling', () => {\n      const testScheduler = new TestScheduler(assertDeepEquals);\n\n      testScheduler.run(({ cold, expectObservable }) => {\n        const output = cold('-a-b-c--------|').pipe(debounceTime(5));\n        const expected = '   ----------c---|';\n        expectObservable(output).toBe(expected);\n      });\n    });\n\n    it('should flush automatically', () => {\n      const testScheduler = new TestScheduler((actual, expected) => {\n        expect(actual).deep.equal(expected);\n      });\n      testScheduler.run(({ cold, expectObservable }) => {\n        const output = cold('-a-b-c|').pipe(concatMap((d) => of(d).pipe(delay(10))));\n        const expected = '   -- 9ms a 9ms b 9ms (c|)';\n        expectObservable(output).toBe(expected);\n\n        expect(testScheduler['flushTests'].length).to.equal(1);\n        expect(testScheduler['actions'].length).to.equal(1);\n      });\n\n      expect(testScheduler['flushTests'].length).to.equal(0);\n      expect(testScheduler['actions'].length).to.equal(0);\n    });\n\n    it('should support explicit flushing', () => {\n      const testScheduler = new TestScheduler(assertDeepEquals);\n\n      testScheduler.run(({ cold, expectObservable, flush }) => {\n        const output = cold('-a-b-c|').pipe(concatMap((d) => of(d).pipe(delay(10))));\n        const expected = '   -- 9ms a 9ms b 9ms (c|)';\n        expectObservable(output).toBe(expected);\n\n        expect(testScheduler['flushTests'].length).to.equal(1);\n        expect(testScheduler['actions'].length).to.equal(1);\n\n        flush();\n\n        expect(testScheduler['flushTests'].length).to.equal(0);\n        expect(testScheduler['actions'].length).to.equal(0);\n      });\n\n      expect(testScheduler['flushTests'].length).to.equal(0);\n      expect(testScheduler['actions'].length).to.equal(0);\n    });\n\n    it('should pass-through return values, e.g. Promises', (done) => {\n      const testScheduler = new TestScheduler(assertDeepEquals);\n\n      testScheduler\n        .run(() => {\n          return Promise.resolve('foo');\n        })\n        .then((value) => {\n          expect(value).to.equal('foo');\n          done();\n        });\n    });\n\n    it('should restore changes upon thrown errors', () => {\n      const testScheduler = new TestScheduler(assertDeepEquals);\n\n      const frameTimeFactor = TestScheduler['frameTimeFactor'];\n      const maxFrames = testScheduler.maxFrames;\n      const runMode = testScheduler['runMode'];\n\n      try {\n        testScheduler.run(() => {\n          throw new Error('kaboom!');\n        });\n      } catch {\n        /* empty */\n      }\n\n      expect(TestScheduler['frameTimeFactor']).to.equal(frameTimeFactor);\n      expect(testScheduler.maxFrames).to.equal(maxFrames);\n      expect(testScheduler['runMode']).to.equal(runMode);\n    });\n\n    it('should flush expectations correctly', () => {\n      expect(() => {\n        const testScheduler = new TestScheduler(assertDeepEquals);\n        testScheduler.run(({ cold, expectObservable, flush }) => {\n          expectObservable(cold('-x')).toBe('-x');\n          expectObservable(cold('-y')).toBe('-y');\n          const expectation = expectObservable(cold('-z'));\n          flush();\n          expectation.toBe('-q');\n        });\n      }).to.throw();\n    });\n\n    describe('animate', () => {\n      it('should throw if animate() is not called when needed', () => {\n        const testScheduler = new TestScheduler(assertDeepEquals);\n        expect(() =>\n          testScheduler.run(() => {\n            animationFrameProvider.schedule(() => {\n              /* pointless lint rule */\n            });\n          })\n        ).to.throw();\n      });\n\n      it('should throw if animate() is called more than once', () => {\n        const testScheduler = new TestScheduler(assertDeepEquals);\n        expect(() =>\n          testScheduler.run(({ animate }) => {\n            animate('--x');\n            animate('--x');\n          })\n        ).to.throw();\n      });\n\n      it('should throw if animate() completes', () => {\n        const testScheduler = new TestScheduler(assertDeepEquals);\n        expect(() =>\n          testScheduler.run(({ animate }) => {\n            animate('--|');\n          })\n        ).to.throw();\n      });\n\n      it('should throw if animate() errors', () => {\n        const testScheduler = new TestScheduler(assertDeepEquals);\n        expect(() =>\n          testScheduler.run(({ animate }) => {\n            animate('--#');\n          })\n        ).to.throw();\n      });\n\n      it('should schedule async requests within animate()', () => {\n        const testScheduler = new TestScheduler(assertDeepEquals);\n        testScheduler.run(({ animate }) => {\n          animate('--x');\n\n          const values: string[] = [];\n          const { schedule } = animationFrameProvider;\n\n          testScheduler.schedule(() => {\n            schedule((t) => values.push(`a@${t}`));\n            expect(values).to.deep.equal([]);\n          }, 0);\n          testScheduler.schedule(() => {\n            schedule((t) => values.push(`b@${t}`));\n            expect(values).to.deep.equal([]);\n          }, 1);\n          testScheduler.schedule(() => {\n            expect(values).to.deep.equal(['a@2', 'b@2']);\n          }, 2);\n        });\n      });\n\n      it('should schedule sync requests within animate()', () => {\n        const testScheduler = new TestScheduler(assertDeepEquals);\n        testScheduler.run(({ animate }) => {\n          animate('--x');\n\n          const values: string[] = [];\n          const { schedule } = animationFrameProvider;\n\n          testScheduler.schedule(() => {\n            schedule((t) => values.push(`a@${t}`));\n            schedule((t) => values.push(`b@${t}`));\n            expect(values).to.deep.equal([]);\n          }, 1);\n          testScheduler.schedule(() => {\n            expect(values).to.deep.equal(['a@2', 'b@2']);\n          }, 2);\n        });\n      });\n\n      it('should support request cancellation within animate()', () => {\n        const testScheduler = new TestScheduler(assertDeepEquals);\n        testScheduler.run(({ animate }) => {\n          animate('--x');\n\n          const values: string[] = [];\n          const { schedule } = animationFrameProvider;\n\n          testScheduler.schedule(() => {\n            const subscription = schedule((t) => values.push(`a@${t}`));\n            schedule((t) => values.push(`b@${t}`));\n            subscription.unsubscribe();\n            expect(values).to.deep.equal([]);\n          }, 1);\n          testScheduler.schedule(() => {\n            expect(values).to.deep.equal(['b@2']);\n          }, 2);\n        });\n      });\n    });\n\n    describe('immediate and interval', () => {\n      it('should schedule immediates', () => {\n        const testScheduler = new TestScheduler(assertDeepEquals);\n        testScheduler.run(() => {\n          const values: string[] = [];\n          const { setImmediate } = immediateProvider;\n          setImmediate(() => {\n            values.push(`a@${testScheduler.now()}`);\n          });\n          expect(values).to.deep.equal([]);\n          testScheduler.schedule(() => {\n            expect(values).to.deep.equal(['a@0']);\n          }, 10);\n        });\n      });\n\n      it('should support clearing immediates', () => {\n        const testScheduler = new TestScheduler(assertDeepEquals);\n        testScheduler.run(() => {\n          const values: string[] = [];\n          const { setImmediate, clearImmediate } = immediateProvider;\n          const handle = setImmediate(() => {\n            values.push(`a@${testScheduler.now()}`);\n          });\n          expect(values).to.deep.equal([]);\n          clearImmediate(handle);\n          testScheduler.schedule(() => {\n            expect(values).to.deep.equal([]);\n          }, 10);\n        });\n      });\n\n      it('should schedule intervals', () => {\n        const testScheduler = new TestScheduler(assertDeepEquals);\n        testScheduler.run(() => {\n          const values: string[] = [];\n          const { setInterval, clearInterval } = intervalProvider;\n          const handle = setInterval(() => {\n            values.push(`a@${testScheduler.now()}`);\n            clearInterval(handle);\n          }, 1);\n          expect(values).to.deep.equal([]);\n          testScheduler.schedule(() => {\n            expect(values).to.deep.equal(['a@1']);\n          }, 10);\n        });\n      });\n\n      it('should reschedule intervals until cleared', () => {\n        const testScheduler = new TestScheduler(assertDeepEquals);\n        testScheduler.run(() => {\n          const values: string[] = [];\n          const { setInterval, clearInterval } = intervalProvider;\n          const handle = setInterval(() => {\n            if (testScheduler.now() <= 3) {\n              values.push(`a@${testScheduler.now()}`);\n            } else {\n              clearInterval(handle);\n            }\n          }, 1);\n          expect(values).to.deep.equal([]);\n          testScheduler.schedule(() => {\n            expect(values).to.deep.equal(['a@1', 'a@2', 'a@3']);\n          }, 10);\n        });\n      });\n\n      it('should schedule timeouts', () => {\n        const testScheduler = new TestScheduler(assertDeepEquals);\n        testScheduler.run(() => {\n          const values: string[] = [];\n          const { setTimeout } = timeoutProvider;\n          setTimeout(() => {\n            values.push(`a@${testScheduler.now()}`);\n          }, 1);\n          expect(values).to.deep.equal([]);\n          testScheduler.schedule(() => {\n            expect(values).to.deep.equal(['a@1']);\n          }, 10);\n        });\n      });\n\n      it('should schedule immediates before intervals and timeouts', () => {\n        const testScheduler = new TestScheduler(assertDeepEquals);\n        testScheduler.run(() => {\n          const values: string[] = [];\n          const { setImmediate } = immediateProvider;\n          const { setInterval, clearInterval } = intervalProvider;\n          const { setTimeout } = timeoutProvider;\n          const handle = setInterval(() => {\n            values.push(`a@${testScheduler.now()}`);\n            clearInterval(handle);\n          }, 0);\n          setTimeout(() => {\n            values.push(`b@${testScheduler.now()}`);\n          }, 0);\n          setImmediate(() => {\n            values.push(`c@${testScheduler.now()}`);\n          });\n          expect(values).to.deep.equal([]);\n          testScheduler.schedule(() => {\n            expect(values).to.deep.equal(['c@0', 'a@0', 'b@0']);\n          }, 10);\n        });\n      });\n    });\n\n    describe('schedulers', () => {\n      it('should support animationFrameScheduler, async and asap schedulers', () => {\n        const testScheduler = new TestScheduler(assertDeepEquals);\n        testScheduler.run(({ animate, cold, expectObservable, time }) => {\n          animate('            ---------x');\n          const mapped = cold('--m-------');\n          const tb = time('      -----|  ');\n          const expected = '   --(dc)-b-a';\n          const result = mapped.pipe(\n            mergeMap(() =>\n              merge(\n                of('a').pipe(delay(0, animationFrameScheduler)),\n                of('b').pipe(delay(tb, asyncScheduler)),\n                of('c').pipe(delay(0, asyncScheduler)),\n                of('d').pipe(delay(0, asapScheduler))\n              )\n            )\n          );\n          expectObservable(result).toBe(expected);\n        });\n      });\n\n      it('should emit asap notifications before async notifications', () => {\n        const testScheduler = new TestScheduler(assertDeepEquals);\n        testScheduler.run(({ cold, expectObservable }) => {\n          const mapped = cold('--ab------');\n          const expected = '   ---(ba)---';\n          const result = mapped.pipe(\n            mergeMap((value) => (value === 'a' ? of(value).pipe(delay(1, asyncScheduler)) : of(value).pipe(delay(0, asapScheduler))))\n          );\n          expectObservable(result).toBe(expected);\n        });\n      });\n\n      it('should support intervals with zero duration', () => {\n        const testScheduler = new TestScheduler(assertDeepEquals);\n        testScheduler.run(({ cold, expectObservable }) => {\n          const mapped = cold('--m-------');\n          const expected = '   --(bbbaaa)';\n          const result = mapped.pipe(\n            mergeMap(() =>\n              merge(interval(0, asyncScheduler).pipe(mapTo('a'), take(3)), interval(0, asapScheduler).pipe(mapTo('b'), take(3)))\n            )\n          );\n          expectObservable(result).toBe(expected);\n        });\n      });\n    });\n\n    describe('time', () => {\n      it('should parse a simple time marble string to a number', () => {\n        const testScheduler = new TestScheduler(assertDeepEquals);\n\n        testScheduler.run(({ time }) => {\n          const t = time('--|');\n          expect(t).to.equal(2);\n        });\n      });\n\n      it('should ignore whitespace', () => {\n        const testScheduler = new TestScheduler(assertDeepEquals);\n\n        testScheduler.run(({ time }) => {\n          const t = time('  --|');\n          expect(t).to.equal(2);\n        });\n      });\n\n      it('should throw if not given good marble input (#)', () => {\n        const testScheduler = new TestScheduler(assertDeepEquals);\n\n        testScheduler.run(({ time }) => {\n          expect(() => {\n            time('-a-b-#');\n          }).to.throw();\n        });\n      });\n\n      it('should throw if not given good marble input (!)', () => {\n        const testScheduler = new TestScheduler(assertDeepEquals);\n\n        testScheduler.run(({ time }) => {\n          expect(() => {\n            time('-a-b-!');\n          }).to.throw();\n        });\n      });\n    });\n\n    it('should unsubscribe source with toBe', () => {\n      const testScheduler = new TestScheduler(assertDeepEquals);\n      let disposed = false;\n      testScheduler.run(({ expectObservable }) => {\n        expectObservable(new Observable((_) => () => (disposed = true)), '^!').toBe('');\n      });\n      expect(disposed).to.be.true;\n    });\n\n    it('should unsubscribe source with toEqual', () => {\n      const testScheduler = new TestScheduler(assertDeepEquals);\n      let disposed = false;\n      testScheduler.run(({ cold, expectObservable }) => {\n        expectObservable(new Observable((_) => () => (disposed = true)), '^!').toEqual(cold(''));\n      });\n      expect(disposed).to.be.true;\n    });\n\n    it('should unsubscribe the expected observable with toEqual', () => {\n      const testScheduler = new TestScheduler(assertDeepEquals);\n      let disposed = false;\n      testScheduler.run(({ cold, expectObservable }) => {\n        expectObservable(cold(''), '^!').toEqual(new Observable((_) => () => (disposed = true)));\n      });\n      expect(disposed).to.be.true;\n    });\n  });\n});\n"
  },
  {
    "path": "packages/rxjs/spec/schedulers/VirtualTimeScheduler-spec.ts",
    "content": "/** @prettier */\nimport { expect } from 'chai';\nimport type { SchedulerAction} from 'rxjs';\nimport { VirtualAction, VirtualTimeScheduler } from 'rxjs';\n\n/** @test {VirtualTimeScheduler} */\ndescribe('VirtualTimeScheduler', () => {\n  it('should exist', () => {\n    expect(VirtualTimeScheduler).exist;\n    expect(VirtualTimeScheduler).to.be.a('function');\n  });\n\n  it('should schedule things in order when flushed if each this is scheduled synchronously', () => {\n    const v = new VirtualTimeScheduler();\n    const invoked: number[] = [];\n    const invoke: any = (state: number) => {\n      invoked.push(state);\n    };\n    v.schedule(invoke, 0, 1);\n    v.schedule(invoke, 0, 2);\n    v.schedule(invoke, 0, 3);\n    v.schedule(invoke, 0, 4);\n    v.schedule(invoke, 0, 5);\n\n    v.flush();\n\n    expect(invoked).to.deep.equal([1, 2, 3, 4, 5]);\n  });\n\n  it('should schedule things in order when flushed if each this is scheduled at random', () => {\n    const v = new VirtualTimeScheduler();\n    const invoked: number[] = [];\n    const invoke: any = (state: number) => {\n      invoked.push(state);\n    };\n    v.schedule(invoke, 0, 1);\n    v.schedule(invoke, 100, 2);\n    v.schedule(invoke, 0, 3);\n    v.schedule(invoke, 500, 4);\n    v.schedule(invoke, 0, 5);\n    v.schedule(invoke, 100, 6);\n\n    v.flush();\n\n    expect(invoked).to.deep.equal([1, 3, 5, 2, 6, 4]);\n  });\n\n  it('should schedule things in order when there are negative delays', () => {\n    const v = new VirtualTimeScheduler();\n    const invoked: number[] = [];\n    const invoke: any = (state: number) => {\n      invoked.push(state);\n    };\n    v.schedule(invoke, 0, 1);\n    v.schedule(invoke, 100, 2);\n    v.schedule(invoke, 0, 3);\n    v.schedule(invoke, -2, 4);\n    v.schedule(invoke, 0, 5);\n    v.schedule(invoke, -10, 6);\n\n    v.flush();\n\n    expect(invoked).to.deep.equal([6, 4, 1, 3, 5, 2]);\n  });\n\n  it('should support recursive scheduling', () => {\n    const v = new VirtualTimeScheduler();\n    let count = 0;\n    const expected = [100, 200, 300];\n\n    v.schedule<string>(\n      function (this: SchedulerAction<string>, state?: string) {\n        if (++count === 3) {\n          return;\n        }\n        const virtualAction = this as VirtualAction<string>;\n        expect(virtualAction.delay).to.equal(expected.shift());\n        this.schedule(state, virtualAction.delay);\n      },\n      100,\n      'test'\n    );\n\n    v.flush();\n    expect(count).to.equal(3);\n  });\n\n  it('should not execute virtual actions that have been rescheduled before flush', () => {\n    const v = new VirtualTimeScheduler();\n    const messages: string[] = [];\n\n    const action: VirtualAction<string> = <VirtualAction<string>>v.schedule((state) => messages.push(state!), 10, 'first message');\n\n    action.schedule('second message', 10);\n    v.flush();\n\n    expect(messages).to.deep.equal(['second message']);\n  });\n\n  it('should execute only those virtual actions that fall into the maxFrames timespan', function () {\n    const MAX_FRAMES = 50;\n    const v = new VirtualTimeScheduler(VirtualAction, MAX_FRAMES);\n    const messages: string[] = ['first message', 'second message', 'third message'];\n\n    const actualMessages: string[] = [];\n\n    messages.forEach((message, index) => {\n      v.schedule((state) => actualMessages.push(state!), index * MAX_FRAMES, message);\n    });\n\n    v.flush();\n\n    expect(actualMessages).to.deep.equal(['first message', 'second message']);\n    expect(v.actions.map((a) => a.state)).to.deep.equal(['third message']);\n  });\n\n  it('should pick up actions execution where it left off after reaching previous maxFrames limit', function () {\n    const MAX_FRAMES = 50;\n    const v = new VirtualTimeScheduler(VirtualAction, MAX_FRAMES);\n    const messages: string[] = ['first message', 'second message', 'third message'];\n\n    const actualMessages: string[] = [];\n\n    messages.forEach((message, index) => {\n      v.schedule((state) => actualMessages.push(state!), index * MAX_FRAMES, message);\n    });\n\n    v.flush();\n    v.maxFrames = 2 * MAX_FRAMES;\n    v.flush();\n\n    expect(actualMessages).to.deep.equal(messages);\n  });\n});\n"
  },
  {
    "path": "packages/rxjs/spec/schedulers/animationFrameProvider-spec.ts",
    "content": "/** @prettier */\nimport { expect } from 'chai';\nimport { animationFrameProvider } from 'rxjs/internal/scheduler/animationFrameProvider';\n\ndescribe('animationFrameProvider', () => {\n  const originalRequest = global.requestAnimationFrame;\n  const originalCancel = global.cancelAnimationFrame;\n\n  afterEach(() => {\n    global.requestAnimationFrame = originalRequest;\n    global.cancelAnimationFrame = originalCancel;\n  });\n\n  it('should be monkey patchable', () => {\n    let requestCalled = false;\n    let cancelCalled = false;\n\n    global.requestAnimationFrame = () => {\n      requestCalled = true;\n      return 0;\n    };\n    global.cancelAnimationFrame = () => {\n      cancelCalled = true;\n    };\n\n    const handle = animationFrameProvider.requestAnimationFrame(() => {\n      /* noop */\n    });\n    animationFrameProvider.cancelAnimationFrame(handle);\n\n    expect(requestCalled).to.be.true;\n    expect(cancelCalled).to.be.true;\n  });\n});\n"
  },
  {
    "path": "packages/rxjs/spec/schedulers/dateTimestampProvider-spec.ts",
    "content": "/** @prettier */\nimport { expect } from 'chai';\nimport { dateTimestampProvider } from 'rxjs/internal/scheduler/dateTimestampProvider';\n\ndescribe('dateTimestampProvider', () => {\n  const originalDate = global.Date;\n\n  afterEach(() => {\n    global.Date = originalDate;\n  });\n\n  it('should be monkey patchable', () => {\n    let nowCalled = false;\n\n    global.Date = {\n      now() {\n        nowCalled = true;\n        return 0;\n      },\n    } as any;\n\n    dateTimestampProvider.now();\n\n    expect(nowCalled).to.be.true;\n  });\n});\n"
  },
  {
    "path": "packages/rxjs/spec/schedulers/intervalProvider-spec.ts",
    "content": "/** @prettier */\nimport { expect } from 'chai';\nimport { intervalProvider } from 'rxjs/internal/scheduler/intervalProvider';\n\ndescribe('intervalProvider', () => {\n  const originalSet = global.setInterval;\n  const originalClear = global.clearInterval;\n\n  afterEach(() => {\n    global.setInterval = originalSet;\n    global.clearInterval = originalClear;\n  });\n\n  it('should be monkey patchable', () => {\n    let setCalled = false;\n    let clearCalled = false;\n\n    global.setInterval = (() => {\n      setCalled = true;\n      return 0 as any;\n    }) as any; // TypeScript complains about a __promisify__ property\n    global.clearInterval = () => {\n      clearCalled = true;\n    };\n\n    const handle = intervalProvider.setInterval(() => {\n      /* noop */\n    });\n    intervalProvider.clearInterval(handle);\n\n    expect(setCalled).to.be.true;\n    expect(clearCalled).to.be.true;\n  });\n});\n"
  },
  {
    "path": "packages/rxjs/spec/schedulers/timeoutProvider-spec.ts",
    "content": "/** @prettier */\nimport { expect } from 'chai';\nimport { timeoutProvider } from 'rxjs/internal/scheduler/timeoutProvider';\n\ndescribe('timeoutProvider', () => {\n  const originalSet = global.setTimeout;\n  const originalClear = global.clearTimeout;\n\n  afterEach(() => {\n    global.setTimeout = originalSet;\n    global.clearTimeout = originalClear;\n  });\n\n  it('should be monkey patchable', () => {\n    let setCalled = false;\n    let clearCalled = false;\n\n    global.setTimeout = (() => {\n      setCalled = true;\n      return 0 as any;\n    }) as any;\n    global.clearTimeout = () => {\n      clearCalled = true;\n    };\n\n    const handle = timeoutProvider.setTimeout(() => {\n      /* noop */\n    });\n    timeoutProvider.clearTimeout(handle);\n\n    expect(setCalled).to.be.true;\n    expect(clearCalled).to.be.true;\n  });\n});\n"
  },
  {
    "path": "packages/rxjs/spec/subjects/AsyncSubject-spec.ts",
    "content": "import { expect } from 'chai';\nimport type { Observer } from 'rxjs';\nimport { AsyncSubject } from 'rxjs';\n\nclass TestObserver implements Observer<number> {\n  results: (number | string)[] = [];\n\n  next(value: number): void {\n    this.results.push(value);\n  }\n\n  error(err: any): void {\n    this.results.push(err);\n  }\n\n  complete(): void {\n    this.results.push('done');\n  }\n}\n\n/** @test {AsyncSubject} */\ndescribe('AsyncSubject', () => {\n  it('should emit the last value when complete', () => {\n    const subject = new AsyncSubject<number>();\n    const observer = new TestObserver();\n    subject.subscribe(observer);\n\n    subject.next(1);\n    expect(observer.results).to.deep.equal([]);\n    subject.next(2);\n    expect(observer.results).to.deep.equal([]);\n    subject.complete();\n    expect(observer.results).to.deep.equal([2, 'done']);\n  });\n\n  it('should emit the last value when subscribing after complete', () => {\n    const subject = new AsyncSubject<number>();\n    const observer = new TestObserver();\n\n    subject.next(1);\n    subject.next(2);\n    subject.complete();\n\n    subject.subscribe(observer);\n    expect(observer.results).to.deep.equal([2, 'done']);\n  });\n\n  it('should keep emitting the last value to subsequent subscriptions', () => {\n    const subject = new AsyncSubject<number>();\n    const observer = new TestObserver();\n    const subscription = subject.subscribe(observer);\n\n    subject.next(1);\n    expect(observer.results).to.deep.equal([]);\n    subject.next(2);\n    expect(observer.results).to.deep.equal([]);\n    subject.complete();\n    expect(observer.results).to.deep.equal([2, 'done']);\n\n    subscription.unsubscribe();\n\n    observer.results = [];\n    subject.subscribe(observer);\n    expect(observer.results).to.deep.equal([2, 'done']);\n  });\n\n  it('should not emit values after complete', () => {\n    const subject = new AsyncSubject<number>();\n    const observer = new TestObserver();\n\n    subject.subscribe(observer);\n\n    subject.next(1);\n    expect(observer.results).to.deep.equal([]);\n    subject.next(2);\n    expect(observer.results).to.deep.equal([]);\n    subject.complete();\n    subject.next(3);\n    expect(observer.results).to.deep.equal([2, 'done']);\n  });\n\n  it('should not allow change value after complete', () => {\n    const subject = new AsyncSubject<number>();\n    const observer = new TestObserver();\n    const otherObserver = new TestObserver();\n    subject.subscribe(observer);\n\n    subject.next(1);\n    expect(observer.results).to.deep.equal([]);\n    subject.complete();\n    expect(observer.results).to.deep.equal([1, 'done']);\n    subject.next(2);\n    subject.subscribe(otherObserver);\n    expect(otherObserver.results).to.deep.equal([1, 'done']);\n  });\n\n  it('should not emit values if unsubscribed before complete', () => {\n    const subject = new AsyncSubject<number>();\n    const observer = new TestObserver();\n    const subscription = subject.subscribe(observer);\n\n    subject.next(1);\n    expect(observer.results).to.deep.equal([]);\n    subject.next(2);\n    expect(observer.results).to.deep.equal([]);\n\n    subscription.unsubscribe();\n\n    subject.next(3);\n    expect(observer.results).to.deep.equal([]);\n    subject.complete();\n    expect(observer.results).to.deep.equal([]);\n  });\n\n  it('should just complete if no value has been nexted into it', () => {\n    const subject = new AsyncSubject<number>();\n    const observer = new TestObserver();\n    subject.subscribe(observer);\n\n    expect(observer.results).to.deep.equal([]);\n    subject.complete();\n    expect(observer.results).to.deep.equal(['done']);\n  });\n\n  it('should keep emitting complete to subsequent subscriptions', () => {\n    const subject = new AsyncSubject<number>();\n    const observer = new TestObserver();\n    const subscription = subject.subscribe(observer);\n\n    expect(observer.results).to.deep.equal([]);\n    subject.complete();\n    expect(observer.results).to.deep.equal(['done']);\n\n    subscription.unsubscribe();\n    observer.results = [];\n\n    subject.error(new Error(''));\n\n    subject.subscribe(observer);\n    expect(observer.results).to.deep.equal(['done']);\n  });\n\n  it('should only error if an error is passed into it', () => {\n    const expected = new Error('bad');\n    const subject = new AsyncSubject<number>();\n    const observer = new TestObserver();\n    subject.subscribe(observer);\n\n    subject.next(1);\n    expect(observer.results).to.deep.equal([]);\n\n    subject.error(expected);\n    expect(observer.results).to.deep.equal([expected]);\n  });\n\n  it('should keep emitting error to subsequent subscriptions', () => {\n    const expected = new Error('bad');\n    const subject = new AsyncSubject<number>();\n    const observer = new TestObserver();\n    const subscription = subject.subscribe(observer);\n\n    subject.next(1);\n    expect(observer.results).to.deep.equal([]);\n\n    subject.error(expected);\n    expect(observer.results).to.deep.equal([expected]);\n\n    subscription.unsubscribe();\n\n    observer.results = [];\n    subject.subscribe(observer);\n    expect(observer.results).to.deep.equal([expected]);\n  });\n\n  it('should not allow send complete after error', () => {\n    const expected = new Error('bad');\n    const subject = new AsyncSubject<number>();\n    const observer = new TestObserver();\n    const subscription = subject.subscribe(observer);\n\n    subject.next(1);\n    expect(observer.results).to.deep.equal([]);\n\n    subject.error(expected);\n    expect(observer.results).to.deep.equal([expected]);\n\n    subscription.unsubscribe();\n\n    observer.results = [];\n\n    subject.complete();\n    subject.subscribe(observer);\n    expect(observer.results).to.deep.equal([expected]);\n  });\n\n  it('should not be reentrant via complete', () => {\n    const subject = new AsyncSubject<number>();\n    let calls = 0;\n    subject.subscribe({\n      next: (value) => {\n        calls++;\n        if (calls < 2) {\n          // if this is more than 1, we're reentrant, and that's bad.\n          subject.complete();\n        }\n      },\n    });\n\n    subject.next(1);\n    subject.complete();\n\n    expect(calls).to.equal(1);\n  });\n\n  it('should not be reentrant via next', () => {\n    const subject = new AsyncSubject<number>();\n    let calls = 0;\n    subject.subscribe({\n      next: (value) => {\n        calls++;\n        if (calls < 2) {\n          // if this is more than 1, we're reentrant, and that's bad.\n          subject.next(value + 1);\n        }\n      },\n    });\n\n    subject.next(1);\n    subject.complete();\n\n    expect(calls).to.equal(1);\n  });\n\n  it('should allow reentrant subscriptions', () => {\n    const subject = new AsyncSubject<number>();\n    const results: any[] = [];\n\n    subject.subscribe({\n      next: (value) => {\n        subject.subscribe({\n          next: (value) => results.push('inner: ' + (value + value)),\n          complete: () => results.push('inner: done'),\n        });\n        results.push('outer: ' + value);\n      },\n      complete: () => results.push('outer: done'),\n    });\n\n    subject.next(1);\n    expect(results).to.deep.equal([]);\n    subject.complete();\n    expect(results).to.deep.equal(['inner: 2', 'inner: done', 'outer: 1', 'outer: done']);\n  });\n});\n"
  },
  {
    "path": "packages/rxjs/spec/subjects/BehaviorSubject-spec.ts",
    "content": "import { expect } from 'chai';\nimport { BehaviorSubject, Subject, of } from 'rxjs';\nimport { tap, mergeMapTo } from 'rxjs/operators';\nimport { asInteropSubject } from '../helpers/interop-helper';\nimport { TestScheduler } from 'rxjs/testing';\nimport { observableMatcher } from '../helpers/observableMatcher';\n\n/** @test {BehaviorSubject} */\ndescribe('BehaviorSubject', () => {\n  let testScheduler: TestScheduler;\n\n  beforeEach(() => {\n    testScheduler = new TestScheduler(observableMatcher);\n  });\n\n  it('should extend Subject', () => {\n    const subject = new BehaviorSubject(null);\n    expect(subject).to.be.instanceof(Subject);\n  });\n\n  it('should throw if it has received an error and getValue() is called', () => {\n    const subject = new BehaviorSubject(null);\n    subject.error(new Error('derp'));\n    expect(() => {\n      subject.getValue();\n    }).to.throw(Error, 'derp');\n  });\n\n  it('should be closed if unsubscribed', () => {\n    const subject = new BehaviorSubject('hi there');\n    subject.unsubscribe();\n    expect(subject.closed).to.be.true;\n  });\n\n  it('should not be closed if not unsubscribed', () => {\n    const subject = new BehaviorSubject('hi there');\n    expect(subject.closed).to.be.false;\n  });\n\n  it('should be closed if it has received an error', () => {\n    const subject = new BehaviorSubject('hi there');\n    subject.error(new Error('derp'));\n    expect(subject.closed).to.be.true;\n  });\n\n  it('should be closed if it has received a complete notification', () => {\n    const subject = new BehaviorSubject('hi there');\n    subject.complete();\n    expect(subject.closed).to.be.true;\n  });\n\n  it('should have a getValue() method to retrieve the current value', () => {\n    const subject = new BehaviorSubject('staltz');\n    expect(subject.getValue()).to.equal('staltz');\n\n    subject.next('oj');\n\n    expect(subject.getValue()).to.equal('oj');\n  });\n\n  it('should not allow you to set `value` directly', () => {\n    const subject = new BehaviorSubject('flibberty');\n\n    try {\n      // XXX: escape from readonly restriction for testing.\n      (subject as any).value = 'jibbets';\n    } catch (e) {\n      //noop\n    }\n\n    expect(subject.getValue()).to.equal('flibberty');\n    expect(subject.value).to.equal('flibberty');\n  });\n\n  it('should still allow you to retrieve the value from the value property', () => {\n    const subject = new BehaviorSubject('fuzzy');\n    expect(subject.value).to.equal('fuzzy');\n    subject.next('bunny');\n    expect(subject.value).to.equal('bunny');\n  });\n\n  it('should start with an initialization value', (done) => {\n    const subject = new BehaviorSubject('foo');\n    const expected = ['foo', 'bar'];\n    let i = 0;\n\n    subject.subscribe({\n      next: (x: string) => {\n        expect(x).to.equal(expected[i++]);\n      },\n      complete: done,\n    });\n\n    subject.next('bar');\n    subject.complete();\n  });\n\n  it('should pump values to multiple subscribers', (done) => {\n    const subject = new BehaviorSubject('init');\n    const expected = ['init', 'foo', 'bar'];\n    let i = 0;\n    let j = 0;\n\n    subject.subscribe((x: string) => {\n      expect(x).to.equal(expected[i++]);\n    });\n\n    subject.subscribe({\n      next: (x: string) => {\n        expect(x).to.equal(expected[j++]);\n      },\n      complete: done,\n    });\n\n    expect(subject.observers.length).to.equal(2);\n    subject.next('foo');\n    subject.next('bar');\n    subject.complete();\n  });\n\n  it('should not pass values nexted after a complete', () => {\n    const subject = new BehaviorSubject('init');\n    const results: string[] = [];\n\n    subject.subscribe((x: string) => {\n      results.push(x);\n    });\n    expect(results).to.deep.equal(['init']);\n\n    subject.next('foo');\n    expect(results).to.deep.equal(['init', 'foo']);\n\n    subject.complete();\n    expect(results).to.deep.equal(['init', 'foo']);\n\n    subject.next('bar');\n    expect(results).to.deep.equal(['init', 'foo']);\n  });\n\n  it('should clean out unsubscribed subscribers', (done) => {\n    const subject = new BehaviorSubject('init');\n\n    const sub1 = subject.subscribe((x: string) => {\n      expect(x).to.equal('init');\n    });\n\n    const sub2 = subject.subscribe((x: string) => {\n      expect(x).to.equal('init');\n    });\n\n    expect(subject.observers.length).to.equal(2);\n    sub1.unsubscribe();\n    expect(subject.observers.length).to.equal(1);\n    sub2.unsubscribe();\n    expect(subject.observers.length).to.equal(0);\n    done();\n  });\n\n  it('should replay the previous value when subscribed', () => {\n    testScheduler.run(({ hot, expectObservable }) => {\n      const behaviorSubject = new BehaviorSubject('0');\n      function feedNextIntoSubject(x: string) {\n        behaviorSubject.next(x);\n      }\n      function feedErrorIntoSubject(err: any) {\n        behaviorSubject.error(err);\n      }\n      function feedCompleteIntoSubject() {\n        behaviorSubject.complete();\n      }\n\n      const sourceTemplate = ' -1-2-3----4------5-6---7--8----9--|';\n      const subscriber1 = hot('------(a|)                         ').pipe(mergeMapTo(behaviorSubject));\n      const unsub1 = '         ---------------------!             ';\n      const expected1 = '      ------3---4------5-6--             ';\n      const subscriber2 = hot('------------(b|)                   ').pipe(mergeMapTo(behaviorSubject));\n      const unsub2 = '         -------------------------!         ';\n      const expected2 = '      ------------4----5-6---7--         ';\n      const subscriber3 = hot('---------------------------(c|)    ').pipe(mergeMapTo(behaviorSubject));\n      const expected3 = '      ---------------------------8---9--|';\n\n      expectObservable(\n        hot(sourceTemplate).pipe(tap({ next: feedNextIntoSubject, error: feedErrorIntoSubject, complete: feedCompleteIntoSubject }))\n      ).toBe(sourceTemplate);\n      expectObservable(subscriber1, unsub1).toBe(expected1);\n      expectObservable(subscriber2, unsub2).toBe(expected2);\n      expectObservable(subscriber3).toBe(expected3);\n    });\n  });\n\n  it('should emit complete when subscribed after completed', () => {\n    testScheduler.run(({ hot, expectObservable }) => {\n      const behaviorSubject = new BehaviorSubject('0');\n      function feedNextIntoSubject(x: string) {\n        behaviorSubject.next(x);\n      }\n      function feedErrorIntoSubject(err: any) {\n        behaviorSubject.error(err);\n      }\n      function feedCompleteIntoSubject() {\n        behaviorSubject.complete();\n      }\n\n      const sourceTemplate = ' -1-2-3--4--|       ';\n      const subscriber1 = hot('---------------(a|)').pipe(mergeMapTo(behaviorSubject));\n      const expected1 = '      ---------------|   ';\n\n      expectObservable(\n        hot(sourceTemplate).pipe(tap({ next: feedNextIntoSubject, error: feedErrorIntoSubject, complete: feedCompleteIntoSubject }))\n      ).toBe(sourceTemplate);\n      expectObservable(subscriber1).toBe(expected1);\n    });\n  });\n\n  it('should be an Observer which can be given to Observable.subscribe', (done) => {\n    const source = of(1, 2, 3, 4, 5);\n    const subject = new BehaviorSubject(0);\n    const expected = [0, 1, 2, 3, 4, 5];\n\n    subject.subscribe({\n      next: (x: number) => {\n        expect(x).to.equal(expected.shift());\n      },\n      error: (x) => {\n        done(new Error('should not be called'));\n      },\n      complete: () => {\n        expect(subject.value).to.equal(5);\n        done();\n      },\n    });\n\n    source.subscribe(subject);\n  });\n\n  it('should be an Observer which can be given to an interop source', (done) => {\n    // This test reproduces a bug reported in this issue:\n    // https://github.com/ReactiveX/rxjs/issues/5105\n    // However, it cannot easily be fixed. See this comment:\n    // https://github.com/ReactiveX/rxjs/issues/5105#issuecomment-578405446\n    const source = of(1, 2, 3, 4, 5);\n    const subject = new BehaviorSubject(0);\n    const expected = [0, 1, 2, 3, 4, 5];\n\n    subject.subscribe({\n      next: (x: number) => {\n        expect(x).to.equal(expected.shift());\n      },\n      error: (x) => {\n        done(new Error('should not be called'));\n      },\n      complete: () => {\n        expect(subject.value).to.equal(5);\n        done();\n      },\n    });\n\n    source.subscribe(asInteropSubject(subject));\n  });\n});\n"
  },
  {
    "path": "packages/rxjs/spec/subjects/ReplaySubject-spec.ts",
    "content": "import { expect } from 'chai';\nimport { ReplaySubject, Subject, of } from 'rxjs';\nimport { mergeMapTo, tap } from 'rxjs/operators';\nimport { TestScheduler } from 'rxjs/testing';\nimport { observableMatcher } from '../helpers/observableMatcher';\n\n/** @test {ReplaySubject} */\ndescribe('ReplaySubject', () => {\n  let rxTestScheduler: TestScheduler;\n\n  beforeEach(() => {\n    rxTestScheduler = new TestScheduler(observableMatcher);\n  });\n\n  it('should extend Subject', () => {\n    const subject = new ReplaySubject();\n    expect(subject).to.be.instanceof(Subject);\n  });\n\n  it('should add the observer before running subscription code', () => {\n    const subject = new ReplaySubject<number>();\n    subject.next(1);\n    const results: number[] = [];\n\n    subject.subscribe((value) => {\n      results.push(value);\n      if (value < 3) {\n        subject.next(value + 1);\n      }\n    });\n\n    expect(results).to.deep.equal([1, 2, 3]);\n  });\n\n  it('should replay values upon subscription', (done) => {\n    const subject = new ReplaySubject<number>();\n    const expects = [1, 2, 3];\n    let i = 0;\n    subject.next(1);\n    subject.next(2);\n    subject.next(3);\n    subject.subscribe({\n      next: (x: number) => {\n        expect(x).to.equal(expects[i++]);\n        if (i === 3) {\n          subject.complete();\n        }\n      },\n      error: (err: any) => {\n        done(new Error('should not be called'));\n      },\n      complete: () => {\n        done();\n      },\n    });\n  });\n\n  it('should replay values and complete', (done) => {\n    const subject = new ReplaySubject<number>();\n    const expects = [1, 2, 3];\n    let i = 0;\n    subject.next(1);\n    subject.next(2);\n    subject.next(3);\n    subject.complete();\n    subject.subscribe({\n      next: (x: number) => {\n        expect(x).to.equal(expects[i++]);\n      },\n      complete: done,\n    });\n  });\n\n  it('should replay values and error', (done) => {\n    const subject = new ReplaySubject<number>();\n    const expects = [1, 2, 3];\n    let i = 0;\n    subject.next(1);\n    subject.next(2);\n    subject.next(3);\n    subject.error('fooey');\n    subject.subscribe({\n      next: (x: number) => {\n        expect(x).to.equal(expects[i++]);\n      },\n      error: (err: any) => {\n        expect(err).to.equal('fooey');\n        done();\n      },\n    });\n  });\n\n  it('should only replay values within its buffer size', (done) => {\n    const subject = new ReplaySubject<number>(2);\n    const expects = [2, 3];\n    let i = 0;\n    subject.next(1);\n    subject.next(2);\n    subject.next(3);\n    subject.subscribe({\n      next: (x: number) => {\n        expect(x).to.equal(expects[i++]);\n        if (i === 2) {\n          subject.complete();\n        }\n      },\n      error: (err: any) => {\n        done(new Error('should not be called'));\n      },\n      complete: () => {\n        done();\n      },\n    });\n  });\n\n  describe('with bufferSize=2', () => {\n    it('should replay 2 previous values when subscribed', () => {\n      rxTestScheduler.run(({ hot, expectObservable }) => {\n        const replaySubject = new ReplaySubject<string>(2);\n        function feedNextIntoSubject(x: string) {\n          replaySubject.next(x);\n        }\n        function feedErrorIntoSubject(err: string) {\n          replaySubject.error(err);\n        }\n        function feedCompleteIntoSubject() {\n          replaySubject.complete();\n        }\n\n        const sourceTemplate = ' -1-2-3----4------5-6---7--8----9--|';\n        const subscriber1 = hot('------(a|)                         ').pipe(mergeMapTo(replaySubject));\n        const unsub1 = '         ---------------------!             ';\n        const expected1 = '      ------(23)4------5-6--             ';\n        const subscriber2 = hot('------------(b|)                   ').pipe(mergeMapTo(replaySubject));\n        const unsub2 = '         -------------------------!         ';\n        const expected2 = '      ------------(34)-5-6---7--         ';\n        const subscriber3 = hot('---------------------------(c|)    ').pipe(mergeMapTo(replaySubject));\n        const expected3 = '      ---------------------------(78)9--|';\n\n        expectObservable(\n          hot(sourceTemplate).pipe(tap({ next: feedNextIntoSubject, error: feedErrorIntoSubject, complete: feedCompleteIntoSubject }))\n        ).toBe(sourceTemplate);\n        expectObservable(subscriber1, unsub1).toBe(expected1);\n        expectObservable(subscriber2, unsub2).toBe(expected2);\n        expectObservable(subscriber3).toBe(expected3);\n      });\n    });\n\n    it('should replay 2 last values for when subscribed after completed', () => {\n      rxTestScheduler.run(({ hot, expectObservable }) => {\n        const replaySubject = new ReplaySubject<string>(2);\n        function feedNextIntoSubject(x: string) {\n          replaySubject.next(x);\n        }\n        function feedErrorIntoSubject(err: string) {\n          replaySubject.error(err);\n        }\n        function feedCompleteIntoSubject() {\n          replaySubject.complete();\n        }\n\n        const sourceTemplate = ' -1-2-3--4--|';\n        const subscriber1 = hot('---------------(a|) ').pipe(mergeMapTo(replaySubject));\n        const expected1 = '      ---------------(34|)';\n\n        expectObservable(\n          hot(sourceTemplate).pipe(tap({ next: feedNextIntoSubject, error: feedErrorIntoSubject, complete: feedCompleteIntoSubject }))\n        ).toBe(sourceTemplate);\n        expectObservable(subscriber1).toBe(expected1);\n      });\n    });\n\n    it('should handle subscribers that arrive and leave at different times, ' + 'subject does not complete', () => {\n      const subject = new ReplaySubject<number>(2);\n      const results1: (number | string)[] = [];\n      const results2: (number | string)[] = [];\n      const results3: (number | string)[] = [];\n\n      subject.next(1);\n      subject.next(2);\n      subject.next(3);\n      subject.next(4);\n\n      const subscription1 = subject.subscribe({\n        next: (x: number) => {\n          results1.push(x);\n        },\n        error: (err: any) => {\n          results1.push('E');\n        },\n        complete: () => {\n          results1.push('C');\n        },\n      });\n\n      subject.next(5);\n\n      const subscription2 = subject.subscribe({\n        next: (x: number) => {\n          results2.push(x);\n        },\n        error: (err: any) => {\n          results2.push('E');\n        },\n        complete: () => {\n          results2.push('C');\n        },\n      });\n\n      subject.next(6);\n      subject.next(7);\n\n      subscription1.unsubscribe();\n\n      subject.next(8);\n\n      subscription2.unsubscribe();\n\n      subject.next(9);\n      subject.next(10);\n\n      const subscription3 = subject.subscribe({\n        next: (x: number) => {\n          results3.push(x);\n        },\n        error: (err: any) => {\n          results3.push('E');\n        },\n        complete: () => {\n          results3.push('C');\n        },\n      });\n\n      subject.next(11);\n\n      subscription3.unsubscribe();\n\n      expect(results1).to.deep.equal([3, 4, 5, 6, 7]);\n      expect(results2).to.deep.equal([4, 5, 6, 7, 8]);\n      expect(results3).to.deep.equal([9, 10, 11]);\n\n      subject.complete();\n    });\n  });\n\n  describe('with windowTime=4', () => {\n    it('should replay previous values since 4 time units ago when subscribed', () => {\n      rxTestScheduler.run(({ hot, expectObservable }) => {\n        const replaySubject = new ReplaySubject<string>(Infinity, 4, rxTestScheduler);\n        function feedNextIntoSubject(x: string) {\n          replaySubject.next(x);\n        }\n        function feedErrorIntoSubject(err: any) {\n          replaySubject.error(err);\n        }\n        function feedCompleteIntoSubject() {\n          replaySubject.complete();\n        }\n\n        const sourceTemplate = ' -1-2-3----4------5-6----7-8----9--|';\n        const subscriber1 = hot('------(a|)                         ').pipe(mergeMapTo(replaySubject));\n        const unsub1 = '         ---------------------!             ';\n        const expected1 = '      ------(23)4------5-6--             ';\n        const subscriber2 = hot('------------(b|)                   ').pipe(mergeMapTo(replaySubject));\n        const unsub2 = '         -------------------------!         ';\n        const expected2 = '      ------------4----5-6----7-         ';\n        const subscriber3 = hot('---------------------------(c|)    ').pipe(mergeMapTo(replaySubject));\n        const expected3 = '      ---------------------------(78)9--|';\n\n        expectObservable(\n          hot(sourceTemplate).pipe(tap({ next: feedNextIntoSubject, error: feedErrorIntoSubject, complete: feedCompleteIntoSubject }))\n        ).toBe(sourceTemplate);\n        expectObservable(subscriber1, unsub1).toBe(expected1);\n        expectObservable(subscriber2, unsub2).toBe(expected2);\n        expectObservable(subscriber3).toBe(expected3);\n      });\n    });\n\n    it('should replay last values since 4 time units ago when subscribed', () => {\n      rxTestScheduler.run(({ hot, expectObservable }) => {\n        const replaySubject = new ReplaySubject<string>(Infinity, 4, rxTestScheduler);\n        function feedNextIntoSubject(x: string) {\n          replaySubject.next(x);\n        }\n        function feedErrorIntoSubject(err: any) {\n          replaySubject.error(err);\n        }\n        function feedCompleteIntoSubject() {\n          replaySubject.complete();\n        }\n\n        const sourceTemplate = ' -1-2-3----4|';\n        const subscriber1 = hot('-------------(a|)').pipe(mergeMapTo(replaySubject));\n        const expected1 = '      -------------(4|)';\n\n        expectObservable(\n          hot(sourceTemplate).pipe(tap({ next: feedNextIntoSubject, error: feedErrorIntoSubject, complete: feedCompleteIntoSubject }))\n        ).toBe(sourceTemplate);\n        expectObservable(subscriber1).toBe(expected1);\n      });\n    });\n\n    it('should only replay bufferSize items when 4 time units ago more were emitted', () => {\n      rxTestScheduler.run(({ hot, expectObservable }) => {\n        const replaySubject = new ReplaySubject<string>(2, 4, rxTestScheduler);\n        function feedNextIntoSubject(x: string) {\n          replaySubject.next(x);\n        }\n        function feedErrorIntoSubject(err: any) {\n          replaySubject.error(err);\n        }\n        function feedCompleteIntoSubject() {\n          replaySubject.complete();\n        }\n\n        const sourceTemplate = ' 1234-------|';\n        const subscriber1 = hot('----(a|)').pipe(mergeMapTo(replaySubject));\n        const expected1 = '      ----(34)---|';\n\n        expectObservable(\n          hot(sourceTemplate).pipe(tap({ next: feedNextIntoSubject, error: feedErrorIntoSubject, complete: feedCompleteIntoSubject }))\n        ).toBe(sourceTemplate);\n        expectObservable(subscriber1).toBe(expected1);\n      });\n    });\n  });\n\n  it('should be an Observer which can be given to Observable.subscribe', () => {\n    const source = of(1, 2, 3, 4, 5);\n    const subject = new ReplaySubject<number>(3);\n    let results: (number | string)[] = [];\n\n    subject.subscribe({ next: (x) => results.push(x), complete: () => results.push('done') });\n\n    source.subscribe(subject);\n\n    expect(results).to.deep.equal([1, 2, 3, 4, 5, 'done']);\n\n    results = [];\n\n    subject.subscribe({ next: (x) => results.push(x), complete: () => results.push('done') });\n\n    expect(results).to.deep.equal([3, 4, 5, 'done']);\n  });\n\n  it('should not buffer nexted values after complete', () => {\n    const results: (number | string)[] = [];\n    const subject = new ReplaySubject<number>();\n    subject.next(1);\n    subject.next(2);\n    subject.complete();\n    subject.next(3);\n    subject.subscribe({\n      next: (value) => results.push(value),\n      complete: () => results.push('C'),\n    });\n    expect(results).to.deep.equal([1, 2, 'C']);\n  });\n\n  it('should not buffer nexted values after error', () => {\n    const results: (number | string)[] = [];\n    const subject = new ReplaySubject<number>();\n    subject.next(1);\n    subject.next(2);\n    subject.error(new Error('Boom!'));\n    subject.next(3);\n    subject.subscribe({\n      next: (value) => results.push(value),\n      error: () => results.push('E'),\n    });\n    expect(results).to.deep.equal([1, 2, 'E']);\n  });\n});\n"
  },
  {
    "path": "packages/rxjs/spec/support/.mocharc.js",
    "content": "module.exports = {\n  require: ['ts-node/register', 'spec/helpers/setup.ts'],\n  reporter: 'dot',\n  extensions: ['ts', 'js'],\n  timeout: 5000,\n  recursive: true,\n  'enable-source-maps': true,\n  'expose-gc': true,\n  // Uncomment this to find all skipped tests.\n  // forbidPending: true\n};\n"
  },
  {
    "path": "packages/rxjs/spec/support/mocha-browser-runner.html",
    "content": "<!DOCTYPE html>\n<html>\n  <head>\n      <meta charset=\"UTF-8\">\n      <base target=\"_blank\">\n      <link rel=\"stylesheet\" href=\"../../node_modules/mocha/mocha.css\" />\n  </head>\n\n  <body>\n      <div id=\"mocha\"></div>\n      <script type=\"text/javascript\" src=\"../../node_modules/babel-polyfill/dist/polyfill.js\"></script>\n      <script type=\"text/javascript\" src=\"../../node_modules/mocha/mocha.js\"></script>\n      <script type=\"text/javascript\" src=\"../../tmp/browser/browser.common.js\"></script>\n      <script type=\"text/javascript\" src=\"../../tmp/browser/browser.testscheduler.js\"></script>\n      <script>\n        Suite = Mocha.Suite;\n        Test = Mocha.Test;\n        mocha.setup({ui: 'testschedulerui'});\n      </script>\n      <script type=\"text/javascript\" src=\"../../tmp/browser/browser.spec.js\"></script>\n      <script type=\"text/javascript\" src=\"../../node_modules/mocha-in-sauce/client.js\"></script>\n      <script>\n        onload = function() {\n          var runner = mocha.run();\n          var failedTests = [];\n\n          function logFailure(test, err) {\n            var flattenTitles = function(test) {\n              var titles = [];\n              while (test.parent.title){\n                titles.push(test.parent.title);\n                test = test.parent;\n              }\n              return titles.reverse();\n            };\n\n            failedTests.push({name: test.title, result: false, message: err.message, stack: err.stack, titles: flattenTitles(test) });\n          };\n\n          runner.on('end', function() {\n            window.mochaResults = runner.stats;\n            window.mochaResults.reports = failedTests;\n            window.chocoReady = true;\n          });\n\n          runner.on('fail', logFailure);\n        };\n      </script>\n  </body>\n</html>"
  },
  {
    "path": "packages/rxjs/spec/support/mocha.sauce.gruntfile.js",
    "content": "module.exports = function (grunt) {\n  grunt.initConfig({\n    pkg: grunt.file.readJSON('../../package.json'),\n\n    run: {\n      sauce: {\n        args: ['./mocha.sauce.runner.js'],\n        options: {\n          wait: true,\n          cwd: './'\n        }\n      }\n    },\n\n    connect: {\n      server: {\n        options: {\n          base: '../../',\n          port: 9876\n        }\n      }\n    }\n  });\n\n  var parentcwd = process.cwd();\n  process.chdir('../../');\n\n  grunt.loadNpmTasks('grunt-contrib-connect');\n  grunt.loadNpmTasks('grunt-run');\n\n  process.chdir(parentcwd);\n\n  grunt.registerTask('default', ['connect', 'run:sauce']);\n};"
  },
  {
    "path": "packages/rxjs/spec/support/mocha.sauce.runner.js",
    "content": "var _ = require('lodash');\nvar mochaSauce = require('mocha-in-sauce');\n\nvar customLaunchers = {\n  sl_chrome: {\n    base: 'SauceLabs',\n    browserName: 'chrome',\n    version: '46'\n  },\n  sl_chrome_beta: {\n    base: 'SauceLabs',\n    browserName: 'chrome',\n    version: 'beta'\n  },\n  /*\n  sl_chrome_dev: {\n    base: 'SauceLabs',\n    browserName: 'chrome',\n    version: 'dev'\n  },*/\n  sl_firefox: {\n    base: 'SauceLabs',\n    browserName: 'firefox',\n    version: '44'\n  },\n  /*sl_firefox_beta: {\n    base: 'SauceLabs',\n    browserName: 'firefox',\n    version: 'beta'\n  },\n  sl_firefox_dev: {\n    base: 'SauceLabs',\n    browserName: 'firefox',\n    version: 'dev'\n  },*/\n  sl_safari7: {\n    base: 'SauceLabs',\n    browserName: 'safari',\n    platform: 'OS X 10.9',\n    version: '7'\n  },\n  sl_safari8: {\n    base: 'SauceLabs',\n    browserName: 'safari',\n    platform: 'OS X 10.10',\n    version: '8'\n  },\n  sl_safari9: {\n    base: 'SauceLabs',\n    browserName: 'safari',\n    platform: 'OS X 10.11',\n    version: '9.0'\n  },\n  sl_ios8: {\n    base: 'SauceLabs',\n    browserName: 'iphone',\n    platform: 'OS X 10.11',\n    version: '8.4'\n  },\n  sl_ios9: {\n    base: 'SauceLabs',\n    browserName: 'iphone',\n    platform: 'OS X 10.11',\n    version: '9.1'\n  },\n  sl_ie9: {\n    base: 'SauceLabs',\n    browserName: 'internet explorer',\n    platform: 'Windows 2008',\n    version: '9'\n  },\n  sl_ie10: {\n    base: 'SauceLabs',\n    browserName: 'internet explorer',\n    platform: 'Windows 2012',\n    version: '10'\n  },\n  sl_ie11: {\n    base: 'SauceLabs',\n    browserName: 'internet explorer',\n    platform: 'Windows 8.1',\n    version: '11'\n  },\n  sl_edge: {\n    base: 'SauceLabs',\n    browserName: 'MicrosoftEdge',\n    platform: 'Windows 10',\n    version: '14.14393'\n  },\n  sl_edge_13: {\n    base: 'SauceLabs',\n    browserName: 'MicrosoftEdge',\n    platform: 'Windows 10',\n    version: '13.10586'\n  },\n  sl_android_4_1: {\n    base: 'SauceLabs',\n    browserName: 'android',\n    platform: 'Linux',\n    version: '4.1'\n  },\n  sl_android_4_2: {\n    base: 'SauceLabs',\n    browserName: 'android',\n    platform: 'Linux',\n    version: '4.2'\n  },\n  sl_android_4_3: {\n    base: 'SauceLabs',\n    browserName: 'android',\n    platform: 'Linux',\n    version: '4.3'\n  },\n  sl_android_4_4: {\n    base: 'SauceLabs',\n    browserName: 'android',\n    platform: 'Linux',\n    version: '4.4'\n  },\n  sl_android5: {\n    base: 'SauceLabs',\n    browserName: 'android',\n    platform: 'Linux',\n    version: '5.1'\n  }\n};\n\nvar sauce = new mochaSauce({\n  name: 'RxJS 5 browser test',\n  build: process.env.TRAVIS_BUILD_NUMBER,\n  username: process.env.SAUCE_USERNAME,\n  accessKey: process.env.SAUCE_ACCESS_KEY,\n  host: 'localhost',\n  port: 4445,\n  runSauceConnect: true, // run sauceConnect automatically\n\n  url: 'http://localhost:9876/spec/support/mocha-browser-runner.html'\n});\n\nsauce.record(true, true);\nsauce.concurrency(1);\n\n_.each(customLaunchers, function (browser) {\n  sauce.browser(browser);\n});\n\nsauce.on('start', function (browser) {\n  console.log('  started %s %s %s ...', browser.browserName, browser.version, browser.platform || '');\n});\n\nsauce.on('end', function (browser, res) {\n  console.log('  completed %s %s %s ... : %d failures', browser.browserName, browser.version, browser.platform || '', res.failures);\n});\n\nsauce.start(function (err, res) {\n  console.log('-------------- done --------------');\n});"
  },
  {
    "path": "packages/rxjs/spec/testing/index-spec.ts",
    "content": "import * as index from 'rxjs/testing';\nimport { expect } from 'chai';\n\ndescribe('index', () => {\n  it('should export TestScheduler', () => {\n    expect(index.TestScheduler).to.exist;\n  });\n});\n"
  },
  {
    "path": "packages/rxjs/spec/tsconfig.json",
    "content": "{\n  \"extends\": \"../tsconfig.json\",\n  \"compilerOptions\": {\n    \"outDir\": \"../dist/spec\",\n    \"module\": \"CommonJS\"\n  },\n  \"references\": [\n    {\n      \"path\": \"../src/tsconfig.types.spec.json\"\n    }\n  ]\n}"
  },
  {
    "path": "packages/rxjs/spec/util/ArgumentOutOfRangeError-spec.ts",
    "content": "import { expect } from 'chai';\nimport { ArgumentOutOfRangeError } from 'rxjs';\n\n/** @test {ArgumentOutOfRangeError} */\ndescribe('ArgumentOutOfRangeError', () => {\n  const error = new ArgumentOutOfRangeError();\n  it('Should have a name', () => {\n    expect(error.name).to.be.equal('ArgumentOutOfRangeError');\n  });\n  it('Should have a message', () => {\n    expect(error.message).to.be.equal('argument out of range');\n  });\n  it('Should have a stack', () => {\n    expect(error.stack).to.be.a('string');\n  });\n});\n"
  },
  {
    "path": "packages/rxjs/spec/util/EmptyError-spec.ts",
    "content": "import { expect } from 'chai';\nimport { EmptyError } from 'rxjs';\n\n/** @test {EmptyError} */\ndescribe('EmptyError', () => {\n  const error = new EmptyError();\n  it('Should have a name', () => {\n    expect(error.name).to.be.equal('EmptyError');\n  });\n  it('Should have a message', () => {\n    expect(error.message).to.be.equal('no elements in sequence');\n  });\n  it('Should have a stack', () => {\n    expect(error.stack).to.be.a('string');\n  });\n});\n"
  },
  {
    "path": "packages/rxjs/spec/util/Immediate-spec.ts",
    "content": "import { expect } from 'chai';\n// TODO: import was changed due to the fact that at startup the test referred to rxjs from node_modules\nimport { Immediate, TestTools } from '../../src/internal/util/Immediate';\n\ndescribe('Immediate', () => {\n  it('should schedule on the next microtask', (done) => {\n    const results: number[] = [];\n    results.push(1);\n    setTimeout(() => results.push(5));\n    Immediate.setImmediate(() => results.push(3));\n    results.push(2);\n    Promise.resolve().then(() => results.push(4));\n\n    setTimeout(() => {\n      expect(results).to.deep.equal([1, 2, 3, 4, 5]);\n      done();\n    });\n  });\n\n  it('should cancel the task with clearImmediate', (done) => {\n    const results: number[] = [];\n    results.push(1);\n    setTimeout(() => results.push(5));\n    const handle = Immediate.setImmediate(() => results.push(3));\n    Immediate.clearImmediate(handle);\n    results.push(2);\n    Promise.resolve().then(() => results.push(4));\n\n    setTimeout(() => {\n      expect(results).to.deep.equal([1, 2, 4, 5]);\n      done();\n    });\n  });\n\n  it('should clear the task after execution', (done) => {\n    const results: number[] = [];\n    Immediate.setImmediate(() => results.push(1));\n    Immediate.setImmediate(() => results.push(2));\n\n    setTimeout(() => {\n      const number = TestTools.pending();\n      expect(number).to.equal(0);\n      done();\n    });\n  });\n});\n"
  },
  {
    "path": "packages/rxjs/spec/util/TimeoutError-spec.ts",
    "content": "import { expect } from 'chai';\nimport { TimeoutError } from 'rxjs';\n\n/** @test {TimeoutError} */\ndescribe('TimeoutError', () => {\n  const error = new TimeoutError();\n  it('Should have a name', () => {\n    expect(error.name).to.be.equal('TimeoutError');\n  });\n  it('Should have a message', () => {\n    expect(error.message).to.be.equal('Timeout has occurred');\n  });\n  it('Should have a stack', () => {\n    expect(error.stack).to.be.a('string');\n  });\n});\n"
  },
  {
    "path": "packages/rxjs/spec/util/UnsubscriptionError-spec.ts",
    "content": "import { expect } from 'chai';\nimport { UnsubscriptionError, Observable, timer, merge } from 'rxjs';\n\n/** @test {UnsubscriptionError} */\ndescribe('UnsubscriptionError', () => {\n  it('should create a message that is a clear indication of its internal errors', () => {\n    const err1 = new Error('Swiss cheese tastes amazing but smells like socks');\n    const err2 = new Error('User too big to fit in tiny European elevator');\n    const source1 = new Observable(() => () => { throw err1; });\n    const source2 = timer(1000);\n    const source3 = new Observable(() => () => { throw err2; });\n    const source = merge(source1, source2, source3);\n\n    const subscription = source.subscribe();\n\n    try {\n      subscription.unsubscribe();\n    } catch (err) {\n      if (err instanceof UnsubscriptionError) {\n        expect(err.errors).to.deep.equal([err1, err2]);\n        expect(err.name).to.equal('UnsubscriptionError');\n        expect(err.stack).to.be.a('string');\n      } else {\n        throw new TypeError('Invalid error type');\n      }\n    }\n  });\n});\n"
  },
  {
    "path": "packages/rxjs/spec/util/isObservable-spec.ts",
    "content": "import { Observable, isObservable } from 'rxjs';\nimport { expect } from 'chai';\n\ndescribe('isObservable', () => {\n  it('should return true for RxJS Observable', () => {\n    const o = new Observable<any>();\n    expect(isObservable(o)).to.be.true;\n  });\n\n  it('should return true for an observable that comes from another RxJS 5+ library', () => {\n    const o: any = {\n      lift() { /* noop */ },\n      subscribe() { /* noop */ },\n    };\n\n    expect(isObservable(o)).to.be.true;\n  });\n\n  it('should NOT return true for any old subscribable', () => {\n    const o: any = {\n      subscribe() { /* noop */ },\n    };\n\n    expect(isObservable(o)).to.be.false;\n  });\n\n  it('should return false for null', () => {\n    expect(isObservable(null)).to.be.false;\n  });\n\n  it('should return false for a number', () => {\n    expect(isObservable(1)).to.be.false;\n  });\n\n});\n"
  },
  {
    "path": "packages/rxjs/spec/util/isPromise-spec.ts",
    "content": "import { of } from 'rxjs';\nimport { expect } from 'chai';\nimport { isPromise } from '@rxjs/observable';\n\ndescribe('isPromise', () => {\n  it('should return true for new Promise', () => {\n    const o = new Promise<any>(() => null);\n    expect(isPromise(o)).to.be.true;\n  });\n\n  it('should NOT return true for any Observable', () => {\n    const o: any = of(null);\n\n    expect(isPromise(o)).to.be.false;\n  });\n\n  it('should return false for null', () => {\n    expect(isPromise(null)).to.be.false;\n  });\n\n  it('should return false for undefined', () => {\n    expect(isPromise(undefined)).to.be.false;\n  });\n\n  it('should return false for a number', () => {\n    expect(isPromise(1)).to.be.false;\n  });\n\n  it('should return false for a string', () => {\n    expect(isPromise('1')).to.be.false;\n  });\n});\n"
  },
  {
    "path": "packages/rxjs/spec/util/pipe-spec.ts",
    "content": "import { expect } from 'chai';\nimport { map, Observable, pipe, rx } from 'rxjs';\n\ndescribe('pipe', () => {\n  it('should exist', () => {\n    expect(pipe).to.be.a('function');\n  });\n\n  it('should pipe two functions together', () => {\n    const a = (x: number) => x + x;\n    const b = (x: number) => x - 1;\n\n    const c = pipe(a, b);\n    expect(c).to.be.a('function');\n    expect(c(1)).to.equal(1);\n    expect(c(10)).to.equal(19);\n  });\n\n  it('should return the same function if only one is passed', () => {\n    const a = <T>(x: T) => x;\n    const c = pipe(a);\n\n    expect(c).to.equal(a);\n  });\n\n  it('should return the identity if not passed any functions', () => {\n    const c = pipe();\n\n    expect(c('whatever')).to.equal('whatever');\n    const someObj = {};\n    expect(c(someObj)).to.equal(someObj);\n  });\n});\n"
  },
  {
    "path": "packages/rxjs/spec/util/rx-spec.ts",
    "content": "import { expect } from \"chai\";\nimport { map, Observable, rx } from \"rxjs\";\n\ndescribe('rx', () => {\n  it('should work like pipe, convert the first argument to an observable', () => {\n    const a = [1, 2, 3];\n    const results: any[] = [];\n    \n    rx(a, map(x => x + 1)).subscribe({\n      next: value => results.push(value),\n      complete: () => {\n        results.push('done');\n      }\n    })\n    expect(results).to.deep.equal([2, 3, 4, 'done'])\n  });\n\n  it('should simply convert the first argument to an observable if it is the only thing provided', () => {\n    const a = [1, 2, 3];\n    const results: any[] = [];\n    \n    rx(a).subscribe({\n      next: value => results.push(value),\n      complete: () => {\n        results.push('done');\n      }\n    })\n    expect(results).to.deep.equal([1, 2, 3, 'done'])\n  });\n\n  it('should allow any kind of custom piping', () => {\n    const a = [1, 2, 3];\n    const result = rx(a, map(x => x + 1), source => source instanceof Observable)\n    expect(result).to.be.true;\n  });\n});\n"
  },
  {
    "path": "packages/rxjs/spec/websocket/index-spec.ts",
    "content": "import * as index from 'rxjs/webSocket';\nimport { expect } from 'chai';\n\ndescribe('index', () => {\n  it('should export static websocket subject creator functions', () => {\n    expect(index.webSocket).to.exist;\n  });\n});\n"
  },
  {
    "path": "packages/rxjs/spec-dtslint/AsyncSubject-spec.ts",
    "content": "import { AsyncSubject } from 'rxjs';\n\ndescribe('AsyncSubject', () => {\n  it('should handle no generic appropriately', () => {\n    const s1 = new AsyncSubject(); // $ExpectType AsyncSubject<unknown>\n    s1.next(); // $ExpectError\n    s1.next('test'); // $ExpectType void\n    s1.subscribe(value => {\n      const x = value; // $ExpectType unknown\n    });\n  });\n\n  it('should handle a generic of string appropriately', () => {\n    const s1 = new AsyncSubject<string>(); // $ExpectType AsyncSubject<string>\n    s1.next(); // $ExpectError\n    s1.next('test'); // $ExpectType void\n    s1.next(32); // $ExpectError\n    s1.subscribe(value => {\n      const x = value; // $ExpectType string\n    });\n  });\n\n  it('should handle a generic of void appropriately', () => {\n    const s1 = new AsyncSubject<void>(); // $ExpectType AsyncSubject<void>\n    s1.next(); // $ExpectType void\n    s1.next(undefined); // $ExpectType void\n    s1.next('test'); // $ExpectError\n    s1.subscribe(value => {\n      const x = value; // $ExpectType void\n    });\n  });\n\n  describe('asObservable', () => {\n    it('should return an observable of the same generic type', () => {\n      const s1 = new AsyncSubject();\n      const o1 = s1.asObservable(); // $ExpectType Observable<unknown>\n\n      const s2 = new AsyncSubject<string>();\n      const o2 = s2.asObservable(); // $ExpectType Observable<string>\n    });\n  });\n});"
  },
  {
    "path": "packages/rxjs/spec-dtslint/BehaviorSubject-spec.ts",
    "content": "import { BehaviorSubject } from 'rxjs';\n\ndescribe('BehaviorSubject', () => {\n  it('should handle no generic appropriately', () => {\n    const s1 = new BehaviorSubject(); // $ExpectError\n  });\n\n  it('should handle an argument of string appropriately', () => {\n    const init = 'some string';\n    const s1 = new BehaviorSubject(init); // $ExpectType BehaviorSubject<string>\n    s1.next(); // $ExpectError\n    s1.next('test'); // $ExpectType void\n    s1.next(32); // $ExpectError\n    s1.subscribe(value => {\n      const x = value; // $ExpectType string\n    });\n    const v = s1.getValue(); // $ExpectType string\n  });\n\n  it('should handle a generic of void appropriately', () => {\n    const s1 = new BehaviorSubject<void>(undefined); // $ExpectType BehaviorSubject<void>\n    s1.next(); // $ExpectType void\n    s1.next('test'); // $ExpectError\n    s1.next(32); // $ExpectError\n    s1.subscribe(value => {\n      const x = value; // $ExpectType void\n    });\n    const v = s1.getValue(); // $ExpectType void\n  });\n\n  describe('asObservable', () => {\n    it('should return an observable of the same generic type', () => {\n      const s1 = new BehaviorSubject('test');\n      const o1 = s1.asObservable(); // $ExpectType Observable<string>\n\n      const s2 = new BehaviorSubject<void>(undefined);\n      const o2 = s2.asObservable(); // $ExpectType Observable<void>\n    });\n  });\n});"
  },
  {
    "path": "packages/rxjs/spec-dtslint/Observable-spec.ts",
    "content": "import type { OperatorFunction } from 'rxjs';\nimport { Observable, of, map, filter } from 'rxjs';\n\nfunction a<I extends string, O extends string>(input: I, output: O): OperatorFunction<I, O>;\nfunction a<I, O extends string>(output: O): OperatorFunction<I, O>;\n\n/**\n * Used to keep the tests uncluttered.\n *\n * Returns an `OperatorFunction` with the specified literal type parameters.\n * That is, `a('0', '1')` returns `OperatorFunction<'0', '1'>`.\n * That means that the `a` function can be used to create consecutive\n * arguments that are either compatible or incompatible.\n * \n * ```javascript\n * a('0', '1'), a('1', '2') // OK\n * a('0', '1'), a('#', '2') // Error '1' is not compatible with '#'\n * ```\n *\n * If passed only one argument, that argument is used for the output\n * type parameter and the input type parameters is inferred.\n *\n * ```javascript\n * of('foo').pipe(\n *   a('1') // OperatorFunction<'foo', '1'>\n * );\n * ```\n *\n * @param {string} input The `OperatorFunction` input type parameter\n * @param {string} output The `OperatorFunction` output type parameter\n */\nfunction a<I, O extends string>(inputOrOutput: I | O, output?: O): OperatorFunction<I, O> {\n  return map(() => output === undefined ? inputOrOutput as O : output);\n}\n\ndescribe('pipe', () => {\n  it('should infer for no arguments', () => {\n    const o = of('foo').pipe(); // $ExpectType Observable<string>\n  });\n\n  it('should infer for 1 argument', () => {\n    const o = of('foo').pipe(a('1')); // $ExpectType Observable<\"1\">\n  });\n\n  it('should infer for 2 arguments', () => {\n    const o = of('foo').pipe(a('1'), a('2')); // $ExpectType Observable<\"2\">\n  });\n\n  it('should infer for 3 arguments', () => {\n    const o = of('foo').pipe(a('1'), a('2'), a('3')); // $ExpectType Observable<\"3\">\n  });\n\n  it('should infer for 4 arguments', () => {\n    const o = of('foo').pipe(a('1'), a('2'), a('3'), a('4')); // $ExpectType Observable<\"4\">\n  });\n\n  it('should infer for 5 arguments', () => {\n    const o = of('foo').pipe(a('1'), a('2'), a('3'), a('4'), a('5')); // $ExpectType Observable<\"5\">\n  });\n\n  it('should infer for 6 arguments', () => {\n    const o = of('foo').pipe(a('1'), a('2'), a('3'), a('4'), a('5'), a('6')); // $ExpectType Observable<\"6\">\n  });\n\n  it('should infer for 7 arguments', () => {\n    const o = of('foo').pipe(a('1'), a('2'), a('3'), a('4'), a('5'), a('6'), a('7')); // $ExpectType Observable<\"7\">\n  });\n\n  it('should infer for 8 arguments', () => {\n    const o = of('foo').pipe(a('1'), a('2'), a('3'), a('4'), a('5'), a('6'), a('7'), a('8')); // $ExpectType Observable<\"8\">\n  });\n\n  it('should infer for 9 arguments', () => {\n    const o = of('foo').pipe(a('1'), a('2'), a('3'), a('4'), a('5'), a('6'), a('7'), a('8'), a('9')); // $ExpectType Observable<\"9\">\n  });\n\n  it('should infer unknown for more than 9 arguments', () => {\n    const o = of('foo').pipe(a('1'), a('2'), a('3'), a('4'), a('5'), a('6'), a('7'), a('8'), a('9'), a('10')); // $ExpectType Observable<unknown>\n  });\n\n  it('should require a type assertion for more than 9 arguments', () => {\n    const o: Observable<'10'> = of('foo').pipe(a('1'), a('2'), a('3'), a('4'), a('5'), a('6'), a('7'), a('8'), a('9'), a('10')); // $ExpectError\n  });\n\n  it('should enforce types for the 1st argument', () => {\n    const o = of('foo').pipe(a('#', '1')); // $ExpectError\n  });\n\n  it('should enforce types for the 2nd argument', () => {\n    const o = of('foo').pipe(a('1'), a('#', '2')); // $ExpectError\n  });\n\n  it('should enforce types for the 3rd argument', () => {\n    const o = of('foo').pipe(a('1'), a('2'), a('#', '3')); // $ExpectError\n  });\n\n  it('should enforce types for the 4th argument', () => {\n    const o = of('foo').pipe(a('1'), a('2'), a('3'), a('#', '4')); // $ExpectError\n  });\n\n  it('should enforce types for the 5th argument', () => {\n    const o = of('foo').pipe(a('1'), a('2'), a('3'), a('4'), a('#', '5')); // $ExpectError\n  });\n\n  it('should enforce types for the 6th argument', () => {\n    const o = of('foo').pipe(a('1'), a('2'), a('3'), a('4'), a('5'), a('#', '6')); // $ExpectError\n  });\n\n  it('should enforce types for the 7th argument', () => {\n    const o = of('foo').pipe(a('1'), a('2'), a('3'), a('4'), a('5'), a('6'), a('#', '7')); // $ExpectError\n  });\n\n  it('should enforce types for the 8th argument', () => {\n    const o = of('foo').pipe(a('1'), a('2'), a('3'), a('4'), a('5'), a('6'), a('7'), a('#', '8')); // $ExpectError\n  });\n\n  it('should enforce types for the 9th argument', () => {\n    const o = of('foo').pipe(a('1'), a('2'), a('3'), a('4'), a('5'), a('6'), a('7'), a('8'), a('#', '9')); // $ExpectError\n  });\n\n  it('should not enforce types beyond the 9th argument', () => {\n    const o = of('foo').pipe(a('1'), a('2'), a('3'), a('4'), a('5'), a('6'), a('7'), a('8'), a('9'), a('#', '10')); // $ExpectType Observable<unknown>\n  });\n\n  it('should support operators that return generics', () => {\n    const customOperator = () => <T>(a: Observable<T>) => a;\n    const o = of('foo').pipe(customOperator()); // $ExpectType Observable<string>\n  });\n\n  it('should infer properly for any reasonable pipe chain', () => {\n    const o1 = of('foo').pipe(source => source.toString(), s => s.length, n => n + 1); // $ExpectType number\n    const o2 = of(123).pipe(map(n => n + '?'), source => source.subscribe()); // $ExpectType Subscription\n    const o3 = of('test').pipe(map(n => n + ':' + n), filter(n => n < 30)); // $ExpectError\n  })\n});\n\nit('should provide the proper types to the subscriber', () => {\n  const o1$ = new Observable<number>(subscriber => {\n    const next = subscriber.next; // $ExpectType (value: number) => void\n    subscriber.next(); // $ExpectError\n  });\n});"
  },
  {
    "path": "packages/rxjs/spec-dtslint/ReplaySubject-spec.ts",
    "content": "import { ReplaySubject } from 'rxjs';\n\ndescribe('ReplaySubject', () => {\n  it('should handle no generic appropriately', () => {\n    const s1 = new ReplaySubject(); // $ExpectType ReplaySubject<unknown>\n    s1.next(); // $ExpectError\n    s1.next('test'); // $ExpectType void\n    s1.subscribe(value => {\n      const x = value; // $ExpectType unknown\n    });\n  });\n\n  it('should handle a generic of string appropriately', () => {\n    const s1 = new ReplaySubject<string>(); // $ExpectType ReplaySubject<string>\n    s1.next(); // $ExpectError\n    s1.next('test'); // $ExpectType void\n    s1.next(32); // $ExpectError\n    s1.subscribe(value => {\n      const x = value; // $ExpectType string\n    });\n  });\n\n  it('should handle a generic of void appropriately', () => {\n    const s1 = new ReplaySubject<void>(); // $ExpectType ReplaySubject<void>\n    s1.next(); // $ExpectType void\n    s1.next(undefined); // $ExpectType void\n    s1.next('test'); // $ExpectError\n    s1.subscribe(value => {\n      const x = value; // $ExpectType void\n    });\n  });\n\n  describe('asObservable', () => {\n    it('should return an observable of the same generic type', () => {\n      const s1 = new ReplaySubject();\n      const o1 = s1.asObservable(); // $ExpectType Observable<unknown>\n\n      const s2 = new ReplaySubject<string>();\n      const o2 = s2.asObservable(); // $ExpectType Observable<string>\n    });\n  });\n});"
  },
  {
    "path": "packages/rxjs/spec-dtslint/Subject-spec.ts",
    "content": "import { Subject } from 'rxjs';\n\ndescribe('Subject', () => {\n  it('should handle no generic appropriately', () => {\n    const s1 = new Subject(); // $ExpectType Subject<unknown>\n    s1.next(); // $ExpectError\n    s1.next('test'); // $ExpectType void\n    s1.subscribe(value => {\n      const x = value; // $ExpectType unknown\n    });\n  });\n\n  it('should handle a generic of string appropriately', () => {\n    const s1 = new Subject<string>(); // $ExpectType Subject<string>\n    s1.next(); // $ExpectError\n    s1.next('test'); // $ExpectType void\n    s1.next(32); // $ExpectError\n    s1.subscribe(value => {\n      const x = value; // $ExpectType string\n    });\n  });\n\n  it('should handle a generic of void appropriately', () => {\n    const s1 = new Subject<void>(); // $ExpectType Subject<void>\n    s1.next(); // $ExpectType void\n    s1.next(undefined); // $ExpectType void\n    s1.next('test'); // $ExpectError\n    s1.subscribe(value => {\n      const x = value; // $ExpectType void\n    });\n  });\n\n  it('should not accept an argument in the ctor', () => {\n    const s1 = new Subject<number>(subscriber => { }); // $ExpectError\n  });\n\n  describe('asObservable', () => {\n    it('should return an observable of the same generic type', () => {\n      const s1 = new Subject();\n      const o1 = s1.asObservable(); // $ExpectType Observable<unknown>\n\n      const s2 = new Subject<string>();\n      const o2 = s2.asObservable(); // $ExpectType Observable<string>\n    });\n  });\n});"
  },
  {
    "path": "packages/rxjs/spec-dtslint/Subscriber-spec.ts",
    "content": "import { Subscriber } from \"rxjs\";\n\ndescribe(\"Subscriber\", () => {\n  it('should have deprecated and internal constructors', () => {\n    const s1 = new Subscriber(); // $ExpectDeprecation\n    const s2 = new Subscriber(() => {}); // $ExpectDeprecation\n    const s3 = new Subscriber({}); // $ExpectDeprecation\n    const s4 = new Subscriber({ next: () => {}}); // $ExpectDeprecation\n    const s5 = new Subscriber({ }, { next: () => {} }); // $ExpectError\n  });\n});"
  },
  {
    "path": "packages/rxjs/spec-dtslint/errors-spec.ts",
    "content": "import { AjaxError } from 'rxjs/ajax';\nimport {\n  ArgumentOutOfRangeError,\n  EmptyError,\n  NotFoundError,\n  SequenceError,\n  TimeoutError,\n  UnsubscriptionError\n} from 'rxjs';\n\nit('should deprecate error construction', () => {\n  let error: Error;\n  error = new AjaxError('message', null!, null!); // $ExpectDeprecation\n  error = new ArgumentOutOfRangeError(); // $ExpectDeprecation\n  error = new EmptyError(); // $ExpectDeprecation\n  error = new NotFoundError('message'); // $ExpectDeprecation\n  error = new SequenceError('message'); // $ExpectDeprecation\n  error = new TimeoutError(); // $ExpectDeprecation\n  error = new UnsubscriptionError([]); // $ExpectDeprecation\n});\n\nit('should not deprecate instanceof use', () => {\n  const error = new Error('message');\n  let b: boolean;\n  b = error instanceof AjaxError; // $ExpectNoDeprecation\n  b = error instanceof ArgumentOutOfRangeError; // $ExpectNoDeprecation\n  b = error instanceof EmptyError; // $ExpectNoDeprecation\n  b = error instanceof NotFoundError; // $ExpectNoDeprecation\n  b = error instanceof SequenceError; // $ExpectNoDeprecation\n  b = error instanceof TimeoutError; // $ExpectNoDeprecation\n  b = error instanceof UnsubscriptionError; // $ExpectNoDeprecation\n});"
  },
  {
    "path": "packages/rxjs/spec-dtslint/firstValueFrom-spec.ts",
    "content": "import { firstValueFrom } from 'rxjs';\nimport { a$ } from 'helpers';\n\ndescribe('firstValueFrom', () => {\n  it('should infer the element type', () => {\n    const r = firstValueFrom(a$); // $ExpectType Promise<A>\n  })\n\n  it('should infer the element type from a default value', () => {\n    const r = firstValueFrom(a$, { defaultValue: null }); // $ExpectType Promise<A | null>\n  });\n\n  it('should require an argument', () => {\n    const r = firstValueFrom(); // $ExpectError\n  });\n\n  it('should require an observable argument', () => {\n    const r = firstValueFrom(Promise.resolve(42)); // $ExpectError\n  });\n});\n"
  },
  {
    "path": "packages/rxjs/spec-dtslint/helpers.ts",
    "content": "import { of } from 'rxjs';\n\nexport class A { a = 0; }\nexport class B { b = 0; }\nexport class C { c = 0; }\nexport class D { d = 0; }\nexport class E { e = 0; }\nexport class F { f = 0; }\nexport class G { g = 0; }\nexport class H { h = 0; }\nexport class I { i = 0; }\nexport class J { j = 0; }\n\nexport const a = new A();\nexport const b = new B();\nexport const c = new C();\nexport const d = new D();\nexport const e = new E();\nexport const f = new F();\nexport const g = new G();\nexport const h = new H();\nexport const i = new I();\nexport const j = new J();\n\nexport const a$ = of(new A());\nexport const b$ = of(new B());\nexport const c$ = of(new C());\nexport const d$ = of(new D());\nexport const e$ = of(new E());\nexport const f$ = of(new F());\nexport const g$ = of(new G());\nexport const h$ = of(new H());\nexport const i$ = of(new I());\nexport const j$ = of(new J());\n"
  },
  {
    "path": "packages/rxjs/spec-dtslint/index.d.ts",
    "content": ""
  },
  {
    "path": "packages/rxjs/spec-dtslint/lastValueFrom-spec.ts",
    "content": "import { lastValueFrom } from 'rxjs';\nimport { a$ } from 'helpers';\n\ndescribe('lastValueFrom', () => {\n  it('should infer the element type', () => {\n    const r = lastValueFrom(a$); // $ExpectType Promise<A>\n  });\n\n  it('should infer the element type from a default value', () => {\n    const r = lastValueFrom(a$, { defaultValue: null }); // $ExpectType Promise<A | null>\n  });\n\n  it('should require an argument', () => {\n    const r = lastValueFrom(); // $ExpectError\n  });\n\n  it('should require an observable argument', () => {\n    const r = lastValueFrom(Promise.resolve(42)); // $ExpectError\n  });\n});\n"
  },
  {
    "path": "packages/rxjs/spec-dtslint/observables/bindCallback-spec.ts",
    "content": "import { bindCallback } from 'rxjs';\nimport type { A, B, C, D, E, F, G } from '../helpers';\nimport { a,  b,  c,  d,  e,  f,  g } from '../helpers';\n\ndescribe('callbackFunc', () => {\n  const f0 = (cb: () => void) => {\n    cb();\n  };\n\n  const f1 = (cb: (res1: A) => void) => {\n    cb(a);\n  };\n\n  const f2 = (cb: (res1: A, res2: B) => void) => {\n    cb(a, b);\n  };\n\n  const f3 = (cb: (res1: A, res2: B, res3: C) => void) => {\n    cb(a, b, c);\n  };\n\n  const f4 = (cb: (res1: A, res2: B, res3: C, res4: D) => void) => {\n    cb(a, b, c, d);\n  };\n\n  it('should enforce function parameter', () => {\n    const o = bindCallback() // $ExpectError\n  });\n\n  it('should accept cb 0 param', () => {\n    const o = bindCallback(f0) // $ExpectType () => Observable<void>\n  });\n\n  it('should accept cb 1 param', () => {\n    const o = bindCallback(f1) // $ExpectType () => Observable<A>\n  });\n\n  it('should accept cb 2 params', () => {\n    const o = bindCallback(f2) // $ExpectType () => Observable<[res1: A, res2: B]>\n  });\n\n  it('should accept cb 3 params', () => {\n    const o = bindCallback(f3) // $ExpectType () => Observable<[res1: A, res2: B, res3: C]>\n  });\n\n  it('should accept cb 4 params', () => {\n    const o = bindCallback(f4) // $ExpectType () => Observable<[res1: A, res2: B, res3: C, res4: D]>\n  });\n});\n\ndescribe('callbackFunc and 1 args', () => {\n  const fa1cb0 = (e: E, cb: () => void) => {\n    cb();\n  };\n\n  const fa1cb1 = (e: E, cb: (res1: A) => void) => {\n    cb(a);\n  };\n\n  const fa1cb2 = (e: E, cb: (res1: A, res2: B) => void) => {\n    cb(a, b);\n  };\n\n  const fa1cb3 = (e: E, cb: (res1: A, res2: B, res3: C) => void) => {\n    cb(a, b, c);\n  };\n\n  const fa1cb4 = (e: E, cb: (res1: A, res2: B, res3: C, res4: D) => void) => {\n    cb(a, b, c, d);\n  };\n\n  it('should accept cb 0 param', () => {\n    const o = bindCallback(fa1cb0) // $ExpectType (e: E) => Observable<void>\n  });\n\n  it('should accept cb 1 param', () => {\n    const o = bindCallback(fa1cb1) // $ExpectType (e: E) => Observable<A>\n  });\n\n  it('should accept cb 2 param', () => {\n    const o = bindCallback(fa1cb2) // $ExpectType (e: E) => Observable<[res1: A, res2: B]>\n  });\n\n  it('should accept cb 3 param', () => {\n    const o = bindCallback(fa1cb3) // $ExpectType (e: E) => Observable<[res1: A, res2: B, res3: C]>\n  });\n\n  it('should accept cb 4 param', () => {\n    const o = bindCallback(fa1cb4) // $ExpectType (e: E) => Observable<[res1: A, res2: B, res3: C, res4: D]>\n  });\n});\n\ndescribe('callbackFunc and 2 args' , () => {\n  const fa2cb0 = (e: E , f: F, cb: () => void) => {\n    cb();\n  };\n\n  const fa2cb1 = (e: E , f: F, cb: (res1: A) => void) => {\n    cb(a);\n  };\n\n  const fa2cb2 = (e: E , f: F, cb: (res1: A, res2: B) => void) => {\n    cb(a, b);\n  };\n\n  const fa2cb3 = (e: E , f: F, cb: (res1: A, res2: B, res3: C) => void) => {\n    cb(a, b, c);\n  };\n\n  const fa2cb4 = (e: E , f: F, cb: (res1: A, res2: B, res3: C, res4: D) => void) => {\n    cb(a, b, c, d);\n  };\n\n  it('should accept cb 0 param', () => {\n    const o = bindCallback(fa2cb0) // $ExpectType (e: E, f: F) => Observable<void>\n  });\n\n  it('should accept cb 1 param', () => {\n    const o = bindCallback(fa2cb1) // $ExpectType (e: E, f: F) => Observable<A>\n  });\n\n  it('should accept cb 2 param', () => {\n    const o = bindCallback(fa2cb2) // $ExpectType (e: E, f: F) => Observable<[res1: A, res2: B]>\n  });\n\n  it('should accept cb 3 param', () => {\n    const o = bindCallback(fa2cb3) // $ExpectType (e: E, f: F) => Observable<[res1: A, res2: B, res3: C]>\n  });\n\n  it('should accept cb 4 param', () => {\n    const o = bindCallback(fa2cb4) // $ExpectType (e: E, f: F) => Observable<[res1: A, res2: B, res3: C, res4: D]>\n  });\n});\n\ndescribe('callbackFunc and 3 args' , () => {\n  const fa3cb0 = (e: E , f: F, g: G, cb: () => void) => {\n    cb();\n  };\n\n  const fa3cb1 = (e: E , f: F, g: G, cb: (res1: A) => void) => {\n    cb(a);\n  };\n\n  const fa3cb2 = (e: E , f: F, g: G, cb: (res1: A, res2: B) => void) => {\n    cb(a, b);\n  };\n\n  const fa3cb3 = (e: E , f: F, g: G, cb: (res1: A, res2: B, res3: C) => void) => {\n    cb(a, b, c);\n  };\n\n  const fa3cb4 = (e: E , f: F, g: G, cb: (res1: A, res2: B, res3: C, res4: D) => void) => {\n    cb(a, b, c, d);\n  };\n\n\n  it('should accept cb 0 param', () => {\n    const o = bindCallback(fa3cb0) // $ExpectType (e: E, f: F, g: G) => Observable<void>\n  });\n\n  it('should accept cb 1 param', () => {\n    const o = bindCallback(fa3cb1) // $ExpectType (e: E, f: F, g: G) => Observable<A>\n  });\n\n  it('should accept cb 2 params', () => {\n    const o = bindCallback(fa3cb2) // $ExpectType (e: E, f: F, g: G) => Observable<[res1: A, res2: B]>\n  });\n\n  it('should accept cb 3 params', () => {\n    const o = bindCallback(fa3cb3) // $ExpectType (e: E, f: F, g: G) => Observable<[res1: A, res2: B, res3: C]>\n  });\n\n  it('should accept cb 4 params', () => {\n    const o = bindCallback(fa3cb4) // $ExpectType (e: E, f: F, g: G) => Observable<[res1: A, res2: B, res3: C, res4: D]>\n  });\n});\n\ndescribe('callbackFunc and 4 args' , () => {\n  const fa4cb0 = (e: E , f: F, g: G, a: A, cb: () => void) => {\n    cb();\n  };\n\n  const fa4cb1 = (e: E , f: F, g: G, a: A, cb: (res1: A) => void) => {\n    cb(a);\n  };\n\n  const fa4cb2 = (e: E , f: F, g: G, a: A, cb: (res1: A, res2: B) => void) => {\n    cb(a, b);\n  };\n\n  const fa4cb3 = (e: E , f: F, g: G, a: A, cb: (res1: A, res2: B, res3: C) => void) => {\n    cb(a, b, c);\n  };\n\n  const fa4cb4 = (e: E , f: F, g: G, a: A, cb: (res1: A, res2: B, res3: C, res4: D) => void) => {\n    cb(a, b, c, d);\n  };\n\n\n  it('should accept cb 0 param', () => {\n    const o = bindCallback(fa4cb0) // $ExpectType (e: E, f: F, g: G, a: A) => Observable<void>\n  });\n\n  it('should accept cb 0 param', () => {\n    const o = bindCallback(fa4cb1) // $ExpectType (e: E, f: F, g: G, a: A) => Observable<A>\n  });\n\n  it('should accept cb 2 params', () => {\n    const o = bindCallback(fa4cb2) // $ExpectType (e: E, f: F, g: G, a: A) => Observable<[res1: A, res2: B]>\n  });\n\n  it('should accept cb 3 params', () => {\n    const o = bindCallback(fa4cb3) // $ExpectType (e: E, f: F, g: G, a: A) => Observable<[res1: A, res2: B, res3: C]>\n  });\n\n  it('should accept cb 4 params', () => {\n    const o = bindCallback(fa4cb4) // $ExpectType (e: E, f: F, g: G, a: A) => Observable<[res1: A, res2: B, res3: C, res4: D]>\n  });\n});\n\ndescribe('callbackFunc and 5 args' , () => {\n  const fa5cb0 = (e: E , f: F, g: G, a: A, b: B, cb: () => void) => {\n    cb();\n  };\n\n  const fa5cb1 = (e: E , f: F, g: G, a: A, b: B, cb: (res1: A) => void) => {\n    cb(a);\n  };\n\n  const fa5cb2 = (e: E , f: F, g: G, a: A, b: B, cb: (res1: A, res2: B) => void) => {\n    cb(a, b);\n  };\n\n  const fa5cb3 = (e: E , f: F, g: G, a: A, b: B, cb: (res1: A, res2: B, res3: C) => void) => {\n    cb(a, b, c);\n  };\n\n  const fa5cb4 = (e: E , f: F, g: G, a: A, b: B, cb: (res1: A, res2: B, res3: C, res4: D) => void) => {\n    cb(a, b, c, d);\n  };\n\n\n  it('should accept cb 0 param', () => {\n    const o = bindCallback(fa5cb0) // $ExpectType (e: E, f: F, g: G, a: A, b: B) => Observable<void>\n  });\n\n  it('should accept cb 0 param', () => {\n    const o = bindCallback(fa5cb1) // $ExpectType (e: E, f: F, g: G, a: A, b: B) => Observable<A>\n  });\n\n  it('should accept cb 2 params', () => {\n    const o = bindCallback(fa5cb2) // $ExpectType (e: E, f: F, g: G, a: A, b: B) => Observable<[res1: A, res2: B]>\n  });\n\n  it('should accept cb 3 params', () => {\n    const o = bindCallback(fa5cb3) // $ExpectType (e: E, f: F, g: G, a: A, b: B) => Observable<[res1: A, res2: B, res3: C]>\n  });\n\n  it('should accept cb 4 params', () => {\n    const o = bindCallback(fa5cb4) // $ExpectType (e: E, f: F, g: G, a: A, b: B) => Observable<[res1: A, res2: B, res3: C, res4: D]>\n  });\n});\n\ndescribe('callbackFunc overkill' , () => {\n  it('should accept 10 args and 5 params', () => {\n    const fa10cb5 = (_1: 1 , _2: 2, _3: 3, _4: 4, _5: 5, _6: 6, _7: 7, _8: 8, _9: 9, _10: 10, cb: (_11: 11, _12: 12, _13: 13, _14: 14, _15: 15) => void) => {\n      cb(11, 12, 13, 14, 15);\n    };\n    const o = bindCallback(fa10cb5) // $ExpectType (_1: 1, _2: 2, _3: 3, _4: 4, _5: 5, _6: 6, _7: 7, _8: 8, _9: 9, _10: 10) => Observable<[_11: 11, _12: 12, _13: 13, _14: 14, _15: 15]>\n  });\n});\n"
  },
  {
    "path": "packages/rxjs/spec-dtslint/observables/combineLatest-spec.ts",
    "content": "import { combineLatest } from 'rxjs';\nimport type { B, C, D, E, F } from '../helpers';\nimport { a$,  b$,  c$,  d$,  e$,  f$,  g$, A } from '../helpers';\n\nit('should accept 1 param', () => {\n  const o = combineLatest([a$]); // $ExpectType Observable<[A]>\n});\n\nit('should accept 2 params', () => {\n  const o = combineLatest([a$, b$]); // $ExpectType Observable<[A, B]>\n});\n\nit('should accept 3 params', () => {\n  const o = combineLatest([a$, b$, c$]); // $ExpectType Observable<[A, B, C]>\n});\n\nit('should accept 4 params', () => {\n  const o = combineLatest([a$, b$, c$, d$]); // $ExpectType Observable<[A, B, C, D]>\n});\n\nit('should accept 5 params', () => {\n  const o = combineLatest([a$, b$, c$, d$, e$]); // $ExpectType Observable<[A, B, C, D, E]>\n});\n\nit('should accept 6 params', () => {\n  const o = combineLatest([a$, b$, c$, d$, e$, f$]); // $ExpectType Observable<[A, B, C, D, E, F]>\n});\n\nit('should have basic support for 7 or more params', () => {\n  const o = combineLatest([a$, b$, c$, d$, e$, f$, g$]); // $ExpectType Observable<[A, B, C, D, E, F, G]>\n});\n\nit('should have full support for 7 or more params with readonly tuples', () => {\n  const o = combineLatest([a$, b$, c$, d$, e$, f$, g$] as const); // $ExpectType Observable<[A, B, C, D, E, F, G]>\n});\n\nit('should handle an array of Observables', () => {\n  const o = combineLatest([a$, a$, a$, a$, a$, a$, a$, a$, a$, a$, a$]); // $ExpectType Observable<[A, A, A, A, A, A, A, A, A, A, A]>\n});\n\nit('should accept 1 param and a result selector', () => {\n  const o = combineLatest([a$], (a: A) => new A()); // $ExpectType Observable<A>\n});\n\nit('should accept 2 params and a result selector', () => {\n  const o = combineLatest([a$, b$], (a: A, b: B) => new A()); // $ExpectType Observable<A>\n});\n\nit('should accept 3 params and a result selector', () => {\n  const o = combineLatest([a$, b$, c$], (a: A, b: B, c: C) => new A()); // $ExpectType Observable<A>\n});\n\nit('should accept 4 params and a result selector', () => {\n  const o = combineLatest([a$, b$, c$, d$], (a: A, b: B, c: C, d: D) => new A()); // $ExpectType Observable<A>\n});\n\nit('should accept 5 params and a result selector', () => {\n  const o = combineLatest([a$, b$, c$, d$, e$], (a: A, b: B, c: C, d: D, e: E) => new A()); // $ExpectType Observable<A>\n});\n\nit('should accept 6 params and a result selector', () => {\n  const o = combineLatest([a$, b$, c$, d$, e$, f$], (a: A, b: B, c: C, d: D, e: E, f: F) => new A()); // $ExpectType Observable<A>\n});\n\nit('should accept 7 or more params and a result selector', () => {\n  const o = combineLatest([a$, b$, c$, d$, e$, f$, g$, g$, g$], (a: any, b: any, c: any, d: any, e: any, f: any, g1: any, g2: any, g3: any) => new A()); // $ExpectType Observable<A>\n});\n\ndescribe('combineLatest({})', () => {\n  it('should properly type empty objects', () => {\n    const res = combineLatest({}); // $ExpectType Observable<never>\n  });\n\n  it('should work for the simple case', () => {\n    const res = combineLatest({ foo: a$, bar: b$, baz: c$ }); // $ExpectType Observable<{ foo: A; bar: B; baz: C; }>\n  });\n\n  it('should not rely upon the excess-properties behavior to identify empty objects', () => {\n    const obj = { foo: a$, bar: b$, baz: c$ };\n    const res = combineLatest(obj); // $ExpectType Observable<{ foo: A; bar: B; baz: C; }>\n  });\n\n  it('should reject non-ObservableInput values', () => {\n    const obj = { answer: 42 };\n    const res = combineLatest(obj); // $ExpectError\n  });\n});\n\nit('should take in any and return Observable<unknown> because we do not know if it is an array or object', () => {\n  const arg: any = null;\n  const res = combineLatest(arg); // $ExpectType Observable<unknown>\n});"
  },
  {
    "path": "packages/rxjs/spec-dtslint/observables/concat-spec.ts",
    "content": "import { of, concat, asyncScheduler } from 'rxjs';\n\nit('should accept 1 param', () => {\n  const o = concat(of(1)); // $ExpectType Observable<number>\n});\n\nit('should accept 2 params', () => {\n  const o = concat(of(1), of(2)); // $ExpectType Observable<number>\n});\n\nit('should accept 3 params', () => {\n  const o = concat(of(1), of(2), of(3)); // $ExpectType Observable<number>\n});\n\nit('should accept 4 params', () => {\n  const o = concat(of(1), of(2), of(3), of(4)); // $ExpectType Observable<number>\n});\n\nit('should accept 5 params', () => {\n  const o = concat(of(1), of(2), of(3), of(4), of(5)); // $ExpectType Observable<number>\n});\n\nit('should accept 6 params', () => {\n  const o = concat(of(1), of(2), of(3), of(4), of(5), of(6)); // $ExpectType Observable<number>\n});\n\nit('should accept more than 6 params', () => {\n  const o = concat(of(1), of(2), of(3), of(4), of(5), of(6), of(7), of(8), of(9)); // $ExpectType Observable<number>\n});\n\nit('should return Observable<unknown> for more than 6 different types of params', () => {\n  const o = concat(of(1), of('a'), of(2), of(true), of(3), of([1, 2, 3]), of(4)); // $ExpectType Observable<string | number | boolean | number[]>\n});\n\nit('should accept scheduler after params', () => {\n  const o = concat(of(4), of(5), of(6), asyncScheduler); // $ExpectType Observable<number>\n});\n\nit('should accept promises', () => {\n  const o = concat(Promise.resolve(4)); // $ExpectType Observable<number>\n});\n\nit('should accept arrays', () => {\n  const o = concat([4, 5]); // $ExpectType Observable<number>\n});\n\nit('should accept iterables', () => {\n  const o = concat([1], 'foo'); // $ExpectType Observable<string | number>\n});\n\nit('should infer correctly with multiple types', () => {\n  const o = concat(of('foo'), Promise.resolve<number[]>([1]), of(6)); // $ExpectType Observable<string | number | number[]>\n});\n\nit('should enforce types', () => {\n  const o = concat(5); // $ExpectError\n  const p = concat(of(5), 6); // $ExpectError\n  const q = concat(of(5), 6, asyncScheduler); // $ExpectError\n  const r = concat(of(5), asyncScheduler, asyncScheduler); // $ExpectError\n  const s = concat(asyncScheduler, asyncScheduler); // $ExpectError\n  const t = concat(asyncScheduler, of(1)); // $ExpectError\n  const u = concat(of(1), asyncScheduler, of(1)); // $ExpectError\n});\n\nit('should support union types', () => {\n  const u = Math.random() > 0.5 ? of(123) : of('abc');\n  const o = concat(u, u, u); // $ExpectType Observable<string | number>\n});\n\nit('should support different union types', () => {\n  const u1 = Math.random() > 0.5 ? of(123) : of('abc');\n  const u2 = Math.random() > 0.5 ? of(true) : of([1, 2, 3]);\n  const o = concat(u1, u2); // $ExpectType Observable<string | number | boolean | number[]>\n});\n"
  },
  {
    "path": "packages/rxjs/spec-dtslint/observables/defer-spec.ts",
    "content": "import { of, defer } from 'rxjs';\n\nit('should enforce function parameter', () => {\n  const a = defer(); // $ExpectError\n});\n\nit('should infer correctly with function return observable', () => {\n  const a = defer(() => of(1, 2, 3)); // $ExpectType Observable<number>\n});\n\nit('should infer correctly with function return promise', () => {\n  const a = defer(() => Promise.resolve(5)); // $ExpectType Observable<number>\n});\n\nit('should support union type returns', () => {\n  const a = defer(() => Math.random() > 0.5 ? of(123) : of('abc')); // $ExpectType Observable<string | number>\n});\n\nit('should infer correctly with function return any', () => {\n  const a = defer(() => 3 as any); // $ExpectType Observable<unknown>\n});\n\nit('should error with void functions', () => {\n  const a = defer(() => {}); // $ExpectError\n});\n\nit('should error if an ObservableInput is not returned', () => {\n  const a = defer(() => 42); // $ExpectError\n});\n\nit('should error if function returns undefined', () => {\n  const a = defer(() => undefined); // $ExpectError\n});\n\nit('should infer if function returns never', () => {\n  const a = defer(() => { throw new Error(); }); // $ExpectType Observable<never>\n});\n\n\nit('should infer correctly with function that sometimes error', () => {\n  // $ExpectType Observable<number>\n  defer(() => {\n    if (Math.random() > 0.5) {\n       throw new Error();\n    }\n    return of(1, 2, 3);\n  });\n});\n\nit('should error with functions that sometimes do not return an ObservableInput', () => {\n  const a = defer(() => { if (Math.random() < 0.5) { return of(42); } }); // $ExpectError\n});\n"
  },
  {
    "path": "packages/rxjs/spec-dtslint/observables/dom/ajax-spec.ts",
    "content": "import { ajax } from 'rxjs/ajax';\n\nit('should enforce function parameter', () => {\n  const o = ajax(); // $ExpectError\n});\n\nit('should accept string param', () => {\n  const o = ajax('/a'); // $ExpectType Observable<AjaxResponse<unknown>>\n});\n\nit('should accept AjaxRequest params', () => {\n  const ajaxRequest = {\n    method: 'GET',\n    url: '/a',\n    body: {a: 'a', b: 'b'},\n  };\n  const o = ajax(ajaxRequest); // $ExpectType Observable<AjaxResponse<unknown>>\n});\n\ndescribe('.getJson', () => {\n  it('should accept string param', () => {\n    const o = ajax.getJSON('/a'); // $ExpectType Observable<unknown>\n  });\n\n  it('should return generic type', () => {\n    const o = ajax.getJSON<number>('/a'); // $ExpectType Observable<number>\n  });\n});\n"
  },
  {
    "path": "packages/rxjs/spec-dtslint/observables/dom/animationFrames-spec.ts",
    "content": "import { animationFrames } from 'rxjs';\n\nit('should just be an observable of numbers', () => {\n  const o$ = animationFrames(); // $ExpectType Observable<{ timestamp: number; elapsed: number; }>\n});\n\nit('should allow the passing of a timestampProvider', () => {\n  const o$ = animationFrames(performance); // $ExpectType Observable<{ timestamp: number; elapsed: number; }>\n});\n\nit('should not allow the passing of an invalid timestamp provider', () => {\n  const o$ = animationFrames({ now() { return 'wee' } }); // $ExpectError\n});"
  },
  {
    "path": "packages/rxjs/spec-dtslint/observables/dom/fetch-spec.ts",
    "content": "import { fromFetch } from 'rxjs/fetch';\r\nimport { a$ } from '../../helpers';\r\n\r\nit('should emit the fetch Response by default', () => {\r\n  const a = fromFetch(\"a\"); // $ExpectType Observable<Response>\r\n});\r\n\r\nit('should support a selector that returns a Response promise', () => {\r\n  const a = fromFetch(\"a\", { selector: response => response.text() }); // $ExpectType Observable<string>\r\n});\r\n\r\nit('should support a selector that returns an arbitrary type', () => {\r\n  const a = fromFetch(\"a\", { selector: response => a$ }); // $ExpectType Observable<A>\r\n});\r\n\r\nit('should error for selectors that don\\'t return an ObservableInput', () => {\r\n  const a = fromFetch(\"a\", { selector: response => 42 }); // $ExpectError\r\n});\r\n"
  },
  {
    "path": "packages/rxjs/spec-dtslint/observables/empty-spec.ts",
    "content": "import { EMPTY } from 'rxjs';\n\nit('should always infer empty observable', () => {\n  // Empty Observable that replace empty static function \n  const a = EMPTY; // $ExpectType Observable<never>\n});\n"
  },
  {
    "path": "packages/rxjs/spec-dtslint/observables/forkJoin-spec.ts",
    "content": "import { a$, b$, c$ } from 'helpers';\nimport { of, forkJoin } from 'rxjs';\n\ndescribe('deprecated rest args', () => {\n  it('should infer correctly with 1 parameter', () => {\n    const a = of(1, 2, 3);\n    const res = forkJoin(a); // $ExpectType Observable<[number]>\n  });\n\n  it('should infer correctly with 2 parameters', () => {\n    const a = of(1, 2, 3);\n    const b = of('a', 'b', 'c');\n    const res = forkJoin(a, b); // $ExpectType Observable<[number, string]>\n  });\n\n  it('should infer correctly with 3 parameters', () => {\n    const a = of(1, 2, 3);\n    const b = of('a', 'b', 'c');\n    const c = of(1, 2, 3);\n    const res = forkJoin(a, b, c); // $ExpectType Observable<[number, string, number]>\n  });\n\n  it('should infer correctly with 4 parameters', () => {\n    const a = of(1, 2, 3);\n    const b = of('a', 'b', 'c');\n    const c = of(1, 2, 3);\n    const d = of(1, 2, 3);\n    const res = forkJoin(a, b, c, d); // $ExpectType Observable<[number, string, number, number]>\n  });\n\n  it('should infer correctly with 5 parameters', () => {\n    const a = of(1, 2, 3);\n    const b = of('a', 'b', 'c');\n    const c = of(1, 2, 3);\n    const d = of(1, 2, 3);\n    const e = of(1, 2, 3);\n    const res = forkJoin(a, b, c, d, e); // $ExpectType Observable<[number, string, number, number, number]>\n  });\n\n  it('should infer correctly with 6 parameters', () => {\n    const a = of(1, 2, 3);\n    const b = of('a', 'b', 'c');\n    const c = of(1, 2, 3);\n    const d = of(1, 2, 3);\n    const e = of(1, 2, 3);\n    const f = of(1, 2, 3);\n    const res = forkJoin(a, b, c, d, e, f); // $ExpectType Observable<[number, string, number, number, number, number]>\n  });\n});\n\nit('should infer of type any for more than 6 parameters', () => {\n  const a = of(1, 2, 3);\n  const b = of('a', 'b', 'c');\n  const c = of(1, 2, 3);\n  const d = of(1, 2, 3);\n  const e = of(1, 2, 3);\n  const f = of(1, 2, 3);\n  const g = of(1, 2, 3);\n  const res = forkJoin(a, b, c, d, e, f, g); // $ExpectType Observable<[number, string, number, number, number, number, number]>\n});\n\ndescribe('forkJoin({})', () => {\n  it('should properly type empty objects', () => {\n    const res = forkJoin({}); // $ExpectType Observable<never>\n  });\n\n  it('should work for the simple case', () => {\n    const res = forkJoin({ foo: of(1), bar: of('two'), baz: of(false) }); // $ExpectType Observable<{ foo: number; bar: string; baz: boolean; }>\n  });\n\n  it('should not rely upon the excess-properties behavior to identify empty objects', () => {\n    const obj = { foo: of(1), bar: of('two'), baz: of(false) };\n    const res = forkJoin(obj); // $ExpectType Observable<{ foo: number; bar: string; baz: boolean; }>\n  });\n\n  it('should reject non-ObservableInput values', () => {\n    const obj = { answer: 42 };\n    const res = forkJoin(obj); // $ExpectError\n\n  });\n});\n\ndescribe('forkJoin([])', () => {\n  it('should properly type empty arrays', () => {\n    const res = forkJoin([]); // $ExpectType Observable<never>\n    const resConst = forkJoin([] as const); // $ExpectType Observable<never>\n  });\n\n    it('should properly type readonly arrays', () => {\n    const res = forkJoin([a$, b$, c$] as const); // $ExpectType Observable<[A, B, C]>\n  });\n\n  it('should infer correctly for array of 1 observable', () => {\n    const res = forkJoin([of(1, 2, 3)]); // $ExpectType Observable<[number]>\n  });\n\n  it('should infer correctly for array of 2 observables', () => {\n    const res = forkJoin([of(1, 2, 3), of('a', 'b', 'c')]); // $ExpectType Observable<[number, string]>\n  });\n\n  it('should infer correctly for array of 3 observables', () => {\n    const res = forkJoin([of(1, 2, 3), of('a', 'b', 'c'), of(true, true, false)]); // $ExpectType Observable<[number, string, boolean]>\n  });\n\n  it('should infer correctly for array of 4 observables', () => {\n    const res = forkJoin([of(1, 2, 3), of('a', 'b', 'c'), of(1, 2, 3), of(1, 2, 3)]); // $ExpectType Observable<[number, string, number, number]>\n  });\n\n  it('should infer correctly for array of 5 observables', () => {\n    const res = forkJoin([of(1, 2, 3), of('a', 'b', 'c'), of(1, 2, 3), of(1, 2, 3), of(1, 2, 3)]); // $ExpectType Observable<[number, string, number, number, number]>\n  });\n\n  it('should infer correctly for array of 6 observables', () => {\n    const res = forkJoin([of(1, 2, 3), of('a', 'b', 'c'), of(1, 2, 3), of(1, 2, 3), of(1, 2, 3), of(1, 2, 3)]); // $ExpectType Observable<[number, string, number, number, number, number]>\n  });\n\n  it('should force user cast for array of 6+ observables', () => {\n    const res = forkJoin([of(1, 2, 3), of('a', 'b', 'c'), of(1, 2, 3), of(1, 2, 3), of(1, 2, 3), of(1, 2, 3), of(1, 2, 3)]); // $ExpectType Observable<[number, string, number, number, number, number, number]>\n  });\n\n  it('should return unknown for argument of any', () => {\n    const arg: any = null;\n    const res = forkJoin(arg); // $ExpectType Observable<unknown>\n  })\n});\n"
  },
  {
    "path": "packages/rxjs/spec-dtslint/observables/from-spec.ts",
    "content": "import { from, of, animationFrameScheduler, ReadableStreamLike } from 'rxjs';\n\nit('should accept an array', () => {\n  const o = from([1, 2, 3, 4]); // $ExpectType Observable<number>\n});\n\nit('should accept a Promise', () => {\n  const o = from(Promise.resolve('test')); // $ExpectType Observable<string>\n});\n\nit('should accept an Iterable', () => {\n  const iterable = (function*() {\n    yield 42;\n  }());\n\n  const o = from(iterable); // $ExpectType Observable<number>\n});\n\nit('should accept an Observable', () => {\n  const o = from(of('test')); // $ExpectType Observable<string>\n});\n\nit('should accept union types', () => {\n  const o = from(Math.random() > 0.5 ? of(123) : of('test')); // $ExpectType Observable<string | number>\n});\n\nit('should accept Observable<Observable<number>>', () => {\n  const o = from(of(of(123))); // $ExpectType Observable<Observable<number>>\n});\n\nit('should accept Observable<number[]>', () => {\n  const o = from(of([1, 2, 3])); // $ExpectType Observable<number[]>\n});\n\nit('should accept an array of Observables', () => {\n  const o = from([of(1), of(2), of(3)]); // $ExpectType Observable<Observable<number>>\n});\n\n// TODO(benlesh): enable this test, once the issue is resolved upstream (https://github.com/Microsoft/dtslint/issues/191)\n\n// NOTE: It appears to be working, it's just that dtslint sometimes says it wants\n// Observable<IterableIterator<number> | Observable<number> | string[]>\n// and if you switch it to that, it wants\n// Observable<Observable<number> | IterableIterator<number> | string[]>\n// and vica versa.\n\n// it('should accept an array of Inputs', () => {\n//   const iterable = (function*() {\n//     yield 42;\n//   }());\n\n//   const o = from([of(1), ['test'], iterable]); // $__TODO__ExpectType Observable<IterableIterator<number> | Observable<number> | string[]>\n// });\n\nit('should accept a ReadableStream', () => {\n  const stream = new ReadableStream<string>({\n    pull(controller) {\n      controller.enqueue('x');\n      controller.close();\n    },\n  });\n  const o = from(stream); // $ExpectType Observable<string>\n});"
  },
  {
    "path": "packages/rxjs/spec-dtslint/observables/fromEvent-spec.ts",
    "content": "import { fromEvent } from 'rxjs';\nimport type {\n  HasEventTargetAddRemove,\n  NodeStyleEventEmitter,\n  NodeCompatibleEventEmitter,\n  JQueryStyleEventEmitter\n} from '../../src/internal/observable/fromEvent';\nimport type { B } from '../helpers';\n\ndeclare const eventTargetSource: EventTarget;\n\nit('should support an event target source', () => {\n  const source: HasEventTargetAddRemove<Event> = eventTargetSource;\n  const a = fromEvent(eventTargetSource, \"click\"); // $ExpectType Observable<Event>\n});\n\nit('should support an event target source result selector', () => {\n  const a = fromEvent(eventTargetSource, \"click\", () => \"clunk\"); // $ExpectType Observable<string>\n});\n\nit('should support an event target source with options', () => {\n    const a = fromEvent(eventTargetSource, \"click\", { once: true }); // $ExpectType Observable<Event>\n});\n\nit('should support an event target source with options and result selector', () => {\n    const a = fromEvent(eventTargetSource, \"click\", { once: true }, () => \"clunk\"); // $ExpectType Observable<string>\n});\n\ndeclare const documentSource: HTMLDocument;\n\nit('should support a document source', () => {\n  const source: HasEventTargetAddRemove<Event> = documentSource;\n  const a = fromEvent(documentSource, \"click\"); // $ExpectType Observable<Event>\n});\n\nit('should support a document source result selector', () => {\n  const a = fromEvent(documentSource, \"click\", () => \"clunk\"); // $ExpectType Observable<string>\n});\n\nit('should support a document source with options', () => {\n    const a = fromEvent(documentSource, \"click\", { once: true }); // $ExpectType Observable<Event>\n});\n\nit('should support a document source with options and result selector', () => {\n    const a = fromEvent(documentSource, \"click\", { once: true }, () => \"clunk\"); // $ExpectType Observable<string>\n});\n\n// Pick the parts that will match NodeStyleEventEmitter. If this isn't done, it\n// will match JQueryStyleEventEmitter - because of the `on` and `off` methods -\n// despite the latter being declared last in the EventTargetLike union.\ndeclare const nodeStyleSource: Pick<typeof process, 'addListener' | 'removeListener'>;\n\nit('should support a node-style source', () => {\n  const source: NodeStyleEventEmitter = nodeStyleSource;\n  const a = fromEvent(nodeStyleSource, \"exit\"); // $ExpectType Observable<unknown>\n  const b = fromEvent<B>(nodeStyleSource, \"exit\"); // $ExpectType Observable<B>\n});\n\nit('should support a node-style source and symbol eventName', () => {\n  const SYMBOL_EVENT = Symbol();\n  const source: NodeStyleEventEmitter = nodeStyleSource;\n  const a = fromEvent(nodeStyleSource, SYMBOL_EVENT); // $ExpectType Observable<unknown>\n  const b = fromEvent<B>(nodeStyleSource, SYMBOL_EVENT); // $ExpectType Observable<B>\n});\n\nit('should deprecate explicit type parameters for a node-style source', () => {\n  const source: NodeStyleEventEmitter = nodeStyleSource;\n  const a = fromEvent(nodeStyleSource, \"exit\"); // $ExpectNoDeprecation\n  const b = fromEvent<B>(nodeStyleSource, \"exit\"); // $ExpectDeprecation\n});\n\nit('should support a node-style source result selector', () => {\n  const a = fromEvent(nodeStyleSource, \"exit\", () => \"bye\"); // $ExpectType Observable<string>\n});\n\nconst nodeCompatibleSource = {\n  addListener(eventName: \"something\", handler: () => void) {},\n  removeListener(eventName: \"something\", handler: () => void) {}\n};\n\nit('should support a node-compatible source', () => {\n  const source: NodeCompatibleEventEmitter = nodeCompatibleSource;\n  const a = fromEvent(nodeCompatibleSource, \"something\"); // $ExpectType Observable<unknown>\n  const b = fromEvent<B>(nodeCompatibleSource, \"something\"); // $ExpectType Observable<B>\n});\n\nit('should deprecate explicit type parameters for a node-compatible source', () => {\n  const source: NodeCompatibleEventEmitter = nodeCompatibleSource;\n  const a = fromEvent(nodeCompatibleSource, \"something\"); // $ExpectNoDeprecation\n  const b = fromEvent<B>(nodeCompatibleSource, \"something\"); // $ExpectDeprecation\n});\n\nit('should support a node-compatible source result selector', () => {\n  const a = fromEvent(nodeCompatibleSource, \"something\", () => \"something else\"); // $ExpectType Observable<string>\n});\n\nconst jQueryStyleSource = {\n  on(eventName: \"something\", handler: (this: any, b: B) => any) {},\n  off(eventName: \"something\", handler: (this: any, b: B) => any) {}\n};\n\nit('should support a jQuery-style source', () => {\n  const source: JQueryStyleEventEmitter<any, any> = jQueryStyleSource;\n  const a = fromEvent(jQueryStyleSource, \"something\"); // $ExpectType Observable<B>\n  const b = fromEvent<B>(jQueryStyleSource, \"something\"); // $ExpectType Observable<B>\n});\n\nit('should support a jQuery-style source result selector', () => {\n  const a = fromEvent(jQueryStyleSource, \"something\", () => \"something else\"); // $ExpectType Observable<string>\n});\n"
  },
  {
    "path": "packages/rxjs/spec-dtslint/observables/iif-spec.ts",
    "content": "import { a$, b$ } from 'helpers';\nimport { iif, EMPTY } from 'rxjs';\n\nconst randomBoolean = () => Math.random() > 0.5;\n\nit('should error for insufficient parameters', () => {\n  const r0 = iif(randomBoolean); // $ExpectError\n  const r1 = iif(randomBoolean, a$); // $ExpectError\n  const r2 = iif(randomBoolean, undefined, b$); // $ExpectError\n});\n\nit('should error for incorrect parameters', () => {\n  const r0 = iif(() => 132, a$, b$); // $ExpectError\n  const r1 = iif(randomBoolean, {}, b$); // $ExpectError\n  const r2 = iif(randomBoolean, a$, {}); // $ExpectError\n});\n\nit('should infer correctly', () => {\n  const r0 = iif(() => false, a$, b$); // $ExpectType Observable<A | B>\n  const r1 = iif(() => true, a$, b$); // $ExpectType Observable<A | B>\n  const r2 = iif(randomBoolean, a$, b$); // $ExpectType Observable<A | B>\n  const r3 = iif(() => false, a$, EMPTY); // $ExpectType Observable<A>\n  const r4 = iif(() => true, EMPTY, b$); // $ExpectType Observable<B>\n  const r5 = iif(randomBoolean, EMPTY, EMPTY); // $ExpectType Observable<never>\n});\n\n\nit('should support inference from a predicate that returns any', () => {\n  function alwaysTrueButReturnsAny(): any {\n    return true;\n  }\n\n  const o$ = iif(alwaysTrueButReturnsAny, a$, b$) // $ExpectType Observable<A | B>\n});"
  },
  {
    "path": "packages/rxjs/spec-dtslint/observables/interval-spec.ts",
    "content": "import { interval, animationFrameScheduler } from 'rxjs';\n\n  it('should infer correctly with number param', () => {\n    const a = interval(1); // $ExpectType Observable<number>\n  });\n\nit('should infer correctly with no param', () => {\n  const a = interval(); // $ExpectType Observable<number>\n});\n\n  it('should support scheduler', () => {\n    const a = interval(1, animationFrameScheduler); // $ExpectType Observable<number>\n  });\n"
  },
  {
    "path": "packages/rxjs/spec-dtslint/observables/never-spec.ts",
    "content": "import { NEVER } from 'rxjs';\n\nit('should be of type Observable<never>', () => {\n  const a = NEVER; // $ExpectType Observable<never>\n});\n"
  },
  {
    "path": "packages/rxjs/spec-dtslint/observables/of-spec.ts",
    "content": "import { of, animationFrameScheduler, queueScheduler } from 'rxjs';\nimport { A, a, b, c, d, e, f, g, h, i, j } from '../helpers';\n\nit('should infer never with 0 params', () => {\n  const res = of(); // $ExpectType Observable<never>\n});\n\nit('forced generic should not cause an issue', () => {\n  const x: any = null;\n  const res2 = of<string>(x); // $ExpectType Observable<string>\n});\n\nit('should infer correctly with 1 param', () => {\n  const res = of(a); // $ExpectType Observable<A>\n});\n\nit('should infer correctly with mixed type of 2 params', () => {\n  const res = of(a, b); // $ExpectType Observable<A | B>\n});\n\nit('should infer correctly with mixed type of 3 params', () => {\n  const res = of(a, b, c); // $ExpectType Observable<A | B | C>\n});\n\nit('should infer correctly with mixed type of 4 params', () => {\n  const res = of(a, b, c, d); // $ExpectType Observable<A | B | C | D>\n});\n\nit('should infer correctly with mixed type of 5 params', () => {\n  const res = of(a, b, c, d, e); // $ExpectType Observable<A | B | C | D | E>\n});\n\nit('should infer correctly with mixed type of 6 params', () => {\n  const res = of(a, b, c, d, e, f); // $ExpectType Observable<A | B | C | D | E | F>\n});\n\nit('should infer correctly with mixed type of 7 params', () => {\n  const res = of(a, b, c, d, e, f, g); // $ExpectType Observable<A | B | C | D | E | F | G>\n});\n\nit('should infer correctly with mixed type of 8 params', () => {\n  const res = of(a, b, c, d, e, f, g, h); // $ExpectType Observable<A | B | C | D | E | F | G | H>\n});\n\nit('should infer correctly with mixed type of 9 params', () => {\n  const res = of(a, b, c, d, e, f, g, h, i); // $ExpectType Observable<A | B | C | D | E | F | G | H | I>\n});\n\nit('should infer correctly with mono type of more than 9 params', () => {\n  const res = of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10); // $ExpectType Observable<number>\n});\n\nit('should support mixed type of 9 params', () => {\n  const res = of(a, b, c, d, e, f, g, h, i, j); // $ExpectType Observable<A | B | C | D | E | F | G | H | I | J>\n});\n\nit('should support mixed type of 13 params', () => {\n  const res = of(a, b, c, d, e, f, g, h, i, j, '', true, 123, 10n); // $ExpectType Observable<string | number | bigint | boolean | A | B | C | D | E | F | G | H | I | J>\n});\n\nit('should support a rest of params', () => {\n  const arr = [a, b, c, d, e, f, g, h, i, j];\n  const res = of(...arr); // $ExpectType Observable<A | B | C | D | E | F | G | H | I | J>\n\n  const arr2 = ['test', 123, a];\n  const res2 = of(...arr2); // $ExpectType Observable<string | number | A>\n\n  const res3 = of(b, ...arr2, c, true); // $ExpectType Observable<string | number | boolean | A | B | C>\n});\n\nit('should infer correctly with array', () => {\n  const res = of([a, b, c]); // $ExpectType Observable<(A | B | C)[]>\n});\n\nit('should handle null and undefined properly', () => {\n  const a = of(undefined); // $ExpectType Observable<undefined>\n  const b = of(null); // $ExpectType Observable<null>\n  const c = [of(1), of(2), of(undefined), of(3)] as const;\n});\n"
  },
  {
    "path": "packages/rxjs/spec-dtslint/observables/onErrorResumeNext-spec.ts",
    "content": "/** @prettier */\nimport { onErrorResumeNext } from 'rxjs';\nimport { a$, b$, c$, d$, e$, f$, g$, h$, i$, j$ } from '../helpers';\n\nit('should infer correctly', () => {\n  const o1 = onErrorResumeNext(); // $ExpectType Observable<never>\n  const o2 = onErrorResumeNext(a$); // $ExpectType Observable<A>\n  const o3 = onErrorResumeNext(a$, b$); // $ExpectType Observable<A | B>\n  const o4 = onErrorResumeNext(a$, b$, c$); // $ExpectType Observable<A | B | C>\n  const o5 = onErrorResumeNext(a$, b$, c$, d$); // $ExpectType Observable<A | B | C | D>\n  const o6 = onErrorResumeNext(a$, b$, c$, d$, e$); // $ExpectType Observable<A | B | C | D | E>\n  const o7 = onErrorResumeNext(a$, b$, c$, d$, e$, f$); // $ExpectType Observable<A | B | C | D | E | F>\n  const o8 = onErrorResumeNext(a$, b$, c$, d$, e$, f$, g$); // $ExpectType Observable<A | B | C | D | E | F | G>\n  const o9 = onErrorResumeNext(a$, b$, c$, d$, e$, f$, g$, h$); // $ExpectType Observable<A | B | C | D | E | F | G | H>\n  const o10 = onErrorResumeNext(a$, b$, c$, d$, e$, f$, g$, h$, i$); // $ExpectType Observable<A | B | C | D | E | F | G | H | I>\n  const o11 = onErrorResumeNext(a$, b$, c$, d$, e$, f$, g$, h$, i$, j$); // $ExpectType Observable<A | B | C | D | E | F | G | H | I | J>\n});\n\nit('should handle non-observable inputs appropriately', () => {\n  const o1 = onErrorResumeNext({ lol: 'test' }); // $ExpectError\n  const o2 = onErrorResumeNext(a$, { haha: 'no' }); // $ExpectError\n});\n\nit('should handle observable inputs okay', () => {\n  const o1 = onErrorResumeNext([1, 2, 3, 'test'], Promise.resolve(true)); // $ExpectType Observable<string | number | boolean>\n  const o2 = onErrorResumeNext( // $ExpecType Observable<string>\n    (function* () {\n      yield 'foo';\n      return 'test';\n    })()\n  );\n});\n"
  },
  {
    "path": "packages/rxjs/spec-dtslint/observables/partition-spec.ts",
    "content": "import { of, from, partition } from 'rxjs';\r\n\r\nit('should infer correctly', () => {\r\n  const o = partition(of('a', 'b', 'c'), (value, index) => true); // $ExpectType [Observable<string>, Observable<string>]\r\n  const p = partition(of('a', 'b', 'c'), () => true); // $ExpectType [Observable<string>, Observable<string>]\r\n});\r\n\r\nit('should support a user-defined type guard', () => {\r\n  const o = partition(of(1, 2, 3), (value: number): value is 1 => value === 1); // $ExpectType [Observable<1>, Observable<number>]\r\n});\r\n\r\nit('should support exclusion based on the user-defined type guard', () => {\r\n  const o = partition(from([1, 2] as const), (value: number): value is 1 => value === 1); // $ExpectType [Observable<1>, Observable<2>]\r\n});\r\n\r\nit('should enforce predicate', () => {\r\n  const o = partition(of('a', 'b', 'c')); // $ExpectError\r\n});\r\n\r\nit('should enforce predicate types', () => {\r\n  const o = partition(of('a', 'b', 'c'), 'nope'); // $ExpectError\r\n  const p = partition(of('a', 'b', 'c'), (value: number) => true); // $ExpectError\r\n  const q = partition(of('a', 'b', 'c'), (value, index: string) => true); // $ExpectError\r\n});\r\n\r\nit('should support this with type guard', () => {\r\n  const thisArg = { limit: 2 };\r\n  const a = partition(of(1, 2, 3), function (val): val is 1 { // $ExpectType [Observable<1>, Observable<number>]\r\n    const limit = this.limit; // $ExpectType number\r\n    return val < limit;\r\n  }, thisArg);\r\n});\r\n\r\nit('should support this with exclusion based on the user-defined type guard', () => {\r\n  const thisArg = { limit: 2 };\r\n  const a = partition(from([1, 2] as const), function (val): val is 1 { // $ExpectType [Observable<1>, Observable<2>]\r\n    const limit = this.limit; // $ExpectType number\r\n    return val < limit;\r\n  }, thisArg);\r\n});\r\n\r\nit('should support this with predicate', () => {\r\n  const thisArg = { limit: 2 };\r\n  const a = partition(of(1, 2, 3), function (val) { // $ExpectType [Observable<number>, Observable<number>]\r\n    const limit = this.limit; // $ExpectType number\r\n    return val < limit;\r\n  }, thisArg);\r\n});\r\n\r\nit('should deprecate thisArg usage', () => {\r\n  const a = partition(of(1, 2, 3), Boolean); // $ExpectNoDeprecation\r\n  const b = partition(of(1, 2, 3), Boolean, {}); // $ExpectDeprecation\r\n  const c = partition(of(1, 2, 3), (value) => Boolean(value)); // $ExpectNoDeprecation\r\n  const d = partition(of(1, 2, 3), (value) => Boolean(value), {}); // $ExpectDeprecation\r\n});"
  },
  {
    "path": "packages/rxjs/spec-dtslint/observables/race-spec.ts",
    "content": "import { race, NEVER, EMPTY } from 'rxjs';\nimport { a$, b, b$, c, c$, d$, e$, f$ } from '../helpers';\n\ndescribe('race(a, b, c)', () => {\n  it('should support N arguments of different types', () => {\n    const o1 = race(a$); // $ExpectType Observable<A>\n    const o2 = race(a$, b$); // $ExpectType Observable<A | B>\n    const o3 = race(a$, b$, c$); // $ExpectType Observable<A | B | C>\n    const o4 = race(a$, b$, c$, d$); // $ExpectType Observable<A | B | C | D>\n    const o5 = race(a$, b$, c$, d$, e$); // $ExpectType Observable<A | B | C | D | E>\n    const o6 = race(a$, b$, c$, d$, e$, f$); // $ExpectType Observable<A | B | C | D | E | F>\n  });\n});\n\ndescribe('race([a, b, c])', () => {\n  it('should support N arguments of different types', () => {\n    const o1 = race([a$]); // $ExpectType Observable<A>\n    const o2 = race([a$, b$]); // $ExpectType Observable<A | B>\n    const o3 = race([a$, b$, c$]); // $ExpectType Observable<A | B | C>\n    const o4 = race([a$, b$, c$, d$]); // $ExpectType Observable<A | B | C | D>\n    const o5 = race([a$, b$, c$, d$, e$]); // $ExpectType Observable<A | B | C | D | E>\n    const o6 = race([a$, b$, c$, d$, e$, f$]); // $ExpectType Observable<A | B | C | D | E | F>\n  });\n});\n\nit('should race observable inputs', () => {\n  const o = race(a$, Promise.resolve(b), [c]); // $ExpectType Observable<A | B | C>\n});\n\nit('should race an array observable inputs', () => {\n  const o = race([a$, Promise.resolve(b), [c]]); // $ExpectType Observable<A | B | C>\n});\n\nit('should handle observables that do not emit', () => {\n  const o1 = race([NEVER, a$, EMPTY, [], b$]); // $ExpectType Observable<A | B>\n  const o2 = race(NEVER, a$, EMPTY, [], b$); // $ExpectType Observable<A | B>\n});\n\n"
  },
  {
    "path": "packages/rxjs/spec-dtslint/observables/range-spec.ts",
    "content": "import { range, animationFrameScheduler } from 'rxjs';\n\nit('should infer correctly with number parameters', () => {\n  const a = range(1, 2); // $ExpectType Observable<number>\n});\n\nit('should accept only number parameters', () => {\n  const a = range('a', 1); // $ExpectError\n});\n\nit('should allow 1 parameter', () => { \n  const a = range(1); // $ExpectType Observable<number>\n});\n\nit('should support scheduler', () => {\n  const a = range(1, 2, animationFrameScheduler); // $ExpectType Observable<number>\n});\n"
  },
  {
    "path": "packages/rxjs/spec-dtslint/observables/throwError-spec.ts",
    "content": "import { throwError } from 'rxjs';\n\nit('should error for incorrect errorFactory', () => {\n  const a = throwError(1); // $ExpectError\n  const b = throwError('a'); // $ExpectError\n  const c = throwError({ a: 1 }); // $ExpectError\n});\n\nit('should accept any type and return never observable with support of factory', () => {\n  const a = throwError(() => (1)); // $ExpectType Observable<never>\n  const b = throwError(() => ('a')); // $ExpectType Observable<never>\n  const c = throwError(() => ({ a: 1 })); // $ExpectType Observable<never>\n  const d = throwError(() => ({ a: 2 })); // $ExpectType Observable<never>\n});\n"
  },
  {
    "path": "packages/rxjs/spec-dtslint/observables/timer-spec.ts",
    "content": "import { timer, animationFrameScheduler } from 'rxjs';\n\nit('should infer correctly with 1 parameter of number type', () => {\n  const a = timer(1); // $ExpectType Observable<0>\n});\n\nit('should infer correctly with 1 parameter of date type', () => {\n  const a = timer((new Date())); // $ExpectType Observable<0>\n});\n\nit('should not support string parameter', () => {\n  const a = timer('a'); // $ExpectError\n});\n\nit('should infer correctly with 2 parameters', () => {\n  const a = timer(1, 2); // $ExpectType Observable<number>\n});\n\nit('should support scheduler as second parameter', () => {\n  const a = timer(1, animationFrameScheduler); // $ExpectType Observable<0>\n});\n\nit('should support scheduler as third parameter', () => {\n  const a = timer(1, 2, animationFrameScheduler); // $ExpectType Observable<number>\n});\n"
  },
  {
    "path": "packages/rxjs/spec-dtslint/observables/using-spec.ts",
    "content": "import { using } from 'rxjs';\nimport { a$, b$ } from '../helpers';\n\nit('should infer with a simple factory', () => {\n  const o = using(() => {}, () => a$); // $ExpectType Observable<A>\n});\n\nit('should infer with a factory that returns a union', () => {\n  const o = using(() => {}, () => Math.random() < 0.5 ? a$ : b$); // $ExpectType Observable<A | B>\n});"
  },
  {
    "path": "packages/rxjs/spec-dtslint/observables/zip-spec.ts",
    "content": "import { of, zip } from 'rxjs';\r\n\r\nit('should support observables', () => {\r\n  const a = of(1); // $ExpectType Observable<number>\r\n  const b = of('foo'); // $ExpectType Observable<string>\r\n  const c = of(true); // $ExpectType Observable<boolean>\r\n  const o1 = zip(a, b, c); // $ExpectType Observable<[number, string, boolean]>\r\n});\r\n\r\nit('should support mixed observables and promises', () => {\r\n  const a = Promise.resolve(1); // $ExpectType Promise<number>\r\n  const b = of('foo'); // $ExpectType Observable<string>\r\n  const c = of(true); // $ExpectType Observable<boolean>\r\n  const d = of(['bar']); // $ExpectType Observable<string[]>\r\n  const o1 = zip(a, b, c, d); // $ExpectType Observable<[number, string, boolean, string[]]>\r\n});\r\n\r\nit('should support arrays of promises', () => {\r\n  const a = [Promise.resolve(1)]; // $ExpectType Promise<number>[]\r\n  const o1 = zip(a); // $ExpectType Observable<number[]>\r\n  const o2 = zip(...a); // $ExpectType Observable<number[]>\r\n});\r\n\r\nit('should support arrays of observables', () => {\r\n  const a = [of(1)]; // $ExpectType Observable<number>[]\r\n  const o1 = zip(a); // $ExpectType Observable<number[]>\r\n  const o2 = zip(...a); // $ExpectType Observable<number[]>\r\n});\r\n\r\nit('should return Array<T> when given a single promise', () => {\r\n  const a = Promise.resolve(1); // $ExpectType Promise<number>\r\n  const o1 = zip(a); // $ExpectType Observable<[number]>\r\n});\r\n\r\nit('should return Array<T> when given a single observable', () => {\r\n  const a = of(1); // $ExpectType Observable<number>\r\n  const o1 = zip(a); // $ExpectType Observable<[number]>\r\n});\r\n\r\nit('should support union types', () => {\r\n  const u = Math.random() > 0.5 ? of(123) : of('abc');\r\n  const o = zip(u, u, u); // $ExpectType Observable<[string | number, string | number, string | number]>\r\n});\r\n\r\nit('should support different union types', () => {\r\n  const u = Math.random() > 0.5 ? of(123) : of('abc');\r\n  const u2 = Math.random() > 0.5 ? of(true) : of([1, 2, 3]);\r\n  const o = zip(u, u2); // $ExpectType Observable<[string | number, boolean | number[]]>\r\n});\r\n"
  },
  {
    "path": "packages/rxjs/spec-dtslint/operators/audit-spec.ts",
    "content": "import { of, NEVER } from 'rxjs';\nimport { audit } from 'rxjs/operators';\n\nit('should infer correctly', () => {\n  const o = of(1, 2, 3).pipe(audit(() => of('foo'))); // $ExpectType Observable<number>\n  const p = of(1, 2, 3).pipe(audit(() => NEVER)); // $ExpectType Observable<number>\n});\n\nit('should infer correctly with a Promise', () => {\n  const o = of(1, 2, 3).pipe(audit(() => new Promise<string>(() => {}))); // $ExpectType Observable<number>\n});\n\nit('should enforce types', () => {\n  const o = of(1, 2, 3).pipe(audit()); // $ExpectError\n  const p = of(1, 2, 3).pipe(audit((p: string) => of('foo'))); // $ExpectError\n});\n"
  },
  {
    "path": "packages/rxjs/spec-dtslint/operators/auditTime-spec.ts",
    "content": "import { of, asyncScheduler } from 'rxjs';\nimport { auditTime } from 'rxjs/operators';\n\nit('should infer correctly', () => {\n  const o = of('a', 'b', 'c').pipe(auditTime(47)); // $ExpectType Observable<string>\n});\n\nit('should support a scheduler', () => {\n  const o = of('a', 'b', 'c').pipe(auditTime(47, asyncScheduler)); // $ExpectType Observable<string>\n});\n\nit('should enforce types', () => {\n  const o = of('a', 'b', 'c').pipe(auditTime()); // $ExpectError\n  const p = of('a', 'b', 'c').pipe(auditTime('47')); // $ExpectError\n  const q = of('a', 'b', 'c').pipe(auditTime(47, 'foo')); // $ExpectError\n});\n"
  },
  {
    "path": "packages/rxjs/spec-dtslint/operators/buffer-spec.ts",
    "content": "import { of } from 'rxjs';\nimport { buffer } from 'rxjs/operators';\n\nit('should infer correctly', () => {\n  const o = of(1, 2, 3).pipe(buffer(of('foo'))); // $ExpectType Observable<number[]>\n});\n\nit('should enforce types', () => {\n  const o = of(1, 2, 3).pipe(buffer()); // $ExpectError\n  const p = of(1, 2, 3).pipe(buffer(6)); // $ExpectError\n});\n\nit('should support Promises', () => {\n  const o = of(1, 2, 3).pipe(buffer(Promise.resolve('foo'))); // $ExpectType Observable<number[]>\n});\n"
  },
  {
    "path": "packages/rxjs/spec-dtslint/operators/bufferCount-spec.ts",
    "content": "import { of } from 'rxjs';\nimport { bufferCount } from 'rxjs/operators';\n\nit('should infer correctly', () => {\n  const o = of(1, 2, 3).pipe(bufferCount(1)); // $ExpectType Observable<number[]>\n  const p = of(1, 2, 3).pipe(bufferCount(1, 7)); // $ExpectType Observable<number[]>\n});\n\nit('should enforce types', () => {\n  const o = of(1, 2, 3).pipe(bufferCount()); // $ExpectError\n});\n\nit('should enforce type of bufferSize', () => {\n  const o = of(1, 2, 3).pipe(bufferCount('7')); // $ExpectError\n});\n\nit('should enforce type of startBufferEvery', () => {\n  const o = of(1, 2, 3).pipe(bufferCount(1, '7')); // $ExpectError\n});\n"
  },
  {
    "path": "packages/rxjs/spec-dtslint/operators/bufferTime-spec.ts",
    "content": "import { of, asyncScheduler } from 'rxjs';\nimport { bufferTime } from 'rxjs/operators';\n\nit('should infer correctly', () => {\n  const o = of(1, 2, 3).pipe(bufferTime(1)); // $ExpectType Observable<number[]>\n  const p = of(1, 2, 3).pipe(bufferTime(1, asyncScheduler)); // $ExpectType Observable<number[]>\n});\n\nit('should support a bufferCreationInterval', () => {\n  const o = of(1, 2, 3).pipe(bufferTime(1, 6)); // $ExpectType Observable<number[]>\n  const p = of(1, 2, 3).pipe(bufferTime(1, 6, asyncScheduler)); // $ExpectType Observable<number[]>\n  const q = of(1, 2, 3).pipe(bufferTime(1, undefined)); // $ExpectType Observable<number[]>\n  const r = of(1, 2, 3).pipe(bufferTime(1, null)); // $ExpectType Observable<number[]>\n});\n\nit('should support a maxBufferSize', () => {\n  const o = of(1, 2, 3).pipe(bufferTime(1, 6, 3)); // $ExpectType Observable<number[]>\n  const p = of(1, 2, 3).pipe(bufferTime(1, 6, 3, asyncScheduler)); // $ExpectType Observable<number[]>\n  const q = of(1, 2, 3).pipe(bufferTime(1, undefined, 3)); // $ExpectType Observable<number[]>\n  const r = of(1, 2, 3).pipe(bufferTime(1, null, 3)); // $ExpectType Observable<number[]>\n});\n\nit('should enforce types', () => {\n  const o = of(1, 2, 3).pipe(bufferTime()); // $ExpectError\n});\n\nit('should enforce type of bufferTimeSpan', () => {\n  const o = of(1, 2, 3).pipe(bufferTime('3')); // $ExpectError\n});\n\nit('should enforce type of scheduler', () => {\n  const o = of(1, 2, 3).pipe(bufferTime(3, '3')); // $ExpectError\n});\n\nit('should enforce type of bufferCreationInterval', () => {\n  const o = of(1, 2, 3).pipe(bufferTime(3, '3', asyncScheduler)); // $ExpectError\n});\n\nit('should enforce type of maxBufferSize', () => {\n  const o = of(1, 2, 3).pipe(bufferTime(3, 3, '3', asyncScheduler)); // $ExpectError\n});\n"
  },
  {
    "path": "packages/rxjs/spec-dtslint/operators/bufferToggle-spec.ts",
    "content": "import { of, NEVER } from 'rxjs';\nimport { bufferToggle } from 'rxjs/operators';\n\nit('should infer correctly', () => {\n  const o = of(1, 2, 3).pipe(bufferToggle(of('a', 'b', 'c'), value => of(new Date()))); // $ExpectType Observable<number[]>\n});\n\nit('should support Promises', () => {\n  const promise = Promise.resolve('a');\n  const o = of(1, 2, 3).pipe(bufferToggle(promise, value => of(new Date()))); // $ExpectType Observable<number[]>\n  const p = of(1, 2, 3).pipe(bufferToggle(of('a', 'b', 'c'), value => promise)); // $ExpectType Observable<number[]>\n  const q = of(1, 2, 3).pipe(bufferToggle(promise, value => promise)); // $ExpectType Observable<number[]>\n});\n\nit('should support NEVER', () => {\n  const o = of(1, 2, 3).pipe(bufferToggle(NEVER, value => of(new Date()))); // $ExpectType Observable<number[]>\n  const p = of(1, 2, 3).pipe(bufferToggle(of('a', 'b', 'c'), value => NEVER)); // $ExpectType Observable<number[]>\n  const q = of(1, 2, 3).pipe(bufferToggle(NEVER, value => NEVER)); // $ExpectType Observable<number[]>\n});\n\nit('should enforce types', () => {\n  const o = of(1, 2, 3).pipe(bufferToggle()); // $ExpectError\n});\n\nit('should enforce type of openings', () => {\n  const o = of(1, 2, 3).pipe(bufferToggle('a', () => of('a', 'b', 'c'))); // $ExpectType Observable<number[]>\n  const o2 = of(1, 2, 3).pipe(bufferToggle('a', (x: number) => of('a', 'b', 'c'))); // $ExpectError\n});\n\nit('should enforce type of closingSelector', () => {\n  const o = of(1, 2, 3).pipe(bufferToggle(of('a', 'b', 'c'), 'a')); // $ExpectError\n  const p = of(1, 2, 3).pipe(bufferToggle(of('a', 'b', 'c'), (value: number) => of('a', 'b', 'c'))); // $ExpectError\n});\n"
  },
  {
    "path": "packages/rxjs/spec-dtslint/operators/bufferWhen-spec.ts",
    "content": "import { of } from 'rxjs';\nimport { bufferWhen } from 'rxjs/operators';\n\nit('should infer correctly', () => {\n  const o = of(1, 2, 3).pipe(bufferWhen(() => of('a', 'b', 'c'))); // $ExpectType Observable<number[]>\n});\n\nit('should enforce types', () => {\n  const o = of(1, 2, 3).pipe(bufferWhen()); // $ExpectError\n});\n\nit('should enforce type of closingSelector', () => {\n  const o = of(1, 2, 3).pipe(bufferWhen(of('a', 'b', 'c'))); // $ExpectError\n});\n"
  },
  {
    "path": "packages/rxjs/spec-dtslint/operators/catchError-spec.ts",
    "content": "import type { Observable} from 'rxjs';\nimport { of, EMPTY } from 'rxjs';\nimport { catchError } from 'rxjs/operators';\n\nit('should infer correctly', () => {\n  const o = of(1, 2, 3).pipe(catchError((() => of(4, 5, 6)))); // $ExpectType Observable<number>\n});\n\nit('should handle empty (never) appropriately', () => {\n  const o = of(1, 2, 3).pipe(catchError(() => EMPTY)); // $ExpectType Observable<number>\n});\n\nit('should handle a throw', () => {\n  const f: () => never = () => { throw new Error('test'); };\n  const o = of(1, 2, 3).pipe(catchError(f)); // $ExpectType Observable<number>\n});\n\nit('should infer correctly when not returning', () => {\n  const o = of(1, 2, 3).pipe(catchError((() => { throw new Error('your hands in the air'); }))); // $ExpectType Observable<number>\n});\n\nit('should infer correctly when returning another type', () => {\n  const o = of(1, 2, 3).pipe(catchError((() => of('a', 'b', 'c')))); // $ExpectType Observable<string | number>\n});\n\nit('should enforce types', () => {\n  const o = of(1, 2, 3).pipe(catchError()); // $ExpectError\n});\n\nit('should enforce that selector returns an Observable', () => {\n  const o = of(1, 2, 3).pipe(catchError((err) => {})); // $ExpectError\n});\n\nit('should enforce type of caught', () => {\n  const o = of(1, 2, 3).pipe(catchError((err, caught: Observable<string>) => of('a', 'b', 'c'))); // $ExpectError\n});\n\nit('should handle union types', () => {\n  const o = of(1, 2, 3).pipe(catchError(err => err.message === 'wee' ? of('fun') : of(123))); // $ExpectType Observable<string | number>\n});\n"
  },
  {
    "path": "packages/rxjs/spec-dtslint/operators/combineLatestAll-spec.ts",
    "content": "import { of } from 'rxjs';\nimport { combineLatestAll } from 'rxjs/operators';\n\nit('should infer correctly', () => {\n  const o = of([1, 2, 3]).pipe(combineLatestAll()); // $ExpectType Observable<number[]>\n});\n\nit('should infer correctly with the projector', () => {\n  const o = of([1, 2, 3]).pipe(combineLatestAll((values: number) => ['x', 'y', 'z'])); // $ExpectType Observable<string[]>\n});\n\nit('should be accept projectors for observables with different types', () => {\n  // An `any` signature is required for the projector to deal with situations\n  // like this in which the source emits observables of different types. The\n  // types of the values passed to the projector depend on the order in which\n  // the source emits its observables and that can't be expressed in the type\n  // system.\n  const o = of(of(['a', 'b', 'c']), of([1, 2, 3])).pipe(combineLatestAll((a: string, b: number) => a + b)); // $ExpectType Observable<string>\n});\n\nit('should enforce types', () => {\n  const o = of(1, 2, 3).pipe(combineLatestAll()); // $ExpectError\n});\n\nit('should enforce type of the projector', () => {\n  const o = of([1, 2, 3]).pipe(combineLatestAll((values: string) => ['x', 'y', 'z'])); // $ExpectError\n  const p = of([1, 2, 3]).pipe(combineLatestAll<number[]>(values => ['x', 'y', 'z'])); // $ExpectError\n});\n"
  },
  {
    "path": "packages/rxjs/spec-dtslint/operators/combineLatestWith-spec.ts",
    "content": "import { of } from 'rxjs';\nimport { combineLatestWith } from 'rxjs/operators';\n\ndescribe('combineLatestWith', () => {\n  describe('without project parameter', () => {\n    it('should infer correctly with 1 param', () => {\n      const a = of(1, 2, 3);\n      const b = of('a', 'b', 'c');\n      const res = a.pipe(combineLatestWith(b)); // $ExpectType Observable<[number, string]>\n    });\n\n    it('should infer correctly with 2 params', () => {\n      const a = of(1, 2, 3);\n      const b = of('a', 'b', 'c');\n      const c = of('d', 'e', 'f');\n      const res = a.pipe(combineLatestWith(b, c)); // $ExpectType Observable<[number, string, string]>\n    });\n\n    it('should infer correctly with 3 params', () => {\n      const a = of(1, 2, 3);\n      const b = of('a', 'b', 'c');\n      const c = of('d', 'e', 'f');\n      const d = of('g', 'h', 'i');\n      const res = a.pipe(combineLatestWith(b, c, d)); // $ExpectType Observable<[number, string, string, string]>\n    });\n\n    it('should infer correctly with 4 params', () => {\n      const a = of(1, 2, 3);\n      const b = of('a', 'b', 'c');\n      const c = of('d', 'e', 'f');\n      const d = of('g', 'h', 'i');\n      const e = of('j', 'k', 'l');\n      const res = a.pipe(combineLatestWith(b, c, d, e)); // $ExpectType Observable<[number, string, string, string, string]>\n    });\n\n    it('should infer correctly with 5 params', () => {\n      const a = of(1, 2, 3);\n      const b = of('a', 'b', 'c');\n      const c = of('d', 'e', 'f');\n      const d = of('g', 'h', 'i');\n      const e = of('j', 'k', 'l');\n      const f = of('m', 'n', 'o');\n      const res = a.pipe(combineLatestWith(b, c, d, e, f)); // $ExpectType Observable<[number, string, string, string, string, string]>\n    });\n\n    it('should accept N params', () => {\n      const a = of(1, 2, 3);\n      const b = of('a', 'b', 'c');\n      const c = of('d', 'e', 'f');\n      const d = of('g', 'h', 'i');\n      const e = of('j', 'k', 'l');\n      const f = of('m', 'n', 'o');\n      const g = of('p', 'q', 'r');\n      const res = a.pipe(combineLatestWith(b, c, d, e, f, g)); // $ExpectType Observable<[number, string, string, string, string, string, string]>\n    });\n  });\n});\n"
  },
  {
    "path": "packages/rxjs/spec-dtslint/operators/concatAll-spec.ts",
    "content": "import { of } from 'rxjs';\nimport { concatAll } from 'rxjs/operators';\n\nit('should infer correctly', () => {\n  const o = of(of(1, 2, 3)).pipe(concatAll()); // $ExpectType Observable<number>\n});\n\nit('should enforce types', () => {\n  const o = of(1, 2, 3).pipe(concatAll()); // $ExpectError\n});\n"
  },
  {
    "path": "packages/rxjs/spec-dtslint/operators/concatMap-spec.ts",
    "content": "import { of } from 'rxjs';\nimport { concatMap } from 'rxjs/operators';\n\nit('should infer correctly', () => {\n  const o = of(1, 2, 3).pipe(concatMap(p => of(Boolean(p)))); // $ExpectType Observable<boolean>\n});\n\nit('should support a projector that takes an index', () => {\n  const o = of(1, 2, 3).pipe(concatMap((p, index) => of(Boolean(p)))); // $ExpectType Observable<boolean>\n});\n\nit('should support union-type projections', () => {\n  const o = of(Math.random()).pipe(concatMap(n => n > 0.5 ? of('life') : of(42))); // $ExpectType Observable<string | number>\n});\n\nit('should enforce types', () => {\n  const o = of(1, 2, 3).pipe(concatMap()); // $ExpectError\n});\n\nit('should enforce the return type', () => {\n  const o = of(1, 2, 3).pipe(concatMap(p => p)); // $ExpectError\n});\n\nit('should produce `Observable<never>` when mapping to an `ObservableInput<never>`', () => {\n  const o = of(1, 2, 3).pipe(concatMap(n => Promise.reject())); // $ExpectType Observable<never>\n});\n"
  },
  {
    "path": "packages/rxjs/spec-dtslint/operators/concatMapTo-spec.ts",
    "content": "import { of } from 'rxjs';\nimport { concatMapTo } from 'rxjs/operators';\n\nit('should infer correctly', () => {\n  const o = of(1, 2, 3).pipe(concatMapTo(of('foo'))); // $ExpectType Observable<string>\n});\n\nit('should infer correctly with multiple types', () => {\n  const o = of(1, 2, 3).pipe(concatMapTo(of('foo', 4))); // $ExpectType Observable<string | number>\n});\n\nit('should infer correctly with an array', () => {\n  const o = of(1, 2, 3).pipe(concatMapTo([4, 5, 6])); // $ExpectType Observable<number>\n});\n\nit('should infer correctly with a Promise', () => {\n  const o = of(1, 2, 3).pipe(concatMapTo(new Promise<string>(() => {}))); // $ExpectType Observable<string>\n});\n\nit('should support union types', () => {\n  const s = Math.random() > 0.5 ? of(123) : of('abc');\n  const r = of(1, 2, 3).pipe(concatMapTo(s)); // $ExpectType Observable<string | number>\n});\n\nit('should support union-type projections with empty streams', () => {\n  const o = of(1, 2, 3).pipe(concatMapTo(Math.random() < 0.5 ? of(123) : of())); // $ExpectType Observable<number>\n});\n\nit('should enforce types', () => {\n  const o = of(1, 2, 3).pipe(concatMapTo()); // $ExpectError\n});\n\nit('should enforce types of the observable parameter', () => {\n  const fn = () => {}\n  const o = of(1, 2, 3).pipe(concatMapTo(fn)); // $ExpectError\n});\n\nit('should enforce the return type', () => {\n  const o = of(1, 2, 3).pipe(concatMapTo(p => p)); // $ExpectError\n  const p = of(1, 2, 3).pipe(concatMapTo(4)); // $ExpectError\n});\n\nit('should produce `Observable<never>` when mapping to an `ObservableInput<never>`', () => {\n  const o = of(1, 2, 3).pipe(concatMapTo(Promise.reject())); // $ExpectType Observable<never>\n});\n\nit('should be deprecated', () => {\n  const o = of(1, 2, 3).pipe(concatMapTo(of(true))); // $ExpectDeprecation\n});\n"
  },
  {
    "path": "packages/rxjs/spec-dtslint/operators/concatWith-spec.ts",
    "content": "import { of } from 'rxjs';\nimport { concatWith } from 'rxjs/operators';\nimport { a$, b$, c$, d$, e$ } from 'helpers';\n\nit('should support rest params', () => {\n  const arr = [b$, c$];\n  const o = a$.pipe(concatWith(...arr)); // $ExpectType Observable<A | B | C>\n  const o2 = a$.pipe(concatWith(d$, ...arr, e$)); // $ExpectType Observable<A | B | C | D | E>\n});\n\nit('should infer correctly', () => {\n  const o = of(1, 2, 3).pipe(concatWith()); // $ExpectType Observable<number>\n});\n\nit('should support one argument', () => {\n  const o = of(1, 2, 3).pipe(concatWith(of(1))); // $ExpectType Observable<number>\n});\n\nit('should support two arguments', () => {\n  const o = of(1, 2, 3).pipe(concatWith(of(1), of(2))); // $ExpectType Observable<number>\n});\n\nit('should support three arguments', () => {\n  const o = of(1, 2, 3).pipe(concatWith(of(1), of(2), of(3))); // $ExpectType Observable<number>\n});\n\nit('should support four arguments', () => {\n  const o = of(1, 2, 3).pipe(concatWith(of(1), of(2), of(3), of(4))); // $ExpectType Observable<number>\n});\n\nit('should support five arguments', () => {\n  const o = of(1, 2, 3).pipe(concatWith(of(1), of(2), of(3), of(4), of(5))); // $ExpectType Observable<number>\n});\n\nit('should support six arguments', () => {\n  const o = of(1, 2, 3).pipe(concatWith(of(1), of(2), of(3), of(4), of(5), of(6))); // $ExpectType Observable<number>\n});\n\nit('should support six or more arguments', () => {\n  const o = of(1, 2, 3).pipe(concatWith(of(1), of(2), of(3), of(4), of(5), of(6), of(7), of(8), of(9))); // $ExpectType Observable<number>\n});\n\nit('should support promises', () => {\n  const o = of(1, 2, 3).pipe(concatWith(Promise.resolve(4))); // $ExpectType Observable<number>\n});\n\nit('should support arrays', () => {\n  const o = of(1, 2, 3).pipe(concatWith([4, 5])); // $ExpectType Observable<number>\n});\n\nit('should support iterables', () => {\n  const o = of(1, 2, 3).pipe(concatWith('foo')); // $ExpectType Observable<string | number>\n});\n\nit('should infer correctly with multiple types', () => {\n  const o = of(1, 2, 3).pipe(concatWith(of('foo'), Promise.resolve([1]), of(6))); // $ExpectType Observable<string | number | number[]>\n});\n\nit('should enforce types', () => {\n  const o = of(1, 2, 3).pipe(concatWith(5)); // $ExpectError\n  const p = of(1, 2, 3).pipe(concatWith(of(5), 6)); // $ExpectError\n});\n"
  },
  {
    "path": "packages/rxjs/spec-dtslint/operators/connect-spec.ts",
    "content": "import { of } from 'rxjs';\nimport { connect } from 'rxjs/operators';\nimport { a$, b$ } from '../helpers';\n\nit('should infer from a union', () => {\n    const o = of(null).pipe(connect(() => Math.random() > 0.5 ? a$ : b$)); // $ExpectType Observable<A | B>\n});"
  },
  {
    "path": "packages/rxjs/spec-dtslint/operators/count-spec.ts",
    "content": "import type { Observable } from 'rxjs';\nimport { of } from 'rxjs';\nimport { count } from 'rxjs/operators';\n\nit('should always infer number', () => {\n  const o = of(1, 2, 3).pipe(count(x => x > 1)); // $ExpectType Observable<number>\n  const j = of('a', 'b', 'c').pipe(count(x => x === 'a')); // $ExpectType Observable<number>\n});\n\nit('should accept empty parameter', () => {\n  const o = of(1, 2, 3).pipe(count()); // $ExpectType Observable<number>\n});\n\nit('should infer source observable type in parameter', () => {\n  const o = of(1, 2, 3).pipe(count((x, i, source: Observable<string>) => x === 3)); // $ExpectError\n});\n\nit('should enforce value type of source type', () => {\n  const o = of(1, 2, 3).pipe(count((x, i, source) => x === '3')); // $ExpectError\n});\n\nit('should enforce index type of number', () => {\n  const o = of(1, 2, 3).pipe(count((x, i, source) => i === '3')); // $ExpectError\n});\n\nit('should expect function parameter', () => {\n  const o = of(1, 2, 3).pipe(count(9)); // $ExpectError\n});\n\nit('should enforce source type', () => {\n  const o = of(1, 2, 3).pipe(count(x => x === '')); // $ExpectError\n});\n"
  },
  {
    "path": "packages/rxjs/spec-dtslint/operators/debounce-spec.ts",
    "content": "import { of, timer } from 'rxjs';\nimport { debounce } from 'rxjs/operators';\n\nit('should infer correctly', () => {\n  const o = of(1, 2, 3).pipe(debounce(() => timer(47))); // $ExpectType Observable<number>\n});\n\nit('should infer correctly with a Promise', () => {\n  const o = of(1, 2, 3).pipe(debounce(() => new Promise<boolean>(() => {}))); // $ExpectType Observable<number>\n});\n\nit('should enforce types', () => {\n  const o = of(1, 2, 3).pipe(debounce()); // $ExpectError\n  const p = of(1, 2, 3).pipe(debounce(() => {})); // $ExpectError\n});\n"
  },
  {
    "path": "packages/rxjs/spec-dtslint/operators/debounceTime-spec.ts",
    "content": "import { of, asyncScheduler } from 'rxjs';\nimport { debounceTime } from 'rxjs/operators';\n\nit('should infer correctly', () => {\n  const o = of(1, 2, 3).pipe(debounceTime(47)); // $ExpectType Observable<number>\n});\n\nit('should support a scheduler', () => {\n  const o = of(1, 2, 3).pipe(debounceTime(47, asyncScheduler)); // $ExpectType Observable<number>\n});\n\nit('should enforce types', () => {\n  const o = of(1, 2, 3).pipe(debounceTime()); // $ExpectError\n  const p = of(1, 2, 3).pipe(debounceTime('foo')); // $ExpectError\n  const q = of(1, 2, 3).pipe(debounceTime(47, 'foo')); // $ExpectError\n});\n"
  },
  {
    "path": "packages/rxjs/spec-dtslint/operators/defaultIfEmpty-spec.ts",
    "content": "import { EMPTY, of } from 'rxjs';\nimport { defaultIfEmpty, map } from 'rxjs/operators';\n\nit('should infer correctly', () => {\n  const o = of(1, 2, 3).pipe(defaultIfEmpty()); // $ExpectError\n  const o2 = of(undefined).pipe(defaultIfEmpty(undefined)); // $ExpectType Observable<undefined>\n});\n\nit('should infer correctly with a defaultValue', () => {\n  const o = of(1, 2, 3).pipe(defaultIfEmpty(47)); // $ExpectType Observable<number>\n});\n\nit('should infer correctly with a different type of defaultValue', () => {\n  const o = of(1, 2, 3).pipe(defaultIfEmpty<number, string>('carbonara')); // $ExpectType Observable<string | number>\n  const o2 = of(1, 2, 3).pipe(defaultIfEmpty('carbonara')); // $ExpectType Observable<string | number>\n});\n\nit('should infer correctly with a subtype passed through parameters', () => {\n  const o = of(true, false).pipe(map(p => p), defaultIfEmpty(true)); // $ExpectType Observable<boolean>\n});\n\nit('should enforce types', () => {\n  const o = of(1, 2, 3).pipe(defaultIfEmpty(4, 5)); // $ExpectError\n});\n\nit('should handle Observable<never> appropriately', () => {\n  const o = EMPTY.pipe(defaultIfEmpty('blah')); // $ExpectType Observable<string>\n})\n"
  },
  {
    "path": "packages/rxjs/spec-dtslint/operators/delay-spec.ts",
    "content": "import { of, asyncScheduler } from 'rxjs';\nimport { delay } from 'rxjs/operators';\n\nit('should infer correctly', () => {\n  const o = of(1, 2, 3).pipe(delay(100)); // $ExpectType Observable<number>\n});\n\nit('should support date parameter', () => {\n  const o = of(1, 2, 3).pipe(delay(new Date(2018, 9, 18))); // $ExpectType Observable<number>\n});\n\nit('should support a scheduler', () => {\n  const o = of(1, 2, 3).pipe(delay(100, asyncScheduler)); // $ExpectType Observable<number>\n});\n\nit('should enforce types', () => {\n  const o = of(1, 2, 3).pipe(delay()); // $ExpectError\n  const p = of(1, 2, 3).pipe(delay('foo')); // $ExpectError\n  const q = of(1, 2, 3).pipe(delay(47, 'foo')); // $ExpectError\n});\n"
  },
  {
    "path": "packages/rxjs/spec-dtslint/operators/delayWhen-spec.ts",
    "content": "import { of, NEVER } from 'rxjs';\nimport { delayWhen } from 'rxjs/operators';\n\nit('should infer correctly', () => {\n  const o = of(1, 2, 3).pipe(delayWhen(() => of('a', 'b', 'c'))); // $ExpectType Observable<number>\n  const p = of(1, 2, 3).pipe(delayWhen((value: number, index: number) => of('a', 'b', 'c'))); // $ExpectType Observable<number>\n});\n\nit('should support an empty notifier', () => {\n  const o = of(1, 2, 3).pipe(delayWhen(() => NEVER)); // $ExpectType Observable<number>\n});\n\nit('should support a subscriptionDelay parameter', () => {\n  const o = of(1, 2, 3).pipe(delayWhen(() => of('a', 'b', 'c'), of(new Date()))); // $ExpectType Observable<number>\n});\n\nit('should enforce types', () => {\n  const o = of(1, 2, 3).pipe(delayWhen()); // $ExpectError\n});\n\nit('should enforce types of delayDurationSelector', () => {\n  const o = of(1, 2, 3).pipe(delayWhen(of('a', 'b', 'c'))); // $ExpectError\n  const p = of(1, 2, 3).pipe(delayWhen((value: string, index) => of('a', 'b', 'c'))); // $ExpectError\n  const q = of(1, 2, 3).pipe(delayWhen((value, index: string) => of('a', 'b', 'c'))); // $ExpectError\n});\n\nit('should enforce types of subscriptionDelay', () => {\n  const o = of(1, 2, 3).pipe(delayWhen(() => of('a', 'b', 'c'), 'a')); // $ExpectError\n});\n\nit('should support Promises', () => {\n  const o = of(1, 2, 3).pipe(delayWhen(() => Promise.resolve('a'))); // $ExpectType Observable<number>\n});\n"
  },
  {
    "path": "packages/rxjs/spec-dtslint/operators/dematerialize-spec.ts",
    "content": "import { of } from 'rxjs';\nimport { dematerialize } from 'rxjs/operators';\n\n\nit('should infer correctly', () => {\n  const o = of({ kind: 'N' as const, value: 'foo' }).pipe(dematerialize()); // $ExpectType Observable<string>\n});\n\nit('should enforce types', () => {\n  const o = of({ kind: 'N' as const, value: 'foo' }).pipe(dematerialize(() => {})); // $ExpectError\n});\n\nit('should enforce types from POJOS', () => {\n  const source = of({\n    kind: 'N' as const,\n    value: 'test'\n  }, {\n    kind: 'N' as const,\n    value: 123\n  },\n  {\n    kind: 'N' as const,\n    value: [true, false]\n  });\n  const o = source.pipe(dematerialize()); // $ExpectType Observable<string | number | boolean[]>\n\n  // NOTE: The `const` is required, because TS doesn't yet have a way to know for certain the\n  // `kind` properties of these objects won't be mutated at runtime.\n  const source2 = of({\n    kind: 'N' as const,\n    value: 1\n  }, {\n    kind: 'C' as const\n  });\n  const o2 = source2.pipe(dematerialize()); // $ExpectType Observable<number>\n\n  const source3 = of({\n    kind: 'C' as const\n  });\n  const o3 = source3.pipe(dematerialize()); // $ExpectType Observable<never>\n\n  const source4 = of({\n    kind: 'E' as const,\n    error: new Error('bad')\n  });\n  const o4 = source4.pipe(dematerialize()); // $ExpectType Observable<never>\n\n  const source5 = of({\n    kind: 'E' as const\n  });\n  const o5 = source5.pipe(dematerialize()); // $ExpectError\n\n\n  // Next notifications should have a value.\n  const source6 = of({\n    kind: 'N' as const\n  });\n  const o6 = source6.pipe(dematerialize()); // $ExpectError\n});\n\nit('should enforce Notification source', () => {\n  const o = of('foo').pipe(dematerialize()); // $ExpectError\n});\n"
  },
  {
    "path": "packages/rxjs/spec-dtslint/operators/distinct-spec.ts",
    "content": "import { of } from 'rxjs';\nimport { asInteropObservable } from '../../spec/helpers/interop-helper';\nimport { distinct } from 'rxjs/operators';\nimport type { ReadableStreamLike } from '../../src/internal/types';\n\nit('should infer correctly', () => {\n  const o = of(1, 2, 3).pipe(distinct()); // $ExpectType Observable<number>\n});\n\nit('should accept a keySelector', () => {\n  interface Person { name: string; }\n  const o = of({ name: 'Tim' } as Person).pipe(distinct(person => person.name)); // $ExpectType Observable<Person>\n});\n\nit('should accept observable flush', () => {\n  const o = of(1, 2, 3).pipe(distinct(n => n, of('t', 'i', 'm'))); // $ExpectType Observable<number>\n});\n\nit('should accept interop observable flush', () => {\n  of(1, 2, 3).pipe(distinct(n => n, asInteropObservable(of('t', 'i', 'm')))); // $ExpectType Observable<number>\n});\n\nit('should accept array-like flush', () => {\n  of(1, 2, 3).pipe(distinct(n => n, [1,2,3])); // $ExpectType Observable<number>\n});\n\nit('should accept promise flush', () => {\n  of(1, 2, 3).pipe(distinct(n => n, Promise.resolve())); // $ExpectType Observable<number>\n});\n\nit('should accept async iterable flush', () => {\n  const asyncRange = {\n    from: 1,\n    to: 2,\n    [Symbol.asyncIterator]() {\n      return {\n        current: this.from,\n        last: this.to,\n        async next() {\n          await Promise.resolve();\n          const done = (this.current > this.last);\n          return {\n            done,\n            value: done ? this.current++ : undefined\n          };\n        }\n      };\n    }\n  };\n  of(1, 2, 3).pipe(distinct(n => n, asyncRange)); // $ExpectType Observable<number>\n});\n\nit('should accept iterable flush', () => {\n  const syncRange = {\n    from: 1,\n    to: 2,\n    [Symbol.iterator]() {\n      return {\n        current: this.from,\n        last: this.to,\n        next() {\n          const done = (this.current > this.last);\n          return {\n            done,\n            value: done ? this.current++ : undefined\n          };\n        }\n      };\n    }\n  };\n  of(1, 2, 3).pipe(distinct(n => n, syncRange)); // $ExpectType Observable<number>\n});\n\nit('should accept readable stream flush', () => {\n  const readable: ReadableStreamLike<string> = new ReadableStream<string>({\n    pull(controller) {\n      controller.enqueue('x');\n      controller.close();\n    },\n  });\n  of(1, 2, 3).pipe(distinct(n => n, readable)); // $ExpectType Observable<number>\n});\n\nit('should error with unsupported flush', () => {\n  of(1, 2, 3).pipe(distinct(n => n, {})); // $ExpectError\n});\n\nit('should enforce types', () => {\n  const o = of(1, 2, 3).pipe(distinct('F00D')); // $ExpectError\n});\n\nit('should enforce types of keySelector', () => {\n  const o = of<{ id: string; }>({id: 'F00D'}).pipe(distinct(item => item.foo)); // $ExpectError\n});\n"
  },
  {
    "path": "packages/rxjs/spec-dtslint/operators/distinctUntilChanged-spec.ts",
    "content": "import { of } from 'rxjs';\nimport { distinctUntilChanged } from 'rxjs/operators';\n\ninterface Person { name: string; }\nconst sample: Person = { name: 'Tim' };\n\nit('should infer correctly', () => {\n  const o = of(sample).pipe(distinctUntilChanged()); // $ExpectType Observable<Person>\n});\n\nit('should accept a compare', () => {\n  const o = of(sample).pipe(distinctUntilChanged((p1, p2) => p1.name === p2.name)); // $ExpectType Observable<Person>\n});\n\nit('should accept a keySelector', () => {\n  const o = of(sample).pipe(distinctUntilChanged((name1, name2) => name1 === name2, p => p.name)); // $ExpectType Observable<Person>\n});\n\nit('should enforce types', () => {\n  const o = of(sample).pipe(distinctUntilChanged('F00D')); // $ExpectError\n});\n\nit('should enforce types of compare', () => {\n  const o = of(sample).pipe(distinctUntilChanged((p1, p2) => p1.foo === p2.name)); // $ExpectError\n  const p = of(sample).pipe(distinctUntilChanged((p1, p2) => p1.name === p2.foo)); // $ExpectError\n});\n\nit('should enforce types of keySelector', () => {\n  const o = of(sample).pipe(distinctUntilChanged((name1 , name2) => name1 === name2, p => p.foo)); // $ExpectError\n});\n\nit('should enforce types of compare in combination with keySelector', () => {\n  const o = of(sample).pipe(distinctUntilChanged((name1: number, name2) => name1 === name2, p => p.name)); // $ExpectError\n  const p = of(sample).pipe(distinctUntilChanged((name1, name2: number) => name1 === name2, p => p.name)); // $ExpectError\n});\n"
  },
  {
    "path": "packages/rxjs/spec-dtslint/operators/distinctUntilKeyChanged-spec.ts",
    "content": "import { of } from 'rxjs';\nimport { distinctUntilKeyChanged } from 'rxjs/operators';\n\nconst sample = {name: 'foobar', num: 42};\n\nit('should infer correctly', () => {\n  const o = of(sample).pipe(distinctUntilKeyChanged('name')); // $ExpectType Observable<{ name: string; num: number; }>\n});\n\nit('should infer correctly with compare', () => {\n  const o = of(sample).pipe(distinctUntilKeyChanged('name', () => true)); // $ExpectType Observable<{ name: string; num: number; }>\n});\n\nit('should enforce key set', () => {\n  const o = of(sample).pipe(distinctUntilKeyChanged('something')); // $ExpectError\n});\n\nit('should enforce key set with compare', () => {\n  const o = of(sample).pipe(distinctUntilKeyChanged('something', () => true)); // $ExpectError\n});\n\nit(\"should enforce compare's type\", () => {\n  const o = of(sample).pipe(distinctUntilKeyChanged('name', (a: number, b: number) => true)); // $ExpectError\n});\n\nit(\"should enforce key set and compare's type\", () => {\n  const o = of(sample).pipe(distinctUntilKeyChanged('something', (a: number, b: number) => true)); // $ExpectError\n});\n"
  },
  {
    "path": "packages/rxjs/spec-dtslint/operators/elementAt-spec.ts",
    "content": "import { of } from 'rxjs';\nimport { elementAt } from 'rxjs/operators';\n\nit('should infer correctly', () => {\n  const o = of('foo').pipe(elementAt(47)); // $ExpectType Observable<string>\n});\n\nit('should support a default value', () => {\n  const o = of('foo').pipe(elementAt(47, 'bar')); // $ExpectType Observable<string>\n});\n\nit('should enforce types', () => {\n  const o = of('foo').pipe(elementAt()); // $ExpectError\n});\n\nit('should enforce passing the index', () => {\n  const o = of('foo').pipe(elementAt('foo')); // $ExpectError\n});\n\nit('should enforce of default', () => {\n  const o = of('foo').pipe(elementAt(5, 5)); // $ExpectType Observable<string | number>\n});\n\nit('should allow undefined default', () => {\n  const o = of('foo').pipe(elementAt(100, undefined)); // $ExpectType Observable<string | undefined>\n});\n"
  },
  {
    "path": "packages/rxjs/spec-dtslint/operators/endWith-spec.ts",
    "content": "import { of } from 'rxjs';\nimport { endWith } from 'rxjs/operators';\nimport type { A, B} from '../helpers';\nimport { a, b, c, d, e, f, g, h } from '../helpers';\n\nit('should infer type for N values', () => {\n  const r0 = of(a).pipe(endWith()); // $ExpectType Observable<A>\n  const r1 = of(a).pipe(endWith(b)); // $ExpectType Observable<A | B>\n  const r2 = of(a).pipe(endWith(b, c)); // $ExpectType Observable<A | B | C>\n  const r3 = of(a).pipe(endWith(b, c, d)); // $ExpectType Observable<A | B | C | D>\n  const r4 = of(a).pipe(endWith(b, c, d, e)); // $ExpectType Observable<A | B | C | D | E>\n  const r5 = of(a).pipe(endWith(b, c, d, e, f)); // $ExpectType Observable<A | B | C | D | E | F>\n  const r6 = of(a).pipe(endWith(b, c, d, e, f, g)); // $ExpectType Observable<A | B | C | D | E | F | G>\n  const r7 = of(a).pipe(endWith(b, c, d, e, f, g, h)); // $ExpectType Observable<A | B | C | D | E | F | G | H>\n});\n\nit('should infer correctly with a single specified type', () => {\n  const r0 = of(a).pipe(endWith<A>(a)); // $ExpectType Observable<A>\n  const r1 = of(a).pipe(endWith<A|B>(b)); // $ExpectType Observable<A | B>\n  const r2 = of(a).pipe(endWith<A|B>(a)); // $ExpectType Observable<A | B>\n});\n"
  },
  {
    "path": "packages/rxjs/spec-dtslint/operators/every-spec.ts",
    "content": "import type { Observable } from 'rxjs';\nimport { of } from 'rxjs';\nimport { every } from 'rxjs/operators';\n\nit('should infer correctly', () => {\n  const a = of(1, 2, 3).pipe(every(val => val < 3)); // $ExpectType Observable<boolean>\n});\n\nit('should support index and its type', () => {\n  const a = of(1, 2, 3).pipe(every((val, index: number) => val < 3)); // $ExpectType Observable<boolean>\n});\n\nit('should support index and its type', () => {\n  const a = of(1, 2, 3).pipe(every((val, index: number) => index < 3)); // $ExpectType Observable<boolean>\n});\n\nit('should infer source observable type in parameter', () => {\n  const a = of(1, 2, 3).pipe(every((val, index, source: Observable<number>) => val < 3)); // $ExpectType Observable<boolean>\n});\n\nit('should support optional thisArg parameter', () => {\n  const a = of(1, 2, 3).pipe(every((val, index, source: Observable<number>) => val < 3, 'any object')); // $ExpectType Observable<boolean>\n});\n\nit('should not accept empty parameter', () => {\n  const a = of(1, 2, 3).pipe(every()); // $ExpectError\n});\n\nit('should support source type', () => {\n  const a = of(1, 2, 3).pipe(every((val) => val === '2')); // $ExpectError\n});\n\nit('should enforce index type of number', () => {\n  const a = of(1, 2, 3).pipe(every((val, i) => i === '3')); // $ExpectError\n});\n\nit('should expect function parameter', () => {\n  const a = of(1, 2, 3).pipe(every(9)); // $ExpectError\n});\n\nit('should handle the Boolean constructor', () => {\n  const a = of(0 as const, '' as const, false as const, null, undefined, -0 as const, 0n as const).pipe(every(Boolean)); // $ExpectType Observable<false>\n  const b = of(0 as const, '' as const, 'hi there' as const, false as const, null, undefined, -0 as const, 0n as const).pipe(every(Boolean)); // $ExpectType Observable<boolean>\n  const c = of('test' as const, true as const, 1 as const, [], {}).pipe(every(Boolean)); // $ExpectType Observable<boolean>\n  const d = of(NaN, NaN, NaN).pipe(every(Boolean)); // $ExpectType Observable<boolean>\n  const e = of(0, 1, 0).pipe(every(Boolean)); // $ExpectType Observable<boolean>\n})\n\nit('should support this', () => {\n  const thisArg = { limit: 5 };\n  const a = of(1, 2, 3).pipe(every(function (val) {\n    const limit = this.limit; // $ExpectType number\n    return val < limit;\n  }, thisArg));\n});\n\nit('should deprecate thisArg usage', () => {\n  const a = of(1, 2, 3).pipe(every(Boolean)); // $ExpectNoDeprecation\n  const b = of(1, 2, 3).pipe(every(Boolean, {})); // $ExpectDeprecation\n  const c = of(1, 2, 3).pipe(every((value) => Boolean(value))); // $ExpectNoDeprecation\n  const d = of(1, 2, 3).pipe(every((value) => Boolean(value), {})); // $ExpectDeprecation\n});"
  },
  {
    "path": "packages/rxjs/spec-dtslint/operators/exhaustAll-spec.ts",
    "content": "import { of } from 'rxjs';\r\nimport { exhaustAll } from 'rxjs/operators';\r\n\r\nit('should infer correctly', () => {\r\n  const o = of(of(1, 2, 3)).pipe(exhaustAll()); // $ExpectType Observable<number>\r\n});\r\n\r\nit('should enforce types', () => {\r\n  const o = of(1, 2, 3).pipe(exhaustAll()); // $ExpectError\r\n});\r\n\r\n// TODO(benlesh): The following test fails for TypeScript 3.1, but passes in TypeScript 3.2\r\n// I'm unsure what we need to do to get this so it ignores the TS 3.1 failure, as that's a bug\r\n// in TypeScript, and this is properly typed now.\r\n\r\n// it('should support union types', () => {\r\n//   const a = Math.random() > 0.5 ? of(123) : of('abc');\r\n//   const b = Math.random() > 0.5 ? of(123) : of('abc');\r\n//   const source = of(a, b);\r\n//   const o = source.pipe(exhaustAll()); // $ExpectType Observable<string | number>\r\n// });\r\n"
  },
  {
    "path": "packages/rxjs/spec-dtslint/operators/exhaustMap-spec.ts",
    "content": "import { of } from 'rxjs';\nimport { exhaustMap } from 'rxjs/operators';\n\nit('should infer correctly', () => {\n  const o = of(1, 2, 3).pipe(exhaustMap(p => of(Boolean(p)))); // $ExpectType Observable<boolean>\n});\n\nit('should support a projector that takes an index', () => {\n  const o = of(1, 2, 3).pipe(exhaustMap((p, index) => of(Boolean(p)))); // $ExpectType Observable<boolean>\n});\n\nit('should report projections to union types', () => {\n  const o = of(Math.random()).pipe(exhaustMap(n => n > 0.5 ? of('life') : of(42))); // $ExpectType Observable<string | number>\n});\n\nit('should support union-type projections with empty streams', () => {\n  const o = of(1, 2, 3).pipe(exhaustMap(n => Math.random() < 0.5 ? of(123) : of())); // $ExpectType Observable<number>\n});\n\nit('should enforce types', () => {\n  const o = of(1, 2, 3).pipe(exhaustMap()); // $ExpectError\n});\n\nit('should enforce the return type', () => {\n  const o = of(1, 2, 3).pipe(exhaustMap(p => p)); // $ExpectError\n});\n\nit('should produce `Observable<never>` when mapping to an `ObservableInput<never>`', () => {\n  const o = of(1, 2, 3).pipe(exhaustMap(n => Promise.reject())); // $ExpectType Observable<never>\n});\n"
  },
  {
    "path": "packages/rxjs/spec-dtslint/operators/expand-spec.ts",
    "content": "import { of, asyncScheduler } from 'rxjs';\r\nimport { expand } from 'rxjs/operators';\r\n\r\nit('should infer correctly', () => {\r\n  const o = of(1, 2, 3).pipe(expand(value => of(value))); // $ExpectType Observable<number>\r\n  const p = of(1, 2, 3).pipe(expand(value => [value])); // $ExpectType Observable<number>\r\n  const q = of(1, 2, 3).pipe(expand(value => Promise.resolve(value))); // $ExpectType Observable<number>\r\n});\r\n\r\nit('should infer correctly with a different type as the source', () => {\r\n  const o = of(1, 2, 3).pipe(expand(value => of('foo'))); // $ExpectType Observable<string>\r\n  const p = of(1, 2, 3).pipe(expand(value => ['foo'])); // $ExpectType Observable<string>\r\n  const q = of(1, 2, 3).pipe(expand(value => Promise.resolve('foo'))); // $ExpectType Observable<string>\r\n});\r\n\r\nit('should support a project function with index', () => {\r\n  const o = of(1, 2, 3).pipe(expand((value, index) => of(index))); // $ExpectType Observable<number>\r\n});\r\n\r\nit('should support concurrent parameter', () => {\r\n  const o = of(1, 2, 3).pipe(expand(value => of(1), 47)); // $ExpectType Observable<number>\r\n});\r\n\r\nit('should support a scheduler', () => {\r\n  const o = of(1, 2, 3).pipe(expand(value => of(1), 47, asyncScheduler)); // $ExpectType Observable<number>\r\n});\r\n\r\nit('should enforce types', () => {\r\n  const o = of(1, 2, 3).pipe(expand()); // $ExpectError\r\n});\r\n\r\nit('should enforce project types', () => {\r\n  const o = of(1, 2, 3).pipe(expand((value: string, index) => of(1))); // $ExpectError\r\n  const p = of(1, 2, 3).pipe(expand((value, index: string) => of(1))); // $ExpectError\r\n});\r\n\r\nit('should enforce project return type', () => {\r\n  const o = of(1, 2, 3).pipe(expand(value => 1)); // $ExpectError\r\n});\r\n\r\nit('should enforce concurrent type', () => {\r\n  const o = of(1, 2, 3).pipe(expand(value => of(1), 'foo')); // $ExpectError\r\n});\r\n\r\nit('should enforce scheduler type', () => {\r\n  const o = of(1, 2, 3).pipe(expand(value => of(1), 47, 'foo')); // $ExpectError\r\n});\r\n\r\nit('should support union types', () => {\r\n  const o = of(1).pipe(expand(x => typeof x === 'string' ? of(123) : of('test'))); // $ExpectType Observable<string | number>\r\n});\r\n"
  },
  {
    "path": "packages/rxjs/spec-dtslint/operators/filter-spec.ts",
    "content": "import type { Observable} from 'rxjs';\nimport { of } from 'rxjs';\nimport { filter, map } from 'rxjs/operators';\n\nit('should support a predicate', () => {\n  const o = of(1, 2, 3).pipe(filter(value => value < 3)); // $ExpectType Observable<number>\n});\n\nit('should support a predicate with an index', () => {\n  const o = of(1, 2, 3).pipe(filter((value, index) => index < 3)); // $ExpectType Observable<number>\n});\n\nit('should support a predicate and an argument', () => {\n  const o = of(1, 2, 3).pipe(filter(value => value < 3, 'bonjour')); // $ExpectType Observable<number>\n});\n\nit('should support a user-defined type guard', () => {\n  const o = of(1, 2, 3).pipe(filter((value: number): value is 1 => value < 3)); // $ExpectType Observable<1>\n});\n\nit('should support a user-defined type guard with an index', () => {\n  const o = of(1, 2, 3).pipe(filter((value: number, index): value is 1 => index < 3)); // $ExpectType Observable<1>\n});\n\nit('should support a user-defined type guard and an argument', () => {\n  const o = of(1, 2, 3).pipe(filter((value: number): value is 1 => value < 3, 'hola')); // $ExpectType Observable<1>\n});\n\nit('should enforce types', () => {\n  const o = of(1, 2, 3).pipe(filter()); // $ExpectError\n});\n\nit('should enforce predicate types', () => {\n  const o = of(1, 2, 3).pipe(filter(value => value < '3')); // $ExpectError\n  const p = of(1, 2, 3).pipe(filter((value, index) => index < '3')); // $ExpectError\n});\n\nit('should enforce user-defined type guard types', () => {\n  const o = of(1, 2, 3).pipe(filter((value: string): value is '1' => value < '3')); // $ExpectError\n  const p = of(1, 2, 3).pipe(filter((value: number, index): value is 1 => index < '3')); // $ExpectError\n});\n\nit('should support Boolean as a predicate', () => {\n  const o = of(1, 2, 3).pipe(filter(Boolean)); // $ExpectType Observable<number>\n  const p = of(1, null, undefined).pipe(filter(Boolean)); // $ExpectType Observable<number>\n  const q = of(null, undefined).pipe(filter(Boolean)); // $ExpectType Observable<never>\n  const r = of(true).pipe(filter(Boolean)); // $ExpectType Observable<true>\n  const s = of(false as const).pipe(filter(Boolean)); // $ExpectType Observable<never>\n  const t = of(0 as const, -0 as const, 1 as const).pipe(filter(Boolean)); // $ExpectType Observable<1>\n  const u = of(0 as const, -0 as const).pipe(filter(Boolean)); // $ExpectType Observable<never>\n  const v = of('' as const, \"foo\" as const, \"bar\" as const).pipe(filter(Boolean)); // $ExpectType Observable<\"foo\" | \"bar\">\n  const w = of('' as const).pipe(filter(Boolean)); // $ExpectType Observable<never>\n  // Intentionally weird looking test... `false` is `boolean`, which is `true | false`.\n  const x = of(false, false, false, false).pipe(filter(Boolean)); // $ExpectType Observable<true>\n});\n\n// I've not been able to effect a failing dtslint test for this situation and a\n// conventional test won't fail because the TypeScript configuration isn't\n// sufficiently strict:\n// https://github.com/ReactiveX/rxjs/issues/4959#issuecomment-520629091\nit('should support inference from a return type with Boolean as a predicate', () => {\n  interface I {\n    a: string | null;\n  }\n\n  const i$: Observable<I> = of();\n  const s$: Observable<string> = i$.pipe(map(i => i.a), filter(Boolean)); // $ExpectType Observable<string>\n});\n\nit('should support inference from a generic return type of the predicate', () => {\n  function isDefined<T>() {\n    return (value: T|undefined|null): value is T => {\n      return value !== undefined && value !== null;\n    };\n  }\n\n  const o$ = of(1, null, {foo: 'bar'}, true, undefined, 'Nick Cage').pipe(filter(isDefined())); // $ExpectType Observable<string | number | boolean | { foo: string; }>\n});\n\nit('should support inference from a predicate that returns any', () => {\n  function isTruthy(value: number): any {\n    return !!value;\n  }\n\n  const o$ = of(1).pipe(filter(isTruthy)); // $ExpectType Observable<number>\n});\n\nit('should support this', () => {\n  const thisArg = { limit: 5 };\n  const a = of(1, 2, 3).pipe(filter(function (val) {\n    const limit = this.limit; // $ExpectType number\n    return val < limit;\n  }, thisArg));\n});\n\nit('should deprecate thisArg usage', () => {\n  const a = of(1, 2, 3).pipe(filter(Boolean)); // $ExpectNoDeprecation\n  const b = of(1, 2, 3).pipe(filter(Boolean, {})); // $ExpectDeprecation\n  const c = of(1, 2, 3).pipe(filter((value) => Boolean(value))); // $ExpectNoDeprecation\n  const d = of(1, 2, 3).pipe(filter((value) => Boolean(value), {})); // $ExpectDeprecation\n});"
  },
  {
    "path": "packages/rxjs/spec-dtslint/operators/finalize-spec.ts",
    "content": "import { of } from 'rxjs';\nimport { finalize } from 'rxjs/operators';\n\nit('should infer correctly', () => {\n  const o = of(1, 2, 3).pipe(finalize(() => {})); // $ExpectType Observable<number>\n});\n\nit('should enforce types', () => {\n  const o = of(1, 2, 3).pipe(finalize()); // $ExpectError\n  const p = of(1, 2, 3).pipe(finalize((value => {}))); // $ExpectError\n});\n"
  },
  {
    "path": "packages/rxjs/spec-dtslint/operators/find-spec.ts",
    "content": "import { of } from 'rxjs';\nimport { find } from 'rxjs/operators';\n\nit('should support a user-defined type guard', () => {\n  const o = of('foo').pipe(find((s): s is 'foo' => true)); // $ExpectType Observable<\"foo\" | undefined>\n});\n\nit('should support a user-defined type guard that takes an index', () => {\n  const o = of('foo').pipe(find((s, index): s is 'foo' => true)); // $ExpectType Observable<\"foo\" | undefined>\n});\n\nit('should support a user-defined type guard that takes an index and the source', () => {\n  const o = of('foo').pipe(find((s, index, source): s is 'foo' => true)); // $ExpectType Observable<\"foo\" | undefined>\n});\n\nit('should support a predicate', () => {\n  const o = of('foo').pipe(find(s => true)); // $ExpectType Observable<string | undefined>\n});\n\nit('should support a predicate that takes an index', () => {\n  const o = of('foo').pipe(find((s, index) => true)); // $ExpectType Observable<string | undefined>\n});\n\nit('should support a predicate that takes an index and the source', () => {\n  const o = of('foo').pipe(find((s, index, source) => true)); // $ExpectType Observable<string | undefined>\n});\n\nit('should support Boolean properly', () => {\n  const o1 = of('' as const).pipe(find(Boolean)); // $ExpectType Observable<never>\n  const o2 = of('' as const, 'hi' as const).pipe(find(Boolean)); // $ExpectType Observable<\"hi\">\n  const o3 = of('' as const, 0 as const, 'test' as const, 'what' as const).pipe(find(Boolean)); // $ExpectType Observable<\"test\" | \"what\">\n  const o5 = of(false as const, null, undefined, '' as const, 0 as const, 0 as const).pipe(find(Boolean)); // $ExpectType Observable<never>\n  // Intentionally weird looking: Because `Observable<boolean>` is `Observable<true | false>` and `true` is the truthy bit.\n  const o4 = of(false, false, false, false).pipe(find(Boolean)); // $ExpectType Observable<true>\n});\n"
  },
  {
    "path": "packages/rxjs/spec-dtslint/operators/findIndex-spec.ts",
    "content": "import type { Observable } from 'rxjs';\nimport { of } from 'rxjs';\nimport { findIndex } from 'rxjs/operators';\n\nit('should infer correctly', () => {\n  const o = of('foo', 'bar', 'baz').pipe(findIndex(p => p === 'foo')); // $ExpectType Observable<number>\n});\n\nit('should support a predicate that takes an index ', () => {\n  const o = of('foo', 'bar', 'baz').pipe(findIndex((p, index) => index === 3)); // $ExpectType Observable<number>\n});\n\nit('should support a predicate that takes a source ', () => {\n  const o = of('foo', 'bar', 'baz').pipe(findIndex((p, index, source) => p === 'foo')); // $ExpectType Observable<number>\n});\n\nit('should enforce types', () => {\n  const o = of('foo', 'bar', 'baz').pipe(findIndex()); // $ExpectError\n});\n\nit('should enforce predicate types', () => {\n  const o = of('foo', 'bar', 'baz').pipe(findIndex((p: number) => p === 3)); // $ExpectError\n  const p = of('foo', 'bar', 'baz').pipe(findIndex((p, index: string) => p === 3)); // $ExpectError\n  const q = of('foo', 'bar', 'baz').pipe(findIndex((p, index, source: Observable<number>) => p === 3)); // $ExpectError\n});\n\nit('should enforce predicate return type', () => {\n  const o = of('foo', 'bar', 'baz').pipe(findIndex(p => p)); // $ExpectError\n});\n\nit('should support Boolean constructor', () => {\n  const a = of(0 as const, -0 as const, null, undefined, false as const, '' as const).pipe(findIndex(Boolean)); // $ExpectType Observable<-1>\n  const b = of(0 as const, -0 as const, null, 'hi there' as const, undefined, false as const, '' as const).pipe(findIndex(Boolean)); // $ExpectType Observable<number>\n});\n\nit('should support inference from a predicate that returns any', () => {\n  function isTruthy(value: number): any {\n    return !!value;\n  }\n  const a = of(1).pipe(findIndex(isTruthy)); // $ExpectType Observable<number>\n});\n"
  },
  {
    "path": "packages/rxjs/spec-dtslint/operators/first-spec.ts",
    "content": "import { of } from 'rxjs';\nimport { first } from 'rxjs/operators';\n\nconst isFooBar = (value: string): value is 'foo' | 'bar' => /^(foo|bar)$/.test(value);\n\nit('should support an undefined predicate with no default', () => {\n  const o = of('foo').pipe(first(undefined)); // $ExpectType Observable<string>\n});\n\nit('should support an undefined predicate with a T default', () => {\n  const o = of('foo').pipe(first(undefined, 'bar')); // $ExpectType Observable<string>\n});\n\nit('should support an undefined predicate with a non-T default', () => {\n  const o = of('foo').pipe(first(undefined, false)); // $ExpectType Observable<string | boolean>\n});\n\nit('should default D to T with an undefined predicate', () => {\n  const o = of('foo').pipe(first<string>(undefined)); // $Observable<string>\n});\n\nit('should support a null predicate with no default', () => {\n  const o = of('foo').pipe(first(null)); // $ExpectType Observable<string>\n});\n\nit('should support a null predicate with a T default', () => {\n  const o = of('foo').pipe(first(null, 'bar')); // $ExpectType Observable<string>\n});\n\nit('should support a null predicate with a non-T default', () => {\n  const o = of('foo').pipe(first(null, false)); // $ExpectType Observable<string | boolean>\n});\n\nit('should default D to T with a null predicate', () => {\n  const o = of('foo').pipe(first<string>(null)); // $Observable<string>\n});\n\nit('should support a user-defined type guard with no default', () => {\n  const o = of('foo').pipe(first(isFooBar)); // $ExpectType Observable<\"foo\" | \"bar\">\n});\n\nit('should support a user-defined type guard with an S default', () => {\n  const o = of('foo').pipe(first(isFooBar, 'bar')); // $ExpectType Observable<\"foo\" | \"bar\">\n});\n\nit('should widen a user-defined type guard with a non-S default', () => {\n  const o = of('foo').pipe(first(isFooBar, false)); // $ExpectType Observable<boolean | \"foo\" | \"bar\">\n});\n\nit('should support a predicate with no default', () => {\n  const o = of('foo').pipe(first(x => !!x)); // $ExpectType Observable<string>\n});\n\nit('should support a predicate with a T default', () => {\n  const o = of('foo').pipe(first(x => !!x, 'bar')); // $ExpectType Observable<string>\n});\n\nit('should support a predicate with a non-T default', () => {\n  const o = of('foo').pipe(first(x => !!x, false)); // $ExpectType Observable<string | boolean>\n});\n\nit('should work properly with the Boolean constructor', () => {\n  const o1 = of('' as const).pipe(first(Boolean)); // $ExpectType Observable<never>\n  const o2 = of('', 'hi').pipe(first(Boolean)); // $ExpectType Observable<string>\n  const o3 = of('' as const, 'hi' as const).pipe(first(Boolean)); // $ExpectType Observable<\"hi\">\n  const o4 = of(0 as const, 'hi' as const).pipe(first(Boolean)); // $ExpectType Observable<\"hi\">\n  const o5 = of(0 as const, 'hi' as const, 'what' as const).pipe(first(Boolean)); // $ExpectType Observable<\"hi\" | \"what\">\n});\n\nit('should support inference from a predicate that returns any', () => {\n  function isTruthy(value: number): any {\n    return !!value;\n  }\n\n  const o$ = of(1).pipe(first(isTruthy)); // $ExpectType Observable<number>\n});"
  },
  {
    "path": "packages/rxjs/spec-dtslint/operators/groupBy-spec.ts",
    "content": "import type { GroupedObservable } from 'rxjs';\nimport { of, Subject } from 'rxjs';\nimport { groupBy, mergeMap } from 'rxjs/operators';\n\nit('should infer correctly', () => {\n  const o = of(1, 2, 3).pipe(groupBy(value => value.toString())); // $ExpectType Observable<GroupedObservable<string, number>>\n});\n\nit('should support an element selector', () => {\n  const o = of(1, 2, 3).pipe(groupBy(value => value.toString(), value => Boolean(value))); // $ExpectType Observable<GroupedObservable<string, boolean>>\n});\n\nit('should support a duration selector', () => {\n  const o = of(1, 2, 3).pipe(groupBy(value => value.toString(), undefined, (value: GroupedObservable<string, number>) => of(true, false))); // $ExpectType Observable<GroupedObservable<string, number>>\n});\n\nit('should infer type of duration selector based on element selector', () => {\n  const o = of(1, 2, 3).pipe(groupBy(value => value.toString(), value => Boolean(value), (value: GroupedObservable<string, boolean>) => value)); // $ExpectType Observable<GroupedObservable<string, boolean>>\n});\n\nit('should support a subject selector', () => {\n  const o = of(1, 2, 3).pipe(groupBy(value => value.toString(), undefined, undefined, () => new Subject<boolean>())); // $ExpectType Observable<GroupedObservable<string, boolean>>\n});\n\nit('should enforce types', () => {\n  const o = of(1, 2, 3).pipe(groupBy()); // $ExpectError\n});\n\nit('should enforce type of key selector', () => {\n  const o = of(1, 2, 3).pipe(groupBy('nope')); // $ExpectError\n});\n\nit('should enforce types of element selector', () => {\n  const o = of(1, 2, 3).pipe(groupBy(value => value, 'foo')); // $ExpectError\n  const p = of(1, 2, 3).pipe(groupBy(value => value, (value: string) => value)); // $ExpectError\n});\n\nit('should enforce types of duration selector', () => {\n  const o = of(1, 2, 3).pipe(groupBy(value => value.toString(), undefined, value => 'foo')); // $ExpectError\n  const p = of(1, 2, 3).pipe(groupBy(value => value.toString(), undefined, (value: GroupedObservable<number, number>) => value)); // $ExpectError\n  const q = of(1, 2, 3).pipe(groupBy(value => value.toString(), undefined, (value: GroupedObservable<string, string>) => value)); // $ExpectError\n  const r = of(1, 2, 3).pipe(groupBy(value => value.toString(), value => Boolean(value), (value: GroupedObservable<string, string>) => value)); // $ExpectError\n  const s = of(1, 2, 3).pipe(groupBy(value => value.toString(), value => Boolean(value), (value: GroupedObservable<boolean, boolean>) => value)); // $ExpectError\n});\n\nit('should enforce types of subject selector', () => {\n  const o = of(1, 2, 3).pipe(groupBy(value => value.toString(), undefined, undefined, () => 'nope')); // $ExpectError\n  const p = of(1, 2, 3).pipe(groupBy(value => value.toString(), undefined, undefined, (value) => new Subject<string>())); // $ExpectError\n});\n\nit('should support a user-defined type guard', () => {\n  function isNumber(value: string | number): value is number {\n    return typeof value === 'number';\n  }\n  const o = of('a', 1, 'b', 2).pipe(\n    groupBy(isNumber),\n    mergeMap((group) => {\n      if (group.key) {\n        const inferred = group; // $ExpectType GroupedObservable<true, number>\n        return inferred;\n      } else {\n        const inferred = group; // $ExpectType GroupedObservable<false, string>\n        return inferred;\n      }\n    })\n  );\n  const inferred = o; // $ExpectType Observable<string | number>\n});\n\nit('should support an inline user-defined type guard', () => {\n  const o = of('a', 1, 'b', 2).pipe(\n    groupBy((value): value is number => typeof value === 'number'),\n    mergeMap((group) => {\n      if (group.key) {\n        const inferred = group; // $ExpectType GroupedObservable<true, number>\n        return inferred;\n      } else {\n        const inferred = group; // $ExpectType GroupedObservable<false, string>\n        return inferred;\n      }\n    })\n  );\n  const inferred = o; // $ExpectType Observable<string | number>\n});\n"
  },
  {
    "path": "packages/rxjs/spec-dtslint/operators/ignoreElements-spec.ts",
    "content": "import { of } from 'rxjs';\nimport { ignoreElements, tap } from 'rxjs/operators';\n\nit('should infer correctly', () => {\n  const o = of(1, 2, 3).pipe(ignoreElements()); // $ExpectType Observable<never>\n});\n\nit('should enforce types', () => {\n  const o = of(1, 2, 3).pipe(ignoreElements('nope')); // $ExpectError\n});\n\nit('should not break the inference of type', () => {\n  const o$ = of(1, 2, 3).pipe(\n    tap((o) => {\n      const t = o; // $ExpectType number\n    }),\n    ignoreElements(),\n  );\n});\n\nit('should not break the inference of types when piped in a larger chain', () => {\n  const o$ = of('a string').pipe(\n    tap((o) => {\n      const t = o; // $ExpectType string\n    }),\n    tap((o) => {\n      const t = o; // $ExpectType string\n    }),\n    ignoreElements(),\n    tap((o) => {\n      const t = o; // $ExpectType never\n    }),\n  );\n});"
  },
  {
    "path": "packages/rxjs/spec-dtslint/operators/isEmpty-spec.ts",
    "content": "import { of } from 'rxjs';\nimport { isEmpty } from 'rxjs/operators';\n\nit('should infer correctly', () => {\n  const o = of(1, 2, 3).pipe(isEmpty()); // $ExpectType Observable<boolean>\n});\n\nit('should enforce types', () => {\n  const o = of(1, 2, 3).pipe(isEmpty('nope')); // $ExpectError\n});\n"
  },
  {
    "path": "packages/rxjs/spec-dtslint/operators/last-spec.ts",
    "content": "import { of } from 'rxjs';\nimport { last } from 'rxjs/operators';\n\nconst isFooBar = (value: string): value is 'foo' | 'bar' => /^(foo|bar)$/.test(value);\n\nit('should support an undefined predicate with no default', () => {\n  const o = of('foo').pipe(last(undefined)); // $ExpectType Observable<string>\n});\n\nit('should support an undefined predicate with a T default', () => {\n  const o = of('foo').pipe(last(undefined, 'bar')); // $ExpectType Observable<string>\n});\n\nit('should support an undefined predicate with a non-T default', () => {\n  const o = of('foo').pipe(last(undefined, false)); // $ExpectType Observable<string | boolean>\n});\n\nit('should default D to T with an undefined predicate', () => {\n  const o = of('foo').pipe(last<string>(undefined)); // $Observable<string>\n});\n\nit('should support a null predicate with no default', () => {\n  const o = of('foo').pipe(last(null)); // $ExpectType Observable<string>\n});\n\nit('should support a null predicate with a T default', () => {\n  const o = of('foo').pipe(last(null, 'bar')); // $ExpectType Observable<string>\n});\n\nit('should support a null predicate with a non-T default', () => {\n  const o = of('foo').pipe(last(null, false)); // $ExpectType Observable<string | boolean>\n});\n\nit('should default D to T with a null predicate', () => {\n  const o = of('foo').pipe(last<string>(null)); // $Observable<string>\n});\n\nit('should support a user-defined type guard with no default', () => {\n  const o = of('foo').pipe(last(isFooBar)); // $ExpectType Observable<\"foo\" | \"bar\">\n});\n\nit('should support a user-defined type guard with an S default', () => {\n  const o = of('foo').pipe(last(isFooBar, 'bar')); // $ExpectType Observable<\"foo\" | \"bar\">\n});\n\nit('should widen a user-defined type guard with a non-S default', () => {\n  const o = of('foo').pipe(last(isFooBar, false)); // $ExpectType Observable<string | boolean>\n});\n\nit('should support a predicate with no default', () => {\n  const o = of('foo').pipe(last(x => !!x)); // $ExpectType Observable<string>\n});\n\nit('should support a predicate with a T default', () => {\n  const o = of('foo').pipe(last(x => !!x, 'bar')); // $ExpectType Observable<string>\n});\n\nit('should support a predicate with a non-T default', () => {\n  const o = of('foo').pipe(last(x => !!x, false)); // $ExpectType Observable<string | boolean>\n});\n\nit('should default D to T with a predicate', () => {\n  const o = of('foo').pipe(last<string>(x => !!x)); // $ExpectType Observable<string>\n});\n\nit('should handle predicates that always return false properly', () => {\n  const a = of('foo', 'bar').pipe(last(() => false as const)); // $ExpectType Observable<string>\n  const b = of('foo', 'bar').pipe(last(() => false as const, 1337 as const)); // $ExpectType Observable<string | 1337>\n});\n\nit('should handle Boolean constructor properly', () => {\n  const a = of(0 as const, -0 as const, null, undefined, false as const, '' as const, 0n as const).pipe(last(Boolean)); // $ExpectType Observable<never>\n  const b = of(0 as const, -0 as const, null, undefined, false as const, '' as const, 0n as const).pipe(last(Boolean, 'test' as const)); // $ExpectType Observable<\"test\">\n  const c = of(0 as const, -0 as const, null, 'hi' as const, undefined, false as const, '' as const, 0n as const).pipe(last(Boolean)); // $ExpectType Observable<\"hi\">\n  const d = of(0 as const, -0 as const, null, 'hi' as const, undefined, false as const, '' as const, 0n as const).pipe(last(Boolean, 'test' as const)); // $ExpectType Observable<\"test\" | \"hi\">\n});\n\nit('should support inference from a predicate that returns any', () => {\n  function isTruthy(value: number): any {\n    return !!value;\n  }\n\n  const o$ = of(1).pipe(last(isTruthy)); // $ExpectType Observable<number>\n});"
  },
  {
    "path": "packages/rxjs/spec-dtslint/operators/map-spec.ts",
    "content": "import { of } from 'rxjs';\r\nimport { map } from 'rxjs/operators';\r\n\r\nit('should infer correctly', () => {\r\n  const o = of(1, 2, 3).pipe(map(value => value)); // $ExpectType Observable<number>\r\n});\r\n\r\nit('should infer correctly when returning a different type', () => {\r\n  const o = of(1, 2, 3).pipe(map(String)); // $ExpectType Observable<string>\r\n});\r\n\r\nit('should support an index parameter', () => {\r\n  const o = of('a', 'b', 'c').pipe(map((value, index) => index)); // $ExpectType Observable<number>\r\n});\r\n\r\nit('should enforce types', () => {\r\n  const o = of(1, 2, 3).pipe(map()); // $ExpectError\r\n});\r\n\r\nit('should enforce the projector types', () => {\r\n  const o = of(1, 2, 3).pipe(map((value: string) => value)); // $ExpectError\r\n  const p = of(1, 2, 3).pipe(map((value, index: string) => value)); // $ExpectError\r\n});\r\n"
  },
  {
    "path": "packages/rxjs/spec-dtslint/operators/mapTo-spec.ts",
    "content": "import { of } from 'rxjs';\nimport { mapTo } from 'rxjs/operators';\n\nit('should infer correctly', () => {\n  const o = of(1, 2, 3).pipe(mapTo(47)); // $ExpectType Observable<number>\n});\n\nit('should infer correctly when returning a different type', () => {\n  const o = of(1, 2, 3).pipe(mapTo('carrot')); // $ExpectType Observable<string>\n});\n\nit('should enforce types', () => {\n  const o = of(1, 2, 3).pipe(mapTo()); // $ExpectError\n});\n\nit('should be deprecated', () => {\n  const o = of(1, 2, 3).pipe(mapTo(true)); // $ExpectDeprecation\n});"
  },
  {
    "path": "packages/rxjs/spec-dtslint/operators/materialize-spec.ts",
    "content": "import { of } from 'rxjs';\nimport { materialize } from 'rxjs/operators';\n\nit('should infer correctly', () => {\n  const o = of('foo').pipe(materialize()); // $ExpectType Observable<ObservableNotification<string>>\n});\n\nit('should enforce types', () => {\n  const o = of('foo').pipe(materialize(() => {})); // $ExpectError\n});\n"
  },
  {
    "path": "packages/rxjs/spec-dtslint/operators/max-spec.ts",
    "content": "import { of } from 'rxjs';\nimport { max } from 'rxjs/operators';\n\nit('should infer correctly', () => {\n    const a = of(1, 2, 3).pipe(max()); // $ExpectType Observable<number>\n    const b = of('abc', 'bcd', 'def').pipe(max()); // $ExpectType Observable<string>\n});\n\nit(' should except empty comparer', () => {\n    const a = of(1, 2, 3).pipe(max()); // $ExpectType Observable<number>\n});\n\nit('should enforce comparer types', () => {\n    const a = of(1, 2, 3).pipe(max((a: number, b: number) => a - b)); // $ExpectType Observable<number>\n    const b = of(1, 2, 3).pipe(max((a: number, b: string) => 0)); // $ExpectError\n    const c = of(1, 2, 3).pipe(max((a: string, b: number) => 0)); // $ExpectError\n});\n"
  },
  {
    "path": "packages/rxjs/spec-dtslint/operators/mergeAll-spec.ts",
    "content": "import { of } from 'rxjs';\nimport { mergeAll } from 'rxjs/operators';\nimport { a$, b$ } from '../helpers';\n\nit('should infer correctly with sources of same type', () => {\n  const o = of(a$, a$).pipe(mergeAll()); // $ExpectType Observable<A>\n});\n\nit('should infer correctly with sources of different types', () => {\n  const o = of(a$, b$).pipe(mergeAll()); // $ExpectType Observable<A | B>\n});\n\nit('should enforce types', () => {\n  const o = a$.pipe(mergeAll()); // $ExpectError\n});\n"
  },
  {
    "path": "packages/rxjs/spec-dtslint/operators/mergeMap-spec.ts",
    "content": "import { of } from 'rxjs';\nimport { mergeMap } from 'rxjs/operators';\n\nit('should infer correctly', () => {\n  const o = of(1, 2, 3).pipe(mergeMap(p => of(Boolean(p)))); // $ExpectType Observable<boolean>\n});\n\nit('should support a projector that takes an index', () => {\n  const o = of(1, 2, 3).pipe(mergeMap((p, index) => of(Boolean(p)))); // $ExpectType Observable<boolean>\n});\n\nit('should support a concurrent parameter', () => {\n  const o = of(1, 2, 3).pipe(mergeMap(p => of(Boolean(p)), 4)); // $ExpectType Observable<boolean>\n});\n\nit('should support union-type projections', () => {\n  const o = of(Math.random()).pipe(mergeMap(n => n > 0.5 ? of('life') : of(42))); // $ExpectType Observable<string | number>\n});\n\nit('should support union-type projections with empty streams', () => {\n  const o = of(1, 2, 3).pipe(mergeMap(n => Math.random() < 0.5 ? of(123) : of())); // $ExpectType Observable<number>\n});\n\nit('should enforce types', () => {\n  const o = of(1, 2, 3).pipe(mergeMap()); // $ExpectError\n});\n\nit('should enforce the return type', () => {\n  const o = of(1, 2, 3).pipe(mergeMap(p => p)); // $ExpectError\n});\n\nit('should produce `Observable<never>` when mapping to an `ObservableInput<never>`', () => {\n  const o = of(1, 2, 3).pipe(mergeMap(n => Promise.reject())); // $ExpectType Observable<never>\n});\n"
  },
  {
    "path": "packages/rxjs/spec-dtslint/operators/mergeMapTo-spec.ts",
    "content": "import { of } from 'rxjs';\nimport { mergeMapTo } from 'rxjs/operators';\n\nit('should infer correctly', () => {\n  const o = of(1, 2, 3).pipe(mergeMapTo(of('foo'))); // $ExpectType Observable<string>\n});\n\nit('should infer correctly multiple types', () => {\n  const o = of(1, 2, 3).pipe(mergeMapTo(of('foo', 4))); // $ExpectType Observable<string | number>\n});\n\nit('should infer correctly with an array', () => {\n  const o = of(1, 2, 3).pipe(mergeMapTo([4, 5, 6])); // $ExpectType Observable<number>\n});\n\nit('should infer correctly with a Promise', () => {\n  const o = of(1, 2, 3).pipe(mergeMapTo(new Promise<string>(() => {}))); // $ExpectType Observable<string>\n});\n\nit('should support a concurrent parameter', () => {\n  const o = of(1, 2, 3).pipe(mergeMapTo(of('foo'), 4)); // $ExpectType Observable<string>\n});\n\nit('should support union-type projections with empty streams', () => {\n  const o = of(1, 2, 3).pipe(mergeMapTo(Math.random() < 0.5 ? of(123) : of())); // $ExpectType Observable<number>\n});\n\nit('should support union types', () => {\n  const s = Math.random() > 0.5 ? of(123) : of('abc');\n  const r = of(1, 2, 3).pipe(mergeMapTo(s)); // $ExpectType Observable<string | number>\n});\n\nit('should enforce types', () => {\n  const o = of(1, 2, 3).pipe(mergeMapTo()); // $ExpectError\n});\n\nit('should enforce types of the observable parameter', () => {\n  const fn = () => {}\n  const o = of(1, 2, 3).pipe(mergeMapTo(fn)); // $ExpectError\n});\n\nit('should enforce the return type', () => {\n  const o = of(1, 2, 3).pipe(mergeMapTo(p => p)); // $ExpectError\n  const p = of(1, 2, 3).pipe(mergeMapTo(4)); // $ExpectError\n});\n\nit('should enforce types of the concurrent parameter', () => {\n  const o = of(1, 2, 3).pipe(mergeMapTo(of('foo'), '4')); // $ExpectError\n});\n\nit('should enforce types of the concurrent parameter with a resultSelector', () => {\n  const o = of(1, 2, 3).pipe(mergeMapTo(of('foo'), (a => a), '4')); // $ExpectError\n});\n\nit('should produce `Observable<never>` when mapping to an `ObservableInput<never>`', () => {\n  const o = of(1, 2, 3).pipe(mergeMapTo(Promise.reject())); // $ExpectType Observable<never>\n});\n\nit('should be deprecated', () => {\n  const o = of(1, 2, 3).pipe(mergeMapTo(of(true))); // $ExpectDeprecation\n});\n"
  },
  {
    "path": "packages/rxjs/spec-dtslint/operators/mergeScan-spec.ts",
    "content": "import { of } from 'rxjs';\nimport { mergeScan } from 'rxjs/operators';\n\nit('should infer correctly', () => {\n  const o = of(1, 2, 3).pipe(mergeScan((acc, value) => of(acc + value), 0)); // $ExpectType Observable<number>\n});\n\nit('should infer correctly by using the seed', () => {\n  const o = of(1, 2, 3).pipe(mergeScan((acc, value) => of(acc + value), '')); // $ExpectType Observable<string>\n});\n\nit('should support the accumulator returning an iterable', () => {\n  const o = of(1, 2, 3).pipe(mergeScan((acc, value) => acc + value, '')); // $ExpectType Observable<string>\n});\n\nit('should support the accumulator returning a promise', () => {\n  const o = of(1, 2, 3).pipe(mergeScan(acc => Promise.resolve(acc), '')); // $ExpectType Observable<string>\n});\n\nit('should support a currency', () => {\n  const o = of(1, 2, 3).pipe(mergeScan((acc, value) => of(acc + value), '', 47)); // $ExpectType Observable<string>\n});\n\nit('should enforce types', () => {\n  const o = of(1, 2, 3).pipe(mergeScan()); // $ExpectError\n});\n\nit('should enforce accumulate types', () => {\n  const o = of(1, 2, 3).pipe(mergeScan((acc: string, value) => of(acc + value), 0)); // $ExpectError\n  const p = of(1, 2, 3).pipe(mergeScan((acc, value: string) => of(acc + value), 0)); // $ExpectError\n});\n\nit('should enforce accumulate return type', () => {\n  const o = of(1, 2, 3).pipe(mergeScan((acc, value) => of(''), 0)); // $ExpectError\n});\n\nit('should enforce concurrent type', () => {\n  const o = of(1, 2, 3).pipe(mergeScan((acc, value) => of(acc + value), 0, '')); // $ExpectError\n});\n\n// TODO(benlesh): It still seems we don't have a great way to do this in TS 3.2\n// it('should support union types', () => {\n//   const o = of(1, 2, 3).pipe(mergeScan(() => Math.random() > 0.5 ? of(123) : of('test'), 0)); // $ExpectType Observable<string | number>\n// });\n"
  },
  {
    "path": "packages/rxjs/spec-dtslint/operators/mergeWith-spec.ts",
    "content": "import { mergeWith } from 'rxjs/operators';\nimport { a$, b$, c$, d$, e$, f$, g$, h$} from '../helpers';\n\nit('should accept N args', () => {\n  const r0 = a$.pipe(mergeWith()); // $ExpectType Observable<A>\n  const r1 = a$.pipe(mergeWith(b$)); // $ExpectType Observable<A | B>\n  const r2 = a$.pipe(mergeWith(b$, c$)); // $ExpectType Observable<A | B | C>\n  const r3 = a$.pipe(mergeWith(b$, c$, d$)); // $ExpectType Observable<A | B | C | D>\n  const r4 = a$.pipe(mergeWith(b$, c$, d$, e$)); // $ExpectType Observable<A | B | C | D | E>\n  const r5 = a$.pipe(mergeWith(b$, c$, d$, e$, f$)); // $ExpectType Observable<A | B | C | D | E | F>\n  const r6 = a$.pipe(mergeWith(b$, c$, d$, e$, f$, g$)); // $ExpectType Observable<A | B | C | D | E | F | G>\n  const r7 = a$.pipe(mergeWith(b$, c$, d$, e$, f$, g$, h$)); // $ExpectType Observable<A | B | C | D | E | F | G | H>\n});"
  },
  {
    "path": "packages/rxjs/spec-dtslint/operators/min-spec.ts",
    "content": "import { of } from 'rxjs';\nimport { min } from 'rxjs/operators';\n\nit('should infer correctly', () => {\n    const a = of(1, 2, 3).pipe(min()); // $ExpectType Observable<number>\n    const b = of('abc', 'bcd', 'def').pipe(min()); // $ExpectType Observable<string>\n});\n\nit('should except empty comparer', () => {\n    const a = of(1, 2, 3).pipe(min()); // $ExpectType Observable<number>\n});\n\nit('should enforce comparer types', () => {\n    const a = of(1, 2, 3).pipe(min((a: number, b: number) => a - b)); // $ExpectType Observable<number>\n    const b = of(1, 2, 3).pipe(min((a: number, b: string) => 0)); // $ExpectError\n    const c = of(1, 2, 3).pipe(min((a: string, b: number) => 0)); // $ExpectError\n});\n"
  },
  {
    "path": "packages/rxjs/spec-dtslint/operators/observeOn-spec.ts",
    "content": "import { of, asyncScheduler } from 'rxjs';\nimport { observeOn } from 'rxjs/operators';\n\nit('should infer correctly', () => {\n  const o = of('apple', 'banana', 'peach').pipe(observeOn(asyncScheduler)); // $ExpectType Observable<string>\n});\n\nit('should support a delay', () => {\n  const o = of('apple', 'banana', 'peach').pipe(observeOn(asyncScheduler, 47)); // $ExpectType Observable<string>\n});\n\nit('should enforce types', () => {\n  const p = of('apple', 'banana', 'peach').pipe(observeOn()); // $ExpectError\n});\n\nit('should enforce scheduler type', () => {\n  const p = of('apple', 'banana', 'peach').pipe(observeOn('fruit')); // $ExpectError\n});\n\nit('should enforce delay type', () => {\n  const p = of('apple', 'banana', 'peach').pipe(observeOn(asyncScheduler, '47')); // $ExpectError\n});\n"
  },
  {
    "path": "packages/rxjs/spec-dtslint/operators/onErrorResumeNextWith-spec.ts",
    "content": "import { of } from 'rxjs';\nimport { onErrorResumeNextWith } from 'rxjs/operators';\n\nit('should infer correctly', () => {\n  const o = of('apple', 'banana', 'peach').pipe(onErrorResumeNextWith()); // $ExpectType Observable<string>\n});\n\nit('should accept one input', () => {\n  const o = of('apple', 'banana', 'peach').pipe(onErrorResumeNextWith(of(1))); // $ExpectType Observable<string | number>\n  const p = of('apple', 'banana', 'peach').pipe(onErrorResumeNextWith(of('5'))); // $ExpectType Observable<string>\n});\n\nit('should accept promises', () => {\n  const o = of('apple', 'banana', 'peach').pipe(onErrorResumeNextWith(Promise.resolve(5))); // $ExpectType Observable<string | number>\n});\n\nit('should accept iterables', () => {\n  const o = of('apple', 'banana', 'peach').pipe(onErrorResumeNextWith('foo')); // $ExpectType Observable<string>\n});\n\nit('should accept arrays', () => {\n  const o = of('apple', 'banana', 'peach').pipe(onErrorResumeNextWith([5])); // $ExpectType Observable<string | number>\n});\n\nit('should accept two inputs', () => {\n  const o = of('apple', 'banana', 'peach').pipe(onErrorResumeNextWith(of(1), of(2))); // $ExpectType Observable<string | number>\n});\n\nit('should accept three inputs', () => {\n  const o = of('apple', 'banana', 'peach').pipe(onErrorResumeNextWith(of(1), of(2), of('3'))); // $ExpectType Observable<string | number>\n});\n\nit('should accept four inputs', () => {\n  const o = of('apple', 'banana', 'peach').pipe(onErrorResumeNextWith(of(1), of(2), of('3'), of('4'))); // $ExpectType Observable<string | number>\n});\n\nit('should accept five inputs', () => {\n  const o = of('apple', 'banana', 'peach').pipe(onErrorResumeNextWith(of(1), of(2), of('3'), of('4'), of(5))); // $ExpectType Observable<string | number>\n});\n\nit('should accept six inputs', () => {\n  const o = of('apple', 'banana', 'peach').pipe(onErrorResumeNextWith(of(1), of(2), of('3'), of('4'), of(5), of('6'))); // $ExpectType Observable<string | number>\n});\n\nit('should accept seven and more inputs', () => {\n  const o = of('apple', 'banana', 'peach').pipe(onErrorResumeNextWith(of(1), of(2), of('3'), of('4'), of(5), of('6'), of(7))); // $ExpectType Observable<string | number>\n});\n\nit('should enforce types', () => {\n  const o = of('apple', 'banana', 'peach').pipe(onErrorResumeNextWith(5)); // $ExpectError\n});\n"
  },
  {
    "path": "packages/rxjs/spec-dtslint/operators/pairwise-spec.ts",
    "content": "import { of } from 'rxjs';\nimport { pairwise } from 'rxjs/operators';\n\nit('should infer correctly', () => {\n  const o = of('apple', 'banana', 'peach').pipe(pairwise()); // $ExpectType Observable<[string, string]>\n});\n\nit('should infer correctly with multiple types', () => {\n  const o = of('apple', 4, 'peach', 7).pipe(pairwise()); // $ExpectType Observable<[string | number, string | number]>\n});\n\nit('should enforce types', () => {\n  const o = of('apple', 'banana', 'peach').pipe(pairwise('lemon')); // $ExpectError\n});\n"
  },
  {
    "path": "packages/rxjs/spec-dtslint/operators/raceWith-spec.ts",
    "content": "import { raceWith } from 'rxjs/operators';\nimport { a$, b, b$, c, c$, d$, e$, f$ } from '../helpers';\n\ndescribe('raceWith', () => {\n  it('should support N arguments of different types', () => {\n    const o1 = a$.pipe(raceWith(b$)); // $ExpectType Observable<A | B>\n    const o2 = a$.pipe(raceWith(b$, c$)); // $ExpectType Observable<A | B | C>\n    const o3 = a$.pipe(raceWith(b$, c$, d$)); // $ExpectType Observable<A | B | C | D>\n    const o4 = a$.pipe(raceWith(b$, c$, d$, e$)); // $ExpectType Observable<A | B | C | D | E>\n    const o5 = a$.pipe(raceWith(b$, c$, d$, e$, f$)); // $ExpectType Observable<A | B | C | D | E | F>\n  });\n});\n\nit('should race observable inputs', () => {\n  const o = a$.pipe(raceWith(Promise.resolve(b), [c])); // $ExpectType Observable<A | B | C>\n});\n"
  },
  {
    "path": "packages/rxjs/spec-dtslint/operators/reduce-spec.ts",
    "content": "import { of } from 'rxjs';\nimport { reduce } from 'rxjs/operators';\n\nit('should enforce parameter', () => {\n  const a = of(1, 2, 3).pipe(reduce()); // $ExpectError\n});\n\nit('should infer correctly ', () => {\n  const a = of(1, 2, 3).pipe(reduce((x, y, z) => x + 1)); // $ExpectType Observable<number>\n});\n\nit('should infer correctly for accumulator of type array', () => {\n  const a = of(1, 2, 3).pipe(reduce((x: number[], y: number, i: number) => x, [])); // $ExpectType Observable<number[]>\n});\n\nit('should accept seed parameter of the same type', () => {\n  const a = of(1, 2, 3).pipe(reduce((x, y, z) => x + 1, 5)); // $ExpectType Observable<number>\n  const b = of(1, 2, 3).pipe(reduce((x, y, z) => x + 1, [])); // $ExpectError\n});\n\nit('should accept seed parameter of the seed array type', () => {\n  const a = of(1, 2, 3).pipe(reduce((x, y, z) => { x.push(y); return x; }, [4])); // $ExpectType Observable<number[]>\n  // Array must be typed...\n  const b = of(1, 2, 3).pipe(reduce((x, y, z) => { x.push(y); return x; }, [])); // $ExpectError\n});\n\nit('should accept seed parameter of a different type', () => {\n  const a = of(1, 2, 3).pipe(reduce((x, y, z) => x + '1', '5')); // $ExpectType Observable<string>\n  const bv: { [key: string]: string } = {};\n  const b = of(1, 2, 3).pipe(reduce((x, y, z) => ({ ...x, [y]: y.toString() }), bv)); // $ExpectType Observable<{ [key: string]: string; }>\n});\n\nit('should act appropriately with no seed', () => {\n  // Starting in TS 3.5, the return type is inferred from the accumulator's type if it's provided without a seed.\n  const a = of(1, 2, 3).pipe(reduce((a: any, v) => '' + v)); // $ExpectType Observable<any>\n  const b = of(1, 2, 3).pipe(reduce((a, v) => v)); // $ExpectType Observable<number>\n  const c = of(1, 2, 3).pipe(reduce(() => {})); // $ExpectType Observable<number | void>\n});\n\nit('should act appropriately with a seed', () => {\n  const a = of(1, 2, 3).pipe(reduce((a, v) => a + v, '')); // $ExpectType Observable<string>\n  const b = of(1, 2, 3).pipe(reduce((a, v) => a + v, 0)); // $ExpectType Observable<number>\n  const c = of(1, 2, 3).pipe(reduce((a, v) => a + 1, [])); // $ExpectError\n});\n\nit('should infer types properly from arguments', () => {\n  function toArrayReducer(arr: number[], item: number, index: number): number[] {\n    if (index === 0) {\n      return [item];\n    }\n    arr.push(item);\n    return arr;\n  }\n\n  const a = reduce(toArrayReducer, [] as number[]); // $ExpectType OperatorFunction<number, number[]>\n});\n"
  },
  {
    "path": "packages/rxjs/spec-dtslint/operators/repeat-spec.ts",
    "content": "import { of } from 'rxjs';\nimport { repeat } from 'rxjs/operators';\n\nit('should infer correctly', () => {\n  const o = of('a', 'b', 'c').pipe(repeat()); // $ExpectType Observable<string>\n});\n\nit('should accept a count parameter', () => {\n  const o = of('a', 'b', 'c').pipe(repeat(47)); // $ExpectType Observable<string>\n});\n\nit('should enforce types', () => {\n  const o = of('a', 'b', 'c').pipe(repeat('aa')); // $ExpectError\n});\n"
  },
  {
    "path": "packages/rxjs/spec-dtslint/operators/repeatWhen-spec.ts",
    "content": "import { of } from 'rxjs';\nimport { repeatWhen } from 'rxjs/operators';\nimport { asInteropObservable } from '../../spec/helpers/interop-helper';\n\nit('should infer correctly', () => {\n  of(1, 2, 3).pipe(repeatWhen(errors => errors)); // $ExpectType Observable<number>\n});\n\nit('should infer correctly when the error observable has a different type', () => {\n  of(1, 2, 3).pipe(repeatWhen(errors => asInteropObservable(of('a', 'b', 'c')))); // $ExpectType Observable<number>\n});\n\nit('should enforce types', () => {\n  of(1, 2, 3).pipe(repeatWhen()); // $ExpectError\n});\n\nit('should accept interop observable notifier', () => {\n  of(1, 2, 3).pipe(repeatWhen(() => asInteropObservable(of(true)))); // $ExpectType Observable<number>\n});\n\nit('should accept promise notifier', () => {\n  of(1, 2, 3).pipe(repeatWhen(() => Promise.resolve(true))); // $ExpectType Observable<number>\n});\n\nit('should async iterable notifier', () => {\n  const asyncRange = {\n    from: 1,\n    to: 2,\n    [Symbol.asyncIterator]() {\n      return {\n        current: this.from,\n        last: this.to,\n        async next() {\n          await Promise.resolve();\n          const done = (this.current > this.last);\n          return {\n            done,\n            value: done ? this.current++ : undefined\n          };\n        }\n      };\n    }\n  };\n  of(1, 2, 3).pipe(repeatWhen(() => asyncRange)); // $ExpectType Observable<number>\n});\n\nit('should accept iterable notifier', () => {\n  const syncRange = {\n    from: 1,\n    to: 2,\n    [Symbol.iterator]() {\n      return {\n        current: this.from,\n        last: this.to,\n        next() {\n          const done = (this.current > this.last);\n          return {\n            done,\n            value: done ? this.current++ : undefined\n          };\n        }\n      };\n    }\n  };\n  of(1, 2, 3).pipe(repeatWhen(() => syncRange)); // $ExpectType Observable<number>\n});\n\nit('should accept readable stream notifier', () => {\n  const readableStream = new ReadableStream<string>({\n    pull(controller) {\n      controller.enqueue('x');\n      controller.close();\n    },\n  });\n  of(1, 2, 3).pipe(repeatWhen(() => readableStream)); // $ExpectType Observable<number>\n});\n\nit('should enforce types of the notifier', () => {\n  of(1, 2, 3).pipe(repeatWhen(() => 8)); // $ExpectError\n});\n\nit('should be deprecated', () => {\n  of(1, 2, 3).pipe(repeatWhen(() => of(true))); // $ExpectDeprecation\n});"
  },
  {
    "path": "packages/rxjs/spec-dtslint/operators/retry-spec.ts",
    "content": "import { of } from 'rxjs';\nimport { retry } from 'rxjs/operators';\n\nit('should infer correctly', () => {\n  const o = of(1, 2, 3).pipe(retry()); // $ExpectType Observable<number>\n});\n\nit('should accept a count parameter', () => {\n  const o = of(1, 2, 3).pipe(retry(47)); // $ExpectType Observable<number>\n});\n\nit('should enforce types', () => {\n  const o = of(1, 2, 3).pipe(retry('aa')); // $ExpectError\n});\n"
  },
  {
    "path": "packages/rxjs/spec-dtslint/operators/retryWhen-spec.ts",
    "content": "import { of } from 'rxjs';\nimport { retryWhen } from 'rxjs/operators';\nimport { asInteropObservable } from '../../spec/helpers/interop-helper';\n\nit('should infer correctly', () => {\n  const o = of(1, 2, 3).pipe(retryWhen(errors => errors)); // $ExpectType Observable<number>\n});\n\nit('should infer correctly when the error observable has a different type', () => {\n  const o = of(1, 2, 3).pipe(retryWhen(retryWhen(errors => of('a', 'b', 'c')))); // $ExpectType Observable<number>\n});\n\nit('should enforce types', () => {\n  const o = of(1, 2, 3).pipe(retryWhen()); // $ExpectError\n});\n\nit('should accept interop observable notifier', () => {\n  of(1, 2, 3).pipe(retryWhen(() => asInteropObservable(of(true)))); // $ExpectType Observable<number>\n});\n\nit('should accept promise notifier', () => {\n  of(1, 2, 3).pipe(retryWhen(() => Promise.resolve(true))); // $ExpectType Observable<number>\n});\n\nit('should async iterable notifier', () => {\n  const asyncRange = {\n    from: 1,\n    to: 2,\n    [Symbol.asyncIterator]() {\n      return {\n        current: this.from,\n        last: this.to,\n        async next() {\n          await Promise.resolve();\n          const done = (this.current > this.last);\n          return {\n            done,\n            value: done ? this.current++ : undefined\n          };\n        }\n      };\n    }\n  };\n  of(1, 2, 3).pipe(retryWhen(() => asyncRange)); // $ExpectType Observable<number>\n});\n\nit('should accept iterable notifier', () => {\n  const syncRange = {\n    from: 1,\n    to: 2,\n    [Symbol.iterator]() {\n      return {\n        current: this.from,\n        last: this.to,\n        next() {\n          const done = (this.current > this.last);\n          return {\n            done,\n            value: done ? this.current++ : undefined\n          };\n        }\n      };\n    }\n  };\n  of(1, 2, 3).pipe(retryWhen(() => syncRange)); // $ExpectType Observable<number>\n});\n\nit('should accept readable stream notifier', () => {\n  const readableStream = new ReadableStream<string>({\n    pull(controller) {\n      controller.enqueue('x');\n      controller.close();\n    },\n  });\n  of(1, 2, 3).pipe(retryWhen(() => readableStream)); // $ExpectType Observable<number>\n});\n\nit('should enforce types of the notifier', () => {\n  of(1, 2, 3).pipe(retryWhen(() => 8)); // $ExpectError\n});\n\nit('should be deprecated', () => {\n  of(1, 2, 3).pipe(retryWhen(() => of(true))); // $ExpectDeprecation\n});"
  },
  {
    "path": "packages/rxjs/spec-dtslint/operators/sample-spec.ts",
    "content": "import { of } from 'rxjs';\nimport { sample } from 'rxjs/operators';\nimport { asInteropObservable } from '../../spec/helpers/interop-helper';\n\nit('should enforce parameter', () => {\n  of(1, 2, 3).pipe(sample()); // $ExpectError\n});\n\nit('should accept observable as notifier parameter', () => {\n  of(1, 2, 3).pipe(sample(of(4))); // $ExpectType Observable<number>\n  of(1, 2, 3).pipe(sample(of('a'))); // $ExpectType Observable<number>\n});\n\nit('should accept interop observable notifier', () => {\n  of(1, 2, 3).pipe(sample(asInteropObservable(of(true)))); // $ExpectType Observable<number>\n});\n\nit('should accept promise notifier', () => {\n  of(1, 2, 3).pipe(sample(Promise.resolve(true))); // $ExpectType Observable<number>\n});\n\nit('should async iterable notifier', () => {\n  const asyncRange = {\n    from: 1,\n    to: 2,\n    [Symbol.asyncIterator]() {\n      return {\n        current: this.from,\n        last: this.to,\n        async next() {\n          await Promise.resolve();\n          const done = (this.current > this.last);\n          return {\n            done,\n            value: done ? this.current++ : undefined\n          };\n        }\n      };\n    }\n  };\n  of(1, 2, 3).pipe(sample(asyncRange)); // $ExpectType Observable<number>\n});\n\nit('should accept iterable notifier', () => {\n  const syncRange = {\n    from: 1,\n    to: 2,\n    [Symbol.iterator]() {\n      return {\n        current: this.from,\n        last: this.to,\n        next() {\n          const done = (this.current > this.last);\n          return {\n            done,\n            value: done ? this.current++ : undefined\n          };\n        }\n      };\n    }\n  };\n  of(1, 2, 3).pipe(sample(syncRange)); // $ExpectType Observable<number>\n});\n\nit('should accept readable stream notifier', () => {\n  const readableStream = new ReadableStream<string>({\n    pull(controller) {\n      controller.enqueue('x');\n      controller.close();\n    },\n  });\n  of(1, 2, 3).pipe(sample(readableStream)); // $ExpectType Observable<number>\n});\n\nit('should enforce types of the notifier', () => {\n  of(1, 2, 3).pipe(sample(8)); // $ExpectError\n});\n"
  },
  {
    "path": "packages/rxjs/spec-dtslint/operators/sampleTime-spec.ts",
    "content": "import { of, asyncScheduler } from 'rxjs';\nimport { sampleTime } from 'rxjs/operators';\n\nit('should enforce period parameter', () => {\n  const a = of(1, 2, 3).pipe(sampleTime()); // $ExpectError\n});\n\nit('should infer correctly', () => { \n  const a = of(1, 2, 3).pipe(sampleTime(1000)); // $ExpectType Observable<number>\n});\n\nit('should accept scheduler parameter', () => {\n  const a = of(1, 2, 3).pipe(sampleTime(1000, asyncScheduler)); // $ExpectType Observable<number>\n});\n"
  },
  {
    "path": "packages/rxjs/spec-dtslint/operators/scan-spec.ts",
    "content": "import { of } from 'rxjs';\nimport { scan } from 'rxjs/operators';\n\nit('should enforce parameter', () => {\n  const a = of(1, 2, 3).pipe(scan()); // $ExpectError\n});\n\nit('should infer correctly ', () => {\n  const a = of(1, 2, 3).pipe(scan((x, y, z) => x + 1)); // $ExpectType Observable<number>\n});\n\nit('should infer correctly for accumulator of type array', () => {\n  const a = of(1, 2, 3).pipe(scan((x: number[], y: number, i: number) => x, [])); // $ExpectType Observable<number[]>\n});\n\nit('should accept seed parameter of the same type', () => {\n  const a = of(1, 2, 3).pipe(scan((x, y, z) => x + 1, 5)); // $ExpectType Observable<number>\n  const b = of(1, 2, 3).pipe(scan((x, y, z) => x + 1, [])); // $ExpectError\n});\n\nit('should accept seed parameter of the seed array type', () => {\n  const a = of(1, 2, 3).pipe(scan((x, y, z) => { x.push(y); return x; }, [4])); // $ExpectType Observable<number[]>\n  // Array must be typed...\n  const b = of(1, 2, 3).pipe(scan((x, y, z) => { x.push(y); return x; }, [])); // $ExpectError\n});\n\nit('should accept seed parameter of a different type', () => {\n  const a = of(1, 2, 3).pipe(scan((x, y, z) => x + '1', '5')); // $ExpectType Observable<string>\n  const bv: { [key: string]: string } = {};\n  const b = of(1, 2, 3).pipe(scan((x, y, z) => ({ ...x, [y]: y.toString() }), bv)); // $ExpectType Observable<{ [key: string]: string; }>\n});\n\nit('should act appropriately with no seed', () => {\n  // Starting in TS 3.5, the return type is inferred from the accumulator's type if it's provided without a seed.\n  const a = of(1, 2, 3).pipe(scan((a: any, v) => '' + v)); // $ExpectType Observable<any>\n  const b = of(1, 2, 3).pipe(scan((a, v) => v)); // $ExpectType Observable<number>\n  const c = of(1, 2, 3).pipe(scan(() => {})); // $ExpectType Observable<number | void>\n});\n\nit('should act appropriately with a seed', () => {\n  const a = of(1, 2, 3).pipe(scan((a, v) => a + v, '')); // $ExpectType Observable<string>\n  const b = of(1, 2, 3).pipe(scan((a, v) => a + v, 0)); // $ExpectType Observable<number>\n  const c = of(1, 2, 3).pipe(scan((a, v) => a + 1, [])); // $ExpectError\n});\n\nit('should infer types properly from arguments', () => {\n  function toArrayReducer(arr: number[], item: number, index: number): number[] {\n    if (index === 0) {\n      return [item];\n    }\n    arr.push(item);\n    return arr;\n  }\n\n  const a = scan(toArrayReducer, [] as number[]); // $ExpectType OperatorFunction<number, number[]>\n});\n"
  },
  {
    "path": "packages/rxjs/spec-dtslint/operators/sequenceEqual-spec.ts",
    "content": "import { of } from 'rxjs';\nimport { sequenceEqual } from 'rxjs/operators';\n\nit('should enforce compareTo Observable', () => {\n  const a = of(1, 2, 3).pipe(sequenceEqual()); // $ExpectError\n});\n\nit('should infer correctly give compareTo Observable', () => {\n  const a = of(1, 2, 3).pipe(sequenceEqual(of(1))); // $ExpectType Observable<boolean>\n});\n\nit('should enforce compareTo to be the same type of Observable', () => {\n  const a = of(1, 2, 3).pipe(sequenceEqual(of('a'))); // $ExpectError\n});\n\nit('should infer correctly given comparator parameter', () => {\n  const a = of(1, 2, 3).pipe(sequenceEqual(of(1), (val1, val2) => val1 === val2)); // $ExpectType Observable<boolean>\n});\n\nit('should support Promises', () => {\n  of(1, 2, 3).pipe(sequenceEqual(Promise.resolve(1))); // $ExpectType Observable<boolean>\n  // Enforce the same types produced by Promise and source observable\n  of(1, 2, 3).pipe(sequenceEqual(Promise.resolve('foo'))); // $ExpectError\n});\n"
  },
  {
    "path": "packages/rxjs/spec-dtslint/operators/share-spec.ts",
    "content": "import { of } from 'rxjs';\nimport { share } from 'rxjs/operators';\n\nit('should infer correctly', () => {\n  const o = of('foo', 'bar', 'baz').pipe(share()); // $ExpectType Observable<string>\n});\n\nit('should enforce types', () => {\n  const o = of('foo', 'bar', 'baz').pipe(share('abc')); // $ExpectError\n});\n\nit('should support Promises', () => {\n  const factory = () => Promise.resolve();\n  of(1, 2, 3).pipe(share({ resetOnError: factory, resetOnComplete: factory, resetOnRefCountZero: factory })); // $ExpectType Observable<number>\n});\n"
  },
  {
    "path": "packages/rxjs/spec-dtslint/operators/shareReplay-spec.ts",
    "content": "import { of, asyncScheduler  } from 'rxjs';\nimport { shareReplay } from 'rxjs/operators';\n\nit('should accept an individual bufferSize parameter', () => {\n  const o = of(1, 2, 3).pipe(shareReplay(1)); // $ExpectType Observable<number>\n});\n\nit('should accept individual bufferSize and windowTime parameters', () => {\n  const o = of(1, 2, 3).pipe(shareReplay(1, 2)); // $ExpectType Observable<number>\n});\n\nit('should accept individual bufferSize, windowTime and scheduler parameters', () => {\n  const o3 = of(1, 2, 3).pipe(shareReplay(1, 2, asyncScheduler)); // $ExpectType Observable<number>\n});\n\nit('should accept a bufferSize config parameter', () => {\n  const o = of(1, 2, 3).pipe(shareReplay({ bufferSize: 1, refCount: true })); // $ExpectType Observable<number>\n});\n\nit('should accept bufferSize and windowTime config parameters', () => {\n  const o = of(1, 2, 3).pipe(shareReplay({ bufferSize: 1, windowTime: 2, refCount: true })); // $ExpectType Observable<number>\n});\n\nit('should accept bufferSize, windowTime and scheduler config parameters', () => {\n  const o = of(1, 2, 3).pipe(shareReplay({ bufferSize: 1, windowTime: 2, scheduler: asyncScheduler, refCount: true })); // $ExpectType Observable<number>\n});\n\nit('should require a refCount config parameter', () => {\n  const o = of(1, 2, 3).pipe(shareReplay({ bufferSize: 1 })); // $ExpectError\n});\n"
  },
  {
    "path": "packages/rxjs/spec-dtslint/operators/single-spec.ts",
    "content": "import type { Observable } from 'rxjs';\nimport { of } from 'rxjs';\nimport { single } from 'rxjs/operators';\n\nit('should infer correctly', () => {\n  const o = of('foo').pipe(single()); // $ExpectType Observable<string>\n});\n\nit('should support a value', () => {\n  const o = of('foo').pipe(single(value => value === 'foo')); // $ExpectType Observable<string>\n});\n\nit('should support an index', () => {\n  const o = of('foo').pipe(single((value, index) => index === 2)); // $Observable<string>\n});\n\nit('should support a source', () => {\n  const o = of('foo').pipe(single((value, index, source) => value === 'foo')); // $Observable<string>\n});\n\nit('should enforce value type', () => {\n  const o = of('foo').pipe(single(((value: number) => value === 2))); // $ExpectError\n});\n\nit('should enforce return type', () => {\n  const o = of('foo').pipe(single(value => value)); // $ExpectError\n});\n\nit('should enforce index type', () => {\n  const o = of('foo').pipe(single(((value, index: string) => index === '2'))); // $ExpectError\n});\n\nit('should enforce source type', () => {\n  const o = of('foo').pipe(single(((value, index, source: Observable<number>) => value === 'foo'))); // $ExpectError\n});\n\nit('should handle Boolean constructor properly', () => {\n  const a = of(null, undefined, 0 as const, -0 as const, 0n as const, '' as const).pipe(single(Boolean)); // $ExpectType Observable<never>\n  const b = of(null, undefined, 0 as const, 'test' as const, -0 as const, 0n as const, '' as const).pipe(single(Boolean)); // $ExpectType Observable<\"test\">\n});\n\nit('should handle predicates that always return false properly', () => {\n  const a = of(1, 2, 3, 4).pipe(single(() => false as const)); // $ExpectType Observable<number>\n});\n\nit('should support inference from a predicate that returns any', () => {\n  function isTruthy(value: number): any {\n    return !!value;\n  }\n\n  const o$ = of(1).pipe(single(isTruthy)); // $ExpectType Observable<number>\n});"
  },
  {
    "path": "packages/rxjs/spec-dtslint/operators/skip-spec.ts",
    "content": "import { of } from 'rxjs';\nimport { skip } from 'rxjs/operators';\n\nit('should infer correctly', () => {\n  const o = of('foo', 'bar', 'baz').pipe(skip(7)); // $ExpectType Observable<string>\n});\n\nit('should enforce types', () => {\n  const o = of('foo', 'bar', 'baz').pipe(skip()); // $ExpectError\n  const p = of('foo', 'bar', 'baz').pipe(skip('7')); // $ExpectError\n});\n"
  },
  {
    "path": "packages/rxjs/spec-dtslint/operators/skipLast-spec.ts",
    "content": "import { of } from 'rxjs';\nimport { skipLast } from 'rxjs/operators';\n\nit('should infer correctly', () => {\n  const o = of('foo', 'bar', 'baz').pipe(skipLast(7)); // $ExpectType Observable<string>\n});\n\nit('should enforce types', () => {\n  const o = of('foo', 'bar', 'baz').pipe(skipLast()); // $ExpectError\n  const p = of('foo', 'bar', 'baz').pipe(skipLast('7')); // $ExpectError\n});\n"
  },
  {
    "path": "packages/rxjs/spec-dtslint/operators/skipUntil-spec.ts",
    "content": "import { of } from 'rxjs';\nimport { skipUntil } from 'rxjs/operators';\n\nit('should infer correctly', () => {\n  const o = of('foo', 'bar', 'baz').pipe(skipUntil(of(4, 'RxJS', 7))); // $ExpectType Observable<string>\n});\n\nit('should enforce types', () => {\n  const o = of('foo', 'bar', 'baz').pipe(skipUntil()); // $ExpectError\n  const p = of('foo', 'bar', 'baz').pipe(skipUntil(7)); // $ExpectError\n});\n\nit('should support Promises', () => {\n  of(1, 2, 3).pipe(skipUntil(Promise.resolve('foo'))); // $ExpectType Observable<number>\n});\n"
  },
  {
    "path": "packages/rxjs/spec-dtslint/operators/skipWhile-spec.ts",
    "content": "import { of } from 'rxjs';\nimport { skipWhile } from 'rxjs/operators';\n\nit('should support a predicate', () => {\n  const o = of('foo', 'bar', 'baz').pipe(skipWhile(value => value === 'bar')); // $ExpectType Observable<string>\n});\n\nit('should support a predicate with an index', () => {\n  const o = of('foo', 'bar', 'baz').pipe(skipWhile((value, index) => index < 3)); // $ExpectType Observable<string>\n});\n\nit('should enforce types', () => {\n  const o = of('foo', 'bar', 'baz').pipe(skipWhile()); // $ExpectError\n});\n\nit('should enforce predicate types', () => {\n  const o = of('foo', 'bar', 'baz').pipe(skipWhile(value => value < 3)); // $ExpectError\n  const p = of('foo', 'bar', 'baz').pipe(skipWhile((value, index) => index < '3')); // $ExpectError\n});\n\nit('should enforce predicate return type', () => {\n  const o = of('foo', 'bar', 'baz').pipe(skipWhile(value => value)); // $ExpectError\n});\n\nit('should handle Boolean constructor properly', () => {\n  // this one is a bit odd, but probably okay.\n  const a = of(null, undefined, 0 as const, -0 as const, '' as const, 0n as const, false as const).pipe(skipWhile(Boolean)); // $ExpectType Observable<false | \"\" | 0 | 0n | null | undefined>\n  const b = of(null, 0 as const, -0 as const, '' as const, 0n as const, false as const).pipe(skipWhile(Boolean)); // $ExpectType Observable<false | \"\" | 0 | 0n | null>\n  const c = of(1, 2, 3, '' as const, 0n as const, false as const, 4).pipe(skipWhile(Boolean)) // $ExpectType Observable<number | false | \"\" | 0n>\n  const d = of(true as const, 123 as const, 'HI' as const, {}, []).pipe(skipWhile(Boolean)); // $ExpectType Observable<never>\n});\n\nit('should handle predicates that always return true properly', () => {\n  const a = of(1, 2, 3, 4).pipe(skipWhile(() => true as const)); // $ExpectType Observable<never>\n});"
  },
  {
    "path": "packages/rxjs/spec-dtslint/operators/startWith-spec.ts",
    "content": "import { of, startWith  } from 'rxjs';\nimport type { A, B} from '../helpers';\nimport { a, b, c, d, e, f, g, h } from '../helpers';\n\nit('should infer correctly with N values', () => {\n  const r0 = of(a).pipe(startWith()); // $ExpectType Observable<A>\n  const r1 = of(a).pipe(startWith(b)); // $ExpectType Observable<A | B>\n  const r2 = of(a).pipe(startWith(b, c)); // $ExpectType Observable<A | B | C>\n  const r3 = of(a).pipe(startWith(b, c, d)); // $ExpectType Observable<A | B | C | D>\n  const r4 = of(a).pipe(startWith(b, c, d, e)); // $ExpectType Observable<A | B | C | D | E>\n  const r5 = of(a).pipe(startWith(b, c, d, e, f)); // $ExpectType Observable<A | B | C | D | E | F>\n  const r6 = of(a).pipe(startWith(b, c, d, e, f, g)); // $ExpectType Observable<A | B | C | D | E | F | G>\n  const r7 = of(a).pipe(startWith(b, c, d, e, f, g, h)); // $ExpectType Observable<A | B | C | D | E | F | G | H>\n});\n\nit('should infer correctly with a single specified type', () => {\n  const r0 = of(a).pipe(startWith<A>(a)); // $ExpectType Observable<A>\n  const r1 = of(a).pipe(startWith<A|B>(b)); // $ExpectType Observable<A | B>\n  const r2 = of(a).pipe(startWith<A|B>(a)); // $ExpectType Observable<A | B>\n});\n"
  },
  {
    "path": "packages/rxjs/spec-dtslint/operators/subscribeOn-spec.ts",
    "content": "import { of, asyncScheduler } from 'rxjs';\nimport { subscribeOn } from 'rxjs/operators';\n\nit('should infer correctly', () => {\n  const o = of('a', 'b', 'c').pipe(subscribeOn(asyncScheduler)); // $ExpectType Observable<string>\n});\n\nit('should support a delay ', () => {\n  const o = of('a', 'b', 'c').pipe(subscribeOn(asyncScheduler, 7)); // $ExpectType Observable<string>\n});\n\nit('should enforce types', () => {\n  const o = of('a', 'b', 'c').pipe(subscribeOn()); // $ExpectError\n});\n\nit('should enforce scheduler type', () => {\n  const o = of('a', 'b', 'c').pipe(subscribeOn('nope')); // $ExpectError\n});\n\nit('should enforce delay type', () => {\n  const o = of('a', 'b', 'c').pipe(subscribeOn(asyncScheduler, 'nope')); // $ExpectError\n});\n"
  },
  {
    "path": "packages/rxjs/spec-dtslint/operators/switchAll-spec.ts",
    "content": "import { of } from 'rxjs';\nimport { switchAll } from 'rxjs/operators';\n\nit('should infer correctly', () => {\n  const o = of(of(1, 2, 3)).pipe(switchAll()); // $ExpectType Observable<number>\n});\n\nit('should enforce types', () => {\n  const o = of(1, 2, 3).pipe(switchAll()); // $ExpectError\n});\n"
  },
  {
    "path": "packages/rxjs/spec-dtslint/operators/switchMap-spec.ts",
    "content": "import { of } from 'rxjs';\nimport { switchMap } from 'rxjs/operators';\n\nit('should infer correctly', () => {\n  const o = of(1, 2, 3).pipe(switchMap(p => of(Boolean(p)))); // $ExpectType Observable<boolean>\n});\n\nit('should support a projector that takes an index', () => {\n  const o = of(1, 2, 3).pipe(switchMap(p => of(Boolean(p)))); // $ExpectType Observable<boolean>\n});\n\nit('should support union-type projections with empty streams', () => {\n  const o = of(1, 2, 3).pipe(switchMap(n => Math.random() < 0.5 ? of(123) : of())); // $ExpectType Observable<number>\n});\n\nit('should enforce types', () => {\n  const o = of(1, 2, 3).pipe(switchMap()); // $ExpectError\n});\n\nit('should enforce the return type', () => {\n  const o = of(1, 2, 3).pipe(switchMap(p => p)); // $ExpectError\n});\n\nit('should support projecting to union types', () => {\n  const o = of(Math.random()).pipe(switchMap(n => n > 0.5 ? of(123) : of('test'))); // $ExpectType Observable<string | number>\n});\n\nit('should produce `Observable<never>` when mapping to an `ObservableInput<never>`', () => {\n  const o = of(1, 2, 3).pipe(switchMap(n => Promise.reject())); // $ExpectType Observable<never>\n});\n"
  },
  {
    "path": "packages/rxjs/spec-dtslint/operators/switchMapTo-spec.ts",
    "content": "import { of } from 'rxjs';\nimport { switchMapTo } from 'rxjs/operators';\n\nit('should infer correctly', () => {\n  const o = of(1, 2, 3).pipe(switchMapTo(of('foo'))); // $ExpectType Observable<string>\n});\n\nit('should infer correctly with multiple types', () => {\n  const o = of(1, 2, 3).pipe(switchMapTo(of('foo', 4))); // $ExpectType Observable<string | number>\n});\n\nit('should infer correctly with an array', () => {\n  const o = of(1, 2, 3).pipe(switchMapTo([4, 5, 6])); // $ExpectType Observable<number>\n});\n\nit('should infer correctly with a Promise', () => {\n  const o = of(1, 2, 3).pipe(switchMapTo(new Promise<string>(() => {}))); // $ExpectType Observable<string>\n});\n\nit('should support union-type projections with empty streams', () => {\n  const o = of(1, 2, 3).pipe(switchMapTo(Math.random() < 0.5 ? of(123) : of())); // $ExpectType Observable<number>\n});\n\nit('should enforce types', () => {\n  const o = of(1, 2, 3).pipe(switchMapTo()); // $ExpectError\n});\n\nit('should enforce types of the observable parameter', () => {\n  const fn = () => {}\n  const o = of(1, 2, 3).pipe(switchMapTo(fn)); // $ExpectError\n});\n\nit('should enforce the return type', () => {\n  const o = of(1, 2, 3).pipe(switchMapTo(p => p)); // $ExpectError\n  const p = of(1, 2, 3).pipe(switchMapTo(4)); // $ExpectError\n});\n\nit('should produce `Observable<never>` when mapping to an `ObservableInput<never>`', () => {\n  const o = of(1, 2, 3).pipe(switchMapTo(Promise.reject())); // $ExpectType Observable<never>\n});\n\nit('should be deprecated', () => {\n  const o = of(1, 2, 3).pipe(switchMapTo(of(true))); // $ExpectDeprecation\n});\n"
  },
  {
    "path": "packages/rxjs/spec-dtslint/operators/switchScan-spec.ts",
    "content": "import { of } from 'rxjs';\nimport { switchScan } from 'rxjs/operators';\n\nit('should infer correctly', () => {\n  const o = of(1, 2, 3).pipe(switchScan((acc: boolean, v: number) => of(Boolean(v)), false)); // $ExpectType Observable<boolean>\n});\n\nit('should infer correctly when using a single type', () => {\n  const o = of(1, 2, 3).pipe(switchScan((acc, v) => of(acc + v), 0)); // $ExpectType Observable<number>\n});\n\nit('should infer correctly when using seed of a different type', () => {\n  const o = of(1, 2, 3).pipe(switchScan((acc, v) => of(acc + v), '0')); // $ExpectType Observable<string>\n});\n\nit('should support a projector that takes an index', () => {\n  const o = of(1, 2, 3).pipe(switchScan((acc, v, index) => of(Boolean(v)), false)); // $ExpectType Observable<boolean>\n});\n\nit('should support projecting to union types', () => {\n  const o = of(Math.random()).pipe(switchScan(n => n > 0.5 ? of(123) : of('test'), 0)); // $ExpectType Observable<string | number>\n});\n\nit('should use the inferred accumulator return type over the seed type', () => {\n  const o = of(1, 2, 3).pipe(switchScan(p => of(1), [])); // $ExpectType Observable<number>\n});\n\nit('should enforce types', () => {\n  const o = of(1, 2, 3).pipe(switchScan()); // $ExpectError\n});\n\nit('should enforce the return type to be Observable', () => {\n  const o = of(1, 2, 3).pipe(switchScan(p => p)); // $ExpectError\n});\n\nit('should enforce seed and accumulator to have the same type', () => {\n  const o = of(1, 2, 3).pipe(switchScan((acc, p) => of([...acc, p]))); // $ExpectError\n});\n"
  },
  {
    "path": "packages/rxjs/spec-dtslint/operators/take-spec.ts",
    "content": "import { of } from 'rxjs';\nimport { take } from 'rxjs/operators';\n\nit('should infer correctly', () => {\n  const o = of(1, 2, 3).pipe(take(7)); // $ExpectType Observable<number>\n});\n\nit('should enforce types', () => {\n  const o = of(1, 2, 3).pipe(take('7')); // $ExpectError\n});\n"
  },
  {
    "path": "packages/rxjs/spec-dtslint/operators/takeLast-spec.ts",
    "content": "import { of } from 'rxjs';\nimport { takeLast } from 'rxjs/operators';\n\nit('should infer correctly', () => {\n  const o = of(1, 2, 3).pipe(takeLast(7)); // $ExpectType Observable<number>\n});\n\nit('should enforce types', () => {\n  const o = of(1, 2, 3).pipe(takeLast('7')); // $ExpectError\n});\n"
  },
  {
    "path": "packages/rxjs/spec-dtslint/operators/takeUntil-spec.ts",
    "content": "import { of } from 'rxjs';\nimport { takeUntil } from 'rxjs/operators';\n\nit('should infer correctly', () => {\n  const o = of(1, 2, 3).pipe(takeUntil(of(1, 2, 3))); // $ExpectType Observable<number>\n});\n\nit('should enforce types', () => {\n  const o = of(1, 2, 3).pipe(takeUntil(value => value < 3)); // $ExpectError\n});\n"
  },
  {
    "path": "packages/rxjs/spec-dtslint/operators/takeWhile-spec.ts",
    "content": "import { of } from 'rxjs';\nimport { takeWhile } from 'rxjs/operators';\n\nit('should support a user-defined type guard', () => {\n  const o = of('foo').pipe(takeWhile((s): s is 'foo' => true)); // $ExpectType Observable<\"foo\">\n});\n\nit('should support a user-defined type guard with inclusive option', () => {\n  const o = of('foo').pipe(takeWhile((s): s is 'foo' => true, false)); // $ExpectType Observable<\"foo\">\n});\n\nit('should support a predicate', () => {\n  const o = of('foo').pipe(takeWhile(s => true)); // $ExpectType Observable<string>\n});\n\nit('should support a predicate with inclusive option', () => {\n  const o = of('foo').pipe(takeWhile(s => true, true)); // $ExpectType Observable<string>\n});\n\nit('should properly support Boolean constructor', () => {\n  const a = of(false as const, 0 as const, -0 as const, 0n as const, '' as const, null, undefined).pipe(takeWhile(Boolean)); // $ExpectType Observable<never>\n  const b = of(false as const, 0 as const, -0 as const, 0n as const, '' as const, null, undefined).pipe(takeWhile(Boolean, true)); // $ExpectType Observable<false | \"\" | 0 | 0n | null | undefined>\n  const c = of(false as const, 0 as const, 'hi' as const, -0 as const, 0n as const, '' as const, null, undefined).pipe(takeWhile(Boolean)); // $ExpectType Observable<\"hi\">\n  const d = of(false as const, 0 as const, 'hi' as const, -0 as const, 0n as const, '' as const, null, undefined).pipe(takeWhile(Boolean, false)); // $ExpectType Observable<\"hi\">\n  const e = of(false as const, 0 as const, 'hi' as const, -0 as const, 0n as const, '' as const, null, undefined).pipe(takeWhile(Boolean, true)); // $ExpectType Observable<false | \"\" | 0 | 0n | \"hi\" | null | undefined>\n  const f = of(1, ['hi'], false as const, 0 as const, -0 as const, 0n as const, '' as const, null, undefined).pipe(takeWhile(Boolean, true)); // $ExpectType Observable<number | false | \"\" | 0n | string[] | null | undefined>\n});\n\nit('should properly handle predicates that always return false', () => {\n  const a = of(1, 2, 3).pipe(takeWhile(() => false as const)); // $ExpectType Observable<number>\n  const b = of(1, 2, 3).pipe(takeWhile(() => false as const, true)); // $ExpectType Observable<number>\n});\n\nit('should support inference from a predicate that returns any', () => {\n  function isTruthy(value: number): any {\n    return !!value;\n  }\n\n  const o$ = of(1).pipe(takeWhile(isTruthy)); // $ExpectType Observable<number>\n});\n"
  },
  {
    "path": "packages/rxjs/spec-dtslint/operators/tap-spec.ts",
    "content": "import { of } from 'rxjs';\nimport { tap } from 'rxjs/operators';\n\nit('should infer correctly', () => {\n  const a = of(1, 2, 3).pipe(tap()); // $ExpectType Observable<number>\n});\n\nit('should accept partial observer', () => {\n  const a = of(1, 2, 3).pipe(tap({ next: (x: number) => { } })); // $ExpectType Observable<number>\n  const b = of(1, 2, 3).pipe(tap({ error: (x: any) => { } })); // $ExpectType Observable<number>\n  const c = of(1, 2, 3).pipe(tap({ complete: () => { } })); // $ExpectType Observable<number>\n});\n\nit('should enforce type for next observer function', () => {\n  const a = of(1, 2, 3).pipe(tap({ next: (x: string) => { } })); // $ExpectError\n});\n\nit('should deprecate the multi-argument usage', () => {\n  const next = (value: number) => {};\n  const error = (error: any) => {};\n  const complete = () => {};\n  const o = of(42);\n  o.pipe(tap()); // $ExpectNoDeprecation\n  o.pipe(tap({ next })); // $ExpectNoDeprecation\n  o.pipe(tap({ next, error })); // $ExpectNoDeprecation\n  o.pipe(tap({ next, complete })); // $ExpectNoDeprecation\n  o.pipe(tap({ next, error, complete })); // $ExpectNoDeprecation\n  o.pipe(tap({ error })); // $ExpectNoDeprecation\n  o.pipe(tap({ error, complete })); // $ExpectNoDeprecation\n  o.pipe(tap({ complete })); // $ExpectNoDeprecation\n  o.pipe(tap(next)); // $ExpectNoDeprecation\n});"
  },
  {
    "path": "packages/rxjs/spec-dtslint/operators/throttle-spec.ts",
    "content": "import { of, timer } from 'rxjs';\nimport { throttle } from 'rxjs/operators';\n\nit('should infer correctly', () => {\n  const o = of(1, 2, 3).pipe(throttle(() => timer(47))); // $ExpectType Observable<number>\n});\n\nit('should infer correctly with a Promise', () => {\n  const o = of(1, 2, 3).pipe(throttle(() => new Promise<boolean>(() => {}))); // $ExpectType Observable<number>\n});\n\nit('should support a config', () => {\n  const o = of(1, 2, 3).pipe(throttle(() => timer(47), { leading: true, trailing: true })); // $ExpectType Observable<number>\n});\n\nit('should enforce types', () => {\n  const o = of(1, 2, 3).pipe(throttle()); // $ExpectError\n  const p = of(1, 2, 3).pipe(throttle(() => {})); // $ExpectError\n});\n\nit('should enforce config types', () => {\n  const o = of(1, 2, 3).pipe(throttle(() => timer(47), { x: 1 })); // $ExpectError\n  const p = of(1, 2, 3).pipe(throttle(() => timer(47), { leading: 1, trailing: 1 })); // $ExpectError\n  const q = of(1, 2, 3).pipe(throttle(() => timer(47), null)); // $ExpectError\n});\n"
  },
  {
    "path": "packages/rxjs/spec-dtslint/operators/throttleTime-spec.ts",
    "content": "import { of, asyncScheduler } from 'rxjs';\nimport { throttleTime } from 'rxjs/operators';\n\nit('should infer correctly', () => {\n  const o = of(1, 2, 3).pipe(throttleTime(47)); // $ExpectType Observable<number>\n});\n\nit('should support a scheduler', () => {\n  const o = of(1, 2, 3).pipe(throttleTime(47, asyncScheduler)); // $ExpectType Observable<number>\n});\n\nit('should support a config', () => {\n  const o = of(1, 2, 3).pipe(throttleTime(47, asyncScheduler, { leading: true, trailing: true })); // $ExpectType Observable<number>\n});\n\nit('should enforce types', () => {\n  const o = of(1, 2, 3).pipe(throttleTime()); // $ExpectError\n  const p = of(1, 2, 3).pipe(throttleTime('foo')); // $ExpectError\n});\n\nit('should enforce scheduler types', () => {\n  const o = of(1, 2, 3).pipe(throttleTime(47, null)); // $ExpectError\n});\n\nit('should enforce config types', () => {\n  const o = of(1, 2, 3).pipe(throttleTime(47, asyncScheduler, { x: 1 })); // $ExpectError\n  const p = of(1, 2, 3).pipe(throttleTime(47, asyncScheduler, { leading: 1, trailing: 1 })); // $ExpectError\n  const q = of(1, 2, 3).pipe(throttleTime(47, asyncScheduler, null)); // $ExpectError\n});\n"
  },
  {
    "path": "packages/rxjs/spec-dtslint/operators/throwIfEmpty-spec.ts",
    "content": "import { of } from 'rxjs';\nimport { throwIfEmpty } from 'rxjs/operators';\n\nit('should infer correctly', () => {\n  const o = of('a', 'b', 'c').pipe(throwIfEmpty()); // $ExpectType Observable<string>\n});\n\nit('should support an errorFactory', () => {\n  const o = of('a', 'b', 'c').pipe(throwIfEmpty(() => 47)); // $ExpectType Observable<string>\n});\n\nit('should enforce errorFactory type', () => {\n  const o = of('a', 'b', 'c').pipe(throwIfEmpty('nope')); // $ExpectError\n  const p = of('a', 'b', 'c').pipe(throwIfEmpty(x => 47)); // $ExpectError\n});\n"
  },
  {
    "path": "packages/rxjs/spec-dtslint/operators/timeInterval-spec.ts",
    "content": "import { of, asyncScheduler } from 'rxjs';\nimport { timeInterval } from 'rxjs/operators';\n\nit('should infer correctly', () => {\n  const o = of('a', 'b', 'c').pipe(timeInterval()); // $ExpectType Observable<TimeInterval<string>>\n});\n\nit('should support a scheduler', () => {\n  const o = of('a', 'b', 'c').pipe(timeInterval(asyncScheduler)); // $ExpectType Observable<TimeInterval<string>>\n});\n\nit('should enforce scheduler type', () => {\n  const o = of('a', 'b', 'c').pipe(timeInterval('nope')); // $ExpectError\n});\n"
  },
  {
    "path": "packages/rxjs/spec-dtslint/operators/timeout-spec.ts",
    "content": "import { of, asyncScheduler } from 'rxjs';\nimport { timeout } from 'rxjs/operators';\nimport { A, a$, b$, c$ } from '../helpers';\n\nit('should infer correctly', () => {\n  const o = of('a', 'b', 'c').pipe(timeout(10)); // $ExpectType Observable<string>\n});\n\nit('should support a date', () => {\n  const o = of('a', 'b', 'c').pipe(timeout(new Date())); // $ExpectType Observable<string>\n});\n\nit('should support a scheduler', () => {\n  const o = of('a', 'b', 'c').pipe(timeout(10, asyncScheduler)); // $ExpectType Observable<string>\n  const p = of('a', 'b', 'c').pipe(timeout(new Date(), asyncScheduler)); // $ExpectType Observable<string>\n});\n\nit('should enforce types', () => {\n  const o = of('a', 'b', 'c').pipe(timeout()); // $ExpectError\n});\n\nit('should enforce types of due', () => {\n  const o = of('a', 'b', 'c').pipe(timeout('foo')); // $ExpectError\n});\n\nit('should enforce types of scheduler', () => {\n  const o = of('a', 'b', 'c').pipe(timeout(5, 'foo')); // $ExpectError\n});\n\nit('Check info argument to factory', () => {\n  const o = of('a').pipe( // $ExpectType Observable<string | number>\n    timeout({\n      meta: new A(),\n      with: (info) => {\n        const i = info; // $ExpectType TimeoutInfo<string, A>\n        const m = info.meta; // $ExpectType A\n        const s = info.seen; // $ExpectType number\n        const l = info.lastValue; // $ExpectType string | null\n        // These should be readonly\n        info.meta = new A(); // $ExpectError\n        info.seen = 12; // $ExpectError\n        info.lastValue = 'blah'; // $ExpectError\n        return of(123);\n      }\n    })\n  );\n});\n\nit('Check config arguments', () => {\n  const o = of('a').pipe( // $ExpectType Observable<string>\n    timeout({\n      first: 1000\n    })\n  );\n});\n\nit('should support a union', () => {\n  const o = a$.pipe( // $ExpectType Observable<A | B | C>\n    timeout({ \n      with: () => Math.random() > 0.5 ? b$ : c$\n    })\n  );\n});"
  },
  {
    "path": "packages/rxjs/spec-dtslint/operators/timeoutWith-spec.ts",
    "content": "import { of, asyncScheduler } from 'rxjs';\nimport { timeoutWith } from 'rxjs/operators';\n\nit('should infer correctly', () => {\n  const o = of('a', 'b', 'c').pipe(timeoutWith(10, of(1, 2, 3))); // $ExpectType Observable<string | number>\n  const p = of('a', 'b', 'c').pipe(timeoutWith(10, [1, 2, 3])); // $ExpectType Observable<string | number>\n  const q = of('a', 'b', 'c').pipe(timeoutWith(10, Promise.resolve(5))); // $ExpectType Observable<string | number>\n  const r = of('a', 'b', 'c').pipe(timeoutWith(10, new Set([1, 2, 3]))); // $ExpectType Observable<string | number>\n  const s = of('a', 'b', 'c').pipe(timeoutWith(10, 'foo')); // $ExpectType Observable<string>\n});\n\nit('should infer correctly while having the same types', () => {\n  const o = of('a', 'b', 'c').pipe(timeoutWith(10, of('x', 'y', 'z'))); // $ExpectType Observable<string>\n});\n\nit('should support a date', () => {\n  const o = of('a', 'b', 'c').pipe(timeoutWith(new Date(), of(1, 2, 3))); // $ExpectType Observable<string | number>\n  const p = of('a', 'b', 'c').pipe(timeoutWith(new Date(), [1, 2, 3])); // $ExpectType Observable<string | number>\n  const q = of('a', 'b', 'c').pipe(timeoutWith(new Date(), Promise.resolve(5))); // $ExpectType Observable<string | number>\n  const r = of('a', 'b', 'c').pipe(timeoutWith(new Date(), new Set([1, 2, 3]))); // $ExpectType Observable<string | number>\n  const s = of('a', 'b', 'c').pipe(timeoutWith(new Date(), 'foo')); // $ExpectType Observable<string>\n});\n\nit('should support a scheduler', () => {\n  const o = of('a', 'b', 'c').pipe(timeoutWith(10, of(1, 2, 3), asyncScheduler)); // $ExpectType Observable<string | number>\n  const p = of('a', 'b', 'c').pipe(timeoutWith(new Date(), of(1, 2, 3), asyncScheduler)); // $ExpectType Observable<string | number>\n});\n\nit('should enforce types', () => {\n  const o = of('a', 'b', 'c').pipe(timeoutWith()); // $ExpectError\n});\n\nit('should enforce types of due', () => {\n  const o = of('a', 'b', 'c').pipe(timeoutWith('foo')); // $ExpectError\n});\n\nit('should enforce types of withObservable', () => {\n  const o = of('a', 'b', 'c').pipe(timeoutWith(10, 10)); // $ExpectError\n});\n\nit('should enforce types of scheduler', () => {\n  const o = of('a', 'b', 'c').pipe(timeoutWith(5, of(1, 2, 3), 'foo')); // $ExpectError\n});\n"
  },
  {
    "path": "packages/rxjs/spec-dtslint/operators/timestamp-spec.ts",
    "content": "import { of, asyncScheduler } from 'rxjs';\nimport { timestamp } from 'rxjs/operators';\n\nit('should infer correctly', () => {\n  const o = of('a', 'b', 'c').pipe(timestamp()); // $ExpectType Observable<Timestamp<string>>\n});\n\nit('should support a scheduler', () => {\n  const o = of('a', 'b', 'c').pipe(timestamp(asyncScheduler)); // $ExpectType Observable<Timestamp<string>>\n});\n\nit('should enforce scheduler type', () => {\n  const o = of('a', 'b', 'c').pipe(timestamp('nope')); // $ExpectError\n});\n"
  },
  {
    "path": "packages/rxjs/spec-dtslint/operators/toArray-spec.ts",
    "content": "import { of } from 'rxjs';\nimport { toArray } from 'rxjs/operators';\n\nit('should infer correctly', () => {\n  const o = of(1, 2, 3).pipe(toArray()); // $ExpectType Observable<number[]>\n});\n\nit('should enforce types', () => {\n  const o = of(1).pipe(toArray('')); // $ExpectError\n});\n"
  },
  {
    "path": "packages/rxjs/spec-dtslint/operators/window-spec.ts",
    "content": "import { of } from 'rxjs';\nimport { window } from 'rxjs/operators';\n\nit('should infer correctly', () => {\n  of(1).pipe(window(of('1'))); // $ExpectType Observable<Observable<number>>\n});\n\nit('should enforce types', () => {\n  of(1).pipe(window()); // $ExpectError\n  of(1).pipe(window(6)); // $ExpectError\n});\n\nit('should support Promises', () => {\n  of(1, 2, 3).pipe(window(Promise.resolve('foo'))); // $ExpectType Observable<Observable<number>>\n});\n"
  },
  {
    "path": "packages/rxjs/spec-dtslint/operators/windowCount-spec.ts",
    "content": "import { of } from 'rxjs';\nimport { windowCount } from 'rxjs/operators';\n\nit('should infer correctly', () => {\n  of('test').pipe(windowCount(1)); // $ExpectType Observable<Observable<string>>\n  of('test').pipe(windowCount(1, 2)); // $ExpectType Observable<Observable<string>>\n});\n\nit('should enforce windowSize type', () => {\n  of(1).pipe(windowCount()); // $ExpectError\n  of(1).pipe(windowCount('1')); // $ExpectError\n});\n\nit('should enforce startEveryWindow type', () => {\n  of(1).pipe(windowCount(1, '2')); // $ExpectError\n});\n"
  },
  {
    "path": "packages/rxjs/spec-dtslint/operators/windowTime-spec.ts",
    "content": "import { of, asyncScheduler } from 'rxjs';\nimport { windowTime } from 'rxjs/operators';\n\nit('should infer correctly', () => {\n  const o = of('a', 'b', 'c').pipe(windowTime(10)); // $ExpectType Observable<Observable<string>>\n  const p = of('a', 'b', 'c').pipe(windowTime(10, asyncScheduler)); // $ExpectType Observable<Observable<string>>\n});\n\nit('should support a windowCreationInterval', () => {\n  const o = of('a', 'b', 'c').pipe(windowTime(10, 30)); // $ExpectType Observable<Observable<string>>\n  const p = of('a', 'b', 'c').pipe(windowTime(10, 30, asyncScheduler)); // $ExpectType Observable<Observable<string>>\n});\n\nit('should support a maxWindowSize', () => {\n  const o = of('a', 'b', 'c').pipe(windowTime(10, 30, 80)); // $ExpectType Observable<Observable<string>>\n  const p = of('a', 'b', 'c').pipe(windowTime(10, 30, 80, asyncScheduler)); // $ExpectType Observable<Observable<string>>\n});\n\nit('should enforce types', () => {\n  const o = of('a', 'b', 'c').pipe(windowTime()); // $ExpectError\n});\n\nit('should enforce windowTimeSpan type', () => {\n  const o = of('a', 'b', 'c').pipe(windowTime('nope')); // $ExpectError\n});\n\nit('should enforce windowCreationInterval type', () => {\n  const o = of('a', 'b', 'c').pipe(windowTime(10, 'nope')); // $ExpectError\n});\n\nit('should enforce maxWindowSize type', () => {\n  const o = of('a', 'b', 'c').pipe(windowTime(10, 30, 'nope')); // $ExpectError\n});\n\nit('should enforce scheduler type', () => {\n  const o = of('a', 'b', 'c').pipe(windowTime(10, 30, 50, 'nope')); // $ExpectError\n});\n"
  },
  {
    "path": "packages/rxjs/spec-dtslint/operators/windowToggle-spec.ts",
    "content": "import { of } from 'rxjs';\nimport { windowToggle } from 'rxjs/operators';\n\nit('should infer correctly', () => {\n  const o = of('a', 'b', 'c').pipe(windowToggle(of(1, 2, 3), () => of({}))); // $ExpectType Observable<Observable<string>>\n});\n\nit('should enforce types', () => {\n  const o = of('a', 'b', 'c').pipe(windowToggle()); // $ExpectError\n});\n\nit('should enforce openings type', () => {\n  const o = of('a', 'b', 'c').pipe(windowToggle('nope')); // $ExpectError\n});\n\nit('should enforce closingSelector type', () => {\n  const o = of('a', 'b', 'c').pipe(windowToggle(of(1, 2, 3), 'nope')); // $ExpectError\n  const p = of('a', 'b', 'c').pipe(windowToggle(of(1, 2, 3), (closingSelector: string) => of(1))); // $ExpectError\n});\n"
  },
  {
    "path": "packages/rxjs/spec-dtslint/operators/windowWhen-spec.ts",
    "content": "import { of } from 'rxjs';\nimport { windowWhen } from 'rxjs/operators';\n\nit('should infer correctly', () => {\n  const o = of('a', 'b', 'c').pipe(windowWhen(() => of(1, 2, 3))); // $ExpectType Observable<Observable<string>>\n});\n\nit('should enforce types', () => {\n  const o = of('a', 'b', 'c').pipe(windowWhen()); // $ExpectError\n});\n\nit('should enforce closingSelector type', () => {\n  const o = of('a', 'b', 'c').pipe(windowWhen('nope')); // $ExpectError\n});\n"
  },
  {
    "path": "packages/rxjs/spec-dtslint/operators/withLatestFrom-spec.ts",
    "content": "import { of } from 'rxjs';\nimport { withLatestFrom } from 'rxjs/operators';\n\ndescribe('withLatestFrom', () => {\n  describe('without project parameter', () => {\n    it('should infer correctly with 1 param', () => {\n      const a = of(1, 2, 3);\n      const b = of('a', 'b', 'c');\n      const res = a.pipe(withLatestFrom(b)); // $ExpectType Observable<[number, string]>\n    });\n\n    it('should infer correctly with 2 params', () => {\n      const a = of(1, 2, 3);\n      const b = of('a', 'b', 'c');\n      const c = of(1, 2, 3);\n      const res = a.pipe(withLatestFrom(b, c)); // $ExpectType Observable<[number, string, number]>\n    });\n\n    it('should infer correctly with 3 params', () => {\n      const a = of(1, 2, 3);\n      const b = of('a', 'b', 'c');\n      const c = of(1, 2, 3);\n      const d = of('g', 'h', 'i');\n      const res = a.pipe(withLatestFrom(b, c, d)); // $ExpectType Observable<[number, string, number, string]>\n    });\n\n    it('should infer correctly with 4 params', () => {\n      const a = of(1, 2, 3);\n      const b = of('a', 'b', 'c');\n      const c = of(1, 2, 3);\n      const d = of('g', 'h', 'i');\n      const e = of(4, 5, 6);\n      const res = a.pipe(withLatestFrom(b, c, d, e)); // $ExpectType Observable<[number, string, number, string, number]>\n    });\n\n    it('should infer correctly with 5 params', () => {\n      const a = of(1, 2, 3);\n      const b = of('a', 'b', 'c');\n      const c = of(1, 2, 3);\n      const d = of('g', 'h', 'i');\n      const e = of(4, 5, 6);\n      const f = of('m', 'n', 'o');\n      const res = a.pipe(withLatestFrom(b, c, d, e, f)); // $ExpectType Observable<[number, string, number, string, number, string]>\n    });\n\n    it('should infer correctly with 6 params', () => {\n      const a = of(1, 2, 3);\n      const b = of('a', 'b', 'c');\n      const c = of(1, 2, 3);\n      const d = of('g', 'h', 'i');\n      const e = of(4, 5, 6);\n      const f = of('m', 'n', 'o');\n      const g = of(7, 8, 9);\n      const res = a.pipe(withLatestFrom(b, c, d, e, f, g)); // $ExpectType Observable<[number, string, number, string, number, string, number]>\n    });\n\n    it('should allow the spreading of input params', () => {\n      const a = of(1, 2, 3);\n      const b = [a, a, a];\n      const res = a.pipe(withLatestFrom(...b)); // $ExpectType Observable<[number, ...number[]]>\n    });\n\n    it('should error with non Observable input', () => {\n      const a = of(1, 2, 3);\n      const b = of('a', 'b', 'c');\n      const c = 1;\n      const d = of('g', 'h', 'i');\n      const res = a.pipe(withLatestFrom(b, c, d)); // $ExpectError\n    });\n\n    it('should error with non Observable input at last position', () => {\n      const a = of(1, 2, 3);\n      const b = 1;\n      const res = a.pipe(withLatestFrom(b)); // $ExpectError\n    });\n  });\n\n  describe('with project parameter', () => {\n    it('should infer correctly with project param', () => {\n      const a = of(1, 2, 3);\n      const res = a.pipe(withLatestFrom(v1 => 'b')); // $ExpectType Observable<string>\n    });\n\n    it('should infer correctly with 1 param', () => {\n      const a = of(1, 2, 3);\n      const b = of('a', 'b', 'c');\n      const res = a.pipe(withLatestFrom(b, (a, b) => b)); // $ExpectType Observable<string>\n    });\n\n    it('should infer correctly with 2 params', () => {\n      const a = of(1, 2, 3);\n      const b = of('a', 'b', 'c');\n      const c = of(1, 2, 3);\n      const res = a.pipe(withLatestFrom(b, c, (a, b, c) => c)); // $ExpectType Observable<number>\n    });\n\n    it('should infer correctly with 3 params', () => {\n      const a = of(1, 2, 3);\n      const b = of('a', 'b', 'c');\n      const c = of(1, 2, 3);\n      const d = of('g', 'h', 'i');\n      const ref = a.pipe(withLatestFrom(b, c, d, (a, b, c, d) => b + c)); // $ExpectType Observable<string>\n    });\n\n    it('should infer correctly with 4 params', () => {\n      const a = of(1, 2, 3);\n      const b = of('a', 'b', 'c');\n      const c = of(1, 2, 3);\n      const d = of('g', 'h', 'i');\n      const e = of(4, 5, 6);\n      const res = a.pipe(withLatestFrom(b, c, d, e, (a, b, c, d, e) => b + c)); // $ExpectType Observable<string>\n    });\n\n    it('should infer correctly with 5 params', () => {\n      const a = of(1, 2, 3);\n      const b = of('a', 'b', 'c');\n      const c = of(1, 2, 3);\n      const d = of('g', 'h', 'i');\n      const e = of(4, 5, 6);\n      const f = of('m', 'n', 'o');\n      const res = a.pipe(withLatestFrom(b, c, d, e, f, (a, b, c, d, e, f) => c + e)); // $ExpectType Observable<number>\n    });\n\n    it('should infer correctly with 6 params', () => {\n      const a = of(1, 2, 3);\n      const b = of('a', 'b', 'c');\n      const c = of(1, 2, 3);\n      const d = of('g', 'h', 'i');\n      const e = of(4, 5, 6);\n      const f = of('m', 'n', 'o');\n      const g = of(7, 8, 9);\n      const res = a.pipe(withLatestFrom(b, c, d, e, f, g, (a, b, c, d, e, f, g) => b + f)); // $ExpectType Observable<string>\n    });\n\n    it('should error with non Observable input', () => {\n      const a = of(1, 2, 3);\n      const b = of('a', 'b', 'c');\n      const c = 1;\n      const d = of('g', 'h', 'i');\n      const res = a.pipe(withLatestFrom(b, c, d, (a, b, c, d) => a + d)); // $ExpectError\n    });\n\n    it('should error with non Observable input at last position', () => {\n      const a = of(1, 2, 3);\n      const b = 1;\n      const res = a.pipe(withLatestFrom(b, (a, b) => a + b)); // $ExpectError\n    });\n\n    it('should error with incorrect number of projected params', () => {\n      const a = of(1, 2, 3);\n      const b = of('a', 'b', 'c');\n      const res = a.pipe(withLatestFrom(b, (a, b, c) => a)); // $ExpectError\n    });\n\n    /*\n     * The following test does not typecheck because the project function is missing a third parameter.\n     * If such an issue occurs in a consumer code base the fix is to specify the missing parameters.\n     * \n     * It looks like this is a TS bug.\n     */\n    // it('should infer correct parameters with fewer arguments to project function', () => {\n    //   const a = of(1, 2, 3);\n    //   const b = of('a', 'b', 'c');\n    //   const c = of(1, 2, 3);\n    //   const res = a.pipe(withLatestFrom(b, c, (a, b) => b)); // $ExpectType Observable<string>\n    // });\n  });\n});\n"
  },
  {
    "path": "packages/rxjs/spec-dtslint/operators/zipAll-spec.ts",
    "content": "import { of } from 'rxjs';\nimport { zipAll } from 'rxjs/operators';\n\nit('should infer correctly', () => {\n  const o = of(of(1, 2, 3)).pipe(zipAll()); // $ExpectType Observable<number[]>\n});\n\nit('should support projecting values', () => {\n  const o = of(of(1, 2, 3)).pipe(zipAll(value => String(value))); // $ExpectType Observable<string>\n});\n\nit('should be accept projectors for observables with different types', () => {\n  // An `any` signature is required for the projector to deal with situations\n  // like this in which the source emits observables of different types. The\n  // types of the values passed to the projector depend on the order in which\n  // the source emits its observables and that can't be expressed in the type\n  // system.\n  const o = of(of(['a', 'b', 'c']), of([1, 2, 3])).pipe(zipAll((a: string, b: number) => a + b)); // $ExpectType Observable<string>\n});\n\nit('should enforce types', () => {\n  const o = of(1, 2, 3).pipe(zipAll()); // $ExpectError\n});\n\nit('should enforce projector types', () => {\n  const o = of(of(1, 2, 3)).pipe(zipAll('foo')); // $ExpectError\n  const p = of(of(1, 2, 3)).pipe(zipAll([4, 5, 6])); // $ExpectError\n  const q = of(of(1, 2, 3)).pipe(zipAll(Promise.resolve(4))); // $ExpectError\n  const r = of(of(1, 2, 3)).pipe(zipAll(of(4, 5, 6))); // $ExpectError\n\n  const myIterator: Iterator<number | undefined> = {\n    next(value) {\n      return {done: false, value};\n    },\n  };\n  const s = of(of(1, 2, 3)).pipe(zipAll(myIterator)); // $ExpectError\n});\n\nit('should still zip Observable<string>, because strings are iterables (GOTCHA)', () => {\n  const o = of('test').pipe(zipAll()); // $ExpectType Observable<string[]>\n});\n"
  },
  {
    "path": "packages/rxjs/spec-dtslint/operators/zipWith-spec.ts",
    "content": "import { of } from 'rxjs';\nimport { zipWith } from 'rxjs/operators';\n\ndescribe('zipWith', () => {\n  describe('without project parameter', () => {\n    it('should infer correctly with 1 param', () => {\n      const a = of(1, 2, 3);\n      const b = of('a', 'b', 'c');\n      const res = a.pipe(zipWith(b)); // $ExpectType Observable<[number, string]>\n    });\n\n    it('should infer correctly with 2 params', () => {\n      const a = of(1, 2, 3);\n      const b = of('a', 'b', 'c');\n      const c = of('d', 'e', 'f');\n      const res = a.pipe(zipWith(b, c)); // $ExpectType Observable<[number, string, string]>\n    });\n\n    it('should infer correctly with 3 params', () => {\n      const a = of(1, 2, 3);\n      const b = of('a', 'b', 'c');\n      const c = of('d', 'e', 'f');\n      const d = of('g', 'h', 'i');\n      const res = a.pipe(zipWith(b, c, d)); // $ExpectType Observable<[number, string, string, string]>\n    });\n\n    it('should infer correctly with 4 params', () => {\n      const a = of(1, 2, 3);\n      const b = of('a', 'b', 'c');\n      const c = of('d', 'e', 'f');\n      const d = of('g', 'h', 'i');\n      const e = of('j', 'k', 'l');\n      const res = a.pipe(zipWith(b, c, d, e)); // $ExpectType Observable<[number, string, string, string, string]>\n    });\n\n    it('should infer correctly with 5 params', () => {\n      const a = of(1, 2, 3);\n      const b = of('a', 'b', 'c');\n      const c = of('d', 'e', 'f');\n      const d = of('g', 'h', 'i');\n      const e = of('j', 'k', 'l');\n      const f = of('m', 'n', 'o');\n      const res = a.pipe(zipWith(b, c, d, e, f)); // $ExpectType Observable<[number, string, string, string, string, string]>\n    });\n\n    it('should accept N params', () => {\n      const a = of(1, 2, 3);\n      const b = of('a', 'b', 'c');\n      const c = of('d', 'e', 'f');\n      const d = of('g', 'h', 'i');\n      const e = of('j', 'k', 'l');\n      const f = of('m', 'n', 'o');\n      const g = of('p', 'q', 'r');\n      const res = a.pipe(zipWith(b, c, d, e, f, g)); // $ExpectType Observable<[number, string, string, string, string, string, string]>\n    });\n  });\n});\n"
  },
  {
    "path": "packages/rxjs/spec-dtslint/tsconfig.json",
    "content": "{\n  \"compilerOptions\": {\n    \"baseUrl\": \".\",\n    \"lib\": [\"esnext\", \"dom\"],\n    \"module\": \"commonjs\",\n    \"noEmit\": true,\n    \"paths\": {\n      \"rxjs\": [\"../dist/types\"],\n      \"rxjs/ajax\": [\"../dist/types/ajax\"],\n      \"rxjs/fetch\": [\"../dist/types/fetch\"],\n      \"rxjs/operators\": [\"../dist/types/operators\"],\n      \"rxjs/testing\": [\"../dist/types/testing\"],\n      \"rxjs/webSocket\": [\"../dist/types/webSocket\"]\n    },\n    \"skipLibCheck\": true,\n    \"strict\": true,\n    \"target\": \"esnext\"\n  }\n}"
  },
  {
    "path": "packages/rxjs/spec-dtslint/types-spec.ts",
    "content": "import type {\n  Observable,\n  ObservedValueOf,\n  ObservedValueUnionFromArray,\n  ObservedValueTupleFromArray,\n  Cons,\n  Head,\n  Tail\n} from 'rxjs';\nimport type { A, B, C } from './helpers';\n\ndescribe('ObservedValueOf', () => {\n  it('should infer from an observable', () => {\n    let explicit: ObservedValueOf<Observable<A>>;\n    const inferred = explicit!; // $ExpectType A\n  });\n\n  it('should infer from an array', () => {\n    let explicit: ObservedValueOf<A[]>;\n    const inferred = explicit!; // $ExpectType A\n  });\n\n  it('should infer from a promise', () => {\n    let explicit: ObservedValueOf<Promise<A>>;\n    const inferred = explicit!; // $ExpectType A\n  });\n});\n\ndescribe('ObservedUnionFromArray', () => {\n  it('should infer from an array of observables', () => {\n    let explicit: ObservedValueUnionFromArray<[Observable<A>, Observable<B>]>;\n    const inferred = explicit!; // $ExpectType A | B\n  });\n\n  it('should infer from an array of arrays', () => {\n    let explicit: ObservedValueUnionFromArray<[A[], B[]]>;\n    const inferred = explicit!; // $ExpectType A | B\n  });\n\n  it('should infer from an array of promises', () => {\n    let explicit: ObservedValueUnionFromArray<[Promise<A>, Promise<B>]>;\n    const inferred = explicit!; // $ExpectType A | B\n  });\n});\n\ndescribe('ObservedTupleFromArray', () => {\n  it('should infer from an array of observables', () => {\n    let explicit: ObservedValueTupleFromArray<[Observable<A>, Observable<B>]>;\n    const inferred = explicit!; // $ExpectType [A, B]\n  });\n\n  it('should infer from an array of arrays', () => {\n    let explicit: ObservedValueTupleFromArray<[A[], B[]]>;\n    const inferred = explicit!; // $ExpectType [A, B]\n  });\n\n  it('should infer from an array of promises', () => {\n    let explicit: ObservedValueTupleFromArray<[Promise<A>, Promise<B>]>;\n    const inferred = explicit!; // $ExpectType [A, B]\n  });\n});\n\ndescribe('Cons', () => {\n  it('should construct a tuple with the specified type at the head', () => {\n    let explicit: Cons<A, [B, C]>;\n    const inferred = explicit!; // $ExpectType [A, B, C]\n  });\n\n  it('should support rest tuples', () => {\n    let explicit: Cons<A, B[]>;\n    const inferred = explicit!; // $ExpectType [arg: A, ...rest: B[]]\n  });\n});\n\ndescribe('Head', () => {\n  it('should return the head of a tuple', () => {\n    let explicit: Head<[A, B, C]>;\n    const inferred = explicit!; // $ExpectType A\n  });\n});\n\ndescribe('Tail', () => {\n  it('should return the tail of a tuple', () => {\n    let explicit: Tail<[A, B, C]>;\n    const inferred = explicit!; // $ExpectType [B, C]\n  });\n});\n"
  },
  {
    "path": "packages/rxjs/spec-dtslint/util/pipe-spec.ts",
    "content": "import type { UnaryFunction, Observable } from 'rxjs';\nimport { pipe, of } from 'rxjs';\n\n/**\n * Used to keep the tests uncluttered.\n *\n * Returns a `UnaryFunction` with the\n * specified literal type parameters.\n * That is, `a('0', '1')` returns `UnaryFunction<'0', '1'>`.\n * That means that the `a` function can be used to create consecutive\n * arguments that are either compatible or incompatible.\n *\n * ```js\n * a('0', '1'), a('1', '2') // OK\n * a('0', '1'), a('#', '2') // Error '1' is not compatible with '#'\n * ```\n *\n * @param {string} input The `UnaryFunction` input type parameter\n * @param {string} output The `UnaryFunction` output type parameter\n */\nfunction a<I extends string, O extends string>(input: I, output: O): UnaryFunction<I, O> {\n  return i => output;\n}\n\nit('should infer unknown for no arguments', () => {\n  const o = pipe(); // $ExpectType <T>(x: T) => T\n});\n\nit('should infer for 1 argument', () => {\n  const o = pipe(a('0', '1')); // $ExpectType UnaryFunction<\"0\", \"1\">\n});\n\nit('should infer for 2 arguments', () => {\n  const o = pipe(a('0', '1'), a('1', '2')); // $ExpectType UnaryFunction<\"0\", \"2\">\n});\n\nit('should infer for 3 arguments', () => {\n  const o = pipe(a('0', '1'), a('1', '2'), a('2', '3')); // $ExpectType UnaryFunction<\"0\", \"3\">\n});\n\nit('should infer for 4 arguments', () => {\n  const o = pipe(a('0', '1'), a('1', '2'), a('2', '3'), a('3', '4')); // $ExpectType UnaryFunction<\"0\", \"4\">\n});\n\nit('should infer for 5 arguments', () => {\n  const o = pipe(a('0', '1'), a('1', '2'), a('2', '3'), a('3', '4'), a('4', '5')); // $ExpectType UnaryFunction<\"0\", \"5\">\n});\n\nit('should infer for 6 arguments', () => {\n  const o = pipe(a('0', '1'), a('1', '2'), a('2', '3'), a('3', '4'), a('4', '5'), a('5', '6')); // $ExpectType UnaryFunction<\"0\", \"6\">\n});\n\nit('should infer for 7 arguments', () => {\n  const o = pipe(a('0', '1'), a('1', '2'), a('2', '3'), a('3', '4'), a('4', '5'), a('5', '6'), a('6', '7')); // $ExpectType UnaryFunction<\"0\", \"7\">\n});\n\nit('should infer for 8 arguments', () => {\n  const o = pipe(a('0', '1'), a('1', '2'), a('2', '3'), a('3', '4'), a('4', '5'), a('5', '6'), a('6', '7'), a('7', '8')); // $ExpectType UnaryFunction<\"0\", \"8\">\n});\n\nit('should infer for 9 arguments', () => {\n  const o = pipe(a('0', '1'), a('1', '2'), a('2', '3'), a('3', '4'), a('4', '5'), a('5', '6'), a('6', '7'), a('7', '8'), a('8', '9')); // $ExpectType UnaryFunction<\"0\", \"9\">\n});\n\nit('should infer unknown for more than 9 arguments', () => {\n  const o =  pipe(a('0', '1'), a('1', '2'), a('2', '3'), a('3', '4'), a('4', '5'), a('5', '6'), a('6', '7'), a('7', '8'), a('8', '9'), a('9', '10'));  // $ExpectType UnaryFunction<\"0\", unknown>\n});\n\nit('should require a type assertion for more than 9 arguments', () => {\n  const o: UnaryFunction<'0', '10'> = pipe(a('0', '1'), a('1', '2'), a('2', '3'), a('3', '4'), a('4', '5'), a('5', '6'), a('6', '7'), a('7', '8'), a('8', '9'), a('9', '10')); // $ExpectError\n});\n\nit('should enforce types for the 2nd argument', () => {\n  const o = pipe(a('0', '1'), a('#', '2')); // $ExpectError\n});\n\nit('should enforce types for the 3rd argument', () => {\n  const o = pipe(a('0', '1'), a('1', '2'), a('#', '3')); // $ExpectError\n});\n\nit('should enforce types for the 4th argument', () => {\n  const o = pipe(a('0', '1'), a('1', '2'), a('2', '3'), a('#', '4')); // $ExpectError\n});\n\nit('should enforce types for the 5th argument', () => {\n  const o = pipe(a('0', '1'), a('1', '2'), a('2', '3'), a('3', '4'), a('#', '5')); // $ExpectError\n});\n\nit('should enforce types for the 6th argument', () => {\n  const o = pipe(a('0', '1'), a('1', '2'), a('2', '3'), a('3', '4'), a('4', '5'), a('#', '6')); // $ExpectError\n});\n\nit('should enforce types for the 7th argument', () => {\n  const o = pipe(a('0', '1'), a('1', '2'), a('2', '3'), a('3', '4'), a('4', '5'), a('5', '6'), a('#', '7')); // $ExpectError\n});\n\nit('should enforce types for the 8th argument', () => {\n  const o = pipe(a('0', '1'), a('1', '2'), a('2', '3'), a('3', '4'), a('4', '5'), a('5', '6'), a('6', '7'), a('#', '8')); // $ExpectError\n});\n\nit('should enforce types for the 9th argument', () => {\n  const o = pipe(a('0', '1'), a('1', '2'), a('2', '3'), a('3', '4'), a('4', '5'), a('5', '6'), a('6', '7'), a('7', '8'), a('#', '9')); // $ExpectError\n});\n\nit('should return a non-narrowed Observable type', () => {\n  const customOperator = <T>(p: T) => (a: Observable<T>) => a;\n\n  const staticPipe = pipe(customOperator('infer'));\n  const o = of('foo').pipe(staticPipe); // $ExpectType Observable<string>\n});\n\nit('should return an explicit Observable type', () => {\n  const customOperator = <T>() => (a: Observable<T>) => a;\n\n  const staticPipe = pipe(customOperator<string>());\n  const o = of('foo').pipe(staticPipe); // $ExpectType Observable<string>\n});\n\nit('should return Observable<unknown> when T cannot be inferred', () => {\n  const customOperator = <T>() => (a: Observable<T>) => a;\n\n  // type can't be possibly be inferred here\n  const staticPipe = pipe(customOperator());\n  const o = of('foo').pipe(staticPipe); // $ExpectType Observable<unknown>\n});\n\nit('should return a non-narrowed type', () => {\n  const func = pipe((value: string) => value, (value: string) => value + value);\n  const value = func('foo'); // $ExpectType string\n});\n"
  },
  {
    "path": "packages/rxjs/spec-dtslint/util/rx-spec.ts",
    "content": "import { rx, map, of, toArray, filter } from 'rxjs';\nimport { A, B, C, D, E, F, G, H, I, J } from '../helpers'\n\nit('should infer conversions from ObservableInputs', () => {\n  const o1 = rx([1, 2, 3]); // $ExpectType Observable<number>\n  const o2 = rx(new Set<number>()); // $ExpectType Observable<number>\n  const o3 = rx(new Map<string, number>()); // $ExpectType Observable<[string, number]>\n  const o4 = rx(of(1, 2, 3)); // $ExpectType Observable<number>\n  const o5 = rx(Promise.resolve(1)); // $ExpectType Observable<number>\n  const o6 = rx(Promise.resolve([1, 2, 3])); // $ExpectType Observable<number[]>\n\n  function* test() {\n    yield 1;\n    yield 2;\n    yield 3;\n  }\n\n  const o7 = rx(test()); // $ExpectType Observable<1 | 2 | 3>\n  \n  async function* test2() {\n    yield 1;\n    yield 2;\n    yield 3;\n  }\n\n  const o8 = rx(test2()); // $ExpectType Observable<1 | 2 | 3>\n  const o9 = rx({}); // $ExpectError\n});\n\nit('should compose with pipeable functions, passing an Observable to the first of those functions', () => {\n  const o1 = rx([1, 2, 3], map(n => n + 1)); // $ExpectType Observable<number>\n  const o2 = rx([1, 2, 3], map(n => n + 1), filter(n => n < 3)); // $ExpectType Observable<number>\n  const o3 = rx([1, 2, 3], map(n => n + 1), filter(n => n < 3), toArray()); // $ExpectType Observable<number[]>\n  const o4 = rx([1, 2, 3], map(n => n + 1), filter(n => n < 3), toArray(), map(n => n.length)); // $ExpectType Observable<number>\n\n  // Even with unary functions that are not RxJS operators\n  const o5 = rx([1, 2, 3], map(n => n + 1), toArray(), source => Object.keys(source), keys => keys.length); // $ExpectType number\n  \n  // Maybe as a means of subscription\n  const o6 = rx([1, 2, 3], map(n => n + 1), toArray(), source => source.subscribe()); // $ExpectType Subscription\n})\n\n\nit('should handle a large number of unary functions appropriately', () => {\n  const r0 = rx([1, 2, 3]); // $ExpectType Observable<number>\n  const r1 = rx([1, 2, 3], () => new A()); // $ExpectType A\n  const r2 = rx([1, 2, 3], () => new A(), () => new B()); // $ExpectType B\n  const r3 = rx([1, 2, 3], () => new A(), () => new B(), () => new C()); // $ExpectType C\n  const r4 = rx([1, 2, 3], () => new A(), () => new B(), () => new C(), () => new D()); // $ExpectType D\n  const r5 = rx([1, 2, 3], () => new A(), () => new B(), () => new C(), () => new D(), () => new E()); // $ExpectType E\n  const r6 = rx([1, 2, 3], () => new A(), () => new B(), () => new C(), () => new D(), () => new E(), () => new F()); // $ExpectType F\n  const r7 = rx([1, 2, 3], () => new A(), () => new B(), () => new C(), () => new D(), () => new E(), () => new F(), () => new G()); // $ExpectType G\n  const r8 = rx([1, 2, 3], () => new A(), () => new B(), () => new C(), () => new D(), () => new E(), () => new F(), () => new G(), () => new H()); // $ExpectType H\n  const r9 = rx([1, 2, 3], () => new A(), () => new B(), () => new C(), () => new D(), () => new E(), () => new F(), () => new G(), () => new H(), () => new I()); // $ExpectType unknown\n  const r10 = rx([1, 2, 3], () => new A(), () => new B(), () => new C(), () => new D(), () => new E(), () => new F(), () => new G(), () => new H(), () => new I(), () => new J()); // $ExpectType unknown\n})"
  },
  {
    "path": "packages/rxjs/src/Rx.global.js",
    "content": "(function (root, factory) {\n  root.Rx = factory();\n})(window || global || this, function () {\n  return require('../dist/package/Rx');\n});"
  },
  {
    "path": "packages/rxjs/src/ajax/index.ts",
    "content": "export { ajax } from '../internal/ajax/ajax.js';\nexport { AjaxError, AjaxTimeoutError } from '../internal/ajax/errors.js';\nexport { AjaxResponse } from '../internal/ajax/AjaxResponse.js';\nexport type { AjaxRequest, AjaxConfig, AjaxDirection } from '../internal/ajax/types.js';\n"
  },
  {
    "path": "packages/rxjs/src/fetch/index.ts",
    "content": "export { fromFetch } from '../internal/observable/dom/fetch.js';\n"
  },
  {
    "path": "packages/rxjs/src/index.ts",
    "content": "//////////////////////////////////////////////////////////\n// Here we need to reference our other deep imports\n// so VS code will figure out where they are\n// see conversation here:\n// https://github.com/microsoft/TypeScript/issues/43034\n//////////////////////////////////////////////////////////\n\n/* eslint-disable @typescript-eslint/triple-slash-reference */\n// It's tempting to add references to all of the deep-import locations, but\n// adding references to those that require DOM types breaks Node projects.\n/// <reference path=\"./operators/index.ts\" />\n/// <reference path=\"./testing/index.ts\" />\n/* eslint-enable @typescript-eslint/triple-slash-reference */\n\n/* Re-export from @rxjs/observable */\nexport type { GlobalConfig, SubscriberOverrides } from '@rxjs/observable';\nexport { Observable, from, config, Subscription, Subscriber, operate, UnsubscriptionError, isObservable } from '@rxjs/observable';\n\n/* Observables */\nexport type { GroupedObservable } from './internal/operators/groupBy.js';\nexport type { Operator } from './internal/Operator.js';\nexport { animationFrames } from './internal/observable/dom/animationFrames.js';\n\n/* Subjects */\nexport { Subject } from './internal/Subject.js';\nexport { BehaviorSubject } from './internal/BehaviorSubject.js';\nexport { ReplaySubject } from './internal/ReplaySubject.js';\nexport { AsyncSubject } from './internal/AsyncSubject.js';\n\n/* Schedulers */\nexport { asapScheduler } from './internal/scheduler/asap.js';\nexport { asyncScheduler } from './internal/scheduler/async.js';\nexport { queueScheduler } from './internal/scheduler/queue.js';\nexport { animationFrameScheduler } from './internal/scheduler/animationFrame.js';\nexport { VirtualTimeScheduler, VirtualAction } from './internal/scheduler/VirtualTimeScheduler.js';\nexport { Scheduler } from './internal/Scheduler.js';\n\n/* Utils */\nexport { rx } from './internal/util/rx.js';\nexport { pipe } from './internal/util/pipe.js';\nexport { noop } from './internal/util/noop.js';\nexport { identity } from './internal/util/identity.js';\n\n/* Promise Conversion */\nexport { lastValueFrom } from './internal/lastValueFrom.js';\nexport { firstValueFrom } from './internal/firstValueFrom.js';\n\n/* Error types */\nexport { ArgumentOutOfRangeError } from './internal/util/ArgumentOutOfRangeError.js';\nexport { EmptyError } from './internal/util/EmptyError.js';\nexport { NotFoundError } from './internal/util/NotFoundError.js';\nexport { SequenceError } from './internal/util/SequenceError.js';\nexport { TimeoutError } from './internal/operators/timeout.js';\n\n/* Static observable creation exports */\nexport { bindCallback } from './internal/observable/bindCallback.js';\nexport { bindNodeCallback } from './internal/observable/bindNodeCallback.js';\nexport { combineLatest } from './internal/observable/combineLatest.js';\nexport { concat } from './internal/observable/concat.js';\nexport { connectable } from './internal/observable/connectable.js';\nexport { defer } from './internal/observable/defer.js';\nexport { forkJoin } from './internal/observable/forkJoin.js';\nexport { fromEvent } from './internal/observable/fromEvent.js';\nexport { fromEventPattern } from './internal/observable/fromEventPattern.js';\nexport { generate } from './internal/observable/generate.js';\nexport { iif } from './internal/observable/iif.js';\nexport { interval } from './internal/observable/interval.js';\nexport { merge } from './internal/observable/merge.js';\nexport { of } from './internal/observable/of.js';\nexport { onErrorResumeNext } from './internal/observable/onErrorResumeNext.js';\nexport { partition } from './internal/observable/partition.js';\nexport { race } from './internal/observable/race.js';\nexport { range } from './internal/observable/range.js';\nexport { throwError } from './internal/observable/throwError.js';\nexport { timer } from './internal/observable/timer.js';\nexport { using } from './internal/observable/using.js';\nexport { zip } from './internal/observable/zip.js';\nexport { scheduled } from './internal/scheduled/scheduled.js';\n\n/* Constants */\nexport { EMPTY } from './internal/observable/empty.js';\nexport { NEVER } from './internal/observable/never.js';\n\n/* Types */\nexport * from './internal/types.js';\n\n/* Operators */\nexport { audit } from './internal/operators/audit.js';\nexport { auditTime } from './internal/operators/auditTime.js';\nexport { buffer } from './internal/operators/buffer.js';\nexport { bufferCount } from './internal/operators/bufferCount.js';\nexport { bufferTime } from './internal/operators/bufferTime.js';\nexport { bufferToggle } from './internal/operators/bufferToggle.js';\nexport { bufferWhen } from './internal/operators/bufferWhen.js';\nexport { catchError } from './internal/operators/catchError.js';\nexport { combineLatestAll } from './internal/operators/combineLatestAll.js';\nexport { combineLatestWith } from './internal/operators/combineLatestWith.js';\nexport { concatAll } from './internal/operators/concatAll.js';\nexport { concatMap } from './internal/operators/concatMap.js';\nexport { concatMapTo } from './internal/operators/concatMapTo.js';\nexport { concatWith } from './internal/operators/concatWith.js';\nexport type { ConnectConfig } from './internal/operators/connect.js';\nexport { connect } from './internal/operators/connect.js';\nexport { count } from './internal/operators/count.js';\nexport { debounce } from './internal/operators/debounce.js';\nexport { debounceTime } from './internal/operators/debounceTime.js';\nexport { defaultIfEmpty } from './internal/operators/defaultIfEmpty.js';\nexport { delay } from './internal/operators/delay.js';\nexport { delayWhen } from './internal/operators/delayWhen.js';\nexport { dematerialize } from './internal/operators/dematerialize.js';\nexport { distinct } from './internal/operators/distinct.js';\nexport { distinctUntilChanged } from './internal/operators/distinctUntilChanged.js';\nexport { distinctUntilKeyChanged } from './internal/operators/distinctUntilKeyChanged.js';\nexport { elementAt } from './internal/operators/elementAt.js';\nexport { endWith } from './internal/operators/endWith.js';\nexport { every } from './internal/operators/every.js';\nexport { exhaustAll } from './internal/operators/exhaustAll.js';\nexport { exhaustMap } from './internal/operators/exhaustMap.js';\nexport { expand } from './internal/operators/expand.js';\nexport { filter } from './internal/operators/filter.js';\nexport { finalize } from './internal/operators/finalize.js';\nexport { find } from './internal/operators/find.js';\nexport { findIndex } from './internal/operators/findIndex.js';\nexport { first } from './internal/operators/first.js';\nexport type { BasicGroupByOptions, GroupByOptionsWithElement } from './internal/operators/groupBy.js';\nexport { groupBy } from './internal/operators/groupBy.js';\nexport { ignoreElements } from './internal/operators/ignoreElements.js';\nexport { isEmpty } from './internal/operators/isEmpty.js';\nexport { last } from './internal/operators/last.js';\nexport { map } from './internal/operators/map.js';\nexport { mapTo } from './internal/operators/mapTo.js';\nexport { materialize } from './internal/operators/materialize.js';\nexport { max } from './internal/operators/max.js';\nexport { mergeAll } from './internal/operators/mergeAll.js';\nexport { mergeMap } from './internal/operators/mergeMap.js';\nexport { mergeMapTo } from './internal/operators/mergeMapTo.js';\nexport { mergeScan } from './internal/operators/mergeScan.js';\nexport { mergeWith } from './internal/operators/mergeWith.js';\nexport { min } from './internal/operators/min.js';\nexport { observeOn } from './internal/operators/observeOn.js';\nexport { onErrorResumeNextWith } from './internal/operators/onErrorResumeNextWith.js';\nexport { pairwise } from './internal/operators/pairwise.js';\nexport { raceWith } from './internal/operators/raceWith.js';\nexport { reduce } from './internal/operators/reduce.js';\nexport type { RepeatConfig } from './internal/operators/repeat.js';\nexport { repeat } from './internal/operators/repeat.js';\nexport { repeatWhen } from './internal/operators/repeatWhen.js';\nexport type { RetryConfig } from './internal/operators/retry.js';\nexport { retry } from './internal/operators/retry.js';\nexport { retryWhen } from './internal/operators/retryWhen.js';\nexport { sample } from './internal/operators/sample.js';\nexport { sampleTime } from './internal/operators/sampleTime.js';\nexport { scan } from './internal/operators/scan.js';\nexport { sequenceEqual } from './internal/operators/sequenceEqual.js';\nexport type { ShareConfig } from './internal/operators/share.js';\nexport { share } from './internal/operators/share.js';\nexport type { ShareReplayConfig } from './internal/operators/shareReplay.js';\nexport { shareReplay } from './internal/operators/shareReplay.js';\nexport { single } from './internal/operators/single.js';\nexport { skip } from './internal/operators/skip.js';\nexport { skipLast } from './internal/operators/skipLast.js';\nexport { skipUntil } from './internal/operators/skipUntil.js';\nexport { skipWhile } from './internal/operators/skipWhile.js';\nexport { startWith } from './internal/operators/startWith.js';\nexport { subscribeOn } from './internal/operators/subscribeOn.js';\nexport { switchAll } from './internal/operators/switchAll.js';\nexport { switchMap } from './internal/operators/switchMap.js';\nexport { switchMapTo } from './internal/operators/switchMapTo.js';\nexport { switchScan } from './internal/operators/switchScan.js';\nexport { take } from './internal/operators/take.js';\nexport { takeLast } from './internal/operators/takeLast.js';\nexport { takeUntil } from './internal/operators/takeUntil.js';\nexport { takeWhile } from './internal/operators/takeWhile.js';\nexport type { TapObserver } from './internal/operators/tap.js';\nexport { tap } from './internal/operators/tap.js';\nexport type { ThrottleConfig } from './internal/operators/throttle.js';\nexport { throttle } from './internal/operators/throttle.js';\nexport { throttleTime } from './internal/operators/throttleTime.js';\nexport { throwIfEmpty } from './internal/operators/throwIfEmpty.js';\nexport { timeInterval } from './internal/operators/timeInterval.js';\nexport type { TimeoutConfig, TimeoutInfo } from './internal/operators/timeout.js';\nexport { timeout } from './internal/operators/timeout.js';\nexport { timeoutWith } from './internal/operators/timeoutWith.js';\nexport { timestamp } from './internal/operators/timestamp.js';\nexport { toArray } from './internal/operators/toArray.js';\nexport { window } from './internal/operators/window.js';\nexport { windowCount } from './internal/operators/windowCount.js';\nexport { windowTime } from './internal/operators/windowTime.js';\nexport { windowToggle } from './internal/operators/windowToggle.js';\nexport { windowWhen } from './internal/operators/windowWhen.js';\nexport { withLatestFrom } from './internal/operators/withLatestFrom.js';\nexport { zipAll } from './internal/operators/zipAll.js';\nexport { zipWith } from './internal/operators/zipWith.js';\n"
  },
  {
    "path": "packages/rxjs/src/internal/AnyCatcher.ts",
    "content": "/*\n * Note that we cannot apply the `internal` tag here because the declaration\n * needs to survive the `stripInternal` option. Otherwise, `AnyCatcher` will\n * be `any` in the `.d.ts` files.\n */\ndeclare const anyCatcherSymbol: unique symbol;\n\n/**\n * This is just a type that we're using to identify `any` being passed to\n * function overloads. This is used because of situations like {@link forkJoin},\n * where it could return an `Observable<T[]>` or an `Observable<{ [key: K]: T }>`,\n * so `forkJoin(any)` would mean we need to return `Observable<unknown>`.\n */\nexport type AnyCatcher = typeof anyCatcherSymbol;\n"
  },
  {
    "path": "packages/rxjs/src/internal/AsyncSubject.ts",
    "content": "import { Subject } from './Subject.js';\nimport type { Subscriber } from '@rxjs/observable';\n\n/**\n * A variant of Subject that only emits a value when it completes. It will emit\n * its latest value to all its observers on completion.\n */\nexport class AsyncSubject<T> extends Subject<T> {\n  private _value: T | null = null;\n  private _hasValue = false;\n  private _isComplete = false;\n\n  /** @internal */\n  protected _checkFinalizedStatuses(subscriber: Subscriber<T>) {\n    const { hasError, _hasValue, _value, thrownError, _closed, _isComplete } = this;\n    if (hasError) {\n      subscriber.error(thrownError);\n    } else if (_closed || _isComplete) {\n      _hasValue && subscriber.next(_value!);\n      subscriber.complete();\n    }\n  }\n\n  next(value: T): void {\n    if (!this._closed) {\n      this._value = value;\n      this._hasValue = true;\n    }\n  }\n\n  complete(): void {\n    const { _hasValue, _value, _isComplete } = this;\n    if (!_isComplete) {\n      this._isComplete = true;\n      _hasValue && super.next(_value!);\n      super.complete();\n    }\n  }\n}\n"
  },
  {
    "path": "packages/rxjs/src/internal/BehaviorSubject.ts",
    "content": "import { Subject } from './Subject.js';\nimport type { Subscriber, Subscription } from '@rxjs/observable';\n\n/**\n * A variant of Subject that requires an initial value and emits its current\n * value whenever it is subscribed to.\n */\nexport class BehaviorSubject<T> extends Subject<T> {\n  constructor(private _value: T) {\n    super();\n  }\n\n  get value(): T {\n    return this.getValue();\n  }\n\n  /** @internal */\n  protected _subscribe(subscriber: Subscriber<T>): Subscription {\n    const subscription = super._subscribe(subscriber);\n    !subscription.closed && subscriber.next(this._value);\n    return subscription;\n  }\n\n  getValue(): T {\n    const { hasError, thrownError, _value } = this;\n    if (hasError) {\n      throw thrownError;\n    }\n    return _value;\n  }\n\n  next(value: T): void {\n    super.next((this._value = value));\n  }\n}\n"
  },
  {
    "path": "packages/rxjs/src/internal/Notification.ts",
    "content": "import type { PartialObserver, ObservableNotification } from './types.js';\n\n/**\n * Executes the appropriate handler on a passed `observer` given the `kind` of notification.\n * If the handler is missing it will do nothing. Even if the notification is an error, if\n * there is no error handler on the observer, an error will not be thrown, it will noop.\n * @param notification The notification object to observe.\n * @param observer The observer to notify.\n */\nexport function observeNotification<T>(notification: ObservableNotification<T>, observer: PartialObserver<T>) {\n  const { kind, value, error } = notification as any;\n  if (typeof kind !== 'string') {\n    throw new TypeError('Invalid notification, missing \"kind\"');\n  }\n  kind === 'N' ? observer.next?.(value!) : kind === 'E' ? observer.error?.(error) : observer.complete?.();\n}\n"
  },
  {
    "path": "packages/rxjs/src/internal/Operator.ts",
    "content": "import type { Subscriber } from '@rxjs/observable';\nimport type { TeardownLogic } from './types.js';\n\n/***\n * @deprecated Internal implementation detail, do not use directly. Will be made internal in v8.\n */\nexport interface Operator<T, R> {\n  call(subscriber: Subscriber<R>, source: any): TeardownLogic;\n}\n"
  },
  {
    "path": "packages/rxjs/src/internal/ReplaySubject.ts",
    "content": "import { Subject } from './Subject.js';\nimport type { TimestampProvider } from './types.js';\nimport type { Subscriber, Subscription } from '@rxjs/observable';\nimport { dateTimestampProvider } from './scheduler/dateTimestampProvider.js';\n\n/**\n * A variant of {@link Subject} that \"replays\" old values to new subscribers by emitting them when they first subscribe.\n *\n * `ReplaySubject` has an internal buffer that will store a specified number of values that it has observed. Like `Subject`,\n * `ReplaySubject` \"observes\" values by having them passed to its `next` method. When it observes a value, it will store that\n * value for a time determined by the configuration of the `ReplaySubject`, as passed to its constructor.\n *\n * When a new subscriber subscribes to the `ReplaySubject` instance, it will synchronously emit all values in its buffer in\n * a First-In-First-Out (FIFO) manner. The `ReplaySubject` will also complete, if it has observed completion; and it will\n * error if it has observed an error.\n *\n * There are two main configuration items to be concerned with:\n *\n * 1. `bufferSize` - This will determine how many items are stored in the buffer, defaults to infinite.\n * 2. `windowTime` - The amount of time to hold a value in the buffer before removing it from the buffer.\n *\n * Both configurations may exist simultaneously. So if you would like to buffer a maximum of 3 values, as long as the values\n * are less than 2 seconds old, you could do so with a `new ReplaySubject(3, 2000)`.\n *\n * ### Differences with BehaviorSubject\n *\n * `BehaviorSubject` is similar to `new ReplaySubject(1)`, with a couple of exceptions:\n *\n * 1. `BehaviorSubject` comes \"primed\" with a single value upon construction.\n * 2. `ReplaySubject` will replay values, even after observing an error, where `BehaviorSubject` will not.\n *\n * @see {@link Subject}\n * @see {@link BehaviorSubject}\n * @see {@link shareReplay}\n */\nexport class ReplaySubject<T> extends Subject<T> {\n  private _buffer: (T | number)[] = [];\n  private _infiniteTimeWindow = true;\n\n  /**\n   * @param _bufferSize The size of the buffer to replay on subscription\n   * @param _windowTime The amount of time the buffered items will stay buffered\n   * @param _timestampProvider An object with a `now()` method that provides the current timestamp. This is used to\n   * calculate the amount of time something has been buffered.\n   */\n  constructor(\n    private _bufferSize = Infinity,\n    private _windowTime = Infinity,\n    private _timestampProvider: TimestampProvider = dateTimestampProvider\n  ) {\n    super();\n    this._infiniteTimeWindow = _windowTime === Infinity;\n    this._bufferSize = Math.max(1, _bufferSize);\n    this._windowTime = Math.max(1, _windowTime);\n  }\n\n  next(value: T): void {\n    const { _closed, _buffer, _infiniteTimeWindow, _timestampProvider, _windowTime } = this;\n    if (!_closed) {\n      _buffer.push(value);\n      !_infiniteTimeWindow && _buffer.push(_timestampProvider.now() + _windowTime);\n    }\n    this._trimBuffer();\n    super.next(value);\n  }\n\n  /** @internal */\n  protected _subscribe(subscriber: Subscriber<T>): Subscription {\n    this._trimBuffer();\n\n    const subscription = this._innerSubscribe(subscriber);\n\n    const { _infiniteTimeWindow, _buffer } = this;\n    // We use a copy here, so reentrant code does not mutate our array while we're\n    // emitting it to a new subscriber.\n    const copy = _buffer.slice();\n    for (let i = 0; i < copy.length && !subscriber.closed; i += _infiniteTimeWindow ? 1 : 2) {\n      subscriber.next(copy[i] as T);\n    }\n\n    this._checkFinalizedStatuses(subscriber);\n\n    return subscription;\n  }\n\n  private _trimBuffer() {\n    const { _bufferSize, _timestampProvider, _buffer, _infiniteTimeWindow } = this;\n    // If we don't have an infinite buffer size, and we're over the length,\n    // use splice to truncate the old buffer values off. Note that we have to\n    // double the size for instances where we're not using an infinite time window\n    // because we're storing the values and the timestamps in the same array.\n    const adjustedBufferSize = (_infiniteTimeWindow ? 1 : 2) * _bufferSize;\n    _bufferSize < Infinity && adjustedBufferSize < _buffer.length && _buffer.splice(0, _buffer.length - adjustedBufferSize);\n\n    // Now, if we're not in an infinite time window, remove all values where the time is\n    // older than what is allowed.\n    if (!_infiniteTimeWindow) {\n      const now = _timestampProvider.now();\n      let last = 0;\n      // Search the array for the first timestamp that isn't expired and\n      // truncate the buffer up to that point.\n      for (let i = 1; i < _buffer.length && (_buffer[i] as number) <= now; i += 2) {\n        last = i;\n      }\n      last && _buffer.splice(0, last + 1);\n    }\n  }\n}\n"
  },
  {
    "path": "packages/rxjs/src/internal/Scheduler.ts",
    "content": "import type { Action } from './scheduler/Action.js';\nimport type { Subscription } from '@rxjs/observable';\nimport type { SchedulerLike, SchedulerAction } from './types.js';\nimport { dateTimestampProvider } from './scheduler/dateTimestampProvider.js';\n\n/**\n * An execution context and a data structure to order tasks and schedule their\n * execution. Provides a notion of (potentially virtual) time, through the\n * `now()` getter method.\n *\n * Each unit of work in a Scheduler is called an `Action`.\n *\n * ```ts\n * class Scheduler {\n *   now(): number;\n *   schedule(work, delay?, state?): Subscription;\n * }\n * ```\n *\n * @deprecated Scheduler is an internal implementation detail of RxJS, and\n * should not be used directly. Rather, create your own class and implement\n * {@link SchedulerLike}. Will be made internal in v8.\n */\nexport class Scheduler implements SchedulerLike {\n  public static now: () => number = dateTimestampProvider.now;\n\n  constructor(private schedulerActionCtor: typeof Action, now: () => number = Scheduler.now) {\n    this.now = now;\n  }\n\n  /**\n   * A getter method that returns a number representing the current time\n   * (at the time this function was called) according to the scheduler's own\n   * internal clock.\n   * @return A number that represents the current time. May or may not\n   * have a relation to wall-clock time. May or may not refer to a time unit\n   * (e.g. milliseconds).\n   */\n  public now: () => number;\n\n  /**\n   * Schedules a function, `work`, for execution. May happen at some point in\n   * the future, according to the `delay` parameter, if specified. May be passed\n   * some context object, `state`, which will be passed to the `work` function.\n   *\n   * The given arguments will be processed an stored as an Action object in a\n   * queue of actions.\n   *\n   * @param work A function representing a task, or some unit of work to be\n   * executed by the Scheduler.\n   * @param delay Time to wait before executing the work, where the time unit is\n   * implicit and defined by the Scheduler itself.\n   * @param state Some contextual data that the `work` function uses when called\n   * by the Scheduler.\n   * @return A subscription in order to be able to unsubscribe the scheduled work.\n   */\n  public schedule<T>(work: (this: SchedulerAction<T>, state?: T) => void, delay: number = 0, state?: T): Subscription {\n    return new this.schedulerActionCtor<T>(this, work).schedule(state, delay);\n  }\n}\n"
  },
  {
    "path": "packages/rxjs/src/internal/Subject.ts",
    "content": "import type { Subscriber} from '@rxjs/observable';\nimport { Observable, Subscription } from '@rxjs/observable';\nimport type { Observer, SubscriptionLike } from './types.js';\n\n/**\n * A Subject is a special type of Observable that allows values to be\n * multicasted to many Observers. Subjects are like EventEmitters.\n *\n * Every Subject is an Observable and an Observer. You can subscribe to a\n * Subject, and you can call next to feed values as well as error and complete.\n */\nexport class Subject<T> extends Observable<T> implements SubscriptionLike {\n  /** @internal */\n  _closed = false;\n\n  /**\n   * Will return true if this subject has been closed and is no longer accepting new values.\n   */\n  get closed() {\n    return this._closed;\n  }\n\n  private _observerCounter = 0;\n  private currentObservers = new Map<number, Observer<T>>();\n\n  /**\n   * This is used to track a known array of observers, so we don't have to\n   * clone them while iterating to prevent reentrant behaviors.\n   * (for example, what if the subject is subscribed to when nexting to an observer)\n   */\n  private observerSnapshot: Observer<T>[] | undefined;\n\n  /** @internal */\n  get observers(): Observer<T>[] {\n    return (this.observerSnapshot ??= Array.from(this.currentObservers.values()));\n  }\n\n  /** @deprecated Internal implementation detail, do not use directly. Will be made internal in v8. */\n  hasError = false;\n\n  /** @deprecated Internal implementation detail, do not use directly. Will be made internal in v8. */\n  thrownError: any = null;\n\n  constructor() {\n    // NOTE: This must be here to obscure Observable's constructor.\n    super();\n  }\n\n  protected _clearObservers() {\n    this.currentObservers.clear();\n    this.observerSnapshot = undefined;\n  }\n\n  next(value: T) {\n    if (!this._closed) {\n      const { observers } = this;\n      const len = observers.length;\n      for (let i = 0; i < len; i++) {\n        observers[i].next(value);\n      }\n    }\n  }\n\n  error(err: any) {\n    if (!this._closed) {\n      this.hasError = this._closed = true;\n      this.thrownError = err;\n      const { observers } = this;\n      const len = observers.length;\n      for (let i = 0; i < len; i++) {\n        observers[i].error(err);\n      }\n      this._clearObservers();\n    }\n  }\n\n  complete() {\n    if (!this._closed) {\n      this._closed = true;\n      const { observers } = this;\n      const len = observers.length;\n      for (let i = 0; i < len; i++) {\n        observers[i].complete();\n      }\n      this._clearObservers();\n    }\n  }\n\n  unsubscribe() {\n    this._closed = true;\n    this._clearObservers();\n  }\n\n  get observed() {\n    return this.currentObservers.size > 0;\n  }\n\n  /** @internal */\n  protected _subscribe(subscriber: Subscriber<T>): Subscription {\n    this._checkFinalizedStatuses(subscriber);\n    return this._innerSubscribe(subscriber);\n  }\n\n  /** @internal */\n  protected _innerSubscribe(subscriber: Subscriber<any>) {\n    if (this.hasError || this._closed) {\n      return Subscription.EMPTY;\n    }\n    const { currentObservers } = this;\n\n    const observerId = this._observerCounter++;\n    currentObservers.set(observerId, subscriber);\n    this.observerSnapshot = undefined;\n    subscriber.add(() => {\n      currentObservers.delete(observerId);\n      this.observerSnapshot = undefined;\n    });\n    return subscriber;\n  }\n\n  /** @internal */\n  protected _checkFinalizedStatuses(subscriber: Subscriber<any>) {\n    const { hasError, thrownError, _closed } = this;\n    if (hasError) {\n      subscriber.error(thrownError);\n    } else if (_closed) {\n      subscriber.complete();\n    }\n  }\n\n  /**\n   * Creates a new Observable with this Subject as the source. You can do this\n   * to create custom Observer-side logic of the Subject and conceal it from\n   * code that uses the Observable.\n   * @return Observable that this Subject casts to.\n   */\n  asObservable(): Observable<T> {\n    return new Observable((subscriber) => this.subscribe(subscriber));\n  }\n}\n"
  },
  {
    "path": "packages/rxjs/src/internal/ajax/AjaxResponse.ts",
    "content": "import type { AjaxRequest, AjaxResponseType } from './types.js';\n\n/**\n * A normalized response from an AJAX request. To get the data from the response,\n * you will want to read the `response` property.\n *\n * - DO NOT create instances of this class directly.\n * - DO NOT subclass this class.\n *\n * It is advised not to hold this object in memory, as it has a reference to\n * the original XHR used to make the request, as well as properties containing\n * request and response data.\n *\n * @see {@link ajax}\n * @see {@link AjaxConfig}\n */\nexport class AjaxResponse<T> {\n  /** The HTTP status code */\n  readonly status: number;\n\n  /**\n   * The response data, if any. Note that this will automatically be converted to the proper type\n   */\n  readonly response: T;\n\n  /**\n   * The responseType set on the request. (For example: `\"\"`, `\"arraybuffer\"`, `\"blob\"`, `\"document\"`, `\"json\"`, or `\"text\"`)\n   * @deprecated There isn't much reason to examine this. It's the same responseType set (or defaulted) on the ajax config.\n   * If you really need to examine this value, you can check it on the `request` or the `xhr`. Will be removed in v8.\n   */\n  readonly responseType: XMLHttpRequestResponseType;\n\n  /**\n   * The total number of bytes loaded so far. To be used with {@link total} while\n   * calculating progress. (You will want to set {@link includeDownloadProgress} or\n   * {@link includeDownloadProgress})\n   */\n  readonly loaded: number;\n\n  /**\n   * The total number of bytes to be loaded. To be used with {@link loaded} while\n   * calculating progress. (You will want to set {@link includeDownloadProgress} or\n   * {@link includeDownloadProgress})\n   */\n  readonly total: number;\n\n  /**\n   * A dictionary of the response headers.\n   */\n  readonly responseHeaders: Record<string, string>;\n\n  /**\n   * A normalized response from an AJAX request. To get the data from the response,\n   * you will want to read the `response` property.\n   *\n   * - DO NOT create instances of this class directly.\n   * - DO NOT subclass this class.\n   *\n   * @param originalEvent The original event object from the XHR `onload` event.\n   * @param xhr The `XMLHttpRequest` object used to make the request. This is useful for examining status code, etc.\n   * @param request The request settings used to make the HTTP request.\n   * @param type The type of the event emitted by the {@link ajax} Observable\n   */\n  constructor(\n    /**\n     * The original event object from the raw XHR event.\n     */\n    public readonly originalEvent: ProgressEvent,\n    /**\n     * The XMLHttpRequest object used to make the request.\n     * NOTE: It is advised not to hold this in memory, as it will retain references to all of it's event handlers\n     * and many other things related to the request.\n     */\n    public readonly xhr: XMLHttpRequest,\n    /**\n     * The request parameters used to make the HTTP request.\n     */\n    public readonly request: AjaxRequest,\n    /**\n     * The event type. This can be used to discern between different events\n     * if you're using progress events with {@link includeDownloadProgress} or\n     * {@link includeUploadProgress} settings in {@link AjaxConfig}.\n     *\n     * The event type consists of two parts: the {@link AjaxDirection} and the\n     * the event type. Merged with `_`, they form the `type` string. The\n     * direction can be an `upload` or a `download` direction, while an event can\n     * be `loadstart`, `progress` or `load`.\n     *\n     * `download_load` is the type of event when download has finished and the\n     * response is available.\n     */\n    public readonly type: AjaxResponseType = 'download_load'\n  ) {\n    const { status, responseType } = xhr;\n    this.status = status ?? 0;\n    this.responseType = responseType ?? '';\n\n    // Parse the response headers in advance for the user. There's really\n    // not a great way to get all of them. So we need to parse the header string\n    // we get back. It comes in a simple enough format:\n    //\n    // header-name: value here\n    // content-type: application/json\n    // other-header-here: some, other, values, or, whatever\n    const allHeaders = xhr.getAllResponseHeaders();\n    this.responseHeaders = allHeaders\n      ? // Split the header text into lines\n        allHeaders.split('\\n').reduce((headers: Record<string, string>, line) => {\n          // Split the lines on the first \": \" as\n          // \"key: value\". Note that the value could\n          // technically have a \": \" in it.\n          const index = line.indexOf(': ');\n          headers[line.slice(0, index)] = line.slice(index + 2);\n          return headers;\n        }, {})\n      : {};\n\n    this.response = xhr.response;\n    const { loaded, total } = originalEvent;\n    this.loaded = loaded;\n    this.total = total;\n  }\n}\n"
  },
  {
    "path": "packages/rxjs/src/internal/ajax/ajax.ts",
    "content": "import { map } from '../operators/map.js';\nimport { Observable } from '@rxjs/observable';\nimport type { AjaxConfig, AjaxRequest, AjaxDirection, ProgressEventType } from './types.js';\nimport { AjaxResponse } from './AjaxResponse.js';\nimport { AjaxTimeoutError, AjaxError } from './errors.js';\n\nexport interface AjaxCreationMethod {\n  /**\n   * Creates an observable that will perform an AJAX request using the\n   * [XMLHttpRequest](https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest) in\n   * global scope by default.\n   *\n   * This is the most configurable option, and the basis for all other AJAX calls in the library.\n   *\n   * ## Example\n   *\n   * ```ts\n   * import { ajax } from 'rxjs/ajax';\n   * import { map, catchError, of } from 'rxjs';\n   *\n   * const obs$ = ajax({\n   *   method: 'GET',\n   *   url: 'https://api.github.com/users?per_page=5',\n   *   responseType: 'json'\n   * }).pipe(\n   *   map(userResponse => console.log('users: ', userResponse)),\n   *   catchError(error => {\n   *     console.log('error: ', error);\n   *     return of(error);\n   *   })\n   * );\n   * ```\n   */\n  <T>(config: AjaxConfig): Observable<AjaxResponse<T>>;\n\n  /**\n   * Perform an HTTP GET using the\n   * [XMLHttpRequest](https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest) in\n   * global scope. Defaults to a `responseType` of `\"json\"`.\n   *\n   * ## Example\n   *\n   * ```ts\n   * import { ajax } from 'rxjs/ajax';\n   * import { map, catchError, of } from 'rxjs';\n   *\n   * const obs$ = ajax('https://api.github.com/users?per_page=5').pipe(\n   *   map(userResponse => console.log('users: ', userResponse)),\n   *   catchError(error => {\n   *     console.log('error: ', error);\n   *     return of(error);\n   *   })\n   * );\n   * ```\n   */\n  <T>(url: string): Observable<AjaxResponse<T>>;\n\n  /**\n   * Performs an HTTP GET using the\n   * [XMLHttpRequest](https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest) in\n   * global scope by default, and a `responseType` of `\"json\"`.\n   *\n   * @param url The URL to get the resource from\n   * @param headers Optional headers. Case-Insensitive.\n   */\n  get<T>(url: string, headers?: Record<string, string>): Observable<AjaxResponse<T>>;\n\n  /**\n   * Performs an HTTP POST using the\n   * [XMLHttpRequest](https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest) in\n   * global scope by default, and a `responseType` of `\"json\"`.\n   *\n   * Before sending the value passed to the `body` argument, it is automatically serialized\n   * based on the specified `responseType`. By default, a JavaScript object will be serialized\n   * to JSON. A `responseType` of `application/x-www-form-urlencoded` will flatten any provided\n   * dictionary object to a url-encoded string.\n   *\n   * @param url The URL to get the resource from\n   * @param body The content to send. The body is automatically serialized.\n   * @param headers Optional headers. Case-Insensitive.\n   */\n  post<T>(url: string, body?: any, headers?: Record<string, string>): Observable<AjaxResponse<T>>;\n\n  /**\n   * Performs an HTTP PUT using the\n   * [XMLHttpRequest](https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest) in\n   * global scope by default, and a `responseType` of `\"json\"`.\n   *\n   * Before sending the value passed to the `body` argument, it is automatically serialized\n   * based on the specified `responseType`. By default, a JavaScript object will be serialized\n   * to JSON. A `responseType` of `application/x-www-form-urlencoded` will flatten any provided\n   * dictionary object to a url-encoded string.\n   *\n   * @param url The URL to get the resource from\n   * @param body The content to send. The body is automatically serialized.\n   * @param headers Optional headers. Case-Insensitive.\n   */\n  put<T>(url: string, body?: any, headers?: Record<string, string>): Observable<AjaxResponse<T>>;\n\n  /**\n   * Performs an HTTP PATCH using the\n   * [XMLHttpRequest](https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest) in\n   * global scope by default, and a `responseType` of `\"json\"`.\n   *\n   * Before sending the value passed to the `body` argument, it is automatically serialized\n   * based on the specified `responseType`. By default, a JavaScript object will be serialized\n   * to JSON. A `responseType` of `application/x-www-form-urlencoded` will flatten any provided\n   * dictionary object to a url-encoded string.\n   *\n   * @param url The URL to get the resource from\n   * @param body The content to send. The body is automatically serialized.\n   * @param headers Optional headers. Case-Insensitive.\n   */\n  patch<T>(url: string, body?: any, headers?: Record<string, string>): Observable<AjaxResponse<T>>;\n\n  /**\n   * Performs an HTTP DELETE using the\n   * [XMLHttpRequest](https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest) in\n   * global scope by default, and a `responseType` of `\"json\"`.\n   *\n   * @param url The URL to get the resource from\n   * @param headers Optional headers. Case-Insensitive.\n   */\n  delete<T>(url: string, headers?: Record<string, string>): Observable<AjaxResponse<T>>;\n\n  /**\n   * Performs an HTTP GET using the\n   * [XMLHttpRequest](https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest) in\n   * global scope by default, and returns the hydrated JavaScript object from the\n   * response.\n   *\n   * @param url The URL to get the resource from\n   * @param headers Optional headers. Case-Insensitive.\n   */\n  getJSON<T>(url: string, headers?: Record<string, string>): Observable<T>;\n}\n\nfunction ajaxGet<T>(url: string, headers?: Record<string, string>): Observable<AjaxResponse<T>> {\n  return ajax({ method: 'GET', url, headers });\n}\n\nfunction ajaxPost<T>(url: string, body?: any, headers?: Record<string, string>): Observable<AjaxResponse<T>> {\n  return ajax({ method: 'POST', url, body, headers });\n}\n\nfunction ajaxDelete<T>(url: string, headers?: Record<string, string>): Observable<AjaxResponse<T>> {\n  return ajax({ method: 'DELETE', url, headers });\n}\n\nfunction ajaxPut<T>(url: string, body?: any, headers?: Record<string, string>): Observable<AjaxResponse<T>> {\n  return ajax({ method: 'PUT', url, body, headers });\n}\n\nfunction ajaxPatch<T>(url: string, body?: any, headers?: Record<string, string>): Observable<AjaxResponse<T>> {\n  return ajax({ method: 'PATCH', url, body, headers });\n}\n\nconst mapResponse = map((x: AjaxResponse<any>) => x.response);\n\nfunction ajaxGetJSON<T>(url: string, headers?: Record<string, string>): Observable<T> {\n  return mapResponse(\n    ajax<T>({\n      method: 'GET',\n      url,\n      headers,\n    })\n  );\n}\n\n/**\n * There is an ajax operator on the Rx object.\n *\n * It creates an observable for an Ajax request with either a request object with\n * url, headers, etc or a string for a URL.\n *\n * ## Examples\n *\n * Using `ajax()` to fetch the response object that is being returned from API\n *\n * ```ts\n * import { ajax } from 'rxjs/ajax';\n * import { map, catchError, of } from 'rxjs';\n *\n * const obs$ = ajax('https://api.github.com/users?per_page=5').pipe(\n *   map(userResponse => console.log('users: ', userResponse)),\n *   catchError(error => {\n *     console.log('error: ', error);\n *     return of(error);\n *   })\n * );\n *\n * obs$.subscribe({\n *   next: value => console.log(value),\n *   error: err => console.log(err)\n * });\n * ```\n *\n * Using `ajax.getJSON()` to fetch data from API\n *\n * ```ts\n * import { ajax } from 'rxjs/ajax';\n * import { map, catchError, of } from 'rxjs';\n *\n * const obs$ = ajax.getJSON('https://api.github.com/users?per_page=5').pipe(\n *   map(userResponse => console.log('users: ', userResponse)),\n *   catchError(error => {\n *     console.log('error: ', error);\n *     return of(error);\n *   })\n * );\n *\n * obs$.subscribe({\n *   next: value => console.log(value),\n *   error: err => console.log(err)\n * });\n * ```\n *\n * Using `ajax()` with object as argument and method POST with a two seconds delay\n *\n * ```ts\n * import { ajax } from 'rxjs/ajax';\n * import { map, catchError, of } from 'rxjs';\n *\n * const users = ajax({\n *   url: 'https://httpbin.org/delay/2',\n *   method: 'POST',\n *   headers: {\n *     'Content-Type': 'application/json',\n *     'rxjs-custom-header': 'Rxjs'\n *   },\n *   body: {\n *     rxjs: 'Hello World!'\n *   }\n * }).pipe(\n *   map(response => console.log('response: ', response)),\n *   catchError(error => {\n *     console.log('error: ', error);\n *     return of(error);\n *   })\n * );\n *\n * users.subscribe({\n *   next: value => console.log(value),\n *   error: err => console.log(err)\n * });\n * ```\n *\n * Using `ajax()` to fetch. An error object that is being returned from the request\n *\n * ```ts\n * import { ajax } from 'rxjs/ajax';\n * import { map, catchError, of } from 'rxjs';\n *\n * const obs$ = ajax('https://api.github.com/404').pipe(\n *   map(userResponse => console.log('users: ', userResponse)),\n *   catchError(error => {\n *     console.log('error: ', error);\n *     return of(error);\n *   })\n * );\n *\n * obs$.subscribe({\n *   next: value => console.log(value),\n *   error: err => console.log(err)\n * });\n * ```\n */\nexport const ajax: AjaxCreationMethod = (() => {\n  const create = <T>(urlOrConfig: string | AjaxConfig) => {\n    const config: AjaxConfig =\n      typeof urlOrConfig === 'string'\n        ? {\n            url: urlOrConfig,\n          }\n        : urlOrConfig;\n    return fromAjax<T>(config);\n  };\n\n  create.get = ajaxGet;\n  create.post = ajaxPost;\n  create.delete = ajaxDelete;\n  create.put = ajaxPut;\n  create.patch = ajaxPatch;\n  create.getJSON = ajaxGetJSON;\n\n  return create;\n})();\n\nconst UPLOAD = 'upload';\nconst DOWNLOAD = 'download';\nconst LOADSTART = 'loadstart';\nconst PROGRESS = 'progress';\nconst LOAD = 'load';\n\nexport function fromAjax<T>(init: AjaxConfig): Observable<AjaxResponse<T>> {\n  return new Observable((destination) => {\n    const config = {\n      // Defaults\n      async: true,\n      crossDomain: false,\n      withCredentials: false,\n      method: 'GET',\n      timeout: 0,\n      responseType: 'json' as XMLHttpRequestResponseType,\n\n      ...init,\n    };\n\n    const { queryParams, body: configuredBody, headers: configuredHeaders } = config;\n\n    let url = config.url;\n    if (!url) {\n      throw new TypeError('url is required');\n    }\n\n    if (queryParams) {\n      let searchParams: URLSearchParams;\n      if (url.includes('?')) {\n        // If the user has passed a URL with a querystring already in it,\n        // we need to combine them. So we're going to split it. There\n        // should only be one `?` in a valid URL.\n        const parts = url.split('?');\n        if (2 < parts.length) {\n          throw new TypeError('invalid url');\n        }\n        // Add the passed queryParams to the params already in the url provided.\n        searchParams = new URLSearchParams(parts[1]);\n        // queryParams is converted to any because the runtime is *much* more permissive than\n        // the types are.\n        new URLSearchParams(queryParams as any).forEach((value, key) => searchParams.set(key, value));\n        // We have to do string concatenation here, because `new URL(url)` does\n        // not like relative URLs like `/this` without a base url, which we can't\n        // specify, nor can we assume `location` will exist, because of node.\n        url = parts[0] + '?' + searchParams;\n      } else {\n        // There is no preexisting querystring, so we can just use URLSearchParams\n        // to convert the passed queryParams into the proper format and encodings.\n        // queryParams is converted to any because the runtime is *much* more permissive than\n        // the types are.\n        searchParams = new URLSearchParams(queryParams as any);\n        url = url + '?' + searchParams;\n      }\n    }\n\n    // Normalize the headers. We're going to make them all lowercase, since\n    // Headers are case insensitive by design. This makes it easier to verify\n    // that we aren't setting or sending duplicates.\n    const headers: Record<string, any> = {};\n    if (configuredHeaders) {\n      for (const key in configuredHeaders) {\n        if (configuredHeaders.hasOwnProperty(key)) {\n          headers[key.toLowerCase()] = configuredHeaders[key];\n        }\n      }\n    }\n\n    const crossDomain = config.crossDomain;\n\n    // Set the x-requested-with header. This is a non-standard header that has\n    // come to be a de facto standard for HTTP requests sent by libraries and frameworks\n    // using XHR. However, we DO NOT want to set this if it is a CORS request. This is\n    // because sometimes this header can cause issues with CORS. To be clear,\n    // None of this is necessary, it's only being set because it's \"the thing libraries do\"\n    // Starting back as far as JQuery, and continuing with other libraries such as Angular 1,\n    // Axios, et al.\n    if (!crossDomain && !('x-requested-with' in headers)) {\n      headers['x-requested-with'] = 'XMLHttpRequest';\n    }\n\n    // Allow users to provide their XSRF cookie name and the name of a custom header to use to\n    // send the cookie.\n    const { withCredentials, xsrfCookieName, xsrfHeaderName } = config;\n    if ((withCredentials || !crossDomain) && xsrfCookieName && xsrfHeaderName) {\n      const xsrfCookie = document?.cookie.match(new RegExp(`(^|;\\\\s*)(${xsrfCookieName})=([^;]*)`))?.pop() ?? '';\n      if (xsrfCookie) {\n        headers[xsrfHeaderName] = xsrfCookie;\n      }\n    }\n\n    // Examine the body and determine whether or not to serialize it\n    // and set the content-type in `headers`, if we're able.\n    const body = extractContentTypeAndMaybeSerializeBody(configuredBody, headers);\n\n    // The final request settings.\n    const _request: Readonly<AjaxRequest> = {\n      ...config,\n\n      // Set values we ensured above\n      url,\n      headers,\n      body,\n    };\n\n    // Create our XHR so we can get started.\n    const xhr = init.createXHR ? init.createXHR() : new XMLHttpRequest();\n\n    {\n      ///////////////////////////////////////////////////\n      // set up the events before open XHR\n      // https://developer.mozilla.org/en/docs/Web/API/XMLHttpRequest/Using_XMLHttpRequest\n      // You need to add the event listeners before calling open() on the request.\n      // Otherwise the progress events will not fire.\n      ///////////////////////////////////////////////////\n\n      const { progressSubscriber, includeDownloadProgress = false, includeUploadProgress = false } = init;\n\n      /**\n       * Wires up an event handler that will emit an error when fired. Used\n       * for timeout and abort events.\n       * @param type The type of event we're treating as an error\n       * @param errorFactory A function that creates the type of error to emit.\n       */\n      const addErrorEvent = (type: string, errorFactory: () => any) => {\n        xhr.addEventListener(type, () => {\n          const error = errorFactory();\n          progressSubscriber?.error?.(error);\n          destination.error(error);\n        });\n      };\n\n      // If the request times out, handle errors appropriately.\n      addErrorEvent('timeout', () => new AjaxTimeoutError(xhr, _request));\n\n      // If the request aborts (due to a network disconnection or the like), handle\n      // it as an error.\n      addErrorEvent('abort', () => new AjaxError('aborted', xhr, _request));\n\n      /**\n       * Creates a response object to emit to the consumer.\n       * @param direction the direction related to the event. Prefixes the event `type` in the\n       * `AjaxResponse` object with \"upload_\" for events related to uploading and \"download_\"\n       * for events related to downloading.\n       * @param event the actual event object.\n       */\n      const createResponse = (direction: AjaxDirection, event: ProgressEvent) =>\n        new AjaxResponse<T>(event, xhr, _request, `${direction}_${event.type as ProgressEventType}` as const);\n\n      /**\n       * Wires up an event handler that emits a Response object to the consumer, used for\n       * all events that emit responses, loadstart, progress, and load.\n       * Note that download load handling is a bit different below, because it has\n       * more logic it needs to run.\n       * @param target The target, either the XHR itself or the Upload object.\n       * @param type The type of event to wire up\n       * @param direction The \"direction\", used to prefix the response object that is\n       * emitted to the consumer. (e.g. \"upload_\" or \"download_\")\n       */\n      const addProgressEvent = (target: any, type: string, direction: AjaxDirection) => {\n        target.addEventListener(type, (event: ProgressEvent) => {\n          destination.next(createResponse(direction, event));\n        });\n      };\n\n      if (includeUploadProgress) {\n        [LOADSTART, PROGRESS, LOAD].forEach((type) => addProgressEvent(xhr.upload, type, UPLOAD));\n      }\n\n      if (progressSubscriber) {\n        [LOADSTART, PROGRESS].forEach((type) => xhr.upload.addEventListener(type, (e: any) => progressSubscriber?.next?.(e)));\n      }\n\n      if (includeDownloadProgress) {\n        [LOADSTART, PROGRESS].forEach((type) => addProgressEvent(xhr, type, DOWNLOAD));\n      }\n\n      const emitError = (status?: number) => {\n        const msg = 'ajax error' + (status ? ' ' + status : '');\n        destination.error(new AjaxError(msg, xhr, _request));\n      };\n\n      xhr.addEventListener('error', (e) => {\n        progressSubscriber?.error?.(e);\n        emitError();\n      });\n\n      xhr.addEventListener(LOAD, (event) => {\n        const { status } = xhr;\n        // 4xx and 5xx should error (https://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html)\n        if (status < 400) {\n          progressSubscriber?.complete?.();\n\n          destination.next(createResponse(DOWNLOAD, event));\n          destination.complete();\n        } else {\n          progressSubscriber?.error?.(event);\n          emitError(status);\n        }\n      });\n    }\n\n    const { user, method, async } = _request;\n    // open XHR\n    if (user) {\n      xhr.open(method, url, async, user, _request.password);\n    } else {\n      xhr.open(method, url, async);\n    }\n\n    // timeout, responseType and withCredentials can be set once the XHR is open\n    if (async) {\n      xhr.timeout = _request.timeout;\n      xhr.responseType = _request.responseType;\n    }\n\n    if ('withCredentials' in xhr) {\n      xhr.withCredentials = _request.withCredentials;\n    }\n\n    // set headers\n    for (const key in headers) {\n      if (headers.hasOwnProperty(key)) {\n        xhr.setRequestHeader(key, headers[key]);\n      }\n    }\n\n    // finally send the request\n    if (body) {\n      xhr.send(body);\n    } else {\n      xhr.send();\n    }\n\n    return () => {\n      if (xhr && xhr.readyState !== 4 /*XHR done*/) {\n        xhr.abort();\n      }\n    };\n  });\n}\n\n/**\n * Examines the body to determine if we need to serialize it for them or not.\n * If the body is a type that XHR handles natively, we just allow it through,\n * otherwise, if the body is something that *we* can serialize for the user,\n * we will serialize it, and attempt to set the `content-type` header, if it's\n * not already set.\n * @param body The body passed in by the user\n * @param headers The normalized headers\n */\nfunction extractContentTypeAndMaybeSerializeBody(body: any, headers: Record<string, string>) {\n  if (\n    !body ||\n    typeof body === 'string' ||\n    isFormData(body) ||\n    isURLSearchParams(body) ||\n    isArrayBuffer(body) ||\n    isFile(body) ||\n    isBlob(body) ||\n    isReadableStream(body)\n  ) {\n    // The XHR instance itself can handle serializing these, and set the content-type for us\n    // so we don't need to do that. https://xhr.spec.whatwg.org/#the-send()-method\n    return body;\n  }\n\n  if (isArrayBufferView(body)) {\n    // This is a typed array (e.g. Float32Array or Uint8Array), or a DataView.\n    // XHR can handle this one too: https://fetch.spec.whatwg.org/#concept-bodyinit-extract\n    return body.buffer;\n  }\n\n  if (typeof body === 'object') {\n    // If we have made it here, this is an object, probably a POJO, and we'll try\n    // to serialize it for them. If this doesn't work, it will throw, obviously, which\n    // is okay. The workaround for users would be to manually set the body to their own\n    // serialized string (accounting for circular references or whatever), then set\n    // the content-type manually as well.\n    headers['content-type'] = headers['content-type'] ?? 'application/json;charset=utf-8';\n    return JSON.stringify(body);\n  }\n\n  // If we've gotten past everything above, this is something we don't quite know how to\n  // handle. Throw an error. This will be caught and emitted from the observable.\n  throw new TypeError('Unknown body type');\n}\n\nconst _toString = Object.prototype.toString;\n\nfunction toStringCheck(obj: any, name: string): boolean {\n  return _toString.call(obj) === `[object ${name}]`;\n}\n\nfunction isArrayBuffer(body: any): body is ArrayBuffer {\n  return toStringCheck(body, 'ArrayBuffer');\n}\n\nfunction isFile(body: any): body is File {\n  return toStringCheck(body, 'File');\n}\n\nfunction isBlob(body: any): body is Blob {\n  return toStringCheck(body, 'Blob');\n}\n\nfunction isArrayBufferView(body: any): body is ArrayBufferView {\n  return typeof ArrayBuffer !== 'undefined' && ArrayBuffer.isView(body);\n}\n\nfunction isFormData(body: any): body is FormData {\n  return typeof FormData !== 'undefined' && body instanceof FormData;\n}\n\nfunction isURLSearchParams(body: any): body is URLSearchParams {\n  return typeof URLSearchParams !== 'undefined' && body instanceof URLSearchParams;\n}\n\nfunction isReadableStream(body: any): body is ReadableStream {\n  return typeof ReadableStream !== 'undefined' && body instanceof ReadableStream;\n}\n"
  },
  {
    "path": "packages/rxjs/src/internal/ajax/errors.ts",
    "content": "import type { AjaxRequest } from './types.js';\n\n/**\n * Thrown when an error occurs during an AJAX request.\n * This is only exported because it is useful for checking to see if an error\n * is an `instanceof AjaxError`. DO NOT create new instances of `AjaxError` with\n * the constructor.\n *\n * @see {@link ajax}\n */\nexport class AjaxError extends Error {\n  /**\n   * The XHR instance associated with the error.\n   */\n  readonly xhr: XMLHttpRequest;\n\n  /**\n   * The AjaxRequest associated with the error.\n   */\n  readonly request: AjaxRequest;\n\n  /**\n   * The HTTP status code, if the request has completed. If not,\n   * it is set to `0`.\n   */\n  readonly status: number;\n\n  /**\n   * The responseType (e.g. 'json', 'arraybuffer', or 'xml').\n   */\n  readonly responseType: XMLHttpRequestResponseType;\n\n  /**\n   * The response data.\n   */\n  readonly response: any;\n\n  /**\n   * @deprecated Internal implementation detail. Do not construct error instances.\n   * Cannot be tagged as internal: https://github.com/ReactiveX/rxjs/issues/6269\n   */\n  constructor(message: string, xhr: XMLHttpRequest, request: AjaxRequest) {\n    super(message);\n    this.name = 'AjaxError';\n    this.xhr = xhr;\n    this.request = request;\n    this.status = xhr.status;\n    this.responseType = xhr.responseType;\n    this.response = xhr.response;\n  }\n}\n\n/**\n * Thrown when an AJAX request times out. Not to be confused with {@link TimeoutError}.\n *\n * This is exported only because it is useful for checking to see if errors are an\n * `instanceof AjaxTimeoutError`. DO NOT use the constructor to create an instance of\n * this type.\n *\n * @see {@link ajax}\n */\nexport class AjaxTimeoutError extends AjaxError {\n  /**\n   * @deprecated Internal implementation detail. Do not construct error instances.\n   * Cannot be tagged as internal: https://github.com/ReactiveX/rxjs/issues/6269\n   */\n  constructor(xhr: XMLHttpRequest, request: AjaxRequest) {\n    super('ajax timeout', xhr, request);\n    this.name = 'AjaxTimeoutError';\n  }\n}\n"
  },
  {
    "path": "packages/rxjs/src/internal/ajax/types.ts",
    "content": "import type { PartialObserver } from '../types.js';\n\n/**\n * Valid Ajax direction types. Prefixes the event `type` in the\n * {@link AjaxResponse} object with \"upload_\" for events related\n * to uploading and \"download_\" for events related to downloading.\n */\nexport type AjaxDirection = 'upload' | 'download';\n\nexport type ProgressEventType = 'loadstart' | 'progress' | 'load';\n\nexport type AjaxResponseType = `${AjaxDirection}_${ProgressEventType}`;\n\n/**\n * The object containing values RxJS used to make the HTTP request.\n *\n * This is provided in {@link AjaxError} instances as the `request`\n * object.\n */\nexport interface AjaxRequest {\n  /**\n   * The URL requested.\n   */\n  url: string;\n\n  /**\n   * The body to send over the HTTP request.\n   */\n  body?: any;\n\n  /**\n   * The HTTP method used to make the HTTP request.\n   */\n  method: string;\n\n  /**\n   * Whether or not the request was made asynchronously.\n   */\n  async: boolean;\n\n  /**\n   * The headers sent over the HTTP request.\n   */\n  headers: Readonly<Record<string, any>>;\n\n  /**\n   * The timeout value used for the HTTP request.\n   * Note: this is only honored if the request is asynchronous (`async` is `true`).\n   */\n  timeout: number;\n\n  /**\n   * The user credentials user name sent with the HTTP request.\n   */\n  user?: string;\n\n  /**\n   * The user credentials password sent with the HTTP request.\n   */\n  password?: string;\n\n  /**\n   * Whether or not the request was a CORS request.\n   */\n  crossDomain: boolean;\n\n  /**\n   * Whether or not a CORS request was sent with credentials.\n   * If `false`, will also ignore cookies in the CORS response.\n   */\n  withCredentials: boolean;\n\n  /**\n   * The [`responseType`](https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/responseType) set before sending the request.\n   */\n  responseType: XMLHttpRequestResponseType;\n}\n\n/**\n * Configuration for the {@link ajax} creation function.\n */\nexport interface AjaxConfig {\n  /** The address of the resource to request via HTTP. */\n  url: string;\n\n  /**\n   * The body of the HTTP request to send.\n   *\n   * This is serialized, by default, based off of the value of the `\"content-type\"` header.\n   * For example, if the `\"content-type\"` is `\"application/json\"`, the body will be serialized\n   * as JSON. If the `\"content-type\"` is `\"application/x-www-form-urlencoded\"`, whatever object passed\n   * to the body will be serialized as URL, using key-value pairs based off of the keys and values of the object.\n   * In all other cases, the body will be passed directly.\n   */\n  body?: any;\n\n  /**\n   * Whether or not to send the request asynchronously. Defaults to `true`.\n   * If set to `false`, this will block the thread until the AJAX request responds.\n   */\n  async?: boolean;\n\n  /**\n   * The HTTP Method to use for the request. Defaults to \"GET\".\n   */\n  method?: string;\n\n  /**\n   * The HTTP headers to apply.\n   *\n   * Note that, by default, RxJS will add the following headers under certain conditions:\n   *\n   * 1. If the `\"content-type\"` header is **NOT** set, and the `body` is [`FormData`](https://developer.mozilla.org/en-US/docs/Web/API/FormData),\n   *    a `\"content-type\"` of `\"application/x-www-form-urlencoded; charset=UTF-8\"` will be set automatically.\n   * 2. If the `\"x-requested-with\"` header is **NOT** set, and the `crossDomain` configuration property is **NOT** explicitly set to `true`,\n   *    (meaning it is not a CORS request), a `\"x-requested-with\"` header with a value of `\"XMLHttpRequest\"` will be set automatically.\n   *    This header is generally meaningless, and is set by libraries and frameworks using `XMLHttpRequest` to make HTTP requests.\n   */\n  headers?: Readonly<Record<string, any>>;\n\n  /**\n   * The time to wait before causing the underlying XMLHttpRequest to timeout. This is only honored if the\n   * `async` configuration setting is unset or set to `true`. Defaults to `0`, which is idiomatic for \"never timeout\".\n   */\n  timeout?: number;\n\n  /** The user credentials user name to send with the HTTP request */\n  user?: string;\n\n  /** The user credentials password to send with the HTTP request*/\n  password?: string;\n\n  /**\n   * Whether or not to send the HTTP request as a CORS request.\n   * Defaults to `false`.\n   *\n   * @deprecated Will be removed in version 8. Cross domain requests and what creates a cross\n   * domain request, are dictated by the browser, and a boolean that forces it to be cross domain\n   * does not make sense. If you need to force cross domain, make sure you're making a secure request,\n   * then add a custom header to the request or use `withCredentials`. For more information on what\n   * triggers a cross domain request, see the [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS#Requests_with_credentials).\n   * In particular, the section on [Simple Requests](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS#Simple_requests) is useful\n   * for understanding when CORS will not be used.\n   */\n  crossDomain?: boolean;\n\n  /**\n   * To send user credentials in a CORS request, set to `true`. To exclude user credentials from\n   * a CORS request, _OR_ when cookies are to be ignored by the CORS response, set to `false`.\n   *\n   * Defaults to `false`.\n   */\n  withCredentials?: boolean;\n\n  /**\n   * The name of your site's XSRF cookie.\n   */\n  xsrfCookieName?: string;\n\n  /**\n   * The name of a custom header that you can use to send your XSRF cookie.\n   */\n  xsrfHeaderName?: string;\n\n  /**\n   * Can be set to change the response type.\n   * Valid values are `\"arraybuffer\"`, `\"blob\"`, `\"document\"`, `\"json\"`, and `\"text\"`.\n   * Note that the type of `\"document\"` (such as an XML document) is ignored if the global context is\n   * not `Window`.\n   *\n   * Defaults to `\"json\"`.\n   */\n  responseType?: XMLHttpRequestResponseType;\n\n  /**\n   * An optional factory used to create the XMLHttpRequest object used to make the AJAX request.\n   * This is useful in environments that lack `XMLHttpRequest`, or in situations where you\n   * wish to override the default `XMLHttpRequest` for some reason.\n   *\n   * If not provided, the `XMLHttpRequest` in global scope will be used.\n   *\n   * NOTE: This AJAX implementation relies on the built-in serialization and setting\n   * of Content-Type headers that is provided by standards-compliant XMLHttpRequest implementations,\n   * be sure any implementation you use meets that standard.\n   */\n  createXHR?: () => XMLHttpRequest;\n\n  /**\n   * An observer for watching the upload progress of an HTTP request. Will\n   * emit progress events, and completes on the final upload load event, will error for\n   * any XHR error or timeout.\n   *\n   * This will **not** error for errored status codes. Rather, it will always _complete_ when\n   * the HTTP response comes back.\n   *\n   * @deprecated If you're looking for progress events, use {@link includeDownloadProgress} and\n   * {@link includeUploadProgress} instead. Will be removed in v8.\n   */\n  progressSubscriber?: PartialObserver<ProgressEvent>;\n\n  /**\n   * If `true`, will emit all download progress and load complete events as {@link AjaxResponse}\n   * from the observable. The final download event will also be emitted as a {@link AjaxResponse}.\n   *\n   * If both this and {@link includeUploadProgress} are `false`, then only the {@link AjaxResponse} will\n   * be emitted from the resulting observable.\n   */\n  includeDownloadProgress?: boolean;\n\n  /**\n   * If `true`, will emit all upload progress and load complete events as {@link AjaxResponse}\n   * from the observable. The final download event will also be emitted as a {@link AjaxResponse}.\n   *\n   * If both this and {@link includeDownloadProgress} are `false`, then only the {@link AjaxResponse} will\n   * be emitted from the resulting observable.\n   */\n  includeUploadProgress?: boolean;\n\n  /**\n   * Query string parameters to add to the URL in the request.\n   * <em>This will require a polyfill for `URL` and `URLSearchParams` in Internet Explorer!</em>\n   *\n   * Accepts either a query string, a `URLSearchParams` object, a dictionary of key/value pairs, or an\n   * array of key/value entry tuples. (Essentially, it takes anything that `new URLSearchParams` would normally take).\n   *\n   * If, for some reason you have a query string in the `url` argument, this will append to the query string in the url,\n   * but it will also overwrite the value of any keys that are an exact match. In other words, a url of `/test?a=1&b=2`,\n   * with queryParams of `{ b: 5, c: 6 }` will result in a url of roughly `/test?a=1&b=5&c=6`.\n   */\n  queryParams?:\n    | string\n    | URLSearchParams\n    | Record<string, string | number | boolean | string[] | number[] | boolean[]>\n    | [string, string | number | boolean | string[] | number[] | boolean[]][];\n}\n"
  },
  {
    "path": "packages/rxjs/src/internal/firstValueFrom.ts",
    "content": "import type { Observable} from '@rxjs/observable';\nimport { Subscriber } from '@rxjs/observable';\nimport { EmptyError } from './util/EmptyError.js';\n\nexport interface FirstValueFromConfig<T> {\n  defaultValue: T;\n}\n\nexport function firstValueFrom<T, D>(source: Observable<T>, config: FirstValueFromConfig<D>): Promise<T | D>;\nexport function firstValueFrom<T>(source: Observable<T>): Promise<T>;\n\n/**\n * Converts an observable to a promise by subscribing to the observable,\n * and returning a promise that will resolve as soon as the first value\n * arrives from the observable. The subscription will then be closed.\n *\n * If the observable stream completes before any values were emitted, the\n * returned promise will reject with {@link EmptyError} or will resolve\n * with the default value if a default was specified.\n *\n * If the observable stream emits an error, the returned promise will reject\n * with that error.\n *\n * **WARNING**: Only use this with observables you *know* will emit at least one value,\n * *OR* complete. If the source observable does not emit one value or complete, you will\n * end up with a promise that is hung up, and potentially all of the state of an\n * async function hanging out in memory. To avoid this situation, look into adding\n * something like {@link timeout}, {@link take}, {@link takeWhile}, or {@link takeUntil}\n * amongst others.\n *\n * ## Example\n *\n * Wait for the first value from a stream and emit it from a promise in\n * an async function\n *\n * ```ts\n * import { interval, firstValueFrom } from 'rxjs';\n *\n * async function execute() {\n *   const source$ = interval(2000);\n *   const firstNumber = await firstValueFrom(source$);\n *   console.log(`The first number is ${ firstNumber }`);\n * }\n *\n * execute();\n *\n * // Expected output:\n * // 'The first number is 0'\n * ```\n *\n * @see {@link lastValueFrom}\n *\n * @param source the observable to convert to a promise\n * @param config a configuration object to define the `defaultValue` to use if the source completes without emitting a value\n */\nexport function firstValueFrom<T, D>(source: Observable<T>, config?: FirstValueFromConfig<D>): Promise<T | D> {\n  const hasConfig = typeof config === 'object';\n  return new Promise<T | D>((resolve, reject) => {\n    const subscriber = new Subscriber({\n      next: (value: T) => {\n        resolve(value);\n        subscriber.unsubscribe();\n      },\n      error: reject,\n      complete: () => {\n        if (hasConfig) {\n          resolve(config!.defaultValue);\n        } else {\n          reject(new EmptyError());\n        }\n      },\n    });\n    source.subscribe(subscriber);\n  });\n}\n"
  },
  {
    "path": "packages/rxjs/src/internal/lastValueFrom.ts",
    "content": "import type { Observable } from '@rxjs/observable';\nimport { EmptyError } from './util/EmptyError.js';\n\nexport interface LastValueFromConfig<T> {\n  defaultValue: T;\n}\n\nexport function lastValueFrom<T, D>(source: Observable<T>, config: LastValueFromConfig<D>): Promise<T | D>;\nexport function lastValueFrom<T>(source: Observable<T>): Promise<T>;\n\n/**\n * Converts an observable to a promise by subscribing to the observable,\n * waiting for it to complete, and resolving the returned promise with the\n * last value from the observed stream.\n *\n * If the observable stream completes before any values were emitted, the\n * returned promise will reject with {@link EmptyError} or will resolve\n * with the default value if a default was specified.\n *\n * If the observable stream emits an error, the returned promise will reject\n * with that error.\n *\n * **WARNING**: Only use this with observables you *know* will complete. If the source\n * observable does not complete, you will end up with a promise that is hung up, and\n * potentially all of the state of an async function hanging out in memory. To avoid\n * this situation, look into adding something like {@link timeout}, {@link take},\n * {@link takeWhile}, or {@link takeUntil} amongst others.\n *\n * ## Example\n *\n * Wait for the last value from a stream and emit it from a promise in\n * an async function\n *\n * ```ts\n * import { interval, take, lastValueFrom } from 'rxjs';\n *\n * async function execute() {\n *   const source$ = interval(2000).pipe(take(10));\n *   const finalNumber = await lastValueFrom(source$);\n *   console.log(`The final number is ${ finalNumber }`);\n * }\n *\n * execute();\n *\n * // Expected output:\n * // 'The final number is 9'\n * ```\n *\n * @see {@link firstValueFrom}\n *\n * @param source the observable to convert to a promise\n * @param config a configuration object to define the `defaultValue` to use if the source completes without emitting a value\n */\nexport function lastValueFrom<T, D>(source: Observable<T>, config?: LastValueFromConfig<D>): Promise<T | D> {\n  const hasConfig = typeof config === 'object';\n  return new Promise<T | D>((resolve, reject) => {\n    let _hasValue = false;\n    let _value: T;\n    source.subscribe({\n      next: (value) => {\n        _value = value;\n        _hasValue = true;\n      },\n      error: reject,\n      complete: () => {\n        if (_hasValue) {\n          resolve(_value);\n        } else if (hasConfig) {\n          resolve(config!.defaultValue);\n        } else {\n          reject(new EmptyError());\n        }\n      },\n    });\n  });\n}\n"
  },
  {
    "path": "packages/rxjs/src/internal/observable/bindCallback.ts",
    "content": "/* @prettier */\nimport type { SchedulerLike } from '../types.js';\nimport type { Observable } from '@rxjs/observable';\nimport { bindCallbackInternals } from './bindCallbackInternals.js';\n\nexport function bindCallback(\n  callbackFunc: (...args: any[]) => void,\n  resultSelector: (...args: any[]) => any,\n  scheduler?: SchedulerLike\n): (...args: any[]) => Observable<any>;\n\n// args is the arguments array and we push the callback on the rest tuple since the rest parameter must be last (only item) in a parameter list\nexport function bindCallback<A extends readonly unknown[], R extends readonly unknown[]>(\n  callbackFunc: (...args: [...A, (...res: R) => void]) => void,\n  schedulerLike?: SchedulerLike\n): (...arg: A) => Observable<R extends [] ? void : R extends [any] ? R[0] : R>;\n\n/**\n * Converts a callback API to a function that returns an Observable.\n *\n * <span class=\"informal\">Give it a function `f` of type `f(x, callback)` and\n * it will return a function `g` that when called as `g(x)` will output an\n * Observable.</span>\n *\n * `bindCallback` is not an operator because its input and output are not\n * Observables. The input is a function `func` with some parameters. The\n * last parameter must be a callback function that `func` calls when it is\n * done.\n *\n * The output of `bindCallback` is a function that takes the same parameters\n * as `func`, except the last one (the callback). When the output function\n * is called with arguments it will return an Observable. If function `func`\n * calls its callback with one argument, the Observable will emit that value.\n * If on the other hand the callback is called with multiple values the resulting\n * Observable will emit an array with said values as arguments.\n *\n * It is **very important** to remember that input function `func` is not called\n * when the output function is, but rather when the Observable returned by the output\n * function is subscribed. This means if `func` makes an AJAX request, that request\n * will be made every time someone subscribes to the resulting Observable, but not before.\n *\n * The last optional parameter - `scheduler` - can be used to control when the call\n * to `func` happens after someone subscribes to Observable, as well as when results\n * passed to callback will be emitted. By default, the subscription to an Observable calls `func`\n * synchronously, but using {@link asyncScheduler} as the last parameter will defer the call to `func`,\n * just like wrapping the call in `setTimeout` with a timeout of `0` would. If you were to use the async Scheduler\n * and call `subscribe` on the output Observable, all function calls that are currently executing\n * will end before `func` is invoked.\n *\n * By default, results passed to the callback are emitted immediately after `func` invokes the callback.\n * In particular, if the callback is called synchronously, then the subscription of the resulting Observable\n * will call the `next` function synchronously as well.  If you want to defer that call,\n * you may use {@link asyncScheduler} just as before.  This means that by using `Scheduler.async` you can\n * ensure that `func` always calls its callback asynchronously, thus avoiding terrifying Zalgo.\n *\n * Note that the Observable created by the output function will always emit a single value\n * and then complete immediately. If `func` calls the callback multiple times, values from subsequent\n * calls will not appear in the stream. If you need to listen for multiple calls,\n *  you probably want to use {@link fromEvent} or {@link fromEventPattern} instead.\n *\n * If `func` depends on some context (`this` property) and is not already bound, the context of `func`\n * will be the context that the output function has at call time. In particular, if `func`\n * is called as a method of some object and if `func` is not already bound, in order to preserve the context\n * it is recommended that the context of the output function is set to that object as well.\n *\n * If the input function calls its callback in the \"node style\" (i.e. first argument to callback is\n * optional error parameter signaling whether the call failed or not), {@link bindNodeCallback}\n * provides convenient error handling and probably is a better choice.\n * `bindCallback` will treat such functions the same as any other and error parameters\n * (whether passed or not) will always be interpreted as regular callback argument.\n *\n * ## Examples\n *\n * Convert jQuery's getJSON to an Observable API\n *\n * ```ts\n * import { bindCallback } from 'rxjs';\n * import * as jQuery from 'jquery';\n *\n * // Suppose we have jQuery.getJSON('/my/url', callback)\n * const getJSONAsObservable = bindCallback(jQuery.getJSON);\n * const result = getJSONAsObservable('/my/url');\n * result.subscribe(x => console.log(x), e => console.error(e));\n * ```\n *\n * Receive an array of arguments passed to a callback\n *\n * ```ts\n * import { bindCallback } from 'rxjs';\n *\n * const someFunction = (n, s, cb) => {\n *   cb(n, s, { someProperty: 'someValue' });\n * };\n *\n * const boundSomeFunction = bindCallback(someFunction);\n * boundSomeFunction(5, 'some string').subscribe((values) => {\n *   console.log(values); // [5, 'some string', {someProperty: 'someValue'}]\n * });\n * ```\n *\n * Compare behaviour with and without `asyncScheduler`\n *\n * ```ts\n * import { bindCallback, asyncScheduler } from 'rxjs';\n *\n * function iCallMyCallbackSynchronously(cb) {\n *   cb();\n * }\n *\n * const boundSyncFn = bindCallback(iCallMyCallbackSynchronously);\n * const boundAsyncFn = bindCallback(iCallMyCallbackSynchronously, null, asyncScheduler);\n *\n * boundSyncFn().subscribe(() => console.log('I was sync!'));\n * boundAsyncFn().subscribe(() => console.log('I was async!'));\n * console.log('This happened...');\n *\n * // Logs:\n * // I was sync!\n * // This happened...\n * // I was async!\n * ```\n *\n * Use `bindCallback` on an object method\n *\n * ```ts\n * import { bindCallback } from 'rxjs';\n *\n * const boundMethod = bindCallback(someObject.methodWithCallback);\n * boundMethod\n *   .call(someObject) // make sure methodWithCallback has access to someObject\n *   .subscribe(subscriber);\n * ```\n *\n * @see {@link bindNodeCallback}\n * @see {@link from}\n *\n * @param callbackFunc A function with a callback as the last parameter.\n * @param resultSelector A mapping function used to transform callback events.\n * @param scheduler The scheduler on which to schedule the callbacks.\n * @return A function which returns the Observable that delivers the same\n * values the callback would deliver.\n */\nexport function bindCallback(\n  callbackFunc: (...args: [...any[], (...res: any) => void]) => void,\n  resultSelector?: ((...args: any[]) => any) | SchedulerLike,\n  scheduler?: SchedulerLike\n): (...args: any[]) => Observable<unknown> {\n  return bindCallbackInternals(false, callbackFunc, resultSelector, scheduler);\n}\n"
  },
  {
    "path": "packages/rxjs/src/internal/observable/bindCallbackInternals.ts",
    "content": "import type { SchedulerLike } from '../types.js';\nimport { isScheduler } from '../util/isScheduler.js';\nimport { Observable } from '@rxjs/observable';\nimport { mapOneOrManyArgs } from '../util/mapOneOrManyArgs.js';\nimport { AsyncSubject } from '../AsyncSubject.js';\nimport { scheduled } from '../scheduled/scheduled.js';\n\nexport function bindCallbackInternals(\n  isNodeStyle: boolean,\n  callbackFunc: any,\n  resultSelector?: any,\n  scheduler?: SchedulerLike\n): (...args: any[]) => Observable<unknown> {\n  if (resultSelector) {\n    if (isScheduler(resultSelector)) {\n      scheduler = resultSelector;\n    } else {\n      // The user provided a result selector.\n      return function (this: any, ...args: any[]) {\n        return mapOneOrManyArgs(resultSelector as any)(\n          (bindCallbackInternals(isNodeStyle, callbackFunc, scheduler) as any).apply(this, args)\n        );\n      };\n    }\n  }\n\n  // If a scheduler was passed, use our `subscribeOn` and `observeOn` operators\n  // to compose that behavior for the user.\n  if (scheduler) {\n    return function (this: any, ...args: any[]) {\n      return scheduled((bindCallbackInternals(isNodeStyle, callbackFunc) as any).apply(this, args), scheduler!);\n    };\n  }\n\n  return function (this: any, ...args: any[]): Observable<any> {\n    // We're using AsyncSubject, because it emits when it completes,\n    // and it will play the value to all late-arriving subscribers.\n    const subject = new AsyncSubject<any>();\n\n    // If this is true, then we haven't called our function yet.\n    let uninitialized = true;\n    return new Observable((subscriber) => {\n      // Add our subscriber to the subject.\n      const subs = subject.subscribe(subscriber);\n\n      if (uninitialized) {\n        uninitialized = false;\n        // We're going to execute the bound function\n        // This bit is to signal that we are hitting the callback asynchronously.\n        // Because we don't have any anti-\"Zalgo\" guarantees with whatever\n        // function we are handed, we use this bit to figure out whether or not\n        // we are getting hit in a callback synchronously during our call.\n        let isAsync = false;\n\n        // This is used to signal that the callback completed synchronously.\n        let isComplete = false;\n\n        // Call our function that has a callback. If at any time during this\n        // call, an error is thrown, it will be caught by the Observable\n        // subscription process and sent to the consumer.\n        callbackFunc.apply(\n          // Pass the appropriate `this` context.\n          this,\n          [\n            // Pass the arguments.\n            ...args,\n            // And our callback handler.\n            (...results: any[]) => {\n              if (isNodeStyle) {\n                // If this is a node callback, shift the first value off of the\n                // results and check it, as it is the error argument. By shifting,\n                // we leave only the argument(s) we want to pass to the consumer.\n                const err = results.shift();\n                if (err != null) {\n                  subject.error(err);\n                  // If we've errored, we can stop processing this function\n                  // as there's nothing else to do. Just return to escape.\n                  return;\n                }\n              }\n              // If we have one argument, notify the consumer\n              // of it as a single value, otherwise, if there's more than one, pass\n              // them as an array. Note that if there are no arguments, `undefined`\n              // will be emitted.\n              subject.next(1 < results.length ? results : results[0]);\n              // Flip this flag, so we know we can complete it in the synchronous\n              // case below.\n              isComplete = true;\n              // If we're not asynchronous, we need to defer the `complete` call\n              // until after the call to the function is over. This is because an\n              // error could be thrown in the function after it calls our callback,\n              // and if that is the case, if we complete here, we are unable to notify\n              // the consumer than an error occurred.\n              if (isAsync) {\n                subject.complete();\n              }\n            },\n          ]\n        );\n        // If we flipped `isComplete` during the call, we resolved synchronously,\n        // notify complete, because we skipped it in the callback to wait\n        // to make sure there were no errors during the call.\n        if (isComplete) {\n          subject.complete();\n        }\n\n        // We're no longer synchronous. If the callback is called at this point\n        // we can notify complete on the spot.\n        isAsync = true;\n      }\n\n      // Return the subscription from adding our subscriber to the subject.\n      return subs;\n    });\n  };\n}\n"
  },
  {
    "path": "packages/rxjs/src/internal/observable/bindNodeCallback.ts",
    "content": "/* @prettier */\nimport type { Observable } from '@rxjs/observable';\nimport type { SchedulerLike } from '../types.js';\nimport { bindCallbackInternals } from './bindCallbackInternals.js';\n\nexport function bindNodeCallback(\n  callbackFunc: (...args: any[]) => void,\n  resultSelector: (...args: any[]) => any,\n  scheduler?: SchedulerLike\n): (...args: any[]) => Observable<any>;\n\n// args is the arguments array and we push the callback on the rest tuple since the rest parameter must be last (only item) in a parameter list\nexport function bindNodeCallback<A extends readonly unknown[], R extends readonly unknown[]>(\n  callbackFunc: (...args: [...A, (err: any, ...res: R) => void]) => void,\n  schedulerLike?: SchedulerLike\n): (...arg: A) => Observable<R extends [] ? void : R extends [any] ? R[0] : R>;\n\n/**\n * Converts a Node.js-style callback API to a function that returns an\n * Observable.\n *\n * <span class=\"informal\">It's just like {@link bindCallback}, but the\n * callback is expected to be of type `callback(error, result)`.</span>\n *\n * `bindNodeCallback` is not an operator because its input and output are not\n * Observables. The input is a function `func` with some parameters, but the\n * last parameter must be a callback function that `func` calls when it is\n * done. The callback function is expected to follow Node.js conventions,\n * where the first argument to the callback is an error object, signaling\n * whether call was successful. If that object is passed to callback, it means\n * something went wrong.\n *\n * The output of `bindNodeCallback` is a function that takes the same\n * parameters as `func`, except the last one (the callback). When the output\n * function is called with arguments, it will return an Observable.\n * If `func` calls its callback with error parameter present, Observable will\n * error with that value as well. If error parameter is not passed, Observable will emit\n * second parameter. If there are more parameters (third and so on),\n * Observable will emit an array with all arguments, except first error argument.\n *\n * Note that `func` will not be called at the same time output function is,\n * but rather whenever resulting Observable is subscribed. By default call to\n * `func` will happen synchronously after subscription, but that can be changed\n * with proper `scheduler` provided as optional third parameter. {@link SchedulerLike}\n * can also control when values from callback will be emitted by Observable.\n * To find out more, check out documentation for {@link bindCallback}, where\n * {@link SchedulerLike} works exactly the same.\n *\n * As in {@link bindCallback}, context (`this` property) of input function will be set to context\n * of returned function, when it is called.\n *\n * After Observable emits value, it will complete immediately. This means\n * even if `func` calls callback again, values from second and consecutive\n * calls will never appear on the stream. If you need to handle functions\n * that call callbacks multiple times, check out {@link fromEvent} or\n * {@link fromEventPattern} instead.\n *\n * Note that `bindNodeCallback` can be used in non-Node.js environments as well.\n * \"Node.js-style\" callbacks are just a convention, so if you write for\n * browsers or any other environment and API you use implements that callback style,\n * `bindNodeCallback` can be safely used on that API functions as well.\n *\n * Remember that Error object passed to callback does not have to be an instance\n * of JavaScript built-in `Error` object. In fact, it does not even have to an object.\n * Error parameter of callback function is interpreted as \"present\", when value\n * of that parameter is truthy. It could be, for example, non-zero number, non-empty\n * string or boolean `true`. In all of these cases resulting Observable would error\n * with that value. This means usually regular style callbacks will fail very often when\n * `bindNodeCallback` is used. If your Observable errors much more often then you\n * would expect, check if callback really is called in Node.js-style and, if not,\n * switch to {@link bindCallback} instead.\n *\n * Note that even if error parameter is technically present in callback, but its value\n * is falsy, it still won't appear in array emitted by Observable.\n *\n * ## Examples\n *\n *  Read a file from the filesystem and get the data as an Observable\n *\n * ```ts\n * import * as fs from 'fs';\n * const readFileAsObservable = bindNodeCallback(fs.readFile);\n * const result = readFileAsObservable('./roadNames.txt', 'utf8');\n * result.subscribe(x => console.log(x), e => console.error(e));\n * ```\n *\n * Use on function calling callback with multiple arguments\n *\n * ```ts\n * someFunction((err, a, b) => {\n *   console.log(err); // null\n *   console.log(a); // 5\n *   console.log(b); // \"some string\"\n * });\n * const boundSomeFunction = bindNodeCallback(someFunction);\n * boundSomeFunction()\n * .subscribe(value => {\n *   console.log(value); // [5, \"some string\"]\n * });\n * ```\n *\n * Use on function calling callback in regular style\n *\n * ```ts\n * someFunction(a => {\n *   console.log(a); // 5\n * });\n * const boundSomeFunction = bindNodeCallback(someFunction);\n * boundSomeFunction()\n * .subscribe(\n *   value => {}             // never gets called\n *   err => console.log(err) // 5\n * );\n * ```\n *\n * @see {@link bindCallback}\n * @see {@link from}\n *\n * @param callbackFunc Function with a Node.js-style callback as the last parameter.\n * @param resultSelector A mapping function used to transform callback events.\n * @param scheduler The scheduler on which to schedule the callbacks.\n * @return A function which returns the Observable that delivers the same values the\n * Node.js callback would deliver.\n */\nexport function bindNodeCallback(\n  callbackFunc: (...args: [...any[], (err: any, ...res: any) => void]) => void,\n  resultSelector?: ((...args: any[]) => any) | SchedulerLike,\n  scheduler?: SchedulerLike\n): (...args: any[]) => Observable<any> {\n  return bindCallbackInternals(true, callbackFunc, resultSelector, scheduler);\n}\n"
  },
  {
    "path": "packages/rxjs/src/internal/observable/combineLatest.ts",
    "content": "import type { Subscriber} from '@rxjs/observable';\nimport { Observable, operate, from } from '@rxjs/observable';\nimport type { ObservableInput, ObservedValueOf, ObservableInputTuple } from '../types.js';\nimport { arrayOrObject } from '../util/argsArgArrayOrObject.js';\nimport { identity } from '../util/identity.js';\nimport { createObject } from '../util/createObject.js';\nimport type { AnyCatcher } from '../AnyCatcher.js';\nimport { EMPTY } from './empty.js';\n\n// combineLatest(any)\n// We put this first because we need to catch cases where the user has supplied\n// _exactly `any`_ as the argument. Since `any` literally matches _anything_,\n// we don't want it to randomly hit one of the other type signatures below,\n// as we have no idea at build-time what type we should be returning when given an any.\n\n/**\n * You have passed `any` here, we can't figure out if it is\n * an array or an object, so you're getting `unknown`. Use better types.\n * @param arg Something typed as `any`\n */\nexport function combineLatest<T extends AnyCatcher>(arg: T): Observable<unknown>;\n\n// combineLatest([a, b, c])\nexport function combineLatest(sources: []): Observable<never>;\nexport function combineLatest<A extends readonly unknown[]>(sources: readonly [...ObservableInputTuple<A>]): Observable<A>;\nexport function combineLatest<A extends readonly unknown[], R>(\n  sources: readonly [...ObservableInputTuple<A>],\n  resultSelector: (...values: A) => R\n): Observable<R>;\n\n// combineLatest({a, b, c})\nexport function combineLatest(sourcesObject: { [K in any]: never }): Observable<never>;\nexport function combineLatest<T extends Record<string, ObservableInput<any>>>(\n  sourcesObject: T\n): Observable<{ [K in keyof T]: ObservedValueOf<T[K]> }>;\n\n/**\n * Combines multiple Observables to create an Observable whose values are\n * calculated from the latest values of each of its input Observables.\n *\n * <span class=\"informal\">Whenever any input Observable emits a value, it\n * computes a formula using the latest values from all the inputs, then emits\n * the output of that formula.</span>\n *\n * ![](combineLatest.png)\n *\n * `combineLatest` combines the values from all the Observables passed in the\n * observables array. This is done by subscribing to each Observable in order and,\n * whenever any Observable emits, collecting an array of the most recent\n * values from each Observable. So if you pass `n` Observables to this operator,\n * the returned Observable will always emit an array of `n` values, in an order\n * corresponding to the order of the passed Observables (the value from the first Observable\n * will be at index 0 of the array and so on).\n *\n * Static version of `combineLatest` accepts an array of Observables. Note that an array of\n * Observables is a good choice, if you don't know beforehand how many Observables\n * you will combine. Passing an empty array will result in an Observable that\n * completes immediately.\n *\n * To ensure the output array always has the same length, `combineLatest` will\n * actually wait for all input Observables to emit at least once,\n * before it starts emitting results. This means if some Observable emits\n * values before other Observables started emitting, all these values but the last\n * will be lost. On the other hand, if some Observable does not emit a value but\n * completes, resulting Observable will complete at the same moment without\n * emitting anything, since it will now be impossible to include a value from the\n * completed Observable in the resulting array. Also, if some input Observable does\n * not emit any value and never completes, `combineLatest` will also never emit\n * and never complete, since, again, it will wait for all streams to emit some\n * value.\n *\n * If at least one Observable was passed to `combineLatest` and all passed Observables\n * emitted something, the resulting Observable will complete when all combined\n * streams complete. So even if some Observable completes, the result of\n * `combineLatest` will still emit values when other Observables do. In case\n * of a completed Observable, its value from now on will always be the last\n * emitted value. On the other hand, if any Observable errors, `combineLatest`\n * will error immediately as well, and all other Observables will be unsubscribed.\n *\n * ## Examples\n *\n * Combine two timer Observables\n *\n * ```ts\n * import { timer, combineLatest } from 'rxjs';\n *\n * const firstTimer = timer(0, 1000); // emit 0, 1, 2... after every second, starting from now\n * const secondTimer = timer(500, 1000); // emit 0, 1, 2... after every second, starting 0,5s from now\n * const combinedTimers = combineLatest([firstTimer, secondTimer]);\n * combinedTimers.subscribe(value => console.log(value));\n * // Logs\n * // [0, 0] after 0.5s\n * // [1, 0] after 1s\n * // [1, 1] after 1.5s\n * // [2, 1] after 2s\n * ```\n *\n * Combine a dictionary of Observables\n *\n * ```ts\n * import { of, delay, startWith, combineLatest } from 'rxjs';\n *\n * const observables = {\n *   a: of(1).pipe(delay(1000), startWith(0)),\n *   b: of(5).pipe(delay(5000), startWith(0)),\n *   c: of(10).pipe(delay(10000), startWith(0))\n * };\n * const combined = combineLatest(observables);\n * combined.subscribe(value => console.log(value));\n * // Logs\n * // { a: 0, b: 0, c: 0 } immediately\n * // { a: 1, b: 0, c: 0 } after 1s\n * // { a: 1, b: 5, c: 0 } after 5s\n * // { a: 1, b: 5, c: 10 } after 10s\n * ```\n *\n * Combine an array of Observables\n *\n * ```ts\n * import { of, delay, startWith, combineLatest } from 'rxjs';\n *\n * const observables = [1, 5, 10].map(\n *   n => of(n).pipe(\n *     delay(n * 1000), // emit 0 and then emit n after n seconds\n *     startWith(0)\n *   )\n * );\n * const combined = combineLatest(observables);\n * combined.subscribe(value => console.log(value));\n * // Logs\n * // [0, 0, 0] immediately\n * // [1, 0, 0] after 1s\n * // [1, 5, 0] after 5s\n * // [1, 5, 10] after 10s\n * ```\n *\n * Use map operator to dynamically calculate the Body-Mass Index\n *\n * ```ts\n * import { of, combineLatest, map } from 'rxjs';\n *\n * const weight = of(70, 72, 76, 79, 75);\n * const height = of(1.76, 1.77, 1.78);\n * const bmi = combineLatest([weight, height]).pipe(\n *   map(([w, h]) => w / (h * h)),\n * );\n * bmi.subscribe(x => console.log('BMI is ' + x));\n *\n * // With output to console:\n * // BMI is 24.212293388429753\n * // BMI is 23.93948099205209\n * // BMI is 23.671253629592222\n * ```\n *\n * @see {@link combineLatestAll}\n * @see {@link merge}\n * @see {@link withLatestFrom}\n *\n * @param args Any number of `ObservableInput`s provided either as an array or as an object\n * to combine with each other. If the last parameter is the function, it will be used to project the\n * values from the combined latest values into a new value on the output Observable.\n * @return An Observable of projected values from the most recent values from each `ObservableInput`,\n * or an array of the most recent values from each `ObservableInput`.\n */\nexport function combineLatest<O extends ObservableInput<any>, R>(\n  sources: Record<string, O> | O[],\n  resultSelector?: (...value: any[]) => R\n): Observable<R> | Observable<ObservedValueOf<O>[]> {\n  const parts = arrayOrObject(sources);\n\n  if (!parts) {\n    throw new TypeError('sources must be an array or object');\n  }\n\n  const { args: observables, keys } = parts;\n\n  if (observables.length === 0) {\n    // If no observables are passed, or someone has passed an empty array\n    // of observables, or even an empty object POJO, we need to just\n    // complete (EMPTY), but we have to honor the scheduler provided if any.\n    return EMPTY;\n  }\n\n  return new Observable<ObservedValueOf<O>[]>(\n    combineLatestInit(\n      observables as ObservableInput<ObservedValueOf<O>>[],\n      keys\n        ? (values: any[]) => createObject(keys, values)\n        : resultSelector\n        ? (values: readonly any[]) => resultSelector(...values)\n        : identity\n    )\n  );\n}\n\nexport function combineLatestInit(observables: ObservableInput<any>[], valueTransform: (values: any[]) => any = identity) {\n  return (destination: Subscriber<any>) => {\n    const { length } = observables;\n    // A store for the values each observable has emitted so far. We match observable to value on index.\n    const values = new Array(length);\n    // The number of currently active subscriptions, as they complete, we decrement this number to see if\n    // we are all done combining values, so we can complete the result.\n    let active = length;\n    // The number of inner sources that still haven't emitted the first value\n    // We need to track this because all sources need to emit one value in order\n    // to start emitting values.\n    let remainingFirstValues = length;\n    // The loop to kick off subscription. We're keying everything on index `i` to relate the observables passed\n    // in to the slot in the output array or the key in the array of keys in the output dictionary.\n    for (let i = 0; i < length; i++) {\n      const source = from(observables[i]);\n      let hasFirstValue = false;\n      source.subscribe(\n        operate({\n          destination,\n          next: (value) => {\n            // When we get a value, record it in our set of values.\n            values[i] = value;\n            if (!hasFirstValue) {\n              // If this is our first value, record that.\n              hasFirstValue = true;\n              remainingFirstValues--;\n            }\n            if (!remainingFirstValues) {\n              // We're not waiting for any more\n              // first values, so we can emit!\n              destination.next(valueTransform(Array.from(values)));\n            }\n          },\n          complete: () => {\n            if (!--active) {\n              // We only complete the result if we have no more active\n              // inner observables.\n              destination.complete();\n            }\n          },\n        })\n      );\n    }\n  };\n}\n"
  },
  {
    "path": "packages/rxjs/src/internal/observable/concat.ts",
    "content": "import type { Observable} from '@rxjs/observable';\nimport { from } from '@rxjs/observable';\nimport type { ObservableInputTuple, SchedulerLike } from '../types.js';\nimport { concatAll } from '../operators/concatAll.js';\nimport { popScheduler } from '../util/args.js';\nimport { scheduled } from '../scheduled/scheduled.js';\n\nexport function concat<T extends readonly unknown[]>(...inputs: [...ObservableInputTuple<T>]): Observable<T[number]>;\nexport function concat<T extends readonly unknown[]>(\n  ...inputsAndScheduler: [...ObservableInputTuple<T>, SchedulerLike]\n): Observable<T[number]>;\n\n/**\n * Creates an output Observable which sequentially emits all values from the first given\n * Observable and then moves on to the next.\n *\n * <span class=\"informal\">Concatenates multiple Observables together by\n * sequentially emitting their values, one Observable after the other.</span>\n *\n * ![](concat.png)\n *\n * `concat` joins multiple Observables together, by subscribing to them one at a time and\n * merging their results into the output Observable. You can pass either an array of\n * Observables, or put them directly as arguments. Passing an empty array will result\n * in Observable that completes immediately.\n *\n * `concat` will subscribe to first input Observable and emit all its values, without\n * changing or affecting them in any way. When that Observable completes, it will\n * subscribe to then next Observable passed and, again, emit its values. This will be\n * repeated, until the operator runs out of Observables. When last input Observable completes,\n * `concat` will complete as well. At any given moment only one Observable passed to operator\n * emits values. If you would like to emit values from passed Observables concurrently, check out\n * {@link merge} instead, especially with optional `concurrent` parameter. As a matter of fact,\n * `concat` is an equivalent of `merge` operator with `concurrent` parameter set to `1`.\n *\n * Note that if some input Observable never completes, `concat` will also never complete\n * and Observables following the one that did not complete will never be subscribed. On the other\n * hand, if some Observable simply completes immediately after it is subscribed, it will be\n * invisible for `concat`, which will just move on to the next Observable.\n *\n * If any Observable in chain errors, instead of passing control to the next Observable,\n * `concat` will error immediately as well. Observables that would be subscribed after\n * the one that emitted error, never will.\n *\n * If you pass to `concat` the same Observable many times, its stream of values\n * will be \"replayed\" on every subscription, which means you can repeat given Observable\n * as many times as you like. If passing the same Observable to `concat` 1000 times becomes tedious,\n * you can always use {@link repeat}.\n *\n * ## Examples\n *\n * Concatenate a timer counting from 0 to 3 with a synchronous sequence from 1 to 10\n *\n * ```ts\n * import { interval, take, range, concat } from 'rxjs';\n *\n * const timer = interval(1000).pipe(take(4));\n * const sequence = range(1, 10);\n * const result = concat(timer, sequence);\n * result.subscribe(x => console.log(x));\n *\n * // results in:\n * // 0 -1000ms-> 1 -1000ms-> 2 -1000ms-> 3 -immediate-> 1 ... 10\n * ```\n *\n * Concatenate 3 Observables\n *\n * ```ts\n * import { interval, take, concat } from 'rxjs';\n *\n * const timer1 = interval(1000).pipe(take(10));\n * const timer2 = interval(2000).pipe(take(6));\n * const timer3 = interval(500).pipe(take(10));\n *\n * const result = concat(timer1, timer2, timer3);\n * result.subscribe(x => console.log(x));\n *\n * // results in the following:\n * // (Prints to console sequentially)\n * // -1000ms-> 0 -1000ms-> 1 -1000ms-> ... 9\n * // -2000ms-> 0 -2000ms-> 1 -2000ms-> ... 5\n * // -500ms-> 0 -500ms-> 1 -500ms-> ... 9\n * ```\n *\n * Concatenate the same Observable to repeat it\n *\n * ```ts\n * import { interval, take, concat } from 'rxjs';\n *\n * const timer = interval(1000).pipe(take(2));\n *\n * concat(timer, timer) // concatenating the same Observable!\n *   .subscribe({\n *     next: value => console.log(value),\n *     complete: () => console.log('...and it is done!')\n *   });\n *\n * // Logs:\n * // 0 after 1s\n * // 1 after 2s\n * // 0 after 3s\n * // 1 after 4s\n * // '...and it is done!' also after 4s\n * ```\n *\n * @see {@link concatAll}\n * @see {@link concatMap}\n * @see {@link concatMapTo}\n * @see {@link startWith}\n * @see {@link endWith}\n *\n * @param args `ObservableInput`s to concatenate.\n */\nexport function concat(...args: any[]): Observable<unknown> {\n  const scheduler = popScheduler(args);\n  return concatAll()(scheduler ? scheduled(args, scheduler) : from(args));\n}\n"
  },
  {
    "path": "packages/rxjs/src/internal/observable/connectable.ts",
    "content": "import type { Connectable, ObservableInput, SubjectLike } from '../types.js';\nimport { Subject } from '../Subject.js';\nimport type { Subscription} from '@rxjs/observable';\nimport { Observable } from '@rxjs/observable';\nimport { defer } from './defer.js';\n\nexport interface ConnectableConfig<T> {\n  /**\n   * A factory function used to create the Subject through which the source\n   * is multicast. By default this creates a {@link Subject}.\n   */\n  connector: () => SubjectLike<T>;\n  /**\n   * If true, the resulting observable will reset internal state upon disconnection\n   * and return to a \"cold\" state. This allows the resulting observable to be\n   * reconnected.\n   * If false, upon disconnection, the connecting subject will remain the\n   * connecting subject, meaning the resulting observable will not go \"cold\" again,\n   * and subsequent repeats or resubscriptions will resubscribe to that same subject.\n   */\n  resetOnDisconnect?: boolean;\n}\n\n/**\n * The default configuration for `connectable`.\n */\nconst DEFAULT_CONFIG: ConnectableConfig<unknown> = {\n  connector: () => new Subject<unknown>(),\n  resetOnDisconnect: true,\n};\n\n/**\n * Creates an observable that multicasts once `connect()` is called on it.\n *\n * @param source The observable source to make connectable.\n * @param config The configuration object for `connectable`.\n * @returns A \"connectable\" observable, that has a `connect()` method, that you must call to\n * connect the source to all consumers through the subject provided as the connector.\n */\nexport function connectable<T>(source: ObservableInput<T>, config: ConnectableConfig<T> = DEFAULT_CONFIG): Connectable<T> {\n  // The subscription representing the connection.\n  let connection: Subscription | null = null;\n  const { connector, resetOnDisconnect = true } = config;\n  let subject = connector();\n\n  const result: any = new Observable<T>((subscriber) => {\n    return subject.subscribe(subscriber);\n  });\n\n  // Define the `connect` function. This is what users must call\n  // in order to \"connect\" the source to the subject that is\n  // multicasting it.\n  result.connect = () => {\n    if (!connection || connection.closed) {\n      connection = defer(() => source).subscribe(subject);\n      if (resetOnDisconnect) {\n        connection.add(() => (subject = connector()));\n      }\n    }\n    return connection;\n  };\n\n  return result;\n}\n"
  },
  {
    "path": "packages/rxjs/src/internal/observable/defer.ts",
    "content": "import { Observable, from } from '@rxjs/observable';\nimport type { ObservedValueOf, ObservableInput } from '../types.js';\n\n/**\n * Creates an Observable that, on subscribe, calls an Observable factory to\n * make an Observable for each new Observer.\n *\n * <span class=\"informal\">Creates the Observable lazily, that is, only when it\n * is subscribed.\n * </span>\n *\n * ![](defer.png)\n *\n * `defer` allows you to create an Observable only when the Observer\n * subscribes. It waits until an Observer subscribes to it, calls the given\n * factory function to get an Observable -- where a factory function typically\n * generates a new Observable -- and subscribes the Observer to this Observable.\n * Last but not least, an exception during the factory function call is\n * transferred to the Observer by calling `error`.\n *\n * ## Example\n *\n * Subscribe to either an Observable of clicks or an Observable of interval, at random\n *\n * ```ts\n * import { defer, fromEvent, interval } from 'rxjs';\n *\n * const clicksOrInterval = defer(() => {\n *   return Math.random() > 0.5\n *     ? fromEvent(document, 'click')\n *     : interval(1000);\n * });\n * clicksOrInterval.subscribe(x => console.log(x));\n *\n * // Results in the following behavior:\n * // If the result of Math.random() is greater than 0.5 it will listen\n * // for clicks anywhere on the \"document\"; when document is clicked it\n * // will log a MouseEvent object to the console. If the result is less\n * // than 0.5 it will emit ascending numbers, one every second(1000ms).\n * ```\n *\n * @see {@link Observable}\n *\n * @param observableFactory The Observable factory function to invoke for each\n * Observer that subscribes to the output Observable. May also return any\n * `ObservableInput`, which will be converted on the fly to an Observable.\n * @return An Observable whose Observers' subscriptions trigger an invocation of the\n * given Observable factory function.\n */\nexport function defer<R extends ObservableInput<any>>(observableFactory: () => R): Observable<ObservedValueOf<R>> {\n  return new Observable<ObservedValueOf<R>>((subscriber) => {\n    from(observableFactory()).subscribe(subscriber);\n  });\n}\n"
  },
  {
    "path": "packages/rxjs/src/internal/observable/dom/WebSocketSubject.ts",
    "content": "import type { Subscriber, Subscription} from '@rxjs/observable';\nimport { Observable, operate } from '@rxjs/observable';\nimport type { NextObserver } from '../../types.js';\n\n/**\n * WebSocketSubjectConfig is a plain Object that allows us to make our\n * webSocket configurable.\n *\n * <span class=\"informal\">Provides flexibility to {@link webSocket}</span>\n *\n * It defines a set of properties to provide custom behavior in specific\n * moments of the socket's lifecycle. When the connection opens we can\n * use `openObserver`, when the connection is closed `closeObserver`, if we\n * are interested in listening for data coming from server: `deserializer`,\n * which allows us to customize the deserialization strategy of data before passing it\n * to the socket client. By default, `deserializer` is going to apply `JSON.parse` to each message coming\n * from the Server.\n *\n * ## Examples\n *\n * **deserializer**, the default for this property is `JSON.parse` but since there are just two options\n * for incoming data, either be text or binary data. We can apply a custom deserialization strategy\n * or just simply skip the default behaviour.\n *\n * ```ts\n * import { webSocket } from 'rxjs/webSocket';\n *\n * const wsSubject = webSocket({\n *   url: 'ws://localhost:8081',\n *   //Apply any transformation of your choice.\n *   deserializer: ({ data }) => data\n * });\n *\n * wsSubject.subscribe(console.log);\n *\n * // Let's suppose we have this on the Server: ws.send('This is a msg from the server')\n * //output\n * //\n * // This is a msg from the server\n * ```\n *\n * **serializer** allows us to apply custom serialization strategy but for the outgoing messages.\n *\n * ```ts\n * import { webSocket } from 'rxjs/webSocket';\n *\n * const wsSubject = webSocket({\n *   url: 'ws://localhost:8081',\n *   // Apply any transformation of your choice.\n *   serializer: msg => JSON.stringify({ channel: 'webDevelopment', msg: msg })\n * });\n *\n * wsSubject.subscribe(() => subject.next('msg to the server'));\n *\n * // Let's suppose we have this on the Server:\n * //   ws.on('message', msg => console.log);\n * //   ws.send('This is a msg from the server');\n * // output at server side:\n * //\n * // {\"channel\":\"webDevelopment\",\"msg\":\"msg to the server\"}\n * ```\n *\n * **closeObserver** allows us to set a custom error when an error raises up.\n *\n * ```ts\n * import { webSocket } from 'rxjs/webSocket';\n *\n * const wsSubject = webSocket({\n *   url: 'ws://localhost:8081',\n *   closeObserver: {\n *     next() {\n *       const customError = { code: 6666, reason: 'Custom evil reason' }\n *       console.log(`code: ${ customError.code }, reason: ${ customError.reason }`);\n *     }\n *   }\n * });\n *\n * // output\n * // code: 6666, reason: Custom evil reason\n * ```\n *\n * **openObserver**, Let's say we need to make some kind of init task before sending/receiving msgs to the\n * webSocket or sending notification that the connection was successful, this is when\n * openObserver is useful for.\n *\n * ```ts\n * import { webSocket } from 'rxjs/webSocket';\n *\n * const wsSubject = webSocket({\n *   url: 'ws://localhost:8081',\n *   openObserver: {\n *     next: () => {\n *       console.log('Connection ok');\n *     }\n *   }\n * });\n *\n * // output\n * // Connection ok\n * ```\n */\nexport interface WebSocketSubjectConfig<In, Out = In> {\n  /** The url of the socket server to connect to */\n  url: string;\n  /** The protocol to use to connect */\n  protocol?: string | Array<string>;\n  /** @deprecated Will be removed in v8. Use {@link deserializer} instead. */\n  resultSelector?: (e: MessageEvent) => Out;\n  /**\n   * A serializer used to create messages from passed values before the\n   * messages are sent to the server. Defaults to JSON.stringify.\n   */\n  serializer?: (value: In) => WebSocketMessage;\n  /**\n   * A deserializer used for messages arriving on the socket from the\n   * server. Defaults to JSON.parse.\n   */\n  deserializer?: (e: MessageEvent) => Out;\n  /**\n   * An Observer that watches when open events occur on the underlying web socket.\n   */\n  openObserver?: NextObserver<Event>;\n  /**\n   * An Observer that watches when close events occur on the underlying web socket\n   */\n  closeObserver?: NextObserver<CloseEvent>;\n  /**\n   * An Observer that watches when a close is about to occur due to\n   * unsubscription.\n   */\n  closingObserver?: NextObserver<void>;\n  /**\n   * A WebSocket constructor to use. This is useful for situations like using a\n   * WebSocket impl in Node (WebSocket is a DOM API), or for mocking a WebSocket\n   * for testing purposes\n   */\n  WebSocketCtor?: { new (url: string, protocols?: string | string[]): WebSocket };\n  /** Sets the `binaryType` property of the underlying WebSocket. */\n  binaryType?: 'blob' | 'arraybuffer';\n}\n\nconst DEFAULT_WEBSOCKET_CONFIG = {\n  deserializer: (e: MessageEvent) => JSON.parse(e.data),\n  serializer: (value: any) => JSON.stringify(value),\n};\n\nconst WEBSOCKETSUBJECT_INVALID_ERROR_OBJECT =\n  'WebSocketSubject.error must be called with an object with an error code, and an optional reason: { code: number, reason: string }';\n\nexport type WebSocketMessage = string | ArrayBuffer | Blob | ArrayBufferView;\n\nexport class WebSocketSubject<In, Out = In> extends Observable<Out> {\n  private _config: WebSocketSubjectConfig<In, Out> &\n    Required<Pick<WebSocketSubjectConfig<In, Out>, 'WebSocketCtor' | 'serializer' | 'deserializer'>>;\n\n  private _socket: WebSocket | null = null;\n\n  private _inputBuffer: In[] = [];\n\n  private _hasError = false;\n\n  private _error: any;\n\n  private _isComplete = false;\n\n  private _subscriberCounter = 0;\n\n  private _subscribers = new Map<number, Subscriber<Out>>();\n\n  get observed() {\n    return this._subscribers.size > 0;\n  }\n\n  constructor(urlConfigOrSource: string | WebSocketSubjectConfig<In, Out>) {\n    super();\n    const userConfig = typeof urlConfigOrSource === 'string' ? { url: urlConfigOrSource } : urlConfigOrSource;\n    this._config = {\n      ...DEFAULT_WEBSOCKET_CONFIG,\n      // Setting this here because a previous version of this allowed\n      // WebSocket to be polyfilled later than DEFAULT_WEBSOCKET_CONFIG\n      // was defined.\n      WebSocketCtor: WebSocket,\n      ...userConfig,\n    };\n\n    if (!this._config.WebSocketCtor) {\n      throw new Error('no WebSocket constructor can be found');\n    }\n  }\n\n  private _resetState() {\n    this._socket = null;\n    this._subscriberCounter = 0;\n    this._subscribers.clear();\n    this._inputBuffer = [];\n    this._hasError = false;\n    this._isComplete = false;\n    this._error = null;\n  }\n\n  /**\n   * Creates an {@link Observable}, that when subscribed to, sends a message,\n   * defined by the `subMsg` function, to the server over the socket to begin a\n   * subscription to data over that socket. Once data arrives, the\n   * `messageFilter` argument will be used to select the appropriate data for\n   * the resulting Observable. When finalization occurs, either due to\n   * unsubscription, completion, or error, a message defined by the `unsubMsg`\n   * argument will be sent to the server over the WebSocketSubject.\n   *\n   * @param subMsg A function to generate the subscription message to be sent to\n   * the server. This will still be processed by the serializer in the\n   * WebSocketSubject's config. (Which defaults to JSON serialization)\n   * @param unsubMsg A function to generate the unsubscription message to be\n   * sent to the server at finalization. This will still be processed by the\n   * serializer in the WebSocketSubject's config.\n   * @param messageFilter A predicate for selecting the appropriate messages\n   * from the server for the output stream.\n   */\n  multiplex(subMsg: () => In, unsubMsg: () => In, messageFilter: (value: Out) => boolean) {\n    return new Observable<Out>((destination) => {\n      this.next(subMsg());\n      destination.add(() => {\n        this.next(unsubMsg());\n      });\n      this.subscribe(\n        operate({\n          destination,\n          next: (x) => {\n            if (messageFilter(x)) {\n              destination.next(x);\n            }\n          },\n        })\n      );\n    });\n  }\n\n  #outputNext(value: Out) {\n    for (const subscriber of Array.from(this._subscribers.values())) {\n      subscriber.next(value);\n    }\n  }\n\n  #outputError(err: any) {\n    const subscribers = Array.from(this._subscribers.values());\n    for (const subscriber of subscribers) {\n      subscriber.error(err);\n    }\n  }\n\n  #outputComplete() {\n    const subscribers = Array.from(this._subscribers.values());\n    for (const subscriber of subscribers) {\n      subscriber.complete();\n    }\n  }\n\n  private _connectSocket() {\n    const { WebSocketCtor, protocol, url, binaryType, deserializer, openObserver, closeObserver } = this._config;\n\n    let socket: WebSocket | null = null;\n    try {\n      socket = protocol ? new WebSocketCtor(url, protocol) : new WebSocketCtor(url);\n      this._socket = socket;\n      if (binaryType) {\n        this._socket.binaryType = binaryType;\n      }\n    } catch (err) {\n      this.#outputError(err);\n      return;\n    }\n\n    socket.onopen = (evt) => {\n      if (socket !== this._socket) {\n        socket?.close();\n        return;\n      }\n\n      openObserver?.next(evt);\n\n      while (this._inputBuffer.length > 0) {\n        this.next(this._inputBuffer.shift()!);\n      }\n\n      if (this._hasError) {\n        this.error(this._error);\n      } else if (this._isComplete) {\n        this.complete();\n      }\n    };\n\n    socket.onerror = (e: Event) => {\n      if (socket !== this._socket) {\n        return;\n      }\n\n      this.#outputError(e);\n    };\n\n    socket.onclose = (e: CloseEvent) => {\n      if (socket !== this._socket) {\n        return;\n      }\n\n      closeObserver?.next(e);\n\n      if (e.wasClean) {\n        this.#outputComplete();\n      } else {\n        this.#outputError(e);\n      }\n    };\n\n    socket.onmessage = (e: MessageEvent) => {\n      try {\n        this.#outputNext(deserializer(e));\n      } catch (err) {\n        this.#outputError(err);\n      }\n    };\n  }\n\n  next(value: In) {\n    if (this._socket?.readyState !== 1) {\n      this._inputBuffer.push(value);\n    } else {\n      try {\n        this._socket.send(this._config.serializer(value));\n      } catch (err: any) {\n        this.error(err);\n      }\n    }\n  }\n\n  error(err: any) {\n    if (this._socket?.readyState === 1) {\n      this._config.closingObserver?.next(undefined);\n      if (err?.code) {\n        this._socket?.close(err.code, err.reason);\n      } else {\n        this.#outputError(new TypeError(WEBSOCKETSUBJECT_INVALID_ERROR_OBJECT));\n      }\n      this._resetState();\n    } else {\n      this._hasError = true;\n      this._error = err;\n    }\n  }\n\n  complete() {\n    if (this._socket?.readyState === 1) {\n      this.#closeSocket();\n    } else {\n      this._isComplete = true;\n    }\n  }\n\n  #closeSocket() {\n    const { _socket } = this;\n    this._config.closingObserver?.next(undefined);\n    if (_socket && _socket.readyState <= 1) {\n      _socket.close();\n    }\n    this._resetState();\n  }\n\n  /** @internal */\n  protected _subscribe(subscriber: Subscriber<Out>): Subscription {\n    if (!this._socket) {\n      this._connectSocket();\n    }\n    const subscriberId = this._subscriberCounter++;\n    this._subscribers.set(subscriberId, subscriber);\n    subscriber.add(() => {\n      this._subscribers.delete(subscriberId);\n      if (!this.observed) {\n        this.#closeSocket();\n      }\n    });\n    return subscriber;\n  }\n\n  unsubscribe() {\n    const subscribers = Array.from(this._subscribers.values());\n    this._subscribers.clear();\n    for (const subscriber of subscribers) {\n      subscriber.unsubscribe();\n    }\n    this._resetState();\n  }\n}\n"
  },
  {
    "path": "packages/rxjs/src/internal/observable/dom/animationFrames.ts",
    "content": "import { Observable } from '@rxjs/observable';\nimport type { TimestampProvider } from '../../types.js';\nimport { performanceTimestampProvider } from '../../scheduler/performanceTimestampProvider.js';\nimport { animationFrameProvider } from '../../scheduler/animationFrameProvider.js';\n\n/**\n * An observable of animation frames\n *\n * Emits the amount of time elapsed since subscription and the timestamp on each animation frame.\n * Defaults to milliseconds provided to the requestAnimationFrame's callback. Does not end on its own.\n *\n * Every subscription will start a separate animation loop. Since animation frames are always scheduled\n * by the browser to occur directly before a repaint, scheduling more than one animation frame synchronously\n * should not be much different or have more overhead than looping over an array of events during\n * a single animation frame. However, if for some reason the developer would like to ensure the\n * execution of animation-related handlers are all executed during the same task by the engine,\n * the `share` operator can be used.\n *\n * This is useful for setting up animations with RxJS.\n *\n * ## Examples\n *\n * Tweening a div to move it on the screen\n *\n * ```ts\n * import { animationFrames, map, takeWhile, endWith } from 'rxjs';\n *\n * function tween(start: number, end: number, duration: number) {\n *   const diff = end - start;\n *   return animationFrames().pipe(\n *     // Figure out what percentage of time has passed\n *     map(({ elapsed }) => elapsed / duration),\n *     // Take the vector while less than 100%\n *     takeWhile(v => v < 1),\n *     // Finish with 100%\n *     endWith(1),\n *     // Calculate the distance traveled between start and end\n *     map(v => v * diff + start)\n *   );\n * }\n *\n * // Setup a div for us to move around\n * const div = document.createElement('div');\n * document.body.appendChild(div);\n * div.style.position = 'absolute';\n * div.style.width = '40px';\n * div.style.height = '40px';\n * div.style.backgroundColor = 'lime';\n * div.style.transform = 'translate3d(10px, 0, 0)';\n *\n * tween(10, 200, 4000).subscribe(x => {\n *   div.style.transform = `translate3d(${ x }px, 0, 0)`;\n * });\n * ```\n *\n * Providing a custom timestamp provider\n *\n * ```ts\n * import { animationFrames, TimestampProvider } from 'rxjs';\n *\n * // A custom timestamp provider\n * let now = 0;\n * const customTSProvider: TimestampProvider = {\n *   now() { return now++; }\n * };\n *\n * const source$ = animationFrames(customTSProvider);\n *\n * // Log increasing numbers 0...1...2... on every animation frame.\n * source$.subscribe(({ elapsed }) => console.log(elapsed));\n * ```\n *\n * @param timestampProvider An object with a `now` method that provides a numeric timestamp\n */\nexport function animationFrames(timestampProvider?: TimestampProvider) {\n  return timestampProvider ? animationFramesFactory(timestampProvider) : DEFAULT_ANIMATION_FRAMES;\n}\n\n/**\n * Does the work of creating the observable for `animationFrames`.\n * @param timestampProvider The timestamp provider to use to create the observable\n */\nfunction animationFramesFactory(timestampProvider?: TimestampProvider) {\n  return new Observable<{ timestamp: number; elapsed: number }>((subscriber) => {\n    // If no timestamp provider is specified, use performance.now() - as it\n    // will return timestamps 'compatible' with those passed to the run\n    // callback and won't be affected by NTP adjustments, etc.\n    const provider = timestampProvider || performanceTimestampProvider;\n\n    // Capture the start time upon subscription, as the run callback can remain\n    // queued for a considerable period of time and the elapsed time should\n    // represent the time elapsed since subscription - not the time since the\n    // first rendered animation frame.\n    const start = provider.now();\n\n    let id = 0;\n    const run = () => {\n      if (!subscriber.closed) {\n        id = animationFrameProvider.requestAnimationFrame((timestamp: DOMHighResTimeStamp | number) => {\n          id = 0;\n          // Use the provider's timestamp to calculate the elapsed time. Note that\n          // this means - if the caller hasn't passed a provider - that\n          // performance.now() will be used instead of the timestamp that was\n          // passed to the run callback. The reason for this is that the timestamp\n          // passed to the callback can be earlier than the start time, as it\n          // represents the time at which the browser decided it would render any\n          // queued frames - and that time can be earlier the captured start time.\n          const now = provider.now();\n          subscriber.next({\n            timestamp: timestampProvider ? now : timestamp,\n            elapsed: now - start,\n          });\n          run();\n        });\n      }\n    };\n\n    run();\n\n    return () => {\n      if (id) {\n        animationFrameProvider.cancelAnimationFrame(id);\n      }\n    };\n  });\n}\n\n/**\n * In the common case, where the timestamp provided by the rAF API is used,\n * we use this shared observable to reduce overhead.\n */\nconst DEFAULT_ANIMATION_FRAMES = animationFramesFactory();\n"
  },
  {
    "path": "packages/rxjs/src/internal/observable/dom/fetch.ts",
    "content": "import { operate, Observable, from } from '@rxjs/observable';\nimport type { ObservableInput } from '../../types.js';\n\nexport function fromFetch<T>(\n  input: string | Request,\n  init: RequestInit & {\n    selector: (response: Response) => ObservableInput<T>;\n  }\n): Observable<T>;\n\nexport function fromFetch(input: string | Request, init?: RequestInit): Observable<Response>;\n\n/**\n * Uses [the Fetch API](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API) to\n * make an HTTP request.\n *\n * **WARNING** Parts of the fetch API are still experimental. `AbortController` is\n * required for this implementation to work and use cancellation appropriately.\n *\n * Will automatically set up an internal [AbortController](https://developer.mozilla.org/en-US/docs/Web/API/AbortController)\n * in order to finalize the internal `fetch` when the subscription tears down.\n *\n * If a `signal` is provided via the `init` argument, it will behave like it usually does with\n * `fetch`. If the provided `signal` aborts, the error that `fetch` normally rejects with\n * in that scenario will be emitted as an error from the observable.\n *\n * ## Examples\n *\n * Basic use\n *\n * ```ts\n * import { fromFetch } from 'rxjs/fetch';\n * import { switchMap, of, catchError } from 'rxjs';\n *\n * const data$ = fromFetch('https://api.github.com/users?per_page=5').pipe(\n *   switchMap(response => {\n *     if (response.ok) {\n *       // OK return data\n *       return response.json();\n *     } else {\n *       // Server is returning a status requiring the client to try something else.\n *       return of({ error: true, message: `Error ${ response.status }` });\n *     }\n *   }),\n *   catchError(err => {\n *     // Network or other error, handle appropriately\n *     console.error(err);\n *     return of({ error: true, message: err.message })\n *   })\n * );\n *\n * data$.subscribe({\n *   next: result => console.log(result),\n *   complete: () => console.log('done')\n * });\n * ```\n *\n * ### Use with Chunked Transfer Encoding\n *\n * With HTTP responses that use [chunked transfer encoding](https://tools.ietf.org/html/rfc7230#section-3.3.1),\n * the promise returned by `fetch` will resolve as soon as the response's headers are\n * received.\n *\n * That means the `fromFetch` observable will emit a `Response` - and will\n * then complete - before the body is received. When one of the methods on the\n * `Response` - like `text()` or `json()` - is called, the returned promise will not\n * resolve until the entire body has been received. Unsubscribing from any observable\n * that uses the promise as an observable input will not abort the request.\n *\n * To facilitate aborting the retrieval of responses that use chunked transfer encoding,\n * a `selector` can be specified via the `init` parameter:\n *\n * ```ts\n * import { of } from 'rxjs';\n * import { fromFetch } from 'rxjs/fetch';\n *\n * const data$ = fromFetch('https://api.github.com/users?per_page=5', {\n *   selector: response => response.json()\n * });\n *\n * data$.subscribe({\n *   next: result => console.log(result),\n *   complete: () => console.log('done')\n * });\n * ```\n *\n * @param input The resource you would like to fetch. Can be a url or a request object.\n * @param initWithSelector A configuration object for the fetch.\n * [See MDN for more details](https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/fetch#Parameters)\n * @returns An Observable, that when subscribed to, performs an HTTP request using the native `fetch`\n * function. The {@link Subscription} is tied to an `AbortController` for the fetch.\n */\nexport function fromFetch<T>(\n  input: string | Request,\n  initWithSelector: RequestInit & {\n    selector?: (response: Response) => ObservableInput<T>;\n  } = {}\n): Observable<Response | T> {\n  const { selector, ...init } = initWithSelector;\n  return new Observable<Response | T>((destination) => {\n    // Our controller for aborting this fetch.\n    // Any externally provided AbortSignal will have to call\n    // abort on this controller when signaled, because the\n    // signal from this controller is what is being passed to `fetch`.\n    const controller = new AbortController();\n    const { signal } = controller;\n    // This flag exists to make sure we don't `abort()` the fetch upon tearing down\n    // this observable after emitting a Response. Aborting in such circumstances\n    // would also abort subsequent methods - like `json()` - that could be called\n    // on the Response. Consider: `rx(fromFetch(), take(1), mergeMap(res => res.json()))`\n    let abortable = true;\n\n    // If the user provided an init configuration object,\n    // let's process it and chain our abort signals, if necessary.\n    // If a signal is provided, just have it finalized. It's a cancellation token, basically.\n    const { signal: outerSignal } = init;\n    if (outerSignal) {\n      if (outerSignal.aborted) {\n        controller.abort();\n      } else {\n        // We got an AbortSignal from the arguments passed into `fromFetch`.\n        // We need to wire up our AbortController to abort when this signal aborts.\n        const outerSignalHandler = () => {\n          if (!signal.aborted) {\n            controller.abort();\n          }\n        };\n        outerSignal.addEventListener('abort', outerSignalHandler);\n        destination.add(() => outerSignal.removeEventListener('abort', outerSignalHandler));\n      }\n    }\n\n    // The initialization object passed to `fetch` as the second\n    // argument. This ferries in important information, including our\n    // AbortSignal. Create a new init, so we don't accidentally mutate the\n    // passed init, or reassign it. This is because the init passed in\n    // is shared between each subscription to the result.\n    const perSubscriberInit: RequestInit = { ...init, signal };\n\n    const handleError = (err: any) => {\n      abortable = false;\n      destination.error(err);\n    };\n\n    fetch(input, perSubscriberInit)\n      .then((response) => {\n        if (selector) {\n          // If we have a selector function, use it to project our response.\n          // Note that any error that comes from our selector will be\n          // sent to the promise `catch` below and handled.\n          from(selector(response)).subscribe(\n            operate({\n              destination,\n              // The projected response is complete.\n              complete: () => {\n                abortable = false;\n                destination.complete();\n              },\n              error: handleError,\n            })\n          );\n        } else {\n          abortable = false;\n          destination.next(response);\n          destination.complete();\n        }\n      })\n      .catch(handleError);\n\n    return () => {\n      if (abortable) {\n        controller.abort();\n      }\n    };\n  });\n}\n"
  },
  {
    "path": "packages/rxjs/src/internal/observable/dom/webSocket.ts",
    "content": "import type { WebSocketSubjectConfig } from './WebSocketSubject.js';\nimport { WebSocketSubject } from './WebSocketSubject.js';\n\n/**\n * Wrapper around the w3c-compatible WebSocket object provided by the browser.\n *\n * <span class=\"informal\">{@link Subject} that communicates with a server via WebSocket</span>\n *\n * `webSocket` is a factory function that produces a `WebSocketSubject`,\n * which can be used to make WebSocket connection with an arbitrary endpoint.\n * `webSocket` accepts as an argument either a string with url of WebSocket endpoint, or an\n * {@link WebSocketSubjectConfig} object for providing additional configuration, as\n * well as Observers for tracking lifecycle of WebSocket connection.\n *\n * When `WebSocketSubject` is subscribed, it attempts to make a socket connection,\n * unless there is one made already. This means that many subscribers will always listen\n * on the same socket, thus saving resources. If however, two instances are made of `WebSocketSubject`,\n * even if these two were provided with the same url, they will attempt to make separate\n * connections. When consumer of a `WebSocketSubject` unsubscribes, socket connection is closed,\n * only if there are no more subscribers still listening. If after some time a consumer starts\n * subscribing again, connection is reestablished.\n *\n * Once connection is made, whenever a new message comes from the server, `WebSocketSubject` will emit that\n * message as a value in the stream. By default, a message from the socket is parsed via `JSON.parse`. If you\n * want to customize how deserialization is handled (if at all), you can provide custom `resultSelector`\n * function in {@link WebSocketSubject}. When connection closes, stream will complete, provided it happened without\n * any errors. If at any point (starting, maintaining or closing a connection) there is an error,\n * stream will also error with whatever WebSocket API has thrown.\n *\n * By virtue of being a {@link Subject}, `WebSocketSubject` allows for receiving and sending messages from the server. In order\n * to communicate with a connected endpoint, use `next`, `error` and `complete` methods. `next` sends a value to the server, so bear in mind\n * that this value will not be serialized beforehand. Because of This, `JSON.stringify` will have to be called on a value by hand,\n * before calling `next` with a result. Note also that if at the moment of nexting value\n * there is no socket connection (for example no one is subscribing), those values will be buffered, and sent when connection\n * is finally established. `complete` method closes socket connection. `error` does the same,\n * as well as notifying the server that something went wrong via status code and string with details of what happened.\n * Since status code is required in WebSocket API, `WebSocketSubject` does not allow, like regular `Subject`,\n * arbitrary values being passed to the `error` method. It needs to be called with an object that has `code`\n * property with status code number and optional `reason` property with string describing details\n * of an error.\n *\n * Calling `next` does not affect subscribers of `WebSocketSubject` - they have no\n * information that something was sent to the server (unless of course the server\n * responds somehow to a message). On the other hand, since calling `complete` triggers\n * an attempt to close socket connection. If that connection is closed without any errors, stream will\n * complete, thus notifying all subscribers. And since calling `error` closes\n * socket connection as well, just with a different status code for the server, if closing itself proceeds\n * without errors, subscribed Observable will not error, as one might expect, but complete as usual. In both cases\n * (calling `complete` or `error`), if process of closing socket connection results in some errors, *then* stream\n * will error.\n *\n * **Multiplexing**\n *\n * `WebSocketSubject` has an additional operator, not found in other Subjects. It is called `multiplex` and it is\n * used to simulate opening several socket connections, while in reality maintaining only one.\n * For example, an application has both chat panel and real-time notifications about sport news. Since these are two distinct functions,\n * it would make sense to have two separate connections for each. Perhaps there could even be two separate services with WebSocket\n * endpoints, running on separate machines with only GUI combining them together. Having a socket connection\n * for each functionality could become too resource expensive. It is a common pattern to have single\n * WebSocket endpoint that acts as a gateway for the other services (in this case chat and sport news services).\n * Even though there is a single connection in a client app, having the ability to manipulate streams as if it\n * were two separate sockets is desirable. This eliminates manually registering and unregistering in a gateway for\n * given service and filter out messages of interest. This is exactly what `multiplex` method is for.\n *\n * Method accepts three parameters. First two are functions returning subscription and unsubscription messages\n * respectively. These are messages that will be sent to the server, whenever consumer of resulting Observable\n * subscribes and unsubscribes. Server can use them to verify that some kind of messages should start or stop\n * being forwarded to the client. In case of the above example application, after getting subscription message with proper identifier,\n * gateway server can decide that it should connect to real sport news service and start forwarding messages from it.\n * Note that both messages will be sent as returned by the functions, they are by default serialized using JSON.stringify, just\n * as messages pushed via `next`. Also bear in mind that these messages will be sent on *every* subscription and\n * unsubscription. This is potentially dangerous, because one consumer of an Observable may unsubscribe and the server\n * might stop sending messages, since it got unsubscription message. This needs to be handled\n * on the server or using {@link connectable} on a Observable returned from 'multiplex'.\n *\n * Last argument to `multiplex` is a `messageFilter` function which should return a boolean. It is used to filter out messages\n * sent by the server to only those that belong to simulated WebSocket stream. For example, server might mark these\n * messages with some kind of string identifier on a message object and `messageFilter` would return `true`\n * if there is such identifier on an object emitted by the socket. Messages which returns `false` in `messageFilter` are simply skipped,\n * and are not passed down the stream.\n *\n * Return value of `multiplex` is an Observable with messages incoming from emulated socket connection. Note that this\n * is not a `WebSocketSubject`, so calling `next` or `multiplex` again will fail. For pushing values to the\n * server, use root `WebSocketSubject`.\n *\n * ## Examples\n *\n * Listening for messages from the server\n *\n * ```ts\n * import { webSocket } from 'rxjs/webSocket';\n *\n * const subject = webSocket<string>('ws://localhost:8081');\n *\n * subject.subscribe({\n *   next: msg => console.log('message received: ' + msg), // Called whenever there is a message from the server.\n *   error: err => console.log(err), // Called if at any point WebSocket API signals some kind of error.\n *   complete: () => console.log('complete') // Called when connection is closed (for whatever reason).\n *  });\n * ```\n *\n * Pushing messages to the server\n *\n * ```ts\n * import { webSocket } from 'rxjs/webSocket';\n *\n * interface SendMsg {\n *  message: string;\n * }\n *\n * interface RespMsg {\n *  data: any;\n * }\n *\n * const subject = webSocket<SendMsg, RespMsg>('ws://localhost:8081');\n *\n * subject.subscribe();\n * // Note that at least one consumer has to subscribe to the created subject - otherwise \"nexted\" values will be just buffered and not sent,\n * // since no connection was established!\n *\n * subject.next({ message: 'some message' });\n * // This will send a message to the server once a connection is made. Remember value is serialized with JSON.stringify by default!\n *\n * subject.complete(); // Closes the connection.\n *\n * subject.error({ code: 4000, reason: 'I think our app just broke!' });\n * // Also closes the connection, but let's the server know that this closing is caused by some error.\n * ```\n *\n * Multiplexing WebSocket\n *\n * ```ts\n * import { webSocket } from 'rxjs/webSocket';\n *\n * interface SubMsg {\n *  subscribe: string;\n * }\n *\n * interface UnsubMsg {\n *  unsubscribe: string;\n * }\n *\n * interface RespMsg {\n *  type: string;\n *  data: any;\n * }\n *\n *\n * const subject = webSocket<SubMsg | UnsubMsg, RespMsg>('ws://localhost:8081');\n *\n * const observableA = subject.multiplex(\n *   () => ({ subscribe: 'A' }), // When server gets this message, it will start sending messages for 'A'...\n *   () => ({ unsubscribe: 'A' }), // ...and when gets this one, it will stop.\n *   message => message.type === 'A' // If the function returns `true` message is passed down the stream. Skipped if the function returns false.\n * );\n *\n * const observableB = subject.multiplex( // And the same goes for 'B'.\n *   () => ({ subscribe: 'B' }),\n *   () => ({ unsubscribe: 'B' }),\n *   message => message.type === 'B'\n * );\n *\n * const subA = observableA.subscribe(messageForA => console.log(messageForA));\n * // At this moment WebSocket connection is established. Server gets '{\"subscribe\": \"A\"}' message and starts sending messages for 'A',\n * // which we log here.\n *\n * const subB = observableB.subscribe(messageForB => console.log(messageForB));\n * // Since we already have a connection, we just send '{\"subscribe\": \"B\"}' message to the server. It starts sending messages for 'B',\n * // which we log here.\n *\n * subB.unsubscribe();\n * // Message '{\"unsubscribe\": \"B\"}' is sent to the server, which stops sending 'B' messages.\n *\n * subA.unsubscribe();\n * // Message '{\"unsubscribe\": \"A\"}' makes the server stop sending messages for 'A'. Since there is no more subscribers to root Subject,\n * // socket connection closes.\n * ```\n *\n * @param urlConfigOrSource The WebSocket endpoint as an url or an object with configuration and additional Observers.\n * @return Subject which allows to both send and receive messages via WebSocket connection.\n */\nexport function webSocket<In, Out = In>(urlConfigOrSource: string | WebSocketSubjectConfig<In, Out>): WebSocketSubject<In, Out> {\n  return new WebSocketSubject<In, Out>(urlConfigOrSource);\n}\n"
  },
  {
    "path": "packages/rxjs/src/internal/observable/empty.ts",
    "content": "import { Observable } from '@rxjs/observable';\n\n/**\n * A simple Observable that emits no items to the Observer and immediately\n * emits a complete notification.\n *\n * <span class=\"informal\">Just emits 'complete', and nothing else.</span>\n *\n * ![](empty.png)\n *\n * A simple Observable that only emits the complete notification. It can be used\n * for composing with other Observables, such as in a {@link mergeMap}.\n *\n * ## Examples\n *\n * Log complete notification\n *\n * ```ts\n * import { EMPTY } from 'rxjs';\n *\n * EMPTY.subscribe({\n *   next: () => console.log('Next'),\n *   complete: () => console.log('Complete!')\n * });\n *\n * // Outputs\n * // Complete!\n * ```\n *\n * Emit the number 7, then complete\n *\n * ```ts\n * import { EMPTY, startWith } from 'rxjs';\n *\n * const result = EMPTY.pipe(startWith(7));\n * result.subscribe(x => console.log(x));\n *\n * // Outputs\n * // 7\n * ```\n *\n * Map and flatten only odd numbers to the sequence `'a'`, `'b'`, `'c'`\n *\n * ```ts\n * import { interval, mergeMap, of, EMPTY } from 'rxjs';\n *\n * const interval$ = interval(1000);\n * const result = interval$.pipe(\n *   mergeMap(x => x % 2 === 1 ? of('a', 'b', 'c') : EMPTY),\n * );\n * result.subscribe(x => console.log(x));\n *\n * // Results in the following to the console:\n * // x is equal to the count on the interval, e.g. (0, 1, 2, 3, ...)\n * // x will occur every 1000ms\n * // if x % 2 is equal to 1, print a, b, c (each on its own)\n * // if x % 2 is not equal to 1, nothing will be output\n * ```\n *\n * @see {@link Observable}\n * @see {@link NEVER}\n * @see {@link of}\n * @see {@link throwError}\n */\nexport const EMPTY = new Observable<never>((subscriber) => subscriber.complete());\n"
  },
  {
    "path": "packages/rxjs/src/internal/observable/forkJoin.ts",
    "content": "import { Observable, from, operate } from '@rxjs/observable';\nimport type { ObservedValueOf, ObservableInputTuple, ObservableInput } from '../types.js';\nimport { argsArgArrayOrObject } from '../util/argsArgArrayOrObject.js';\nimport { popResultSelector } from '../util/args.js';\nimport { mapOneOrManyArgs } from '../util/mapOneOrManyArgs.js';\nimport { createObject } from '../util/createObject.js';\nimport type { AnyCatcher } from '../AnyCatcher.js';\nimport { EmptyError } from '../util/EmptyError.js';\n\n// forkJoin(any)\n// We put this first because we need to catch cases where the user has supplied\n// _exactly `any`_ as the argument. Since `any` literally matches _anything_,\n// we don't want it to randomly hit one of the other type signatures below,\n// as we have no idea at build-time what type we should be returning when given an any.\n\n/**\n * You have passed `any` here, we can't figure out if it is\n * an array or an object, so you're getting `unknown`. Use better types.\n * @param arg Something typed as `any`\n */\nexport function forkJoin<T extends AnyCatcher>(arg: T): Observable<unknown>;\n\n// forkJoin(null | undefined)\nexport function forkJoin(scheduler: null | undefined): Observable<never>;\n\n// forkJoin([a, b, c])\nexport function forkJoin(sources: readonly []): Observable<never>;\nexport function forkJoin<A extends readonly unknown[]>(sources: readonly [...ObservableInputTuple<A>]): Observable<A>;\nexport function forkJoin<A extends readonly unknown[], R>(\n  sources: readonly [...ObservableInputTuple<A>],\n  resultSelector: (...values: A) => R\n): Observable<R>;\n\n// forkJoin(a, b, c)\n/** @deprecated Pass an array of sources instead. The rest-parameters signature will be removed in v8. Details: https://rxjs.dev/deprecations/array-argument */\nexport function forkJoin<A extends readonly unknown[]>(...sources: [...ObservableInputTuple<A>]): Observable<A>;\n/** @deprecated Pass an array of sources instead. The rest-parameters signature will be removed in v8. Details: https://rxjs.dev/deprecations/array-argument */\nexport function forkJoin<A extends readonly unknown[], R>(\n  ...sourcesAndResultSelector: [...ObservableInputTuple<A>, (...values: A) => R]\n): Observable<R>;\n\n// forkJoin({a, b, c})\nexport function forkJoin(sourcesObject: { [K in any]: never }): Observable<never>;\nexport function forkJoin<T extends Record<string, ObservableInput<any>>>(\n  sourcesObject: T\n): Observable<{ [K in keyof T]: ObservedValueOf<T[K]> }>;\n\n/**\n * Accepts an `Array` of {@link ObservableInput} or a dictionary `Object` of {@link ObservableInput} and returns\n * an {@link Observable} that emits either an array of values in the exact same order as the passed array,\n * or a dictionary of values in the same shape as the passed dictionary.\n *\n * <span class=\"informal\">Wait for Observables to complete and then combine last values they emitted;\n * complete immediately if an empty array is passed.</span>\n *\n * ![](forkJoin.png)\n *\n * `forkJoin` is an operator that takes any number of input observables which can be passed either as an array\n * or a dictionary of input observables. If no input observables are provided (e.g. an empty array is passed),\n * then the resulting stream will complete immediately.\n *\n * `forkJoin` will wait for all passed observables to emit and complete and then it will emit an array or an object with last\n * values from corresponding observables.\n *\n * If you pass an array of `n` observables to the operator, then the resulting\n * array will have `n` values, where the first value is the last one emitted by the first observable,\n * second value is the last one emitted by the second observable and so on.\n *\n * If you pass a dictionary of observables to the operator, then the resulting\n * objects will have the same keys as the dictionary passed, with their last values they have emitted\n * located at the corresponding key.\n *\n * That means `forkJoin` will not emit more than once and it will complete after that. If you need to emit combined\n * values not only at the end of the lifecycle of passed observables, but also throughout it, try out {@link combineLatest}\n * or {@link zip} instead.\n *\n * In order for the resulting array to have the same length as the number of input observables, whenever any of\n * the given observables completes without emitting any value, `forkJoin` will complete at that moment as well\n * and it will not emit anything either, even if it already has some last values from other observables.\n * Conversely, if there is an observable that never completes, `forkJoin` will never complete either,\n * unless at any point some other observable completes without emitting a value, which brings us back to\n * the previous case. Overall, in order for `forkJoin` to emit a value, all given observables\n * have to emit something at least once and complete.\n *\n * If any given observable errors at some point, `forkJoin` will error as well and immediately unsubscribe\n * from the other observables.\n *\n * Optionally `forkJoin` accepts a `resultSelector` function, that will be called with values which normally\n * would land in the emitted array. Whatever is returned by the `resultSelector`, will appear in the output\n * observable instead. This means that the default `resultSelector` can be thought of as a function that takes\n * all its arguments and puts them into an array. Note that the `resultSelector` will be called only\n * when `forkJoin` is supposed to emit a result.\n *\n * ## Examples\n *\n * Use `forkJoin` with a dictionary of observable inputs\n *\n * ```ts\n * import { forkJoin, of, timer } from 'rxjs';\n *\n * const observable = forkJoin({\n *   foo: of(1, 2, 3, 4),\n *   bar: Promise.resolve(8),\n *   baz: timer(4000)\n * });\n * observable.subscribe({\n *  next: value => console.log(value),\n *  complete: () => console.log('This is how it ends!'),\n * });\n *\n * // Logs:\n * // { foo: 4, bar: 8, baz: 0 } after 4 seconds\n * // 'This is how it ends!' immediately after\n * ```\n *\n * Use `forkJoin` with an array of observable inputs\n *\n * ```ts\n * import { forkJoin, of, timer } from 'rxjs';\n *\n * const observable = forkJoin([\n *   of(1, 2, 3, 4),\n *   Promise.resolve(8),\n *   timer(4000)\n * ]);\n * observable.subscribe({\n *  next: value => console.log(value),\n *  complete: () => console.log('This is how it ends!'),\n * });\n *\n * // Logs:\n * // [4, 8, 0] after 4 seconds\n * // 'This is how it ends!' immediately after\n * ```\n *\n * @see {@link combineLatest}\n * @see {@link zip}\n *\n * @param args Any number of `ObservableInput`s provided either as an array or as an object\n * passed directly to the operator.\n * @return Observable emitting either an array of last values emitted by passed Observables\n * or value from project function.\n */\nexport function forkJoin(...args: any[]): Observable<any> {\n  const resultSelector = popResultSelector(args);\n  const { args: sources, keys } = argsArgArrayOrObject(args);\n  const result = new Observable((destination) => {\n    const { length } = sources;\n    if (!length) {\n      destination.complete();\n      return;\n    }\n    const values = new Array(length);\n    let remainingCompletions = length;\n    let remainingEmissions = length;\n    for (let sourceIndex = 0; sourceIndex < length; sourceIndex++) {\n      let hasValue = false;\n      from(sources[sourceIndex]).subscribe(\n        operate({\n          destination,\n          next: (value) => {\n            if (!hasValue) {\n              hasValue = true;\n              remainingEmissions--;\n            }\n            values[sourceIndex] = value;\n          },\n          complete: () => remainingCompletions--,\n          finalize: () => {\n            if (!remainingCompletions || !hasValue) {\n              if (remainingEmissions === 0) {\n                destination.next(keys ? createObject(keys, values) : values);\n                destination.complete();\n              } else {\n                destination.error(new EmptyError());\n              }\n            }\n          },\n        })\n      );\n    }\n  });\n  return resultSelector ? mapOneOrManyArgs(resultSelector)(result) : result;\n}\n"
  },
  {
    "path": "packages/rxjs/src/internal/observable/fromEvent.ts",
    "content": "import type { Subscriber } from '@rxjs/observable';\nimport { Observable, isArrayLike, isFunction } from '@rxjs/observable';\nimport { mapOneOrManyArgs } from '../util/mapOneOrManyArgs.js';\n\n// These constants are used to create handler registry functions using array mapping below.\nconst nodeEventEmitterMethods = ['addListener', 'removeListener'] as const;\nconst eventTargetMethods = ['addEventListener', 'removeEventListener'] as const;\nconst jqueryMethods = ['on', 'off'] as const;\n\nexport interface NodeStyleEventEmitter {\n  addListener(eventName: string | symbol, handler: NodeEventHandler): this;\n  removeListener(eventName: string | symbol, handler: NodeEventHandler): this;\n}\n\nexport type NodeEventHandler = (...args: any[]) => void;\n\n// For APIs that implement `addListener` and `removeListener` methods that may\n// not use the same arguments or return EventEmitter values\n// such as React Native\nexport interface NodeCompatibleEventEmitter {\n  // this should probably be `void | unknown` eventually\n  // eslint-disable-next-line @typescript-eslint/ban-types\n  addListener(eventName: string, handler: NodeEventHandler): void | {};\n  // eslint-disable-next-line @typescript-eslint/ban-types\n  removeListener(eventName: string, handler: NodeEventHandler): void | {};\n}\n\n// Use handler types like those in @types/jquery. See:\n// https://github.com/DefinitelyTyped/DefinitelyTyped/blob/847731ba1d7fa6db6b911c0e43aa0afe596e7723/types/jquery/misc.d.ts#L6395\nexport interface JQueryStyleEventEmitter<TContext, T> {\n  on(eventName: string, handler: (this: TContext, t: T, ...args: any[]) => any): void;\n  off(eventName: string, handler: (this: TContext, t: T, ...args: any[]) => any): void;\n}\n\nexport interface EventListenerObject<E> {\n  handleEvent(evt: E): void;\n}\n\nexport interface HasEventTargetAddRemove<E> {\n  addEventListener(\n    type: string,\n    listener: ((evt: E) => void) | EventListenerObject<E> | null,\n    options?: boolean | AddEventListenerOptions\n  ): void;\n  removeEventListener(\n    type: string,\n    listener: ((evt: E) => void) | EventListenerObject<E> | null,\n    options?: EventListenerOptions | boolean\n  ): void;\n}\n\nexport interface EventListenerOptions {\n  capture?: boolean;\n  passive?: boolean;\n  once?: boolean;\n}\n\nexport interface AddEventListenerOptions extends EventListenerOptions {\n  once?: boolean;\n  passive?: boolean;\n}\n\nexport function fromEvent<T>(target: HasEventTargetAddRemove<T> | ArrayLike<HasEventTargetAddRemove<T>>, eventName: string): Observable<T>;\nexport function fromEvent<T, R>(\n  target: HasEventTargetAddRemove<T> | ArrayLike<HasEventTargetAddRemove<T>>,\n  eventName: string,\n  resultSelector: (event: T) => R\n): Observable<R>;\nexport function fromEvent<T>(\n  target: HasEventTargetAddRemove<T> | ArrayLike<HasEventTargetAddRemove<T>>,\n  eventName: string,\n  options: EventListenerOptions\n): Observable<T>;\nexport function fromEvent<T, R>(\n  target: HasEventTargetAddRemove<T> | ArrayLike<HasEventTargetAddRemove<T>>,\n  eventName: string,\n  options: EventListenerOptions,\n  resultSelector: (event: T) => R\n): Observable<R>;\n\nexport function fromEvent(\n  target: NodeStyleEventEmitter | ArrayLike<NodeStyleEventEmitter>,\n  eventName: string | symbol\n): Observable<unknown>;\nexport function fromEvent<T>(target: NodeStyleEventEmitter | ArrayLike<NodeStyleEventEmitter>, eventName: string | symbol): Observable<T>;\nexport function fromEvent<R>(\n  target: NodeStyleEventEmitter | ArrayLike<NodeStyleEventEmitter>,\n  eventName: string | symbol,\n  resultSelector: (...args: any[]) => R\n): Observable<R>;\n\nexport function fromEvent(\n  target: NodeCompatibleEventEmitter | ArrayLike<NodeCompatibleEventEmitter>,\n  eventName: string\n): Observable<unknown>;\nexport function fromEvent<T>(target: NodeCompatibleEventEmitter | ArrayLike<NodeCompatibleEventEmitter>, eventName: string): Observable<T>;\nexport function fromEvent<R>(\n  target: NodeCompatibleEventEmitter | ArrayLike<NodeCompatibleEventEmitter>,\n  eventName: string,\n  resultSelector: (...args: any[]) => R\n): Observable<R>;\n\nexport function fromEvent<T>(\n  target: JQueryStyleEventEmitter<any, T> | ArrayLike<JQueryStyleEventEmitter<any, T>>,\n  eventName: string\n): Observable<T>;\nexport function fromEvent<T, R>(\n  target: JQueryStyleEventEmitter<any, T> | ArrayLike<JQueryStyleEventEmitter<any, T>>,\n  eventName: string,\n  resultSelector: (value: T, ...args: any[]) => R\n): Observable<R>;\n\n/**\n * Creates an Observable that emits events of a specific type coming from the\n * given event target.\n *\n * <span class=\"informal\">Creates an Observable from DOM events, or Node.js\n * EventEmitter events or others.</span>\n *\n * ![](fromEvent.png)\n *\n * `fromEvent` accepts as a first argument event target, which is an object with methods\n * for registering event handler functions. As a second argument it takes string that indicates\n * type of event we want to listen for. `fromEvent` supports selected types of event targets,\n * which are described in detail below. If your event target does not match any of the ones listed,\n * you should use {@link fromEventPattern}, which can be used on arbitrary APIs.\n * When it comes to APIs supported by `fromEvent`, their methods for adding and removing event\n * handler functions have different names, but they all accept a string describing event type\n * and function itself, which will be called whenever said event happens.\n *\n * Every time resulting Observable is subscribed, event handler function will be registered\n * to event target on given event type. When that event fires, value\n * passed as a first argument to registered function will be emitted by output Observable.\n * When Observable is unsubscribed, function will be unregistered from event target.\n *\n * Note that if event target calls registered function with more than one argument, second\n * and following arguments will not appear in resulting stream. In order to get access to them,\n * you can pass to `fromEvent` optional project function, which will be called with all arguments\n * passed to event handler. Output Observable will then emit value returned by project function,\n * instead of the usual value.\n *\n * Remember that event targets listed below are checked via duck typing. It means that\n * no matter what kind of object you have and no matter what environment you work in,\n * you can safely use `fromEvent` on that object if it exposes described methods (provided\n * of course they behave as was described above). So for example if Node.js library exposes\n * event target which has the same method names as DOM EventTarget, `fromEvent` is still\n * a good choice.\n *\n * If the API you use is more callback then event handler oriented (subscribed\n * callback function fires only once and thus there is no need to manually\n * unregister it), you should use {@link bindCallback} or {@link bindNodeCallback}\n * instead.\n *\n * `fromEvent` supports following types of event targets:\n *\n * **DOM EventTarget**\n *\n * This is an object with `addEventListener` and `removeEventListener` methods.\n *\n * In the browser, `addEventListener` accepts - apart from event type string and event\n * handler function arguments - optional third parameter, which is either an object or boolean,\n * both used for additional configuration how and when passed function will be called. When\n * `fromEvent` is used with event target of that type, you can provide this values\n * as third parameter as well.\n *\n * **Node.js EventEmitter**\n *\n * An object with `addListener` and `removeListener` methods.\n *\n * **JQuery-style event target**\n *\n * An object with `on` and `off` methods\n *\n * **DOM NodeList**\n *\n * List of DOM Nodes, returned for example by `document.querySelectorAll` or `Node.childNodes`.\n *\n * Although this collection is not event target in itself, `fromEvent` will iterate over all Nodes\n * it contains and install event handler function in every of them. When returned Observable\n * is unsubscribed, function will be removed from all Nodes.\n *\n * **DOM HtmlCollection**\n *\n * Just as in case of NodeList it is a collection of DOM nodes. Here as well event handler function is\n * installed and removed in each of elements.\n *\n *\n * ## Examples\n *\n * Emit clicks happening on the DOM document\n *\n * ```ts\n * import { fromEvent } from 'rxjs';\n *\n * const clicks = fromEvent(document, 'click');\n * clicks.subscribe(x => console.log(x));\n *\n * // Results in:\n * // MouseEvent object logged to console every time a click\n * // occurs on the document.\n * ```\n *\n * Use `addEventListener` with capture option\n *\n * ```ts\n * import { fromEvent } from 'rxjs';\n *\n * const div = document.createElement('div');\n * div.style.cssText = 'width: 200px; height: 200px; background: #09c;';\n * document.body.appendChild(div);\n *\n * // note optional configuration parameter which will be passed to addEventListener\n * const clicksInDocument = fromEvent(document, 'click', { capture: true });\n * const clicksInDiv = fromEvent(div, 'click');\n *\n * clicksInDocument.subscribe(() => console.log('document'));\n * clicksInDiv.subscribe(() => console.log('div'));\n *\n * // By default events bubble UP in DOM tree, so normally\n * // when we would click on div in document\n * // \"div\" would be logged first and then \"document\".\n * // Since we specified optional `capture` option, document\n * // will catch event when it goes DOWN DOM tree, so console\n * // will log \"document\" and then \"div\".\n * ```\n *\n * @see {@link bindCallback}\n * @see {@link bindNodeCallback}\n * @see {@link fromEventPattern}\n *\n * @param target The DOM EventTarget, Node.js EventEmitter, JQuery-like event target,\n * NodeList or HTMLCollection to attach the event handler to.\n * @param eventName The event name of interest, being emitted by the `target`.\n * @param options Options to pass through to the underlying `addListener`,\n * `addEventListener` or `on` functions.\n * @param resultSelector A mapping function used to transform events. It takes the\n * arguments from the event handler and should return a single value.\n * @return An Observable emitting events registered through `target`'s\n * listener handlers.\n */\nexport function fromEvent<T>(\n  target: any,\n  eventName: string | symbol,\n  options?: EventListenerOptions | ((...args: any[]) => T),\n  resultSelector?: (...args: any[]) => T\n): Observable<T> {\n  if (isFunction(options)) {\n    resultSelector = options;\n    options = undefined;\n  }\n\n  if (resultSelector) {\n    return mapOneOrManyArgs(resultSelector)(fromEvent<T>(target, eventName as string, options as EventListenerOptions));\n  }\n\n  const isValidTarget = isNodeStyleEventEmitter(target) || isJQueryStyleEventEmitter(target) || isEventTarget(target);\n\n  if (!isValidTarget && !isArrayLike(target)) {\n    throw new TypeError('Invalid event target');\n  }\n\n  return new Observable<T>((subscriber) => {\n    const handler = (...args: any[]) => subscriber.next(1 < args.length ? args : args[0]);\n    if (isValidTarget) {\n      // Valid event targets, even if they have a `length` property\n      // will be subscribed to as a single item.\n      doSubscribe(handler, subscriber, target, eventName, options);\n    } else {\n      // If it wasn't a valid event target, it must be an array-like.\n      // Subscribe to each item in the array-like.\n      for (let i = 0; i < target.length && !subscriber.closed; i++) {\n        const subTarget = target[i];\n        doSubscribe(handler, subscriber, subTarget, eventName, options);\n      }\n    }\n  });\n}\n\nfunction doSubscribe(\n  handler: (...args: any[]) => void,\n  subscriber: Subscriber<any>,\n  subTarget: any,\n  eventName: string | symbol,\n  options: any\n) {\n  const [addMethod, removeMethod] = getRegistryMethodNames(subTarget);\n  if (!addMethod || !removeMethod) {\n    throw new TypeError('Invalid event target');\n  }\n  subTarget[addMethod](eventName, handler, options);\n  subscriber.add(() => subTarget[removeMethod](eventName, handler, options));\n}\n\nfunction getRegistryMethodNames(target: any) {\n  // If it is an EventTarget, we need to use a slightly different method than the other two patterns.\n  return isEventTarget(target)\n    ? eventTargetMethods\n    : // In all other cases, the call pattern is identical with the exception of the method names.\n    isNodeStyleEventEmitter(target)\n    ? nodeEventEmitterMethods\n    : isJQueryStyleEventEmitter(target)\n    ? jqueryMethods\n    : [];\n}\n\n/**\n * Checks to see if the target implements the required node-style EventEmitter methods\n * for adding and removing event handlers.\n * @param target the object to check\n */\nfunction isNodeStyleEventEmitter(target: any): target is NodeStyleEventEmitter {\n  return isFunction(target.addListener) && isFunction(target.removeListener);\n}\n\n/**\n * Checks to see if the target implements the required jQuery-style EventEmitter methods\n * for adding and removing event handlers.\n * @param target the object to check\n */\nfunction isJQueryStyleEventEmitter(target: any): target is JQueryStyleEventEmitter<any, any> {\n  return isFunction(target.on) && isFunction(target.off);\n}\n\n/**\n * Checks to see if the target implements the required EventTarget methods\n * for adding and removing event handlers.\n * @param target the object to check\n */\nfunction isEventTarget(target: any): target is HasEventTargetAddRemove<any> {\n  return isFunction(target.addEventListener) && isFunction(target.removeEventListener);\n}\n"
  },
  {
    "path": "packages/rxjs/src/internal/observable/fromEventPattern.ts",
    "content": "import { Observable, isFunction } from '@rxjs/observable';\nimport type { NodeEventHandler } from './fromEvent.js';\nimport { mapOneOrManyArgs } from '../util/mapOneOrManyArgs.js';\n\nexport function fromEventPattern<T>(\n  addHandler: (handler: NodeEventHandler) => any,\n  removeHandler?: (handler: NodeEventHandler, signal?: any) => void\n): Observable<T>;\nexport function fromEventPattern<T>(\n  addHandler: (handler: NodeEventHandler) => any,\n  removeHandler?: (handler: NodeEventHandler, signal?: any) => void,\n  resultSelector?: (...args: any[]) => T\n): Observable<T>;\n\n/**\n * Creates an Observable from an arbitrary API for registering event handlers.\n *\n * <span class=\"informal\">When that method for adding event handler was something {@link fromEvent}\n * was not prepared for.</span>\n *\n * ![](fromEventPattern.png)\n *\n * `fromEventPattern` allows you to convert into an Observable any API that supports registering handler functions\n * for events. It is similar to {@link fromEvent}, but far\n * more flexible. In fact, all use cases of {@link fromEvent} could be easily handled by\n * `fromEventPattern` (although in slightly more verbose way).\n *\n * This operator accepts as a first argument an `addHandler` function, which will be injected with\n * handler parameter. That handler is actually an event handler function that you now can pass\n * to API expecting it. `addHandler` will be called whenever Observable\n * returned by the operator is subscribed, so registering handler in API will not\n * necessarily happen when `fromEventPattern` is called.\n *\n * After registration, every time an event that we listen to happens,\n * Observable returned by `fromEventPattern` will emit value that event handler\n * function was called with. Note that if event handler was called with more\n * than one argument, second and following arguments will not appear in the Observable.\n *\n * If API you are using allows to unregister event handlers as well, you can pass to `fromEventPattern`\n * another function - `removeHandler` - as a second parameter. It will be injected\n * with the same handler function as before, which now you can use to unregister\n * it from the API. `removeHandler` will be called when consumer of resulting Observable\n * unsubscribes from it.\n *\n * In some APIs unregistering is actually handled differently. Method registering an event handler\n * returns some kind of token, which is later used to identify which function should\n * be unregistered or it itself has method that unregisters event handler.\n * If that is the case with your API, make sure token returned\n * by registering method is returned by `addHandler`. Then it will be passed\n * as a second argument to `removeHandler`, where you will be able to use it.\n *\n * If you need access to all event handler parameters (not only the first one),\n * or you need to transform them in any way, you can call `fromEventPattern` with optional\n * third parameter - project function which will accept all arguments passed to\n * event handler when it is called. Whatever is returned from project function will appear on\n * resulting stream instead of usual event handlers first argument. This means\n * that default project can be thought of as function that takes its first parameter\n * and ignores the rest.\n *\n * ## Examples\n *\n * Emits clicks happening on the DOM document\n *\n * ```ts\n * import { fromEventPattern } from 'rxjs';\n *\n * function addClickHandler(handler) {\n *   document.addEventListener('click', handler);\n * }\n *\n * function removeClickHandler(handler) {\n *   document.removeEventListener('click', handler);\n * }\n *\n * const clicks = fromEventPattern(\n *   addClickHandler,\n *   removeClickHandler\n * );\n * clicks.subscribe(x => console.log(x));\n *\n * // Whenever you click anywhere in the browser, DOM MouseEvent\n * // object will be logged.\n * ```\n *\n * Use with API that returns cancellation token\n *\n * ```ts\n * import { fromEventPattern } from 'rxjs';\n *\n * const token = someAPI.registerEventHandler(function() {});\n * someAPI.unregisterEventHandler(token); // this APIs cancellation method accepts\n *                                        // not handler itself, but special token.\n *\n * const someAPIObservable = fromEventPattern(\n *   function(handler) { return someAPI.registerEventHandler(handler); }, // Note that we return the token here...\n *   function(handler, token) { someAPI.unregisterEventHandler(token); }  // ...to then use it here.\n * );\n * ```\n *\n * Use with project function\n *\n * ```ts\n * import { fromEventPattern } from 'rxjs';\n *\n * someAPI.registerEventHandler((eventType, eventMessage) => {\n *   console.log(eventType, eventMessage); // Logs 'EVENT_TYPE' 'EVENT_MESSAGE' to console.\n * });\n *\n * const someAPIObservable = fromEventPattern(\n *   handler => someAPI.registerEventHandler(handler),\n *   handler => someAPI.unregisterEventHandler(handler)\n *   (eventType, eventMessage) => eventType + ' --- ' + eventMessage // without that function only 'EVENT_TYPE'\n * );                                                                // would be emitted by the Observable\n *\n * someAPIObservable.subscribe(value => console.log(value));\n *\n * // Logs:\n * // 'EVENT_TYPE --- EVENT_MESSAGE'\n * ```\n *\n * @see {@link fromEvent}\n * @see {@link bindCallback}\n * @see {@link bindNodeCallback}\n *\n * @param addHandler A function that takes a `handler` function as argument and attaches it\n * somehow to the actual source of events.\n * @param removeHandler A function that takes a `handler` function as an argument and removes\n * it from the event source. If `addHandler` returns some kind of token, `removeHandler` function\n * will have it as a second parameter.\n * @param resultSelector A function to transform results. It takes the arguments from the event\n * handler and should return a single value.\n * @return Observable which, when an event happens, emits first parameter passed to registered\n * event handler. Alternatively it emits whatever project function returns at that moment.\n */\nexport function fromEventPattern<T>(\n  addHandler: (handler: NodeEventHandler) => any,\n  removeHandler?: (handler: NodeEventHandler, signal?: any) => void,\n  resultSelector?: (...args: any[]) => T\n): Observable<T | T[]> {\n  if (resultSelector) {\n    return mapOneOrManyArgs(resultSelector)(fromEventPattern<T>(addHandler, removeHandler));\n  }\n\n  return new Observable<T | T[]>((subscriber) => {\n    const handler = (...e: T[]) => subscriber.next(e.length === 1 ? e[0] : e);\n    const retValue = addHandler(handler);\n    return isFunction(removeHandler) ? () => removeHandler(handler, retValue) : undefined;\n  });\n}\n"
  },
  {
    "path": "packages/rxjs/src/internal/observable/fromSubscribable.ts",
    "content": "import type { Subscriber } from '@rxjs/observable';\nimport { Observable } from '@rxjs/observable';\nimport type { Subscribable } from '../types.js';\n\n/**\n * Used to convert a subscribable to an observable.\n *\n * Currently, this is only used within internals.\n *\n * TODO: Discuss ObservableInput supporting \"Subscribable\".\n * https://github.com/ReactiveX/rxjs/issues/5909\n *\n * @param subscribable A subscribable\n */\nexport function fromSubscribable<T>(subscribable: Subscribable<T>) {\n  return new Observable((subscriber: Subscriber<T>) => subscribable.subscribe(subscriber));\n}\n"
  },
  {
    "path": "packages/rxjs/src/internal/observable/generate.ts",
    "content": "import type { Observable } from '@rxjs/observable';\nimport { identity } from '../util/identity.js';\nimport type { ObservableInput, SchedulerLike } from '../types.js';\nimport { isScheduler } from '../util/isScheduler.js';\nimport { defer } from './defer.js';\nimport { scheduleIterable } from '../scheduled/scheduleIterable.js';\n\ntype ConditionFunc<S> = (state: S) => boolean;\ntype IterateFunc<S> = (state: S) => S;\ntype ResultFunc<S, T> = (state: S) => T;\n\nexport interface GenerateBaseOptions<S> {\n  /**\n   * Initial state.\n   */\n  initialState: S;\n  /**\n   * Condition function that accepts state and returns boolean.\n   * When it returns false, the generator stops.\n   * If not specified, a generator never stops.\n   */\n  condition?: ConditionFunc<S>;\n  /**\n   * Iterate function that accepts state and returns new state.\n   */\n  iterate: IterateFunc<S>;\n  /**\n   * SchedulerLike to use for generation process.\n   * By default, a generator starts immediately.\n   */\n  scheduler?: SchedulerLike;\n}\n\nexport interface GenerateOptions<T, S> extends GenerateBaseOptions<S> {\n  /**\n   * Result selection function that accepts state and returns a value to emit.\n   */\n  resultSelector: ResultFunc<S, T>;\n}\n\n/**\n * Generates an observable sequence by running a state-driven loop\n * producing the sequence's elements, using the specified scheduler\n * to send out observer messages.\n *\n * ![](generate.png)\n *\n * ## Examples\n *\n * Produces sequence of numbers\n *\n * ```ts\n * import { generate } from 'rxjs';\n *\n * const result = generate(0, x => x < 3, x => x + 1, x => x);\n *\n * result.subscribe(x => console.log(x));\n *\n * // Logs:\n * // 0\n * // 1\n * // 2\n * ```\n *\n * Use `asapScheduler`\n *\n * ```ts\n * import { generate, asapScheduler } from 'rxjs';\n *\n * const result = generate(1, x => x < 5, x => x * 2, x => x + 1, asapScheduler);\n *\n * result.subscribe(x => console.log(x));\n *\n * // Logs:\n * // 2\n * // 3\n * // 5\n * ```\n *\n * @see {@link from}\n * @see {@link Observable}\n *\n * @param initialState Initial state.\n * @param condition Condition to terminate generation (upon returning false).\n * @param iterate Iteration step function.\n * @param resultSelector Selector function for results produced in the sequence.\n * @param scheduler A {@link SchedulerLike} on which to run the generator loop.\n * If not provided, defaults to emit immediately.\n * @returns The generated sequence.\n * @deprecated Instead of passing separate arguments, use the options argument.\n * Signatures taking separate arguments will be removed in v8.\n */\nexport function generate<T, S>(\n  initialState: S,\n  condition: ConditionFunc<S>,\n  iterate: IterateFunc<S>,\n  resultSelector: ResultFunc<S, T>,\n  scheduler?: SchedulerLike\n): Observable<T>;\n\n/**\n * Generates an Observable by running a state-driven loop\n * that emits an element on each iteration.\n *\n * <span class=\"informal\">Use it instead of nexting values in a for loop.</span>\n *\n * ![](generate.png)\n *\n * `generate` allows you to create a stream of values generated with a loop very similar to\n * a traditional for loop. The first argument of `generate` is a beginning value. The second argument\n * is a function that accepts this value and tests if some condition still holds. If it does,\n * then the loop continues, if not, it stops. The third value is a function which takes the\n * previously defined value and modifies it in some way on each iteration. Note how these three parameters\n * are direct equivalents of three expressions in a traditional for loop: the first expression\n * initializes some state (for example, a numeric index), the second tests if the loop can perform the next\n * iteration (for example, if the index is lower than 10) and the third states how the defined value\n * will be modified on every step (for example, the index will be incremented by one).\n *\n * Return value of a `generate` operator is an Observable that on each loop iteration\n * emits a value. First of all, the condition function is ran. If it returns true, then the Observable\n * emits the currently stored value (initial value at the first iteration) and finally updates\n * that value with iterate function. If at some point the condition returns false, then the Observable\n * completes at that moment.\n *\n * Optionally you can pass a fourth parameter to `generate` - a result selector function which allows you\n * to immediately map the value that would normally be emitted by an Observable.\n *\n * If you find three anonymous functions in `generate` call hard to read, you can provide\n * a single object to the operator instead where the object has the properties: `initialState`,\n * `condition`, `iterate` and `resultSelector`, which should have respective values that you\n * would normally pass to `generate`. `resultSelector` is still optional, but that form\n * of calling `generate` allows you to omit `condition` as well. If you omit it, that means\n * condition always holds, or in other words the resulting Observable will never complete.\n *\n * Both forms of `generate` can optionally accept a scheduler. In case of a multi-parameter call,\n * scheduler simply comes as a last argument (no matter if there is a `resultSelector`\n * function or not). In case of a single-parameter call, you can provide it as a\n * `scheduler` property on the object passed to the operator. In both cases, a scheduler decides when\n * the next iteration of the loop will happen and therefore when the next value will be emitted\n * by the Observable. For example, to ensure that each value is pushed to the Observer\n * on a separate task in the event loop, you could use the `asyncScheduler` scheduler. Note that\n * by default (when no scheduler is passed) values are simply emitted synchronously.\n *\n *\n * ## Examples\n *\n * Use with condition and iterate functions\n *\n * ```ts\n * import { generate } from 'rxjs';\n *\n * const result = generate(0, x => x < 3, x => x + 1);\n *\n * result.subscribe({\n *   next: value => console.log(value),\n *   complete: () => console.log('Complete!')\n * });\n *\n * // Logs:\n * // 0\n * // 1\n * // 2\n * // 'Complete!'\n * ```\n *\n * Use with condition, iterate and resultSelector functions\n *\n * ```ts\n * import { generate } from 'rxjs';\n *\n * const result = generate(0, x => x < 3, x => x + 1, x => x * 1000);\n *\n * result.subscribe({\n *   next: value => console.log(value),\n *   complete: () => console.log('Complete!')\n * });\n *\n * // Logs:\n * // 0\n * // 1000\n * // 2000\n * // 'Complete!'\n * ```\n *\n * Use with options object\n *\n * ```ts\n * import { generate } from 'rxjs';\n *\n * const result = generate({\n *   initialState: 0,\n *   condition(value) { return value < 3; },\n *   iterate(value) { return value + 1; },\n *   resultSelector(value) { return value * 1000; }\n * });\n *\n * result.subscribe({\n *   next: value => console.log(value),\n *   complete: () => console.log('Complete!')\n * });\n *\n * // Logs:\n * // 0\n * // 1000\n * // 2000\n * // 'Complete!'\n * ```\n *\n * Use options object without condition function\n *\n * ```ts\n * import { generate } from 'rxjs';\n *\n * const result = generate({\n *   initialState: 0,\n *   iterate(value) { return value + 1; },\n *   resultSelector(value) { return value * 1000; }\n * });\n *\n * result.subscribe({\n *   next: value => console.log(value),\n *   complete: () => console.log('Complete!') // This will never run\n * });\n *\n * // Logs:\n * // 0\n * // 1000\n * // 2000\n * // 3000\n * // ...and never stops.\n * ```\n *\n * @see {@link from}\n *\n * @param initialState Initial state.\n * @param condition Condition to terminate generation (upon returning false).\n * @param iterate Iteration step function.\n * @param scheduler A {@link Scheduler} on which to run the generator loop. If not\n * provided, defaults to emitting immediately.\n * @return The generated sequence.\n * @deprecated Instead of passing separate arguments, use the options argument.\n * Signatures taking separate arguments will be removed in v8.\n */\nexport function generate<S>(\n  initialState: S,\n  condition: ConditionFunc<S>,\n  iterate: IterateFunc<S>,\n  scheduler?: SchedulerLike\n): Observable<S>;\n\n/**\n * Generates an observable sequence by running a state-driven loop\n * producing the sequence's elements, using the specified scheduler\n * to send out observer messages.\n * The overload accepts options object that might contain initial state, iterate,\n * condition and scheduler.\n *\n * ![](generate.png)\n *\n * ## Examples\n *\n * Use options object with condition function\n *\n * ```ts\n * import { generate } from 'rxjs';\n *\n * const result = generate({\n *   initialState: 0,\n *   condition: x => x < 3,\n *   iterate: x => x + 1\n * });\n *\n * result.subscribe({\n *   next: value => console.log(value),\n *   complete: () => console.log('Complete!')\n * });\n *\n * // Logs:\n * // 0\n * // 1\n * // 2\n * // 'Complete!'\n * ```\n *\n * @see {@link from}\n * @see {@link Observable}\n *\n * @param options Object that must contain initialState, iterate and might contain condition and scheduler.\n * @returns The generated sequence.\n */\nexport function generate<S>(options: GenerateBaseOptions<S>): Observable<S>;\n\n/**\n * Generates an observable sequence by running a state-driven loop\n * producing the sequence's elements, using the specified scheduler\n * to send out observer messages.\n * The overload accepts options object that might contain initial state, iterate,\n * condition, result selector and scheduler.\n *\n * ![](generate.png)\n *\n * ## Examples\n *\n * Use options object with condition and iterate function\n *\n * ```ts\n * import { generate } from 'rxjs';\n *\n * const result = generate({\n *   initialState: 0,\n *   condition: x => x < 3,\n *   iterate: x => x + 1,\n *   resultSelector: x => x\n * });\n *\n * result.subscribe({\n *   next: value => console.log(value),\n *   complete: () => console.log('Complete!')\n * });\n *\n * // Logs:\n * // 0\n * // 1\n * // 2\n * // 'Complete!'\n * ```\n *\n * @see {@link from}\n * @see {@link Observable}\n *\n * @param options Object that must contain initialState, iterate, resultSelector and might contain condition and scheduler.\n * @returns The generated sequence.\n */\nexport function generate<T, S>(options: GenerateOptions<T, S>): Observable<T>;\n\nexport function generate<T, S>(\n  initialStateOrOptions: S | GenerateOptions<T, S>,\n  condition?: ConditionFunc<S>,\n  iterate?: IterateFunc<S>,\n  resultSelectorOrScheduler?: ResultFunc<S, T> | SchedulerLike,\n  scheduler?: SchedulerLike\n): Observable<T> {\n  let resultSelector: ResultFunc<S, T>;\n  let initialState: S;\n\n  // TODO: Remove this as we move away from deprecated signatures\n  // and move towards a configuration object argument.\n  if (arguments.length === 1) {\n    // If we only have one argument, we can assume it is a configuration object.\n    // Note that folks not using TypeScript may trip over this.\n    ({\n      initialState,\n      condition,\n      iterate,\n      resultSelector = identity as ResultFunc<S, T>,\n      scheduler,\n    } = initialStateOrOptions as GenerateOptions<T, S>);\n  } else {\n    // Deprecated arguments path. Figure out what the user\n    // passed and set it here.\n    initialState = initialStateOrOptions as S;\n    if (!resultSelectorOrScheduler || isScheduler(resultSelectorOrScheduler)) {\n      resultSelector = identity as ResultFunc<S, T>;\n      scheduler = resultSelectorOrScheduler as SchedulerLike;\n    } else {\n      resultSelector = resultSelectorOrScheduler as ResultFunc<S, T>;\n    }\n  }\n\n  // The actual generator used to \"generate\" values.\n  function* gen() {\n    for (let state = initialState; !condition || condition(state); state = iterate!(state)) {\n      yield resultSelector(state);\n    }\n  }\n\n  // We use `defer` because we want to defer the creation of the iterator from the iterable.\n  return defer(\n    (scheduler\n      ? // If a scheduler was provided, use `scheduleIterable` to ensure that iteration/generation\n        // happens on the scheduler.\n        () => scheduleIterable(gen(), scheduler!)\n      : // Otherwise, if there's no scheduler, we can just use the generator function directly in\n        // `defer` and executing it will return the generator (which is iterable).\n        gen) as () => ObservableInput<T>\n  );\n}\n"
  },
  {
    "path": "packages/rxjs/src/internal/observable/iif.ts",
    "content": "import type { Observable } from '@rxjs/observable';\nimport { defer } from './defer.js';\nimport type { ObservableInput } from '../types.js';\n\n/**\n * Checks a boolean at subscription time, and chooses between one of two observable sources\n *\n * `iif` expects a function that returns a boolean (the `condition` function), and two sources,\n * the `trueResult` and the `falseResult`, and returns an Observable.\n *\n * At the moment of subscription, the `condition` function is called. If the result is `true`, the\n * subscription will be to the source passed as the `trueResult`, otherwise, the subscription will be\n * to the source passed as the `falseResult`.\n *\n * If you need to check more than two options to choose between more than one observable, have a look at the {@link defer} creation method.\n *\n * ## Examples\n *\n * Change at runtime which Observable will be subscribed\n *\n * ```ts\n * import { iif, of } from 'rxjs';\n *\n * let subscribeToFirst;\n * const firstOrSecond = iif(\n *   () => subscribeToFirst,\n *   of('first'),\n *   of('second')\n * );\n *\n * subscribeToFirst = true;\n * firstOrSecond.subscribe(value => console.log(value));\n *\n * // Logs:\n * // 'first'\n *\n * subscribeToFirst = false;\n * firstOrSecond.subscribe(value => console.log(value));\n *\n * // Logs:\n * // 'second'\n * ```\n *\n * Control access to an Observable\n *\n * ```ts\n * import { iif, of, EMPTY } from 'rxjs';\n *\n * let accessGranted;\n * const observableIfYouHaveAccess = iif(\n *   () => accessGranted,\n *   of('It seems you have an access...'),\n *   EMPTY\n * );\n *\n * accessGranted = true;\n * observableIfYouHaveAccess.subscribe({\n *   next: value => console.log(value),\n *   complete: () => console.log('The end')\n * });\n *\n * // Logs:\n * // 'It seems you have an access...'\n * // 'The end'\n *\n * accessGranted = false;\n * observableIfYouHaveAccess.subscribe({\n *   next: value => console.log(value),\n *   complete: () => console.log('The end')\n * });\n *\n * // Logs:\n * // 'The end'\n * ```\n *\n * @see {@link defer}\n *\n * @param condition Condition which Observable should be chosen.\n * @param trueResult An Observable that will be subscribed if condition is true.\n * @param falseResult An Observable that will be subscribed if condition is false.\n * @return An observable that proxies to `trueResult` or `falseResult`, depending on the result of the `condition` function.\n */\nexport function iif<T, F>(condition: () => boolean, trueResult: ObservableInput<T>, falseResult: ObservableInput<F>): Observable<T | F> {\n  return defer(() => (condition() ? trueResult : falseResult));\n}\n"
  },
  {
    "path": "packages/rxjs/src/internal/observable/interval.ts",
    "content": "import type { Observable } from '@rxjs/observable';\nimport { asyncScheduler } from '../scheduler/async.js';\nimport type { SchedulerLike } from '../types.js';\nimport { timer } from './timer.js';\n\n/**\n * Creates an Observable that emits sequential numbers every specified\n * interval of time, on a specified {@link SchedulerLike}.\n *\n * <span class=\"informal\">Emits incremental numbers periodically in time.</span>\n *\n * ![](interval.png)\n *\n * `interval` returns an Observable that emits an infinite sequence of\n * ascending integers, with a constant interval of time of your choosing\n * between those emissions. The first emission is not sent immediately, but\n * only after the first period has passed. By default, this operator uses the\n * `asyncScheduler` {@link SchedulerLike} to provide a notion of time, but you may pass any\n * {@link SchedulerLike} to it.\n *\n * ## Example\n *\n * Emits ascending numbers, one every second (1000ms) up to the number 3\n *\n * ```ts\n * import { interval, take } from 'rxjs';\n *\n * const numbers = interval(1000);\n *\n * const takeFourNumbers = numbers.pipe(take(4));\n *\n * takeFourNumbers.subscribe(x => console.log('Next: ', x));\n *\n * // Logs:\n * // Next: 0\n * // Next: 1\n * // Next: 2\n * // Next: 3\n * ```\n *\n * @see {@link timer}\n * @see {@link delay}\n *\n * @param period The interval size in milliseconds (by default) or the time unit determined\n * by the scheduler's clock.\n * @param scheduler The {@link SchedulerLike} to use for scheduling the emission of values,\n * and providing a notion of \"time\".\n * @return An Observable that emits a sequential number each time interval.\n */\nexport function interval(period = 0, scheduler: SchedulerLike = asyncScheduler): Observable<number> {\n  if (period < 0) {\n    // We cannot schedule an interval in the past.\n    period = 0;\n  }\n\n  return timer(period, period, scheduler);\n}\n"
  },
  {
    "path": "packages/rxjs/src/internal/observable/merge.ts",
    "content": "import type { Observable} from '@rxjs/observable';\nimport { from } from '@rxjs/observable';\nimport type { ObservableInput, ObservableInputTuple, SchedulerLike } from '../types.js';\nimport { mergeAll } from '../operators/mergeAll.js';\nimport { EMPTY } from './empty.js';\nimport { popNumber, popScheduler } from '../util/args.js';\nimport { scheduled } from '../scheduled/scheduled.js';\n\nexport function merge<A extends readonly unknown[]>(...sources: [...ObservableInputTuple<A>]): Observable<A[number]>;\nexport function merge<A extends readonly unknown[]>(...sourcesAndConcurrency: [...ObservableInputTuple<A>, number?]): Observable<A[number]>;\n/** @deprecated The `scheduler` parameter will be removed in v8. Use `scheduled` and `mergeAll`. Details: https://rxjs.dev/deprecations/scheduler-argument */\nexport function merge<A extends readonly unknown[]>(\n  ...sourcesAndScheduler: [...ObservableInputTuple<A>, SchedulerLike?]\n): Observable<A[number]>;\n/** @deprecated The `scheduler` parameter will be removed in v8. Use `scheduled` and `mergeAll`. Details: https://rxjs.dev/deprecations/scheduler-argument */\nexport function merge<A extends readonly unknown[]>(\n  ...sourcesAndConcurrencyAndScheduler: [...ObservableInputTuple<A>, number?, SchedulerLike?]\n): Observable<A[number]>;\n\n/**\n * Creates an output Observable which concurrently emits all values from every\n * given input Observable.\n *\n * <span class=\"informal\">Flattens multiple Observables together by blending\n * their values into one Observable.</span>\n *\n * ![](merge.png)\n *\n * `merge` subscribes to each given input Observable (as arguments), and simply\n * forwards (without doing any transformation) all the values from all the input\n * Observables to the output Observable. The output Observable only completes\n * once all input Observables have completed. Any error delivered by an input\n * Observable will be immediately emitted on the output Observable.\n *\n * ## Examples\n *\n * Merge together two Observables: 1s interval and clicks\n *\n * ```ts\n * import { merge, fromEvent, interval } from 'rxjs';\n *\n * const clicks = fromEvent(document, 'click');\n * const timer = interval(1000);\n * const clicksOrTimer = merge(clicks, timer);\n * clicksOrTimer.subscribe(x => console.log(x));\n *\n * // Results in the following:\n * // timer will emit ascending values, one every second(1000ms) to console\n * // clicks logs MouseEvents to console every time the \"document\" is clicked\n * // Since the two streams are merged you see these happening\n * // as they occur.\n * ```\n *\n * Merge together 3 Observables, but run only 2 concurrently\n *\n * ```ts\n * import { interval, take, merge } from 'rxjs';\n *\n * const timer1 = interval(1000).pipe(take(10));\n * const timer2 = interval(2000).pipe(take(6));\n * const timer3 = interval(500).pipe(take(10));\n *\n * const concurrent = 2; // the argument\n * const merged = merge(timer1, timer2, timer3, concurrent);\n * merged.subscribe(x => console.log(x));\n *\n * // Results in the following:\n * // - First timer1 and timer2 will run concurrently\n * // - timer1 will emit a value every 1000ms for 10 iterations\n * // - timer2 will emit a value every 2000ms for 6 iterations\n * // - after timer1 hits its max iteration, timer2 will\n * //   continue, and timer3 will start to run concurrently with timer2\n * // - when timer2 hits its max iteration it terminates, and\n * //   timer3 will continue to emit a value every 500ms until it is complete\n * ```\n *\n * @see {@link mergeAll}\n * @see {@link mergeMap}\n * @see {@link mergeMapTo}\n * @see {@link mergeScan}\n *\n * @param args `ObservableInput`s to merge together. If the last parameter\n * is of type number, `merge` will use it to limit number of concurrently\n * subscribed `ObservableInput`s.\n * @return An Observable that emits items that are the result of every input Observable.\n */\nexport function merge(...args: (ObservableInput<unknown> | number | SchedulerLike)[]): Observable<unknown> {\n  const scheduler = popScheduler(args);\n  const concurrent = popNumber(args, Infinity);\n  const sources = args as ObservableInput<unknown>[];\n  return !sources.length\n    ? // No source provided\n      EMPTY\n    : sources.length === 1\n    ? // One source? Just return it.\n      from(sources[0])\n    : // Merge all sources\n      mergeAll(concurrent)(scheduler ? scheduled(sources, scheduler) : from(sources));\n}\n"
  },
  {
    "path": "packages/rxjs/src/internal/observable/never.ts",
    "content": "import { Observable } from '@rxjs/observable';\nimport { noop } from '../util/noop.js';\n\n/**\n * An Observable that emits no items to the Observer and never completes.\n *\n * ![](never.png)\n *\n * A simple Observable that emits neither values nor errors nor the completion\n * notification. It can be used for testing purposes or for composing with other\n * Observables. Please note that by never emitting a complete notification, this\n * Observable keeps the subscription from being disposed automatically.\n * Subscriptions need to be manually disposed.\n *\n * ##  Example\n *\n * Emit the number 7, then never emit anything else (not even complete)\n *\n * ```ts\n * import { NEVER, startWith } from 'rxjs';\n *\n * const info = () => console.log('Will not be called');\n *\n * const result = NEVER.pipe(startWith(7));\n * result.subscribe({\n *   next: x => console.log(x),\n *   error: info,\n *   complete: info\n * });\n * ```\n *\n * @see {@link Observable}\n * @see {@link EMPTY}\n * @see {@link of}\n * @see {@link throwError}\n */\nexport const NEVER = new Observable<never>(noop);\n"
  },
  {
    "path": "packages/rxjs/src/internal/observable/of.ts",
    "content": "import type { ValueFromArray } from '../types.js';\nimport type { Observable} from '@rxjs/observable';\nimport { fromArrayLike } from '@rxjs/observable';\n\n// Devs are more likely to pass null or undefined than they are a scheduler\n// without accompanying values. To make things easier for (naughty) devs who\n// use the `strictNullChecks: false` TypeScript compiler option, these\n// overloads with explicit null and undefined values are included.\n\nexport function of(value: null): Observable<null>;\nexport function of(value: undefined): Observable<undefined>;\n\nexport function of(): Observable<never>;\nexport function of<T>(value: T): Observable<T>;\nexport function of<A extends readonly unknown[]>(...values: A): Observable<ValueFromArray<A>>;\n\n/**\n * Converts the arguments to an observable sequence.\n *\n * <span class=\"informal\">Each argument becomes a `next` notification.</span>\n *\n * ![](of.png)\n *\n * Unlike {@link from}, it does not do any flattening and emits each argument in whole\n * as a separate `next` notification.\n *\n * ## Examples\n *\n * Emit the values `10, 20, 30`\n *\n * ```ts\n * import { of } from 'rxjs';\n *\n * of(10, 20, 30)\n *   .subscribe({\n *     next: value => console.log('next:', value),\n *     error: err => console.log('error:', err),\n *     complete: () => console.log('the end'),\n *   });\n *\n * // Outputs\n * // next: 10\n * // next: 20\n * // next: 30\n * // the end\n * ```\n *\n * Emit the array `[1, 2, 3]`\n *\n * ```ts\n * import { of } from 'rxjs';\n *\n * of([1, 2, 3])\n *   .subscribe({\n *     next: value => console.log('next:', value),\n *     error: err => console.log('error:', err),\n *     complete: () => console.log('the end'),\n *   });\n *\n * // Outputs\n * // next: [1, 2, 3]\n * // the end\n * ```\n *\n * @see {@link from}\n * @see {@link range}\n *\n * @param values A comma separated list of arguments you want to be emitted.\n * @return An Observable that synchronously emits the arguments described\n * above and then immediately completes.\n */\nexport function of<T>(...values: T[]): Observable<T> {\n  return fromArrayLike<T>(values);\n}\n"
  },
  {
    "path": "packages/rxjs/src/internal/observable/onErrorResumeNext.ts",
    "content": "import { Observable, operate, from } from '@rxjs/observable';\nimport type { ObservableInputTuple } from '../types.js';\nimport { argsOrArgArray } from '../util/argsOrArgArray.js';\nimport { noop } from '../util/noop.js';\n\nexport function onErrorResumeNext<A extends readonly unknown[]>(sources: [...ObservableInputTuple<A>]): Observable<A[number]>;\nexport function onErrorResumeNext<A extends readonly unknown[]>(...sources: [...ObservableInputTuple<A>]): Observable<A[number]>;\n\n/**\n * When any of the provided Observable emits a complete or an error notification, it immediately subscribes to the next one\n * that was passed.\n *\n * <span class=\"informal\">Execute series of Observables no matter what, even if it means swallowing errors.</span>\n *\n * ![](onErrorResumeNext.png)\n *\n * `onErrorResumeNext` will subscribe to each observable source it is provided, in order.\n * If the source it's subscribed to emits an error or completes, it will move to the next source\n * without error.\n *\n * If `onErrorResumeNext` is provided no arguments, or a single, empty array, it will return {@link EMPTY}.\n *\n * `onErrorResumeNext` is basically {@link concatWith}, only it will continue, even if one of its\n * sources emits an error.\n *\n * Note that there is no way to handle any errors thrown by sources via the result of\n * `onErrorResumeNext`. If you want to handle errors thrown in any given source, you can\n * always use the {@link catchError} operator on them before passing them into `onErrorResumeNext`.\n *\n * ## Example\n *\n * Subscribe to the next Observable after map fails\n *\n * ```ts\n * import { onErrorResumeNext, of, map } from 'rxjs';\n *\n * onErrorResumeNext(\n *   of(1, 2, 3, 0).pipe(\n *     map(x => {\n *       if (x === 0) {\n *         throw Error();\n *       }\n *       return 10 / x;\n *     })\n *   ),\n *   of(1, 2, 3)\n * )\n * .subscribe({\n *   next: value => console.log(value),\n *   error: err => console.log(err),     // Will never be called.\n *   complete: () => console.log('done')\n * });\n *\n * // Logs:\n * // 10\n * // 5\n * // 3.3333333333333335\n * // 1\n * // 2\n * // 3\n * // 'done'\n * ```\n *\n * @see {@link concat}\n * @see {@link catchError}\n *\n * @param sources `ObservableInput`s passed either directly or as an array.\n * @return An Observable that concatenates all sources, one after the other,\n * ignoring all errors, such that any error causes it to move on to the next source.\n */\nexport function onErrorResumeNext<A extends readonly unknown[]>(\n  ...sources: [[...ObservableInputTuple<A>]] | [...ObservableInputTuple<A>]\n): Observable<A[number]> {\n  const nextSources: ObservableInputTuple<A> = argsOrArgArray(sources) as any;\n\n  return new Observable((destination) => {\n    let sourceIndex = 0;\n    const subscribeNext = () => {\n      if (sourceIndex < nextSources.length) {\n        let nextSource: Observable<A[number]>;\n        try {\n          nextSource = from(nextSources[sourceIndex++]);\n        } catch (err) {\n          subscribeNext();\n          return;\n        }\n        const innerSubscriber = operate({ destination, error: noop, complete: noop });\n        nextSource.subscribe(innerSubscriber);\n        innerSubscriber.add(subscribeNext);\n      } else {\n        destination.complete();\n      }\n    };\n    subscribeNext();\n  });\n}\n"
  },
  {
    "path": "packages/rxjs/src/internal/observable/partition.ts",
    "content": "import { not } from '../util/not.js';\nimport { filter } from '../operators/filter.js';\nimport type { ObservableInput } from '../types.js';\nimport type { Observable} from '@rxjs/observable';\nimport { from } from '@rxjs/observable';\n\n/** @deprecated Use a closure instead of a `thisArg`. Signatures accepting a `thisArg` will be removed in v8. */\nexport function partition<T, U extends T, A>(\n  source: ObservableInput<T>,\n  predicate: (this: A, value: T, index: number) => value is U,\n  thisArg: A\n): [Observable<U>, Observable<Exclude<T, U>>];\nexport function partition<T, U extends T>(\n  source: ObservableInput<T>,\n  predicate: (value: T, index: number) => value is U\n): [Observable<U>, Observable<Exclude<T, U>>];\n\n/** @deprecated Use a closure instead of a `thisArg`. Signatures accepting a `thisArg` will be removed in v8. */\nexport function partition<T, A>(\n  source: ObservableInput<T>,\n  predicate: (this: A, value: T, index: number) => boolean,\n  thisArg: A\n): [Observable<T>, Observable<T>];\nexport function partition<T>(source: ObservableInput<T>, predicate: (value: T, index: number) => boolean): [Observable<T>, Observable<T>];\n\n/**\n * Splits the source Observable into two, one with values that satisfy a\n * predicate, and another with values that don't satisfy the predicate.\n *\n * <span class=\"informal\">It's like {@link filter}, but returns two Observables:\n * one like the output of {@link filter}, and the other with values that did not\n * pass the condition.</span>\n *\n * ![](partition.png)\n *\n * `partition` outputs an array with two Observables that partition the values\n * from the source Observable through the given `predicate` function. The first\n * Observable in that array emits source values for which the predicate argument\n * returns true. The second Observable emits source values for which the\n * predicate returns false. The first behaves like {@link filter} and the second\n * behaves like {@link filter} with the predicate negated.\n *\n * ## Example\n *\n * Partition a set of numbers into odds and evens observables\n *\n * ```ts\n * import { of, partition } from 'rxjs';\n *\n * const observableValues = of(1, 2, 3, 4, 5, 6);\n * const [evens$, odds$] = partition(observableValues, value => value % 2 === 0);\n *\n * odds$.subscribe(x => console.log('odds', x));\n * evens$.subscribe(x => console.log('evens', x));\n *\n * // Logs:\n * // odds 1\n * // odds 3\n * // odds 5\n * // evens 2\n * // evens 4\n * // evens 6\n * ```\n *\n * @see {@link filter}\n *\n * @param source The source `ObservableInput` that will be split into a tuple of\n * two Observable elements.\n * @param predicate A function that evaluates each value emitted by the source\n * Observable. If it returns `true`, the value is emitted on the first Observable\n * in the returned array, if `false` the value is emitted on the second Observable\n * in the array. The `index` parameter is the number `i` for the i-th source\n * emission that has happened since the subscription, starting from the number `0`.\n * @param thisArg An optional argument to determine the value of `this` in the\n * `predicate` function.\n * @return An array with two Observables: one with values that passed the\n * predicate, and another with values that did not pass the predicate.\n */\nexport function partition<T>(\n  source: ObservableInput<T>,\n  predicate: (this: any, value: T, index: number) => boolean,\n  thisArg?: any\n): [Observable<T>, Observable<T>] {\n  return [filter(predicate, thisArg)(from(source)), filter(not(predicate, thisArg))(from(source))] as [Observable<T>, Observable<T>];\n}\n"
  },
  {
    "path": "packages/rxjs/src/internal/observable/race.ts",
    "content": "import type { Subscription, Subscriber} from '@rxjs/observable';\nimport { Observable, from, operate } from '@rxjs/observable';\nimport type { ObservableInput, ObservableInputTuple } from '../types.js';\nimport { argsOrArgArray } from '../util/argsOrArgArray.js';\n\nexport function race<T extends readonly unknown[]>(inputs: [...ObservableInputTuple<T>]): Observable<T[number]>;\nexport function race<T extends readonly unknown[]>(...inputs: [...ObservableInputTuple<T>]): Observable<T[number]>;\n\n/**\n * Returns an observable that mirrors the first source observable to emit an item.\n *\n * ![](race.png)\n *\n * `race` returns an observable, that when subscribed to, subscribes to all source observables immediately.\n * As soon as one of the source observables emits a value, the result unsubscribes from the other sources.\n * The resulting observable will forward all notifications, including error and completion, from the \"winning\"\n * source observable.\n *\n * If one of the used source observable throws an errors before a first notification\n * the race operator will also throw an error, no matter if another source observable\n * could potentially win the race.\n *\n * `race` can be useful for selecting the response from the fastest network connection for\n * HTTP or WebSockets. `race` can also be useful for switching observable context based on user\n * input.\n *\n * ## Example\n *\n * Subscribes to the observable that was the first to start emitting.\n *\n * ```ts\n * import { interval, map, race } from 'rxjs';\n *\n * const obs1 = interval(7000).pipe(map(() => 'slow one'));\n * const obs2 = interval(3000).pipe(map(() => 'fast one'));\n * const obs3 = interval(5000).pipe(map(() => 'medium one'));\n *\n * race(obs1, obs2, obs3)\n *   .subscribe(winner => console.log(winner));\n *\n * // Outputs\n * // a series of 'fast one'\n * ```\n *\n * @param sources Used to race for which `ObservableInput` emits first.\n * @return An Observable that mirrors the output of the first Observable to emit an item.\n */\nexport function race<T>(...sources: (ObservableInput<T> | ObservableInput<T>[])[]): Observable<any> {\n  sources = argsOrArgArray(sources);\n  // If only one source was passed, just return it. Otherwise return the race.\n  return sources.length === 1 ? from(sources[0] as ObservableInput<T>) : new Observable<T>(raceInit(sources as ObservableInput<T>[]));\n}\n\n/**\n * An observable initializer function for both the static version and the\n * operator version of race.\n * @param sources The sources to race\n */\nexport function raceInit<T>(sources: ObservableInput<T>[]) {\n  return (destination: Subscriber<T>) => {\n    let subscriptions: Subscription[] = [];\n\n    // Subscribe to all of the sources. Note that we are checking `subscriptions` here\n    // Is is an array of all actively \"racing\" subscriptions, and it is `null` after the\n    // race has been won. So, if we have racer that synchronously \"wins\", this loop will\n    // stop before it subscribes to any more.\n    for (let i = 0; subscriptions && !destination.closed && i < sources.length; i++) {\n      subscriptions.push(\n        from(sources[i] as ObservableInput<T>).subscribe(\n          operate({\n            destination,\n            next: (value) => {\n              if (subscriptions) {\n                // We're still racing, but we won! So unsubscribe\n                // all other subscriptions that we have, except this one.\n                for (let s = 0; s < subscriptions.length; s++) {\n                  s !== i && subscriptions[s].unsubscribe();\n                }\n                subscriptions = null!;\n              }\n              destination.next(value);\n            },\n          })\n        )\n      );\n    }\n  };\n}\n"
  },
  {
    "path": "packages/rxjs/src/internal/observable/range.ts",
    "content": "import type { SchedulerLike } from '../types.js';\nimport { Observable } from '@rxjs/observable';\nimport { EMPTY } from './empty.js';\nimport { executeSchedule } from '../util/executeSchedule.js';\n\nexport function range(start: number, count?: number): Observable<number>;\n\n/**\n * @deprecated The `scheduler` parameter will be removed in v8. Use `range(start, count).pipe(observeOn(scheduler))` instead. Details: Details: https://rxjs.dev/deprecations/scheduler-argument\n */\nexport function range(start: number, count: number | undefined, scheduler: SchedulerLike): Observable<number>;\n\n/**\n * Creates an Observable that emits a sequence of numbers within a specified\n * range.\n *\n * <span class=\"informal\">Emits a sequence of numbers in a range.</span>\n *\n * ![](range.png)\n *\n * `range` operator emits a range of sequential integers, in order, where you\n * select the `start` of the range and its `length`. By default, uses no\n * {@link SchedulerLike} and just delivers the notifications synchronously, but may use\n * an optional {@link SchedulerLike} to regulate those deliveries.\n *\n * ## Example\n *\n * Produce a range of numbers\n *\n * ```ts\n * import { range } from 'rxjs';\n *\n * const numbers = range(1, 3);\n *\n * numbers.subscribe({\n *   next: value => console.log(value),\n *   complete: () => console.log('Complete!')\n * });\n *\n * // Logs:\n * // 1\n * // 2\n * // 3\n * // 'Complete!'\n * ```\n *\n * @see {@link timer}\n * @see {@link interval}\n *\n * @param start The value of the first integer in the sequence.\n * @param count The number of sequential integers to generate.\n * @param scheduler A {@link SchedulerLike} to use for scheduling the emissions\n * of the notifications.\n * @return An Observable of numbers that emits a finite range of sequential integers.\n */\nexport function range(start: number, count?: number, scheduler?: SchedulerLike): Observable<number> {\n  if (count == null) {\n    // If one argument was passed, it's the count, not the start.\n    count = start;\n    start = 0;\n  }\n\n  if (count <= 0) {\n    // No count? We're going nowhere. Return EMPTY.\n    return EMPTY;\n  }\n\n  // Where the range should stop.\n  const end = count + start;\n\n  return new Observable(\n    scheduler\n      ? // The deprecated scheduled path.\n        (subscriber) => {\n          let n = start;\n          const emit = () => {\n            if (n < end) {\n              subscriber.next(n++);\n              if (!subscriber.closed) {\n                executeSchedule(subscriber, scheduler, emit);\n              }\n            } else {\n              subscriber.complete();\n            }\n          };\n          executeSchedule(subscriber, scheduler, emit);\n        }\n      : // Standard synchronous range.\n        (subscriber) => {\n          let n = start;\n          while (n < end && !subscriber.closed) {\n            subscriber.next(n++);\n          }\n          subscriber.complete();\n        }\n  );\n}\n"
  },
  {
    "path": "packages/rxjs/src/internal/observable/throwError.ts",
    "content": "import { Observable } from '@rxjs/observable';\n\n/**\n * Creates an observable that will create an error instance and push it to the consumer as an error\n * immediately upon subscription.\n *\n * <span class=\"informal\">Just errors and does nothing else</span>\n *\n * ![](throw.png)\n *\n * This creation function is useful for creating an observable that will create an error and error every\n * time it is subscribed to. Generally, inside of most operators when you might want to return an errored\n * observable, this is unnecessary. In most cases, such as in the inner return of {@link concatMap},\n * {@link mergeMap}, {@link defer}, and many others, you can simply throw the error, and RxJS will pick\n * that up and notify the consumer of the error.\n *\n * ## Example\n *\n * Create a simple observable that will create a new error with a timestamp and log it\n * and the message every time you subscribe to it\n *\n * ```ts\n * import { throwError } from 'rxjs';\n *\n * let errorCount = 0;\n *\n * const errorWithTimestamp$ = throwError(() => {\n *   const error: any = new Error(`This is error number ${ ++errorCount }`);\n *   error.timestamp = Date.now();\n *   return error;\n * });\n *\n * errorWithTimestamp$.subscribe({\n *   error: err => console.log(err.timestamp, err.message)\n * });\n *\n * errorWithTimestamp$.subscribe({\n *   error: err => console.log(err.timestamp, err.message)\n * });\n *\n * // Logs the timestamp and a new error message for each subscription\n * ```\n *\n * ### Unnecessary usage\n *\n * Using `throwError` inside of an operator or creation function\n * with a callback, is usually not necessary\n *\n * ```ts\n * import { of, concatMap, timer, throwError } from 'rxjs';\n *\n * const delays$ = of(1000, 2000, Infinity, 3000);\n *\n * delays$.pipe(\n *   concatMap(ms => {\n *     if (ms < 10000) {\n *       return timer(ms);\n *     } else {\n *       // This is probably overkill.\n *       return throwError(() => new Error(`Invalid time ${ ms }`));\n *     }\n *   })\n * )\n * .subscribe({\n *   next: console.log,\n *   error: console.error\n * });\n * ```\n *\n * You can just throw the error instead\n *\n * ```ts\n * import { of, concatMap, timer } from 'rxjs';\n *\n * const delays$ = of(1000, 2000, Infinity, 3000);\n *\n * delays$.pipe(\n *   concatMap(ms => {\n *     if (ms < 10000) {\n *       return timer(ms);\n *     } else {\n *       // Cleaner and easier to read for most folks.\n *       throw new Error(`Invalid time ${ ms }`);\n *     }\n *   })\n * )\n * .subscribe({\n *   next: console.log,\n *   error: console.error\n * });\n * ```\n *\n * @param errorFactory A factory function that will create the error instance that is pushed.\n */\nexport function throwError(errorFactory: () => any): Observable<never> {\n  return new Observable((subscriber) => {\n    subscriber.error(errorFactory());\n  });\n}\n"
  },
  {
    "path": "packages/rxjs/src/internal/observable/timer.ts",
    "content": "import { Observable } from '@rxjs/observable';\nimport type { SchedulerLike } from '../types.js';\nimport { asyncScheduler } from '../scheduler/async.js';\nimport { isScheduler } from '../util/isScheduler.js';\nimport { isValidDate } from '../util/isDate.js';\nimport { executeSchedule } from '../util/executeSchedule.js';\n\n/**\n * Creates an observable that will wait for a specified time period, or exact date, before\n * emitting the number 0.\n *\n * <span class=\"informal\">Used to emit a notification after a delay.</span>\n *\n * This observable is useful for creating delays in code, or racing against other values\n * for ad-hoc timeouts.\n *\n * The `delay` is specified by default in milliseconds, however providing a custom scheduler could\n * create a different behavior.\n *\n * ## Examples\n *\n * Wait 3 seconds and start another observable\n *\n * You might want to use `timer` to delay subscription to an\n * observable by a set amount of time. Here we use a timer with\n * {@link concatMapTo} or {@link concatMap} in order to wait\n * a few seconds and start a subscription to a source.\n *\n * ```ts\n * import { of, timer, concatMap } from 'rxjs';\n *\n * // This could be any observable\n * const source = of(1, 2, 3);\n *\n * timer(3000)\n *   .pipe(concatMap(() => source))\n *   .subscribe(console.log);\n * ```\n *\n * Take all values until the start of the next minute\n *\n * Using a `Date` as the trigger for the first emission, you can\n * do things like wait until midnight to fire an event, or in this case,\n * wait until a new minute starts (chosen so the example wouldn't take\n * too long to run) in order to stop watching a stream. Leveraging\n * {@link takeUntil}.\n *\n * ```ts\n * import { interval, takeUntil, timer } from 'rxjs';\n *\n * // Build a Date object that marks the\n * // next minute.\n * const currentDate = new Date();\n * const startOfNextMinute = new Date(\n *   currentDate.getFullYear(),\n *   currentDate.getMonth(),\n *   currentDate.getDate(),\n *   currentDate.getHours(),\n *   currentDate.getMinutes() + 1\n * );\n *\n * // This could be any observable stream\n * const source = interval(1000);\n *\n * const result = source.pipe(\n *   takeUntil(timer(startOfNextMinute))\n * );\n *\n * result.subscribe(console.log);\n * ```\n *\n * ### Known Limitations\n *\n * - The {@link asyncScheduler} uses `setTimeout` which has limitations for how far in the future it can be scheduled.\n *\n * - If a `scheduler` is provided that returns a timestamp other than an epoch from `now()`, and\n * a `Date` object is passed to the `dueTime` argument, the calculation for when the first emission\n * should occur will be incorrect. In this case, it would be best to do your own calculations\n * ahead of time, and pass a `number` in as the `dueTime`.\n *\n * @param due If a `number`, the amount of time in milliseconds to wait before emitting.\n * If a `Date`, the exact time at which to emit.\n * @param scheduler The scheduler to use to schedule the delay. Defaults to {@link asyncScheduler}.\n */\nexport function timer(due: number | Date, scheduler?: SchedulerLike): Observable<0>;\n\n/**\n * Creates an observable that starts an interval after a specified delay, emitting incrementing numbers -- starting at `0` --\n * on each interval afterwards.\n *\n * The `delay` and `intervalDuration` are specified by default in milliseconds, however providing a custom scheduler could\n * create a different behavior.\n *\n * ## Example\n *\n * ### Start an interval that starts right away\n *\n * Since {@link interval} waits for the passed delay before starting,\n * sometimes that's not ideal. You may want to start an interval immediately.\n * `timer` works well for this. Here we have both side-by-side so you can\n * see them in comparison.\n *\n * Note that this observable will never complete.\n *\n * ```ts\n * import { timer, interval } from 'rxjs';\n *\n * timer(0, 1000).subscribe(n => console.log('timer', n));\n * interval(1000).subscribe(n => console.log('interval', n));\n * ```\n *\n * ### Known Limitations\n *\n * - The {@link asyncScheduler} uses `setTimeout` which has limitations for how far in the future it can be scheduled.\n *\n * - If a `scheduler` is provided that returns a timestamp other than an epoch from `now()`, and\n * a `Date` object is passed to the `dueTime` argument, the calculation for when the first emission\n * should occur will be incorrect. In this case, it would be best to do your own calculations\n * ahead of time, and pass a `number` in as the `startDue`.\n * @param startDue If a `number`, is the time to wait before starting the interval.\n * If a `Date`, is the exact time at which to start the interval.\n * @param intervalDuration The delay between each value emitted in the interval. Passing a\n * negative number here will result in immediate completion after the first value is emitted, as though\n * no `intervalDuration` was passed at all.\n * @param scheduler The scheduler to use to schedule the delay. Defaults to {@link asyncScheduler}.\n */\nexport function timer(startDue: number | Date, intervalDuration: number, scheduler?: SchedulerLike): Observable<number>;\n\n/**\n * @deprecated The signature allowing `undefined` to be passed for `intervalDuration` will be removed in v8. Use the `timer(dueTime, scheduler?)` signature instead.\n */\nexport function timer(dueTime: number | Date, unused: undefined, scheduler?: SchedulerLike): Observable<0>;\n\nexport function timer(\n  dueTime: number | Date = 0,\n  intervalOrScheduler?: number | SchedulerLike,\n  scheduler: SchedulerLike = asyncScheduler\n): Observable<number> {\n  // Since negative intervalDuration is treated as though no\n  // interval was specified at all, we start with a negative number.\n  let intervalDuration = -1;\n\n  if (intervalOrScheduler != null) {\n    // If we have a second argument, and it's a scheduler,\n    // override the scheduler we had defaulted. Otherwise,\n    // it must be an interval.\n    if (isScheduler(intervalOrScheduler)) {\n      scheduler = intervalOrScheduler;\n    } else {\n      // Note that this *could* be negative, in which case\n      // it's like not passing an intervalDuration at all.\n      intervalDuration = intervalOrScheduler;\n    }\n  }\n\n  return new Observable((subscriber) => {\n    // If a valid date is passed, calculate how long to wait before\n    // executing the first value... otherwise, if it's a number just schedule\n    // that many milliseconds (or scheduler-specified unit size) in the future.\n    let due = isValidDate(dueTime) ? +dueTime - scheduler!.now() : dueTime;\n\n    if (due < 0) {\n      // Ensure we don't schedule in the future.\n      due = 0;\n    }\n\n    // The incrementing value we emit.\n    let n = 0;\n\n    // Start the timer.\n    return executeSchedule(\n      subscriber,\n      scheduler,\n      () => {\n        // Emit the first value and schedule the next.\n        subscriber.next(n++);\n\n        if (0 <= intervalDuration) {\n          // If we have a interval after the initial timer,\n          // reschedule with the period.\n          executeSchedule(\n            subscriber,\n            scheduler,\n            () => {\n              // Emit the interval values.\n              subscriber.next(n++);\n            },\n            intervalDuration,\n            true\n          );\n        } else {\n          // We didn't have an interval. So just complete.\n          subscriber.complete();\n        }\n      },\n      due\n    );\n  });\n}\n"
  },
  {
    "path": "packages/rxjs/src/internal/observable/using.ts",
    "content": "import { Observable, from } from '@rxjs/observable';\nimport type { Unsubscribable, ObservableInput, ObservedValueOf } from '../types.js';\nimport { EMPTY } from './empty.js';\n\n/**\n * Creates an Observable that uses a resource which will be disposed at the same time as the Observable.\n *\n * <span class=\"informal\">Use it when you catch yourself cleaning up after an Observable.</span>\n *\n * `using` is a factory operator, which accepts two functions. First function returns a disposable resource.\n * It can be an arbitrary object that implements `unsubscribe` method. Second function will be injected with\n * that object and should return an Observable. That Observable can use resource object during its execution.\n * Both functions passed to `using` will be called every time someone subscribes - neither an Observable nor\n * resource object will be shared in any way between subscriptions.\n *\n * When Observable returned by `using` is subscribed, Observable returned from the second function will be subscribed\n * as well. All its notifications (nexted values, completion and error events) will be emitted unchanged by the output\n * Observable. If however someone unsubscribes from the Observable or source Observable completes or errors by itself,\n * the `unsubscribe` method on resource object will be called. This can be used to do any necessary clean up, which\n * otherwise would have to be handled by hand. Note that complete or error notifications are not emitted when someone\n * cancels subscription to an Observable via `unsubscribe`, so `using` can be used as a hook, allowing you to make\n * sure that all resources which need to exist during an Observable execution will be disposed at appropriate time.\n *\n * @see {@link defer}\n *\n * @param resourceFactory A function which creates any resource object that implements `unsubscribe` method.\n * @param observableFactory A function which creates an Observable, that can use injected resource object.\n * @return An Observable that behaves the same as Observable returned by `observableFactory`, but\n * which - when completed, errored or unsubscribed - will also call `unsubscribe` on created resource object.\n */\nexport function using<T extends ObservableInput<any>>(\n  resourceFactory: () => Unsubscribable | void,\n  observableFactory: (resource: Unsubscribable | void) => T | void\n): Observable<ObservedValueOf<T>> {\n  return new Observable<ObservedValueOf<T>>((subscriber) => {\n    const resource = resourceFactory();\n    const result = observableFactory(resource);\n    const source = result ? from(result) : EMPTY;\n    source.subscribe(subscriber);\n    return () => {\n      // NOTE: Optional chaining did not work here.\n      // Related TS Issue: https://github.com/microsoft/TypeScript/issues/40818\n      if (resource) {\n        resource.unsubscribe();\n      }\n    };\n  });\n}\n"
  },
  {
    "path": "packages/rxjs/src/internal/observable/zip.ts",
    "content": "import { Observable, from, operate } from '@rxjs/observable';\nimport type { ObservableInputTuple } from '../types.js';\nimport { argsOrArgArray } from '../util/argsOrArgArray.js';\nimport { EMPTY } from './empty.js';\nimport { popResultSelector } from '../util/args.js';\n\nexport function zip<A extends readonly unknown[]>(sources: [...ObservableInputTuple<A>]): Observable<A>;\nexport function zip<A extends readonly unknown[], R>(\n  sources: [...ObservableInputTuple<A>],\n  resultSelector: (...values: A) => R\n): Observable<R>;\nexport function zip<A extends readonly unknown[]>(...sources: [...ObservableInputTuple<A>]): Observable<A>;\nexport function zip<A extends readonly unknown[], R>(\n  ...sourcesAndResultSelector: [...ObservableInputTuple<A>, (...values: A) => R]\n): Observable<R>;\n\n/**\n * Combines multiple Observables to create an Observable whose values are calculated from the values, in order, of each\n * of its input Observables.\n *\n * If the last parameter is a function, this function is used to compute the created value from the input values.\n * Otherwise, an array of the input values is returned.\n *\n * ## Example\n *\n * Combine age and name from different sources\n *\n * ```ts\n * import { of, zip, map } from 'rxjs';\n *\n * const age$ = of(27, 25, 29);\n * const name$ = of('Foo', 'Bar', 'Beer');\n * const isDev$ = of(true, true, false);\n *\n * zip(age$, name$, isDev$).pipe(\n *   map(([age, name, isDev]) => ({ age, name, isDev }))\n * )\n * .subscribe(x => console.log(x));\n *\n * // Outputs\n * // { age: 27, name: 'Foo', isDev: true }\n * // { age: 25, name: 'Bar', isDev: true }\n * // { age: 29, name: 'Beer', isDev: false }\n * ```\n *\n * @param args Any number of `ObservableInput`s provided either as an array or as an object\n * to combine with each other.\n * @return An Observable of array values of the values emitted at the same index from each\n * individual `ObservableInput`.\n */\nexport function zip(...args: unknown[]): Observable<unknown> {\n  const resultSelector = popResultSelector(args);\n\n  const sources = argsOrArgArray(args) as Observable<unknown>[];\n\n  return sources.length\n    ? new Observable<unknown[]>((destination) => {\n        // A collection of buffers of values from each source.\n        // Keyed by the same index with which the sources were passed in.\n        let buffers: unknown[][] = sources.map(() => []);\n\n        // An array of flags of whether or not the sources have completed.\n        // This is used to check to see if we should complete the result.\n        // Keyed by the same index with which the sources were passed in.\n        let completed = sources.map(() => false);\n\n        // When everything is done, release the arrays above.\n        destination.add(() => {\n          buffers = completed = null!;\n        });\n\n        // Loop over our sources and subscribe to each one. The index `i` is\n        // especially important here, because we use it in closures below to\n        // access the related buffers and completion properties\n        for (let sourceIndex = 0; !destination.closed && sourceIndex < sources.length; sourceIndex++) {\n          from(sources[sourceIndex]).subscribe(\n            operate({\n              destination,\n              next: (value) => {\n                buffers[sourceIndex].push(value);\n                // if every buffer has at least one value in it, then we\n                // can shift out the oldest value from each buffer and emit\n                // them as an array.\n                if (buffers.every((buffer) => buffer.length)) {\n                  const result: any = buffers.map((buffer) => buffer.shift()!);\n                  // Emit the array. If theres' a result selector, use that.\n                  destination.next(resultSelector ? resultSelector(...result) : result);\n                  // If any one of the sources is both complete and has an empty buffer\n                  // then we complete the result. This is because we cannot possibly have\n                  // any more values to zip together.\n                  if (buffers.some((buffer, i) => !buffer.length && completed[i])) {\n                    destination.complete();\n                  }\n                }\n              },\n              complete: () => {\n                // This source completed. Mark it as complete so we can check it later\n                // if we have to.\n                completed[sourceIndex] = true;\n                // But, if this complete source has nothing in its buffer, then we\n                // can complete the result, because we can't possibly have any more\n                // values from this to zip together with the other values.\n                !buffers[sourceIndex].length && destination.complete();\n              },\n            })\n          );\n        }\n\n        // When everything is done, release the arrays above.\n        return () => {\n          buffers = completed = null!;\n        };\n      })\n    : EMPTY;\n}\n"
  },
  {
    "path": "packages/rxjs/src/internal/operators/audit.ts",
    "content": "import type { Subscriber} from '@rxjs/observable';\nimport { operate, Observable, from } from '@rxjs/observable';\nimport type { MonoTypeOperatorFunction, ObservableInput } from '../types.js';\n\n/**\n * Ignores source values for a duration determined by another Observable, then\n * emits the most recent value from the source Observable, then repeats this\n * process.\n *\n * <span class=\"informal\">It's like {@link auditTime}, but the silencing\n * duration is determined by a second Observable.</span>\n *\n * ![](audit.svg)\n *\n * `audit` is similar to `throttle`, but emits the last value from the silenced\n * time window, instead of the first value. `audit` emits the most recent value\n * from the source Observable on the output Observable as soon as its internal\n * timer becomes disabled, and ignores source values while the timer is enabled.\n * Initially, the timer is disabled. As soon as the first source value arrives,\n * the timer is enabled by calling the `durationSelector` function with the\n * source value, which returns the \"duration\" Observable. When the duration\n * Observable emits a value, the timer is disabled, then the most\n * recent source value is emitted on the output Observable, and this process\n * repeats for the next source value.\n *\n * ## Example\n *\n * Emit clicks at a rate of at most one click per second\n *\n * ```ts\n * import { fromEvent, audit, interval } from 'rxjs';\n *\n * const clicks = fromEvent(document, 'click');\n * const result = clicks.pipe(audit(ev => interval(1000)));\n * result.subscribe(x => console.log(x));\n * ```\n *\n * @see {@link auditTime}\n * @see {@link debounce}\n * @see {@link delayWhen}\n * @see {@link sample}\n * @see {@link throttle}\n *\n * @param durationSelector A function\n * that receives a value from the source Observable, for computing the silencing\n * duration, returned as an Observable or a Promise.\n * @return A function that returns an Observable that performs rate-limiting of\n * emissions from the source Observable.\n */\nexport function audit<T>(durationSelector: (value: T) => ObservableInput<any>): MonoTypeOperatorFunction<T> {\n  return (source) =>\n    new Observable((destination) => {\n      let hasValue = false;\n      let lastValue: T | null = null;\n      let durationSubscriber: Subscriber<any> | null = null;\n      let isComplete = false;\n\n      const endDuration = () => {\n        durationSubscriber?.unsubscribe();\n        durationSubscriber = null;\n        if (hasValue) {\n          hasValue = false;\n          const value = lastValue!;\n          lastValue = null;\n          destination.next(value);\n        }\n        isComplete && destination.complete();\n      };\n\n      const cleanupDuration = () => {\n        durationSubscriber = null;\n        isComplete && destination.complete();\n      };\n\n      source.subscribe(\n        operate({\n          destination,\n          next: (value) => {\n            hasValue = true;\n            lastValue = value;\n            if (!durationSubscriber) {\n              from(durationSelector(value)).subscribe(\n                (durationSubscriber = operate({\n                  destination,\n                  next: endDuration,\n                  complete: cleanupDuration,\n                }))\n              );\n            }\n          },\n          complete: () => {\n            isComplete = true;\n            (!hasValue || !durationSubscriber || durationSubscriber.closed) && destination.complete();\n          },\n        })\n      );\n    });\n}\n"
  },
  {
    "path": "packages/rxjs/src/internal/operators/auditTime.ts",
    "content": "import { asyncScheduler } from '../scheduler/async.js';\nimport { audit } from './audit.js';\nimport { timer } from '../observable/timer.js';\nimport type { MonoTypeOperatorFunction, SchedulerLike } from '../types.js';\n\n/**\n * Ignores source values for `duration` milliseconds, then emits the most recent\n * value from the source Observable, then repeats this process.\n *\n * <span class=\"informal\">When it sees a source value, it ignores that plus\n * the next ones for `duration` milliseconds, and then it emits the most recent\n * value from the source.</span>\n *\n * ![](auditTime.png)\n *\n * `auditTime` is similar to `throttleTime`, but emits the last value from the\n * silenced time window, instead of the first value. `auditTime` emits the most\n * recent value from the source Observable on the output Observable as soon as\n * its internal timer becomes disabled, and ignores source values while the\n * timer is enabled. Initially, the timer is disabled. As soon as the first\n * source value arrives, the timer is enabled. After `duration` milliseconds (or\n * the time unit determined internally by the optional `scheduler`) has passed,\n * the timer is disabled, then the most recent source value is emitted on the\n * output Observable, and this process repeats for the next source value.\n * Optionally takes a {@link SchedulerLike} for managing timers.\n *\n * ## Example\n *\n * Emit clicks at a rate of at most one click per second\n *\n * ```ts\n * import { fromEvent, auditTime } from 'rxjs';\n *\n * const clicks = fromEvent(document, 'click');\n * const result = clicks.pipe(auditTime(1000));\n * result.subscribe(x => console.log(x));\n * ```\n *\n * @see {@link audit}\n * @see {@link debounceTime}\n * @see {@link delay}\n * @see {@link sampleTime}\n * @see {@link throttleTime}\n *\n * @param duration Time to wait before emitting the most recent source value,\n * measured in milliseconds or the time unit determined internally by the\n * optional `scheduler`.\n * @param scheduler The {@link SchedulerLike} to use for managing the timers\n * that handle the rate-limiting behavior.\n * @return A function that returns an Observable that performs rate-limiting of\n * emissions from the source Observable.\n */\nexport function auditTime<T>(duration: number, scheduler: SchedulerLike = asyncScheduler): MonoTypeOperatorFunction<T> {\n  return audit(() => timer(duration, scheduler));\n}\n"
  },
  {
    "path": "packages/rxjs/src/internal/operators/buffer.ts",
    "content": "import type { OperatorFunction, ObservableInput } from '../types.js';\nimport { Observable, operate, from } from '@rxjs/observable';\nimport { noop } from '../util/noop.js';\n\n/**\n * Buffers the source Observable values until `closingNotifier` emits.\n *\n * <span class=\"informal\">Collects values from the past as an array, and emits\n * that array only when another Observable emits.</span>\n *\n * ![](buffer.png)\n *\n * Buffers the incoming Observable values until the given `closingNotifier`\n * `ObservableInput` (that internally gets converted to an Observable)\n * emits a value, at which point it emits the buffer on the output\n * Observable and starts a new buffer internally, awaiting the next time\n * `closingNotifier` emits.\n *\n * ## Example\n *\n * On every click, emit array of most recent interval events\n *\n * ```ts\n * import { fromEvent, interval, buffer } from 'rxjs';\n *\n * const clicks = fromEvent(document, 'click');\n * const intervalEvents = interval(1000);\n * const buffered = intervalEvents.pipe(buffer(clicks));\n * buffered.subscribe(x => console.log(x));\n * ```\n *\n * @see {@link bufferCount}\n * @see {@link bufferTime}\n * @see {@link bufferToggle}\n * @see {@link bufferWhen}\n * @see {@link window}\n *\n * @param closingNotifier An `ObservableInput` that signals the\n * buffer to be emitted on the output Observable.\n * @return A function that returns an Observable of buffers, which are arrays\n * of values.\n */\nexport function buffer<T>(closingNotifier: ObservableInput<any>): OperatorFunction<T, T[]> {\n  return (source) =>\n    new Observable((destination) => {\n      // The current buffered values.\n      let currentBuffer: T[] = [];\n\n      // Subscribe to the closing notifier first.\n      from(closingNotifier).subscribe(\n        operate({\n          destination,\n          next: () => {\n            // Start a new buffer and emit the previous one.\n            const b = currentBuffer;\n            currentBuffer = [];\n            destination.next(b);\n          },\n          complete: noop,\n        })\n      );\n\n      // Subscribe to our source.\n      source.subscribe(\n        operate({\n          destination,\n          next: (value) => currentBuffer.push(value),\n          complete: () => {\n            destination.next(currentBuffer);\n            destination.complete();\n          },\n        })\n      );\n\n      return () => {\n        // Ensure buffered values are released on finalization.\n        currentBuffer = null!;\n      };\n    });\n}\n"
  },
  {
    "path": "packages/rxjs/src/internal/operators/bufferCount.ts",
    "content": "import type { OperatorFunction } from '../types.js';\nimport { Observable, operate } from '@rxjs/observable';\nimport { arrRemove } from '../util/arrRemove.js';\n\n/**\n * Buffers the source Observable values until the size hits the maximum\n * `bufferSize` given.\n *\n * <span class=\"informal\">Collects values from the past as an array, and emits\n * that array only when its size reaches `bufferSize`.</span>\n *\n * ![](bufferCount.png)\n *\n * Buffers a number of values from the source Observable by `bufferSize` then\n * emits the buffer and clears it, and starts a new buffer each\n * `startBufferEvery` values. If `startBufferEvery` is not provided or is\n * `null`, then new buffers are started immediately at the start of the source\n * and when each buffer closes and is emitted.\n *\n * ## Examples\n *\n * Emit the last two click events as an array\n *\n * ```ts\n * import { fromEvent, bufferCount } from 'rxjs';\n *\n * const clicks = fromEvent(document, 'click');\n * const buffered = clicks.pipe(bufferCount(2));\n * buffered.subscribe(x => console.log(x));\n * ```\n *\n * On every click, emit the last two click events as an array\n *\n * ```ts\n * import { fromEvent, bufferCount } from 'rxjs';\n *\n * const clicks = fromEvent(document, 'click');\n * const buffered = clicks.pipe(bufferCount(2, 1));\n * buffered.subscribe(x => console.log(x));\n * ```\n *\n * @see {@link buffer}\n * @see {@link bufferTime}\n * @see {@link bufferToggle}\n * @see {@link bufferWhen}\n * @see {@link pairwise}\n * @see {@link windowCount}\n *\n * @param bufferSize The maximum size of the buffer emitted.\n * @param startBufferEvery Interval at which to start a new buffer.\n * For example if `startBufferEvery` is `2`, then a new buffer will be started\n * on every other value from the source. A new buffer is started at the\n * beginning of the source by default.\n * @return A function that returns an Observable of arrays of buffered values.\n */\nexport function bufferCount<T>(bufferSize: number, startBufferEvery: number | null = null): OperatorFunction<T, T[]> {\n  // If no `startBufferEvery` value was supplied, then we're\n  // opening and closing on the bufferSize itself.\n  startBufferEvery = startBufferEvery ?? bufferSize;\n\n  return (source) =>\n    new Observable((destination) => {\n      let buffers: T[][] = [];\n      let count = 0;\n\n      source.subscribe(\n        operate({\n          destination,\n          next: (value) => {\n            let toEmit: T[][] | null = null;\n\n            // Check to see if we need to start a buffer.\n            // This will start one at the first value, and then\n            // a new one every N after that.\n            if (count++ % startBufferEvery! === 0) {\n              buffers.push([]);\n            }\n\n            // Push our value into our active buffers.\n            for (const buffer of buffers) {\n              buffer.push(value);\n              // Check to see if we're over the bufferSize\n              // if we are, record it so we can emit it later.\n              // If we emitted it now and removed it, it would\n              // mutate the `buffers` array while we're looping\n              // over it.\n              if (bufferSize <= buffer.length) {\n                toEmit = toEmit ?? [];\n                toEmit.push(buffer);\n              }\n            }\n\n            if (toEmit) {\n              // We have found some buffers that are over the\n              // `bufferSize`. Emit them, and remove them from our\n              // buffers list.\n              for (const buffer of toEmit) {\n                arrRemove(buffers, buffer);\n                destination.next(buffer);\n              }\n            }\n          },\n          complete: () => {\n            // When the source completes, emit all of our\n            // active buffers.\n            for (const buffer of buffers) {\n              destination.next(buffer);\n            }\n            destination.complete();\n          },\n          finalize: () => {\n            // Clean up our memory when we finalize\n            buffers = null!;\n          },\n        })\n      );\n    });\n}\n"
  },
  {
    "path": "packages/rxjs/src/internal/operators/bufferTime.ts",
    "content": "import { Subscription, Observable, operate } from '@rxjs/observable';\nimport type { OperatorFunction, SchedulerLike } from '../types.js';\nimport { arrRemove } from '../util/arrRemove.js';\nimport { asyncScheduler } from '../scheduler/async.js';\nimport { popScheduler } from '../util/args.js';\nimport { executeSchedule } from '../util/executeSchedule.js';\n\nexport function bufferTime<T>(bufferTimeSpan: number, scheduler?: SchedulerLike): OperatorFunction<T, T[]>;\nexport function bufferTime<T>(\n  bufferTimeSpan: number,\n  bufferCreationInterval: number | null | undefined,\n  scheduler?: SchedulerLike\n): OperatorFunction<T, T[]>;\nexport function bufferTime<T>(\n  bufferTimeSpan: number,\n  bufferCreationInterval: number | null | undefined,\n  maxBufferSize: number,\n  scheduler?: SchedulerLike\n): OperatorFunction<T, T[]>;\n\n/**\n * Buffers the source Observable values for a specific time period.\n *\n * <span class=\"informal\">Collects values from the past as an array, and emits\n * those arrays periodically in time.</span>\n *\n * ![](bufferTime.png)\n *\n * Buffers values from the source for a specific time duration `bufferTimeSpan`.\n * Unless the optional argument `bufferCreationInterval` is given, it emits and\n * resets the buffer every `bufferTimeSpan` milliseconds. If\n * `bufferCreationInterval` is given, this operator opens the buffer every\n * `bufferCreationInterval` milliseconds and closes (emits and resets) the\n * buffer every `bufferTimeSpan` milliseconds. When the optional argument\n * `maxBufferSize` is specified, the buffer will be closed either after\n * `bufferTimeSpan` milliseconds or when it contains `maxBufferSize` elements.\n *\n * ## Examples\n *\n * Every second, emit an array of the recent click events\n *\n * ```ts\n * import { fromEvent, bufferTime } from 'rxjs';\n *\n * const clicks = fromEvent(document, 'click');\n * const buffered = clicks.pipe(bufferTime(1000));\n * buffered.subscribe(x => console.log(x));\n * ```\n *\n * Every 5 seconds, emit the click events from the next 2 seconds\n *\n * ```ts\n * import { fromEvent, bufferTime } from 'rxjs';\n *\n * const clicks = fromEvent(document, 'click');\n * const buffered = clicks.pipe(bufferTime(2000, 5000));\n * buffered.subscribe(x => console.log(x));\n * ```\n *\n * @see {@link buffer}\n * @see {@link bufferCount}\n * @see {@link bufferToggle}\n * @see {@link bufferWhen}\n * @see {@link windowTime}\n *\n * @param bufferTimeSpan The amount of time to fill each buffer array.\n * @param otherArgs Other configuration arguments such as:\n * - `bufferCreationInterval` - the interval at which to start new buffers;\n * - `maxBufferSize` - the maximum buffer size;\n * - `scheduler` - the scheduler on which to schedule the intervals that determine buffer boundaries.\n * @return A function that returns an Observable of arrays of buffered values.\n */\nexport function bufferTime<T>(bufferTimeSpan: number, ...otherArgs: any[]): OperatorFunction<T, T[]> {\n  const scheduler = popScheduler(otherArgs) ?? asyncScheduler;\n  const bufferCreationInterval = (otherArgs[0] as number) ?? null;\n  const maxBufferSize = (otherArgs[1] as number) || Infinity;\n\n  return (source) =>\n    new Observable((destination) => {\n      // The active buffers, their related subscriptions, and removal functions.\n      let bufferRecords: { buffer: T[]; subs: Subscription }[] | null = [];\n      // If true, it means that every time we emit a buffer, we want to start a new buffer\n      // this is only really used for when *just* the buffer time span is passed.\n      let restartOnEmit = false;\n\n      /**\n       * Does the work of emitting the buffer from the record, ensuring that the\n       * record is removed before the emission so reentrant code (from some custom scheduling, perhaps)\n       * does not alter the buffer. Also checks to see if a new buffer needs to be started\n       * after the emit.\n       */\n      const emit = (record: { buffer: T[]; subs: Subscription }) => {\n        const { buffer, subs } = record;\n        subs.unsubscribe();\n        arrRemove(bufferRecords, record);\n        destination.next(buffer);\n        restartOnEmit && startBuffer();\n      };\n\n      /**\n       * Called every time we start a new buffer. This does\n       * the work of scheduling a job at the requested bufferTimeSpan\n       * that will emit the buffer (if it's not unsubscribed before then).\n       */\n      const startBuffer = () => {\n        if (bufferRecords) {\n          const subs = new Subscription();\n          destination.add(subs);\n          const buffer: T[] = [];\n          const record = {\n            buffer,\n            subs,\n          };\n          bufferRecords.push(record);\n          executeSchedule(subs, scheduler, () => emit(record), bufferTimeSpan);\n        }\n      };\n\n      if (bufferCreationInterval !== null && bufferCreationInterval >= 0) {\n        // The user passed both a bufferTimeSpan (required), and a creation interval\n        // That means we need to start new buffers on the interval, and those buffers need\n        // to wait the required time span before emitting.\n        executeSchedule(destination, scheduler, startBuffer, bufferCreationInterval, true);\n      } else {\n        restartOnEmit = true;\n      }\n\n      startBuffer();\n\n      const bufferTimeSubscriber = operate({\n        destination,\n        next: (value: T) => {\n          // Copy the records, so if we need to remove one we\n          // don't mutate the array. It's hard, but not impossible to\n          // set up a buffer time that could mutate the array and\n          // cause issues here.\n          const recordsCopy = bufferRecords!.slice();\n          for (const record of recordsCopy) {\n            // Loop over all buffers and\n            const { buffer } = record;\n            buffer.push(value);\n            // If the buffer is over the max size, we need to emit it.\n            maxBufferSize <= buffer.length && emit(record);\n          }\n        },\n        complete: () => {\n          // The source completed, emit all of the active\n          // buffers we have before we complete.\n          while (bufferRecords?.length) {\n            destination.next(bufferRecords.shift()!.buffer);\n          }\n          bufferTimeSubscriber?.unsubscribe();\n          destination.complete();\n          destination.unsubscribe();\n        },\n        // Clean up\n        finalize: () => (bufferRecords = null),\n      });\n\n      source.subscribe(bufferTimeSubscriber);\n    });\n}\n"
  },
  {
    "path": "packages/rxjs/src/internal/operators/bufferToggle.ts",
    "content": "import { Subscription, Observable, operate, from } from '@rxjs/observable';\nimport type { OperatorFunction, ObservableInput } from '../types.js';\nimport { noop } from '../util/noop.js';\nimport { arrRemove } from '../util/arrRemove.js';\n\n/**\n * Buffers the source Observable values starting from an emission from\n * `openings` and ending when the output of `closingSelector` emits.\n *\n * <span class=\"informal\">Collects values from the past as an array. Starts\n * collecting only when `opening` emits, and calls the `closingSelector`\n * function to get an Observable that tells when to close the buffer.</span>\n *\n * ![](bufferToggle.png)\n *\n * Buffers values from the source by opening the buffer via signals from an\n * Observable provided to `openings`, and closing and sending the buffers when\n * a Subscribable or Promise returned by the `closingSelector` function emits.\n *\n * ## Example\n *\n * Every other second, emit the click events from the next 500ms\n *\n * ```ts\n * import { fromEvent, interval, bufferToggle, EMPTY } from 'rxjs';\n *\n * const clicks = fromEvent(document, 'click');\n * const openings = interval(1000);\n * const buffered = clicks.pipe(bufferToggle(openings, i =>\n *   i % 2 ? interval(500) : EMPTY\n * ));\n * buffered.subscribe(x => console.log(x));\n * ```\n *\n * @see {@link buffer}\n * @see {@link bufferCount}\n * @see {@link bufferTime}\n * @see {@link bufferWhen}\n * @see {@link windowToggle}\n *\n * @param openings A Subscribable or Promise of notifications to start new\n * buffers.\n * @param closingSelector A function that takes\n * the value emitted by the `openings` observable and returns a Subscribable or Promise,\n * which, when it emits, signals that the associated buffer should be emitted\n * and cleared.\n * @return A function that returns an Observable of arrays of buffered values.\n */\nexport function bufferToggle<T, O>(\n  openings: ObservableInput<O>,\n  closingSelector: (value: O) => ObservableInput<any>\n): OperatorFunction<T, T[]> {\n  return (source) =>\n    new Observable((destination) => {\n      const buffers: T[][] = [];\n\n      // Subscribe to the openings notifier first\n      from(openings).subscribe(\n        operate({\n          destination,\n          next: (openValue) => {\n            const buffer: T[] = [];\n            buffers.push(buffer);\n            // We use this composite subscription, so that\n            // when the closing notifier emits, we can tear it down.\n            const closingSubscription = new Subscription();\n\n            const emitBuffer = () => {\n              arrRemove(buffers, buffer);\n              destination.next(buffer);\n              closingSubscription.unsubscribe();\n            };\n\n            // The line below will add the subscription to the parent subscriber *and* the closing subscription.\n            closingSubscription.add(from(closingSelector(openValue)).subscribe(operate({ destination, next: emitBuffer, complete: noop })));\n          },\n          complete: noop,\n        })\n      );\n\n      source.subscribe(\n        operate({\n          destination,\n          next: (value) => {\n            // Value from our source. Add it to all pending buffers.\n            for (const buffer of buffers) {\n              buffer.push(value);\n            }\n          },\n          complete: () => {\n            // Source complete. Emit all pending buffers.\n            while (buffers.length > 0) {\n              destination.next(buffers.shift()!);\n            }\n            destination.complete();\n          },\n        })\n      );\n    });\n}\n"
  },
  {
    "path": "packages/rxjs/src/internal/operators/bufferWhen.ts",
    "content": "import type { Subscriber} from '@rxjs/observable';\nimport { operate, Observable, from } from '@rxjs/observable';\nimport type { ObservableInput, OperatorFunction } from '../types.js';\nimport { noop } from '../util/noop.js';\n\n/**\n * Buffers the source Observable values, using a factory function of closing\n * Observables to determine when to close, emit, and reset the buffer.\n *\n * <span class=\"informal\">Collects values from the past as an array. When it\n * starts collecting values, it calls a function that returns an Observable that\n * tells when to close the buffer and restart collecting.</span>\n *\n * ![](bufferWhen.svg)\n *\n * Opens a buffer immediately, then closes the buffer when the observable\n * returned by calling `closingSelector` function emits a value. When it closes\n * the buffer, it immediately opens a new buffer and repeats the process.\n *\n * ## Example\n *\n * Emit an array of the last clicks every [1-5] random seconds\n *\n * ```ts\n * import { fromEvent, bufferWhen, interval } from 'rxjs';\n *\n * const clicks = fromEvent(document, 'click');\n * const buffered = clicks.pipe(\n *   bufferWhen(() => interval(1000 + Math.random() * 4000))\n * );\n * buffered.subscribe(x => console.log(x));\n * ```\n *\n * @see {@link buffer}\n * @see {@link bufferCount}\n * @see {@link bufferTime}\n * @see {@link bufferToggle}\n * @see {@link windowWhen}\n *\n * @param closingSelector A function that takes no arguments and returns an\n * Observable that signals buffer closure.\n * @return A function that returns an Observable of arrays of buffered values.\n */\nexport function bufferWhen<T>(closingSelector: () => ObservableInput<any>): OperatorFunction<T, T[]> {\n  return (source) =>\n    new Observable((subscriber) => {\n      // The buffer we keep and emit.\n      let buffer: T[] | null = null;\n      // A reference to the subscriber used to subscribe to\n      // the closing notifier. We need to hold this so we can\n      // end the subscription after the first notification.\n      let closingSubscriber: Subscriber<T> | null = null;\n\n      // Ends the previous closing notifier subscription, so it\n      // terminates after the first emission, then emits\n      // the current buffer  if there is one, starts a new buffer, and starts a\n      // new closing notifier.\n      const openBuffer = () => {\n        // Make sure to finalize the closing subscription, we only cared\n        // about one notification.\n        closingSubscriber?.unsubscribe();\n        // emit the buffer if we have one, and start a new buffer.\n        const b = buffer;\n        buffer = [];\n        b && subscriber.next(b);\n\n        // Get a new closing notifier and subscribe to it.\n        from(closingSelector()).subscribe(\n          (closingSubscriber = operate({\n            destination: subscriber,\n            next: openBuffer,\n            complete: noop,\n          }))\n        );\n      };\n\n      // Start the first buffer.\n      openBuffer();\n\n      // Subscribe to our source.\n      source.subscribe(\n        operate({\n          destination: subscriber,\n          // Add every new value to the current buffer.\n          next: (value) => buffer?.push(value),\n          // When we complete, emit the buffer if we have one,\n          // then complete the result.\n          complete: () => {\n            buffer && subscriber.next(buffer);\n            subscriber.complete();\n          },\n          // Release memory on finalization\n          finalize: () => (buffer = closingSubscriber = null!),\n        })\n      );\n    });\n}\n"
  },
  {
    "path": "packages/rxjs/src/internal/operators/catchError.ts",
    "content": "import type { Subscription} from '@rxjs/observable';\nimport { Observable, operate, from } from '@rxjs/observable';\nimport type { ObservableInput, OperatorFunction, ObservedValueOf } from '../types.js';\n\nexport function catchError<T, O extends ObservableInput<any>>(\n  selector: (err: any, caught: Observable<T>) => O\n): OperatorFunction<T, T | ObservedValueOf<O>>;\n\n/**\n * Catches errors on the observable to be handled by returning a new observable or throwing an error.\n *\n * <span class=\"informal\">\n * It only listens to the error channel and ignores notifications.\n * Handles errors from the source observable, and maps them to a new observable.\n * The error may also be rethrown, or a new error can be thrown to emit an error from the result.\n * </span>\n *\n * ![](catch.png)\n *\n * This operator handles errors, but forwards along all other events to the resulting observable.\n * If the source observable terminates with an error, it will map that error to a new observable,\n * subscribe to it, and forward all of its events to the resulting observable.\n *\n * ## Examples\n *\n * Continue with a different Observable when there's an error\n *\n * ```ts\n * import { of, map, catchError } from 'rxjs';\n *\n * of(1, 2, 3, 4, 5)\n *   .pipe(\n *     map(n => {\n *       if (n === 4) {\n *         throw 'four!';\n *       }\n *       return n;\n *     }),\n *     catchError(err => of('I', 'II', 'III', 'IV', 'V'))\n *   )\n *   .subscribe(x => console.log(x));\n *   // 1, 2, 3, I, II, III, IV, V\n * ```\n *\n * Retry the caught source Observable again in case of error, similar to `retry()` operator\n *\n * ```ts\n * import { of, map, catchError, take } from 'rxjs';\n *\n * of(1, 2, 3, 4, 5)\n *   .pipe(\n *     map(n => {\n *       if (n === 4) {\n *         throw 'four!';\n *       }\n *       return n;\n *     }),\n *     catchError((err, caught) => caught),\n *     take(30)\n *   )\n *   .subscribe(x => console.log(x));\n *   // 1, 2, 3, 1, 2, 3, ...\n * ```\n *\n * Throw a new error when the source Observable throws an error\n *\n * ```ts\n * import { of, map, catchError } from 'rxjs';\n *\n * of(1, 2, 3, 4, 5)\n *   .pipe(\n *     map(n => {\n *       if (n === 4) {\n *         throw 'four!';\n *       }\n *       return n;\n *     }),\n *     catchError(err => {\n *       throw 'error in source. Details: ' + err;\n *     })\n *   )\n *   .subscribe({\n *     next: x => console.log(x),\n *     error: err => console.log(err)\n *   });\n *   // 1, 2, 3, error in source. Details: four!\n * ```\n *\n * @see {@link onErrorResumeNextWith}\n * @see {@link repeat}\n * @see {@link repeatWhen}\n * @see {@link retry }\n * @see {@link retryWhen}\n *\n * @param selector A function that takes as arguments `err`, which is the error, and `caught`, which\n * is the source observable, in case you'd like to \"retry\" that observable by returning it again.\n * Whatever observable is returned by the `selector` will be used to continue the observable chain.\n * @return A function that returns an Observable that originates from either\n * the source or the Observable returned by the `selector` function.\n */\nexport function catchError<T, O extends ObservableInput<any>>(\n  selector: (err: any, caught: Observable<T>) => O\n): OperatorFunction<T, T | ObservedValueOf<O>> {\n  return (source) =>\n    new Observable((destination) => {\n      let innerSub: Subscription | null = null;\n      let syncUnsub = false;\n      let handledResult: Observable<ObservedValueOf<O>>;\n\n      innerSub = source.subscribe(\n        operate({\n          destination,\n          error: (err) => {\n            handledResult = from(selector(err, catchError(selector)(source)));\n            if (innerSub) {\n              innerSub.unsubscribe();\n              innerSub = null;\n              handledResult.subscribe(destination);\n            } else {\n              // We don't have an innerSub yet, that means the error was synchronous\n              // because the subscribe call hasn't returned yet.\n              syncUnsub = true;\n            }\n          },\n        })\n      );\n\n      if (syncUnsub) {\n        // We have a synchronous error, we need to make sure to\n        // finalize right away. This ensures that callbacks in the `finalize` operator are called\n        // at the right time, and that finalization occurs at the expected\n        // time between the source error and the subscription to the\n        // next observable.\n        innerSub.unsubscribe();\n        innerSub = null;\n        handledResult!.subscribe(destination);\n      }\n    });\n}\n"
  },
  {
    "path": "packages/rxjs/src/internal/operators/combineLatestAll.ts",
    "content": "import { combineLatest } from '../observable/combineLatest.js';\nimport type { OperatorFunction, ObservableInput } from '../types.js';\nimport { joinAllInternals } from './joinAllInternals.js';\n\nexport function combineLatestAll<T>(): OperatorFunction<ObservableInput<T>, T[]>;\nexport function combineLatestAll<T>(): OperatorFunction<any, T[]>;\nexport function combineLatestAll<T, R>(project: (...values: T[]) => R): OperatorFunction<ObservableInput<T>, R>;\nexport function combineLatestAll<R>(project: (...values: Array<any>) => R): OperatorFunction<any, R>;\n\n/**\n * Flattens an Observable-of-Observables by applying {@link combineLatest} when the Observable-of-Observables completes.\n *\n * `combineLatestAll` takes an Observable of Observables, and collects all Observables from it. Once the outer Observable completes,\n * it subscribes to all collected Observables and combines their values using the {@link combineLatest} strategy, such that:\n *\n * * Every time an inner Observable emits, the output Observable emits\n * * When the returned observable emits, it emits all of the latest values by:\n *    * If a `project` function is provided, it is called with each recent value from each inner Observable in whatever order they\n *      arrived, and the result of the `project` function is what is emitted by the output Observable.\n *    * If there is no `project` function, an array of all the most recent values is emitted by the output Observable.\n *\n * ## Example\n *\n * Map two click events to a finite interval Observable, then apply `combineLatestAll`\n *\n * ```ts\n * import { fromEvent, map, interval, take, combineLatestAll } from 'rxjs';\n *\n * const clicks = fromEvent(document, 'click');\n * const higherOrder = clicks.pipe(\n *   map(() => interval(Math.random() * 2000).pipe(take(3))),\n *   take(2)\n * );\n * const result = higherOrder.pipe(combineLatestAll());\n *\n * result.subscribe(x => console.log(x));\n * ```\n *\n * @see {@link combineLatest}\n * @see {@link combineLatestWith}\n * @see {@link mergeAll}\n *\n * @param project optional function to map the most recent values from each inner Observable into a new result.\n * Takes each of the most recent values from each collected inner Observable as arguments, in order.\n * @return A function that returns an Observable that flattens Observables\n * emitted by the source Observable.\n */\nexport function combineLatestAll<R>(project?: (...values: Array<any>) => R) {\n  return joinAllInternals(combineLatest, project);\n}\n"
  },
  {
    "path": "packages/rxjs/src/internal/operators/combineLatestWith.ts",
    "content": "import { combineLatestInit } from '../observable/combineLatest.js';\nimport { Observable } from '@rxjs/observable';\nimport type { Cons, ObservableInputTuple, OperatorFunction } from '../types.js';\n\n/**\n * Create an observable that combines the latest values from all passed observables and the source\n * into arrays and emits them.\n *\n * Returns an observable, that when subscribed to, will subscribe to the source observable and all\n * sources provided as arguments. Once all sources emit at least one value, all of the latest values\n * will be emitted as an array. After that, every time any source emits a value, all of the latest values\n * will be emitted as an array.\n *\n * This is a useful operator for eagerly calculating values based off of changed inputs.\n *\n * ## Example\n *\n * Simple concatenation of values from two inputs\n *\n * ```ts\n * import { fromEvent, combineLatestWith, map } from 'rxjs';\n *\n * // Setup: Add two inputs to the page\n * const input1 = document.createElement('input');\n * document.body.appendChild(input1);\n * const input2 = document.createElement('input');\n * document.body.appendChild(input2);\n *\n * // Get streams of changes\n * const input1Changes$ = fromEvent(input1, 'change');\n * const input2Changes$ = fromEvent(input2, 'change');\n *\n * // Combine the changes by adding them together\n * input1Changes$.pipe(\n *   combineLatestWith(input2Changes$),\n *   map(([e1, e2]) => (<HTMLInputElement>e1.target).value + ' - ' + (<HTMLInputElement>e2.target).value)\n * )\n * .subscribe(x => console.log(x));\n * ```\n *\n * @param otherSources the other sources to subscribe to.\n * @return A function that returns an Observable that emits the latest\n * emissions from both source and provided Observables.\n */\nexport function combineLatestWith<T, A extends readonly unknown[]>(\n  ...otherSources: [...ObservableInputTuple<A>]\n): OperatorFunction<T, Cons<T, A>> {\n  return (source) => new Observable((subscriber) => combineLatestInit([source, ...otherSources])(subscriber));\n}\n"
  },
  {
    "path": "packages/rxjs/src/internal/operators/concatAll.ts",
    "content": "import { mergeAll } from './mergeAll.js';\nimport type { OperatorFunction, ObservableInput, ObservedValueOf } from '../types.js';\n\n/**\n * Converts a higher-order Observable into a first-order Observable by\n * concatenating the inner Observables in order.\n *\n * <span class=\"informal\">Flattens an Observable-of-Observables by putting one\n * inner Observable after the other.</span>\n *\n * ![](concatAll.svg)\n *\n * Joins every Observable emitted by the source (a higher-order Observable), in\n * a serial fashion. It subscribes to each inner Observable only after the\n * previous inner Observable has completed, and merges all of their values into\n * the returned observable.\n *\n * __Warning:__ If the source Observable emits Observables quickly and\n * endlessly, and the inner Observables it emits generally complete slower than\n * the source emits, you can run into memory issues as the incoming Observables\n * collect in an unbounded buffer.\n *\n * Note: `concatAll` is equivalent to `mergeAll` with concurrency parameter set\n * to `1`.\n *\n * ## Example\n *\n * For each click event, tick every second from 0 to 3, with no concurrency\n *\n * ```ts\n * import { fromEvent, map, interval, take, concatAll } from 'rxjs';\n *\n * const clicks = fromEvent(document, 'click');\n * const higherOrder = clicks.pipe(\n *   map(() => interval(1000).pipe(take(4)))\n * );\n * const firstOrder = higherOrder.pipe(concatAll());\n * firstOrder.subscribe(x => console.log(x));\n *\n * // Results in the following:\n * // (results are not concurrent)\n * // For every click on the \"document\" it will emit values 0 to 3 spaced\n * // on a 1000ms interval\n * // one click = 1000ms-> 0 -1000ms-> 1 -1000ms-> 2 -1000ms-> 3\n * ```\n *\n * @see {@link combineLatestAll}\n * @see {@link concat}\n * @see {@link concatMap}\n * @see {@link concatMapTo}\n * @see {@link exhaustAll}\n * @see {@link mergeAll}\n * @see {@link switchAll}\n * @see {@link switchMap}\n * @see {@link zipAll}\n *\n * @return A function that returns an Observable emitting values from all the\n * inner Observables concatenated.\n */\nexport function concatAll<O extends ObservableInput<any>>(): OperatorFunction<O, ObservedValueOf<O>> {\n  return mergeAll(1);\n}\n"
  },
  {
    "path": "packages/rxjs/src/internal/operators/concatMap.ts",
    "content": "import { mergeMap } from './mergeMap.js';\nimport type { ObservableInput, OperatorFunction, ObservedValueOf } from '../types.js';\n\n/**\n * Projects each source value to an Observable which is merged in the output\n * Observable, in a serialized fashion waiting for each one to complete before\n * merging the next.\n *\n * <span class=\"informal\">Maps each value to an Observable, then flattens all of\n * these inner Observables using {@link concatAll}.</span>\n *\n * ![](concatMap.png)\n *\n * Returns an Observable that emits items based on applying a function that you\n * supply to each item emitted by the source Observable, where that function\n * returns an (so-called \"inner\") Observable. Each new inner Observable is\n * concatenated with the previous inner Observable.\n *\n * __Warning:__ if source values arrive endlessly and faster than their\n * corresponding inner Observables can complete, it will result in memory issues\n * as inner Observables amass in an unbounded buffer waiting for their turn to\n * be subscribed to.\n *\n * Note: `concatMap` is equivalent to `mergeMap` with concurrency parameter set\n * to `1`.\n *\n * ## Example\n *\n * For each click event, tick every second from 0 to 3, with no concurrency\n *\n * ```ts\n * import { fromEvent, concatMap, interval, take } from 'rxjs';\n *\n * const clicks = fromEvent(document, 'click');\n * const result = clicks.pipe(\n *   concatMap(ev => interval(1000).pipe(take(4)))\n * );\n * result.subscribe(x => console.log(x));\n *\n * // Results in the following:\n * // (results are not concurrent)\n * // For every click on the \"document\" it will emit values 0 to 3 spaced\n * // on a 1000ms interval\n * // one click = 1000ms-> 0 -1000ms-> 1 -1000ms-> 2 -1000ms-> 3\n * ```\n *\n * @see {@link concat}\n * @see {@link concatAll}\n * @see {@link concatMapTo}\n * @see {@link exhaustMap}\n * @see {@link mergeMap}\n * @see {@link switchMap}\n *\n * @param project A function that, when applied to an item emitted by the source\n * Observable, returns an Observable.\n * @return A function that returns an Observable that emits the result of\n * applying the projection function to each item emitted by the source Observable\n * and taking values from each projected inner Observable sequentially.\n */\nexport function concatMap<T, O extends ObservableInput<any>>(\n  project: (value: T, index: number) => O\n): OperatorFunction<T, ObservedValueOf<O>> {\n  return mergeMap(project, 1);\n}\n"
  },
  {
    "path": "packages/rxjs/src/internal/operators/concatMapTo.ts",
    "content": "import { concatMap } from './concatMap.js';\nimport type { ObservableInput, OperatorFunction, ObservedValueOf } from '../types.js';\n\n/**\n * Projects each source value to the same Observable which is merged multiple\n * times in a serialized fashion on the output Observable.\n *\n * <span class=\"informal\">It's like {@link concatMap}, but maps each value\n * always to the same inner Observable.</span>\n *\n * ![](concatMapTo.png)\n *\n * Maps each source value to the given Observable `innerObservable` regardless\n * of the source value, and then flattens those resulting Observables into one\n * single Observable, which is the output Observable. Each new `innerObservable`\n * instance emitted on the output Observable is concatenated with the previous\n * `innerObservable` instance.\n *\n * __Warning:__ if source values arrive endlessly and faster than their\n * corresponding inner Observables can complete, it will result in memory issues\n * as inner Observables amass in an unbounded buffer waiting for their turn to\n * be subscribed to.\n *\n * Note: `concatMapTo` is equivalent to `mergeMapTo` with concurrency parameter\n * set to `1`.\n *\n * ## Example\n *\n * For each click event, tick every second from 0 to 3, with no concurrency\n *\n * ```ts\n * import { fromEvent, concatMapTo, interval, take } from 'rxjs';\n *\n * const clicks = fromEvent(document, 'click');\n * const result = clicks.pipe(\n *   concatMapTo(interval(1000).pipe(take(4)))\n * );\n * result.subscribe(x => console.log(x));\n *\n * // Results in the following:\n * // (results are not concurrent)\n * // For every click on the \"document\" it will emit values 0 to 3 spaced\n * // on a 1000ms interval\n * // one click = 1000ms-> 0 -1000ms-> 1 -1000ms-> 2 -1000ms-> 3\n * ```\n *\n * @see {@link concat}\n * @see {@link concatAll}\n * @see {@link concatMap}\n * @see {@link mergeMapTo}\n * @see {@link switchMapTo}\n *\n * @param innerObservable An `ObservableInput` to replace each value from the\n * source Observable.\n * @return A function that returns an Observable of values merged together by\n * joining the passed Observable with itself, one after the other, for each\n * value emitted from the source.\n * @deprecated Will be removed in v9. Use {@link concatMap} instead: `concatMap(() => result)`\n */\nexport function concatMapTo<O extends ObservableInput<unknown>>(innerObservable: O): OperatorFunction<unknown, ObservedValueOf<O>> {\n  return concatMap(() => innerObservable);\n}\n"
  },
  {
    "path": "packages/rxjs/src/internal/operators/concatWith.ts",
    "content": "import type { ObservableInputTuple, OperatorFunction } from '../types.js';\nimport { Observable, from } from '@rxjs/observable';\nimport { concatAll } from '../operators/concatAll.js';\n\n/**\n * Emits all of the values from the source observable, then, once it completes, subscribes\n * to each observable source provided, one at a time, emitting all of their values, and not subscribing\n * to the next one until it completes.\n *\n * `concat(a$, b$, c$)` is the same as `a$.pipe(concatWith(b$, c$))`.\n *\n * ## Example\n *\n * Listen for one mouse click, then listen for all mouse moves.\n *\n * ```ts\n * import { fromEvent, map, take, concatWith } from 'rxjs';\n *\n * const clicks$ = fromEvent(document, 'click');\n * const moves$ = fromEvent(document, 'mousemove');\n *\n * clicks$.pipe(\n *   map(() => 'click'),\n *   take(1),\n *   concatWith(\n *     moves$.pipe(\n *       map(() => 'move')\n *     )\n *   )\n * )\n * .subscribe(x => console.log(x));\n *\n * // 'click'\n * // 'move'\n * // 'move'\n * // 'move'\n * // ...\n * ```\n *\n * @param otherSources Other observable sources to subscribe to, in sequence, after the original source is complete.\n * @return A function that returns an Observable that concatenates\n * subscriptions to the source and provided Observables subscribing to the next\n * only once the current subscription completes.\n */\nexport function concatWith<T, A extends readonly unknown[]>(\n  ...otherSources: [...ObservableInputTuple<A>]\n): OperatorFunction<T, T | A[number]> {\n  return (source) =>\n    new Observable((subscriber) => {\n      concatAll()(from([source, ...otherSources])).subscribe(subscriber);\n    });\n}\n"
  },
  {
    "path": "packages/rxjs/src/internal/operators/connect.ts",
    "content": "import type { OperatorFunction, ObservableInput, ObservedValueOf, SubjectLike } from '../types.js';\nimport { Observable, from } from '@rxjs/observable';\nimport { Subject } from '../Subject.js';\nimport { fromSubscribable } from '../observable/fromSubscribable.js';\n\n/**\n * An object used to configure {@link connect} operator.\n */\nexport interface ConnectConfig<T> {\n  /**\n   * A factory function used to create the Subject through which the source\n   * is multicast. By default, this creates a {@link Subject}.\n   */\n  connector: () => SubjectLike<T>;\n}\n\n/**\n * The default configuration for `connect`.\n */\nconst DEFAULT_CONFIG: ConnectConfig<unknown> = {\n  connector: () => new Subject<unknown>(),\n};\n\n/**\n * Creates an observable by multicasting the source within a function that\n * allows the developer to define the usage of the multicast prior to connection.\n *\n * This is particularly useful if the observable source you wish to multicast could\n * be synchronous or asynchronous. This sets it apart from {@link share}, which, in the\n * case of totally synchronous sources will fail to share a single subscription with\n * multiple consumers, as by the time the subscription to the result of {@link share}\n * has returned, if the source is synchronous its internal reference count will jump from\n * 0 to 1 back to 0 and reset.\n *\n * To use `connect`, you provide a `selector` function that will give you\n * a multicast observable that is not yet connected. You then use that multicast observable\n * to create a resulting observable that, when subscribed, will set up your multicast. This is\n * generally, but not always, accomplished with {@link merge}.\n *\n * Note that using a {@link takeUntil} inside of `connect`'s `selector` _might_ mean you were looking\n * to use the {@link takeWhile} operator instead.\n *\n * When you subscribe to the result of `connect`, the `selector` function will be called. After\n * the `selector` function returns, the observable it returns will be subscribed to, _then_ the\n * multicast will be connected to the source.\n *\n * ## Example\n *\n * Sharing a totally synchronous observable\n *\n * ```ts\n * import { of, tap, connect, merge, map, filter } from 'rxjs';\n *\n * const source$ = of(1, 2, 3, 4, 5).pipe(\n *   tap({\n *     subscribe: () => console.log('subscription started'),\n *     next: n => console.log(`source emitted ${ n }`)\n *   })\n * );\n *\n * source$.pipe(\n *   // Notice in here we're merging 3 subscriptions to `shared$`.\n *   connect(shared$ => merge(\n *     shared$.pipe(map(n => `all ${ n }`)),\n *     shared$.pipe(filter(n => n % 2 === 0), map(n => `even ${ n }`)),\n *     shared$.pipe(filter(n => n % 2 === 1), map(n => `odd ${ n }`))\n *   ))\n * )\n * .subscribe(console.log);\n *\n * // Expected output: (notice only one subscription)\n * 'subscription started'\n * 'source emitted 1'\n * 'all 1'\n * 'odd 1'\n * 'source emitted 2'\n * 'all 2'\n * 'even 2'\n * 'source emitted 3'\n * 'all 3'\n * 'odd 3'\n * 'source emitted 4'\n * 'all 4'\n * 'even 4'\n * 'source emitted 5'\n * 'all 5'\n * 'odd 5'\n * ```\n *\n * @param selector A function used to set up the multicast. Gives you a multicast observable\n * that is not yet connected. With that, you're expected to create and return\n * an Observable, that when subscribed to, will utilize the multicast observable.\n * After this function is executed -- and its return value subscribed to -- the\n * operator will subscribe to the source, and the connection will be made.\n * @param config The configuration object for `connect`.\n */\nexport function connect<T, O extends ObservableInput<unknown>>(\n  selector: (shared: Observable<T>) => O,\n  config: ConnectConfig<T> = DEFAULT_CONFIG\n): OperatorFunction<T, ObservedValueOf<O>> {\n  const { connector } = config;\n  return (source) =>\n    new Observable((subscriber) => {\n      const subject = connector();\n      from(selector(fromSubscribable(subject))).subscribe(subscriber);\n      subscriber.add(source.subscribe(subject));\n    });\n}\n"
  },
  {
    "path": "packages/rxjs/src/internal/operators/count.ts",
    "content": "import type { OperatorFunction } from '../types.js';\nimport { reduce } from './reduce.js';\n\n/**\n * Counts the number of emissions on the source and emits that number when the\n * source completes.\n *\n * <span class=\"informal\">Tells how many values were emitted, when the source\n * completes.</span>\n *\n * ![](count.png)\n *\n * `count` transforms an Observable that emits values into an Observable that\n * emits a single value that represents the number of values emitted by the\n * source Observable. If the source Observable terminates with an error, `count`\n * will pass this error notification along without emitting a value first. If\n * the source Observable does not terminate at all, `count` will neither emit\n * a value nor terminate. This operator takes an optional `predicate` function\n * as argument, in which case the output emission will represent the number of\n * source values that matched `true` with the `predicate`.\n *\n * ## Examples\n *\n * Counts how many seconds have passed before the first click happened\n *\n * ```ts\n * import { interval, fromEvent, takeUntil, count } from 'rxjs';\n *\n * const seconds = interval(1000);\n * const clicks = fromEvent(document, 'click');\n * const secondsBeforeClick = seconds.pipe(takeUntil(clicks));\n * const result = secondsBeforeClick.pipe(count());\n * result.subscribe(x => console.log(x));\n * ```\n *\n * Counts how many odd numbers are there between 1 and 7\n *\n * ```ts\n * import { range, count } from 'rxjs';\n *\n * const numbers = range(1, 7);\n * const result = numbers.pipe(count(i => i % 2 === 1));\n * result.subscribe(x => console.log(x));\n * // Results in:\n * // 4\n * ```\n *\n * @see {@link max}\n * @see {@link min}\n * @see {@link reduce}\n *\n * @param predicate A function that is used to analyze the value and the index and\n * determine whether or not to increment the count. Return `true` to increment the count,\n * and return `false` to keep the count the same.\n * If the predicate is not provided, every value will be counted.\n * @return A function that returns an Observable that emits one number that\n * represents the count of emissions.\n */\nexport function count<T>(predicate?: (value: T, index: number) => boolean): OperatorFunction<T, number> {\n  return reduce((total, value, i) => (!predicate || predicate(value, i) ? total + 1 : total), 0);\n}\n"
  },
  {
    "path": "packages/rxjs/src/internal/operators/debounce.ts",
    "content": "import type { Subscriber} from '@rxjs/observable';\nimport { operate, Observable, from } from '@rxjs/observable';\nimport type { MonoTypeOperatorFunction, ObservableInput } from '../types.js';\nimport { noop } from '../util/noop.js';\n\n/**\n * Emits a notification from the source Observable only after a particular time span\n * determined by another Observable has passed without another source emission.\n *\n * <span class=\"informal\">It's like {@link debounceTime}, but the time span of\n * emission silence is determined by a second Observable.</span>\n *\n * ![](debounce.svg)\n *\n * `debounce` delays notifications emitted by the source Observable, but drops previous\n * pending delayed emissions if a new notification arrives on the source Observable.\n * This operator keeps track of the most recent notification from the source\n * Observable, and spawns a duration Observable by calling the\n * `durationSelector` function. The notification is emitted only when the duration\n * Observable emits a next notification, and if no other notification was emitted on\n * the source Observable since the duration Observable was spawned. If a new\n * notification appears before the duration Observable emits, the previous notification will\n * not be emitted and a new duration is scheduled from `durationSelector` is scheduled.\n * If the completing event happens during the scheduled duration the last cached notification\n * is emitted before the completion event is forwarded to the output observable.\n * If the error event happens during the scheduled duration or after it only the error event is\n * forwarded to the output observable. The cache notification is not emitted in this case.\n *\n * Like {@link debounceTime}, this is a rate-limiting operator, and also a\n * delay-like operator since output emissions do not necessarily occur at the\n * same time as they did on the source Observable.\n *\n * ## Example\n *\n * Emit the most recent click after a burst of clicks\n *\n * ```ts\n * import { fromEvent, scan, debounce, interval } from 'rxjs';\n *\n * const clicks = fromEvent(document, 'click');\n * const result = clicks.pipe(\n *   scan(i => ++i, 1),\n *   debounce(i => interval(200 * i))\n * );\n * result.subscribe(x => console.log(x));\n * ```\n *\n * @see {@link audit}\n * @see {@link auditTime}\n * @see {@link debounceTime}\n * @see {@link delay}\n * @see {@link sample}\n * @see {@link sampleTime}\n * @see {@link throttle}\n * @see {@link throttleTime}\n *\n * @param durationSelector A function\n * that receives a value from the source Observable, for computing the timeout\n * duration for each source value, returned as an Observable or a Promise.\n * @return A function that returns an Observable that delays the emissions of\n * the source Observable by the specified duration Observable returned by\n * `durationSelector`, and may drop some values if they occur too frequently.\n */\nexport function debounce<T>(durationSelector: (value: T) => ObservableInput<any>): MonoTypeOperatorFunction<T> {\n  return (source) =>\n    new Observable((destination) => {\n      let hasValue = false;\n      let lastValue: T | null = null;\n      // The subscriber/subscription for the current debounce, if there is one.\n      let durationSubscriber: Subscriber<any> | null = null;\n\n      const emit = () => {\n        // Unsubscribe any current debounce subscription we have,\n        // we only cared about the first notification from it, and we\n        // want to clean that subscription up as soon as possible.\n        durationSubscriber?.unsubscribe();\n        durationSubscriber = null;\n        if (hasValue) {\n          // We have a value! Free up memory first, then emit the value.\n          hasValue = false;\n          const value = lastValue!;\n          lastValue = null;\n          destination.next(value);\n        }\n      };\n\n      source.subscribe(\n        operate({\n          destination,\n          next: (value: T) => {\n            // Cancel any pending debounce duration. We don't\n            // need to null it out here yet tho, because we're just going\n            // to create another one in a few lines.\n            durationSubscriber?.unsubscribe();\n            hasValue = true;\n            lastValue = value;\n            // Capture our duration subscriber, so we can unsubscribe it when we're notified\n            // and we're going to emit the value.\n            durationSubscriber = operate({ destination, next: emit, complete: noop });\n            // Subscribe to the duration.\n            from(durationSelector(value)).subscribe(durationSubscriber);\n          },\n          complete: () => {\n            // Source completed.\n            // Emit any pending debounced values then complete\n            emit();\n            destination.complete();\n          },\n          finalize: () => {\n            // Finalization.\n            lastValue = durationSubscriber = null;\n          },\n        })\n      );\n    });\n}\n"
  },
  {
    "path": "packages/rxjs/src/internal/operators/debounceTime.ts",
    "content": "import { asyncScheduler } from '../scheduler/async.js';\nimport type { Subscription } from '@rxjs/observable';\nimport { Observable, operate } from '@rxjs/observable';\nimport type { MonoTypeOperatorFunction, SchedulerLike } from '../types.js';\nimport { executeSchedule } from '../util/executeSchedule.js';\n\n/**\n * Emits a notification from the source Observable only after a particular time span\n * has passed without another source emission.\n *\n * <span class=\"informal\">It's like {@link delay}, but passes only the most\n * recent notification from each burst of emissions.</span>\n *\n * ![](debounceTime.png)\n *\n * `debounceTime` delays notifications emitted by the source Observable, but drops\n * previous pending delayed emissions if a new notification arrives on the source\n * Observable. This operator keeps track of the most recent notification from the\n * source Observable, and emits that only when `dueTime` has passed\n * without any other notification appearing on the source Observable. If a new value\n * appears before `dueTime` silence occurs, the previous notification will be dropped\n * and will not be emitted and a new `dueTime` is scheduled.\n * If the completing event happens during `dueTime` the last cached notification\n * is emitted before the completion event is forwarded to the output observable.\n * If the error event happens during `dueTime` or after it only the error event is\n * forwarded to the output observable. The cache notification is not emitted in this case.\n *\n * This is a rate-limiting operator, because it is impossible for more than one\n * notification to be emitted in any time window of duration `dueTime`, but it is also\n * a delay-like operator since output emissions do not occur at the same time as\n * they did on the source Observable. Optionally takes a {@link SchedulerLike} for\n * managing timers.\n *\n * ## Example\n *\n * Emit the most recent click after a burst of clicks\n *\n * ```ts\n * import { fromEvent, debounceTime } from 'rxjs';\n *\n * const clicks = fromEvent(document, 'click');\n * const result = clicks.pipe(debounceTime(1000));\n * result.subscribe(x => console.log(x));\n * ```\n *\n * @see {@link audit}\n * @see {@link auditTime}\n * @see {@link debounce}\n * @see {@link sample}\n * @see {@link sampleTime}\n * @see {@link throttle}\n * @see {@link throttleTime}\n *\n * @param dueTime The timeout duration in milliseconds (or the time unit determined\n * internally by the optional `scheduler`) for the window of time required to wait\n * for emission silence before emitting the most recent source value.\n * @param scheduler The {@link SchedulerLike} to use for managing the timers that\n * handle the timeout for each value.\n * @return A function that returns an Observable that delays the emissions of\n * the source Observable by the specified `dueTime`, and may drop some values\n * if they occur too frequently.\n */\nexport function debounceTime<T>(dueTime: number, scheduler: SchedulerLike = asyncScheduler): MonoTypeOperatorFunction<T> {\n  return (source) =>\n    new Observable((destination) => {\n      let lastValue: T;\n      let activeTask: Subscription | void;\n\n      source.subscribe(\n        operate({\n          destination,\n          next: (value: T) => {\n            lastValue = value;\n            // Clear any pending task and schedule a new one.\n            activeTask?.unsubscribe();\n\n            activeTask = executeSchedule(\n              destination,\n              scheduler,\n              () => {\n                activeTask = undefined;\n                const v = lastValue;\n                lastValue = null!;\n                destination.next(v);\n              },\n              dueTime\n            );\n          },\n          complete: () => {\n            // Source completed.\n            // Emit any pending debounced values then complete\n            if (activeTask) {\n              destination.next(lastValue);\n            }\n            destination.complete();\n          },\n          finalize: () => {\n            // Finalization.\n            lastValue = activeTask = null!;\n          },\n        })\n      );\n    });\n}\n"
  },
  {
    "path": "packages/rxjs/src/internal/operators/defaultIfEmpty.ts",
    "content": "import type { OperatorFunction } from '../types.js';\nimport { Observable, operate } from '@rxjs/observable';\n\n/**\n * Emits a given value if the source Observable completes without emitting any\n * `next` value, otherwise mirrors the source Observable.\n *\n * <span class=\"informal\">If the source Observable turns out to be empty, then\n * this operator will emit a default value.</span>\n *\n * ![](defaultIfEmpty.png)\n *\n * `defaultIfEmpty` emits the values emitted by the source Observable or a\n * specified default value if the source Observable is empty (completes without\n * having emitted any `next` value).\n *\n * ## Example\n *\n * If no clicks happen in 5 seconds, then emit 'no clicks'\n *\n * ```ts\n * import { fromEvent, takeUntil, interval, defaultIfEmpty } from 'rxjs';\n *\n * const clicks = fromEvent(document, 'click');\n * const clicksBeforeFive = clicks.pipe(takeUntil(interval(5000)));\n * const result = clicksBeforeFive.pipe(defaultIfEmpty('no clicks'));\n * result.subscribe(x => console.log(x));\n * ```\n *\n * @see {@link EMPTY}\n * @see {@link last}\n *\n * @param defaultValue The default value used if the source\n * Observable is empty.\n * @return A function that returns an Observable that emits either the\n * specified `defaultValue` if the source Observable emits no items, or the\n * values emitted by the source Observable.\n */\nexport function defaultIfEmpty<T, R>(defaultValue: R): OperatorFunction<T, T | R> {\n  return (source) =>\n    new Observable((destination) => {\n      let hasValue = false;\n      source.subscribe(\n        operate({\n          destination,\n          next: (value) => {\n            hasValue = true;\n            destination.next(value);\n          },\n          complete: () => {\n            if (!hasValue) {\n              destination.next(defaultValue!);\n            }\n            destination.complete();\n          },\n        })\n      );\n    });\n}\n"
  },
  {
    "path": "packages/rxjs/src/internal/operators/delay.ts",
    "content": "import { asyncScheduler } from '../scheduler/async.js';\nimport type { MonoTypeOperatorFunction, SchedulerLike } from '../types.js';\nimport { delayWhen } from './delayWhen.js';\nimport { timer } from '../observable/timer.js';\n\n/**\n * Delays the emission of items from the source Observable by a given timeout or\n * until a given Date.\n *\n * <span class=\"informal\">Time shifts each item by some specified amount of\n * milliseconds.</span>\n *\n * ![](delay.svg)\n *\n * If the delay argument is a Number, this operator time shifts the source\n * Observable by that amount of time expressed in milliseconds. The relative\n * time intervals between the values are preserved.\n *\n * If the delay argument is a Date, this operator time shifts the start of the\n * Observable execution until the given date occurs.\n *\n * ## Examples\n *\n * Delay each click by one second\n *\n * ```ts\n * import { fromEvent, delay } from 'rxjs';\n *\n * const clicks = fromEvent(document, 'click');\n * const delayedClicks = clicks.pipe(delay(1000)); // each click emitted after 1 second\n * delayedClicks.subscribe(x => console.log(x));\n * ```\n *\n * Delay all clicks until a future date happens\n *\n * ```ts\n * import { fromEvent, delay } from 'rxjs';\n *\n * const clicks = fromEvent(document, 'click');\n * const date = new Date('March 15, 2050 12:00:00'); // in the future\n * const delayedClicks = clicks.pipe(delay(date)); // click emitted only after that date\n * delayedClicks.subscribe(x => console.log(x));\n * ```\n *\n * @see {@link delayWhen}\n * @see {@link throttle}\n * @see {@link throttleTime}\n * @see {@link debounce}\n * @see {@link debounceTime}\n * @see {@link sample}\n * @see {@link sampleTime}\n * @see {@link audit}\n * @see {@link auditTime}\n *\n * @param due The delay duration in milliseconds (a `number`) or a `Date` until\n * which the emission of the source items is delayed.\n * @param scheduler The {@link SchedulerLike} to use for managing the timers\n * that handle the time-shift for each item.\n * @return A function that returns an Observable that delays the emissions of\n * the source Observable by the specified timeout or Date.\n */\nexport function delay<T>(due: number | Date, scheduler: SchedulerLike = asyncScheduler): MonoTypeOperatorFunction<T> {\n  const duration = timer(due, scheduler);\n  return delayWhen(() => duration);\n}\n"
  },
  {
    "path": "packages/rxjs/src/internal/operators/delayWhen.ts",
    "content": "import type { Observable } from '@rxjs/observable';\nimport type { MonoTypeOperatorFunction, ObservableInput } from '../types.js';\nimport { concat } from '../observable/concat.js';\nimport { take } from './take.js';\nimport { ignoreElements } from './ignoreElements.js';\nimport { mergeMap } from './mergeMap.js';\nimport { rx } from '../util/rx.js';\nimport { map } from './map.js';\n\n/** @deprecated The `subscriptionDelay` parameter will be removed in v8. */\nexport function delayWhen<T>(\n  delayDurationSelector: (value: T, index: number) => ObservableInput<any>,\n  subscriptionDelay: Observable<any>\n): MonoTypeOperatorFunction<T>;\nexport function delayWhen<T>(delayDurationSelector: (value: T, index: number) => ObservableInput<any>): MonoTypeOperatorFunction<T>;\n\n/**\n * Delays the emission of items from the source Observable by a given time span\n * determined by the emissions of another Observable.\n *\n * <span class=\"informal\">It's like {@link delay}, but the time span of the\n * delay duration is determined by a second Observable.</span>\n *\n * ![](delayWhen.png)\n *\n * `delayWhen` operator shifts each emitted value from the source Observable by\n * a time span determined by another Observable. When the source emits a value,\n * the `delayDurationSelector` function is called with the value emitted from\n * the source Observable as the first argument to the `delayDurationSelector`.\n * The `delayDurationSelector` function should return an {@link ObservableInput},\n * that is internally converted to an Observable that is called the \"duration\"\n * Observable.\n *\n * The source value is emitted on the output Observable only when the \"duration\"\n * Observable emits ({@link guide/glossary-and-semantics#next next}s) any value.\n * Upon that, the \"duration\" Observable gets unsubscribed.\n *\n * Before RxJS V7, the {@link guide/glossary-and-semantics#complete completion}\n * of the \"duration\" Observable would have been triggering the emission of the\n * source value to the output Observable, but with RxJS V7, this is not the case\n * anymore.\n *\n * Only next notifications (from the \"duration\" Observable) trigger values from\n * the source Observable to be passed to the output Observable. If the \"duration\"\n * Observable only emits the complete notification (without next), the value\n * emitted by the source Observable will never get to the output Observable - it\n * will be swallowed. If the \"duration\" Observable errors, the error will be\n * propagated to the output Observable.\n *\n * Optionally, `delayWhen` takes a second argument, `subscriptionDelay`, which\n * is an Observable. When `subscriptionDelay` emits its first value or\n * completes, the source Observable is subscribed to and starts behaving like\n * described in the previous paragraph. If `subscriptionDelay` is not provided,\n * `delayWhen` will subscribe to the source Observable as soon as the output\n * Observable is subscribed.\n *\n * ## Example\n *\n * Delay each click by a random amount of time, between 0 and 5 seconds\n *\n * ```ts\n * import { fromEvent, delayWhen, interval } from 'rxjs';\n *\n * const clicks = fromEvent(document, 'click');\n * const delayedClicks = clicks.pipe(\n *   delayWhen(() => interval(Math.random() * 5000))\n * );\n * delayedClicks.subscribe(x => console.log(x));\n * ```\n *\n * @see {@link delay}\n * @see {@link throttle}\n * @see {@link throttleTime}\n * @see {@link debounce}\n * @see {@link debounceTime}\n * @see {@link sample}\n * @see {@link sampleTime}\n * @see {@link audit}\n * @see {@link auditTime}\n *\n * @param delayDurationSelector A function that returns an `ObservableInput` for\n * each `value` emitted by the source Observable, which is then used to delay the\n * emission of that `value` on the output Observable until the `ObservableInput`\n * returned from this function emits a next value. When called, beside `value`,\n * this function receives a zero-based `index` of the emission order.\n * @param subscriptionDelay An Observable that triggers the subscription to the\n * source Observable once it emits any value.\n * @return A function that returns an Observable that delays the emissions of\n * the source Observable by an amount of time specified by the Observable\n * returned by `delayDurationSelector`.\n */\nexport function delayWhen<T>(\n  delayDurationSelector: (value: T, index: number) => ObservableInput<any>,\n  subscriptionDelay?: Observable<any>\n): MonoTypeOperatorFunction<T> {\n  if (subscriptionDelay) {\n    // DEPRECATED PATH\n    return (source: Observable<T>) =>\n      concat(rx(subscriptionDelay, take(1), ignoreElements()), rx(source, delayWhen(delayDurationSelector)));\n  }\n\n  return mergeMap(\n    (value, index) =>\n      rx(\n        delayDurationSelector(value, index),\n        take(1),\n        map(() => value)\n      ) as Observable<T>\n  );\n}\n"
  },
  {
    "path": "packages/rxjs/src/internal/operators/dematerialize.ts",
    "content": "import { observeNotification } from '../Notification.js';\nimport type { OperatorFunction, ObservableNotification, ValueFromNotification } from '../types.js';\nimport { Observable, operate } from '@rxjs/observable';\n\n/**\n * Converts an Observable of {@link ObservableNotification} objects into the emissions\n * that they represent.\n *\n * <span class=\"informal\">Unwraps {@link ObservableNotification} objects as actual `next`,\n * `error` and `complete` emissions. The opposite of {@link materialize}.</span>\n *\n * ![](dematerialize.png)\n *\n * `dematerialize` is assumed to operate an Observable that only emits\n * {@link ObservableNotification} objects as `next` emissions, and does not emit any\n * `error`. Such Observable is the output of a `materialize` operation. Those\n * notifications are then unwrapped using the metadata they contain, and emitted\n * as `next`, `error`, and `complete` on the output Observable.\n *\n * Use this operator in conjunction with {@link materialize}.\n *\n * ## Example\n *\n * Convert an Observable of Notifications to an actual Observable\n *\n * ```ts\n * import { NextNotification, ErrorNotification, of, dematerialize } from 'rxjs';\n *\n * const notifA: NextNotification<string> = { kind: 'N', value: 'A' };\n * const notifB: NextNotification<string> = { kind: 'N', value: 'B' };\n * const notifE: ErrorNotification = { kind: 'E', error: new TypeError('x.toUpperCase is not a function') };\n *\n * const materialized = of(notifA, notifB, notifE);\n *\n * const upperCase = materialized.pipe(dematerialize());\n * upperCase.subscribe({\n *   next: x => console.log(x),\n *   error: e => console.error(e)\n * });\n *\n * // Results in:\n * // A\n * // B\n * // TypeError: x.toUpperCase is not a function\n * ```\n *\n * @see {@link materialize}\n *\n * @return A function that returns an Observable that emits items and\n * notifications embedded in Notification objects emitted by the source\n * Observable.\n */\nexport function dematerialize<N extends ObservableNotification<any>>(): OperatorFunction<N, ValueFromNotification<N>> {\n  return (source) =>\n    new Observable((destination) => {\n      source.subscribe(operate({ destination, next: (notification) => observeNotification(notification, destination) }));\n    });\n}\n"
  },
  {
    "path": "packages/rxjs/src/internal/operators/distinct.ts",
    "content": "import type { MonoTypeOperatorFunction, ObservableInput } from '../types.js';\nimport { Observable, operate, from } from '@rxjs/observable';\nimport { noop } from '../util/noop.js';\n\n/**\n * Returns an Observable that emits all items emitted by the source Observable that are distinct by comparison from previous items.\n *\n * If a `keySelector` function is provided, then it will project each value from the source observable into a new value that it will\n * check for equality with previously projected values. If the `keySelector` function is not provided, it will use each value from the\n * source observable directly with an equality check against previous values.\n *\n * In JavaScript runtimes that support `Set`, this operator will use a `Set` to improve performance of the distinct value checking.\n *\n * In other runtimes, this operator will use a minimal implementation of `Set` that relies on an `Array` and `indexOf` under the\n * hood, so performance will degrade as more values are checked for distinction. Even in newer browsers, a long-running `distinct`\n * use might result in memory leaks. To help alleviate this in some scenarios, an optional `flushes` parameter is also provided so\n * that the internal `Set` can be \"flushed\", basically clearing it of values.\n *\n * ## Examples\n *\n * A simple example with numbers\n *\n * ```ts\n * import { of, distinct } from 'rxjs';\n *\n * of(1, 1, 2, 2, 2, 1, 2, 3, 4, 3, 2, 1)\n *   .pipe(distinct())\n *   .subscribe(x => console.log(x));\n *\n * // Outputs\n * // 1\n * // 2\n * // 3\n * // 4\n * ```\n *\n * An example using the `keySelector` function\n *\n * ```ts\n * import { of, distinct } from 'rxjs';\n *\n * of(\n *   { age: 4, name: 'Foo'},\n *   { age: 7, name: 'Bar'},\n *   { age: 5, name: 'Foo'}\n * )\n * .pipe(distinct(({ name }) => name))\n * .subscribe(x => console.log(x));\n *\n * // Outputs\n * // { age: 4, name: 'Foo' }\n * // { age: 7, name: 'Bar' }\n * ```\n * @see {@link distinctUntilChanged}\n * @see {@link distinctUntilKeyChanged}\n *\n * @param keySelector Optional `function` to select which value you want to check as distinct.\n * @param flushes Optional `ObservableInput` for flushing the internal HashSet of the operator.\n * @return A function that returns an Observable that emits items from the\n * source Observable with distinct values.\n */\nexport function distinct<T, K>(keySelector?: (value: T) => K, flushes?: ObservableInput<any>): MonoTypeOperatorFunction<T> {\n  return (source) =>\n    new Observable((destination) => {\n      const distinctKeys = new Set();\n      source.subscribe(\n        operate({\n          destination,\n          next: (value) => {\n            const key = keySelector ? keySelector(value) : value;\n            if (!distinctKeys.has(key)) {\n              distinctKeys.add(key);\n              destination.next(value);\n            }\n          },\n        })\n      );\n\n      flushes && from(flushes).subscribe(operate({ destination, next: () => distinctKeys.clear(), complete: noop }));\n    });\n}\n"
  },
  {
    "path": "packages/rxjs/src/internal/operators/distinctUntilChanged.ts",
    "content": "import type { MonoTypeOperatorFunction } from '../types.js';\nimport { identity } from '../util/identity.js';\nimport { Observable, operate } from '@rxjs/observable';\n\nexport function distinctUntilChanged<T>(comparator?: (previous: T, current: T) => boolean): MonoTypeOperatorFunction<T>;\nexport function distinctUntilChanged<T, K>(\n  comparator: (previous: K, current: K) => boolean,\n  keySelector: (value: T) => K\n): MonoTypeOperatorFunction<T>;\n\n/**\n * Returns a result {@link Observable} that emits all values pushed by the source observable if they\n * are distinct in comparison to the last value the result observable emitted.\n *\n * When provided without parameters or with the first parameter (`{@link distinctUntilChanged#comparator comparator}`),\n * it behaves like this:\n *\n * 1. It will always emit the first value from the source.\n * 2. For all subsequent values pushed by the source, they will be compared to the previously emitted values\n *    using the provided `comparator` or an `===` equality check.\n * 3. If the value pushed by the source is determined to be unequal by this check, that value is emitted and\n *    becomes the new \"previously emitted value\" internally.\n *\n * When the second parameter (`{@link distinctUntilChanged#keySelector keySelector}`) is provided, the behavior\n * changes:\n *\n * 1. It will always emit the first value from the source.\n * 2. The `keySelector` will be run against all values, including the first value.\n * 3. For all values after the first, the selected key will be compared against the key selected from\n *    the previously emitted value using the `comparator`.\n * 4. If the keys are determined to be unequal by this check, the value (not the key), is emitted\n *    and the selected key from that value is saved for future comparisons against other keys.\n *\n * ## Examples\n *\n * A very basic example with no `{@link distinctUntilChanged#comparator comparator}`. Note that `1` is emitted more than once,\n * because it's distinct in comparison to the _previously emitted_ value,\n * not in comparison to _all other emitted values_.\n *\n * ```ts\n * import { of, distinctUntilChanged } from 'rxjs';\n *\n * of(1, 1, 1, 2, 2, 2, 1, 1, 3, 3)\n *   .pipe(distinctUntilChanged())\n *   .subscribe(console.log);\n * // Logs: 1, 2, 1, 3\n * ```\n *\n * With a `{@link distinctUntilChanged#comparator comparator}`, you can do custom comparisons. Let's say\n * you only want to emit a value when all of its components have\n * changed:\n *\n * ```ts\n * import { of, distinctUntilChanged } from 'rxjs';\n *\n * const totallyDifferentBuilds$ = of(\n *   { engineVersion: '1.1.0', transmissionVersion: '1.2.0' },\n *   { engineVersion: '1.1.0', transmissionVersion: '1.4.0' },\n *   { engineVersion: '1.3.0', transmissionVersion: '1.4.0' },\n *   { engineVersion: '1.3.0', transmissionVersion: '1.5.0' },\n *   { engineVersion: '2.0.0', transmissionVersion: '1.5.0' }\n * ).pipe(\n *   distinctUntilChanged((prev, curr) => {\n *     return (\n *       prev.engineVersion === curr.engineVersion ||\n *       prev.transmissionVersion === curr.transmissionVersion\n *     );\n *   })\n * );\n *\n * totallyDifferentBuilds$.subscribe(console.log);\n *\n * // Logs:\n * // { engineVersion: '1.1.0', transmissionVersion: '1.2.0' }\n * // { engineVersion: '1.3.0', transmissionVersion: '1.4.0' }\n * // { engineVersion: '2.0.0', transmissionVersion: '1.5.0' }\n * ```\n *\n * You can also provide a custom `{@link distinctUntilChanged#comparator comparator}` to check that emitted\n * changes are only in one direction. Let's say you only want to get\n * the next record temperature:\n *\n * ```ts\n * import { of, distinctUntilChanged } from 'rxjs';\n *\n * const temps$ = of(30, 31, 20, 34, 33, 29, 35, 20);\n *\n * const recordHighs$ = temps$.pipe(\n *   distinctUntilChanged((prevHigh, temp) => {\n *     // If the current temp is less than\n *     // or the same as the previous record,\n *     // the record hasn't changed.\n *     return temp <= prevHigh;\n *   })\n * );\n *\n * recordHighs$.subscribe(console.log);\n * // Logs: 30, 31, 34, 35\n * ```\n *\n * Selecting update events only when the `updatedBy` field shows\n * the account changed hands.\n *\n * ```ts\n * import { of, distinctUntilChanged } from 'rxjs';\n *\n * // A stream of updates to a given account\n * const accountUpdates$ = of(\n *   { updatedBy: 'blesh', data: [] },\n *   { updatedBy: 'blesh', data: [] },\n *   { updatedBy: 'ncjamieson', data: [] },\n *   { updatedBy: 'ncjamieson', data: [] },\n *   { updatedBy: 'blesh', data: [] }\n * );\n *\n * // We only want the events where it changed hands\n * const changedHands$ = accountUpdates$.pipe(\n *   distinctUntilChanged(undefined, update => update.updatedBy)\n * );\n *\n * changedHands$.subscribe(console.log);\n * // Logs:\n * // { updatedBy: 'blesh', data: Array[0] }\n * // { updatedBy: 'ncjamieson', data: Array[0] }\n * // { updatedBy: 'blesh', data: Array[0] }\n * ```\n *\n * @see {@link distinct}\n * @see {@link distinctUntilKeyChanged}\n *\n * @param comparator A function used to compare the previous and current keys for\n * equality. Defaults to a `===` check.\n * @param keySelector Used to select a key value to be passed to the `comparator`.\n *\n * @return A function that returns an Observable that emits items from the\n * source Observable with distinct values.\n */\nexport function distinctUntilChanged<T, K>(\n  comparator?: (previous: K, current: K) => boolean,\n  keySelector: (value: T) => K = identity as (value: T) => K\n): MonoTypeOperatorFunction<T> {\n  // We've been allowing `null` do be passed as the `compare`, so we can't do\n  // a default value for the parameter, because that will only work\n  // for `undefined`.\n  comparator = comparator ?? defaultCompare;\n\n  return (source) =>\n    new Observable((destination) => {\n      // The previous key, used to compare against keys selected\n      // from new arrivals to determine \"distinctiveness\".\n      let previousKey: K;\n      // Whether or not this is the first value we've gotten.\n      let first = true;\n\n      source.subscribe(\n        operate({\n          destination,\n          next: (value) => {\n            // We always call the key selector.\n            const currentKey = keySelector(value);\n\n            // If it's the first value, we always emit it.\n            // Otherwise, we compare this key to the previous key, and\n            // if the comparer returns false, we emit.\n            if (first || !comparator!(previousKey, currentKey)) {\n              // Update our state *before* we emit the value\n              // as emission can be the source of re-entrant code\n              // in functional libraries like this. We only really\n              // need to do this if it's the first value, or if the\n              // key we're tracking in previous needs to change.\n              first = false;\n              previousKey = currentKey;\n\n              // Emit the value!\n              destination.next(value);\n            }\n          },\n        })\n      );\n    });\n}\n\nfunction defaultCompare(a: any, b: any) {\n  return a === b;\n}\n"
  },
  {
    "path": "packages/rxjs/src/internal/operators/distinctUntilKeyChanged.ts",
    "content": "import { distinctUntilChanged } from './distinctUntilChanged.js';\nimport type { MonoTypeOperatorFunction } from '../types.js';\n\nexport function distinctUntilKeyChanged<T>(key: keyof T): MonoTypeOperatorFunction<T>;\nexport function distinctUntilKeyChanged<T, K extends keyof T>(key: K, compare: (x: T[K], y: T[K]) => boolean): MonoTypeOperatorFunction<T>;\n\n/**\n * Returns an Observable that emits all items emitted by the source Observable that\n * are distinct by comparison from the previous item, using a property accessed by\n * using the key provided to check if the two items are distinct.\n *\n * If a comparator function is provided, then it will be called for each item to\n * test for whether that value should be emitted or not.\n *\n * If a comparator function is not provided, an equality check is used by default.\n *\n * ## Examples\n *\n * An example comparing the name of persons\n *\n * ```ts\n * import { of, distinctUntilKeyChanged } from 'rxjs';\n *\n * of(\n *   { age: 4, name: 'Foo' },\n *   { age: 7, name: 'Bar' },\n *   { age: 5, name: 'Foo' },\n *   { age: 6, name: 'Foo' }\n * ).pipe(\n *   distinctUntilKeyChanged('name')\n * )\n * .subscribe(x => console.log(x));\n *\n * // displays:\n * // { age: 4, name: 'Foo' }\n * // { age: 7, name: 'Bar' }\n * // { age: 5, name: 'Foo' }\n * ```\n *\n * An example comparing the first letters of the name\n *\n * ```ts\n * import { of, distinctUntilKeyChanged } from 'rxjs';\n *\n * of(\n *   { age: 4, name: 'Foo1' },\n *   { age: 7, name: 'Bar' },\n *   { age: 5, name: 'Foo2' },\n *   { age: 6, name: 'Foo3' }\n * ).pipe(\n *   distinctUntilKeyChanged('name', (x, y) => x.substring(0, 3) === y.substring(0, 3))\n * )\n * .subscribe(x => console.log(x));\n *\n * // displays:\n * // { age: 4, name: 'Foo1' }\n * // { age: 7, name: 'Bar' }\n * // { age: 5, name: 'Foo2' }\n * ```\n *\n * @see {@link distinct}\n * @see {@link distinctUntilChanged}\n *\n * @param key String key for object property lookup on each item.\n * @param compare Optional comparison function called to test if an item is distinct\n * from the previous item in the source.\n * @return A function that returns an Observable that emits items from the source\n * Observable with distinct values based on the key specified.\n */\nexport function distinctUntilKeyChanged<T, K extends keyof T>(\n  key: K,\n  compare?: (x: T[K], y: T[K]) => boolean\n): MonoTypeOperatorFunction<T> {\n  return distinctUntilChanged((x: T, y: T) => (compare ? compare(x[key], y[key]) : x[key] === y[key]));\n}\n"
  },
  {
    "path": "packages/rxjs/src/internal/operators/elementAt.ts",
    "content": "import { ArgumentOutOfRangeError } from '../util/ArgumentOutOfRangeError.js';\nimport { Observable, operate } from '@rxjs/observable';\nimport type { OperatorFunction } from '../types.js';\nimport { take } from './take.js';\n\n/**\n * Emits the single value at the specified `index` in a sequence of emissions\n * from the source Observable.\n *\n * <span class=\"informal\">Emits only the i-th value, then completes.</span>\n *\n * ![](elementAt.png)\n *\n * `elementAt` returns an Observable that emits the item at the specified\n * `index` in the source Observable, or a default value if that `index` is out\n * of range and the `default` argument is provided. If the `default` argument is\n * not given and the `index` is out of range, the output Observable will emit an\n * `ArgumentOutOfRangeError` error.\n *\n * ## Example\n *\n * Emit only the third click event\n *\n * ```ts\n * import { fromEvent, elementAt } from 'rxjs';\n *\n * const clicks = fromEvent(document, 'click');\n * const result = clicks.pipe(elementAt(2));\n * result.subscribe(x => console.log(x));\n *\n * // Results in:\n * // click 1 = nothing\n * // click 2 = nothing\n * // click 3 = MouseEvent object logged to console\n * ```\n *\n * @see {@link first}\n * @see {@link last}\n * @see {@link skip}\n * @see {@link single}\n * @see {@link take}\n *\n * @throws {ArgumentOutOfRangeError} When using `elementAt(i)`, it delivers an\n * `ArgumentOutOfRangeError` to the Observer's `error` callback if `i < 0` or the\n * Observable has completed before emitting the i-th `next` notification.\n *\n * @param index Is the number `i` for the i-th source emission that has happened\n * since the subscription, starting from the number `0`.\n * @param defaultValue The default value returned for missing indices.\n * @return A function that returns an Observable that emits a single item, if\n * it is found. Otherwise, it will emit the default value if given. If not, it\n * emits an error.\n */\nexport function elementAt<T, D = T>(index: number, defaultValue?: D): OperatorFunction<T, T | D> {\n  if (index < 0) {\n    throw new ArgumentOutOfRangeError();\n  }\n  const hasDefaultValue = arguments.length >= 2;\n  return (source: Observable<T>) =>\n    new Observable((destination) => {\n      let i = 0;\n      const operatorSubscriber = operate<T, T | D>({\n        destination,\n        next: (value) => {\n          if (i++ === index) {\n            // We want to unsubscribe from the source as soon as we know\n            // we can. This will prevent reentrancy issues if calling\n            // `destination.next()` happens to emit another value from source.\n            operatorSubscriber.unsubscribe();\n            destination.next(value);\n            destination.complete();\n          }\n        },\n        complete: () => {\n          if (!hasDefaultValue) {\n            destination.error(new ArgumentOutOfRangeError());\n          } else {\n            destination.next(defaultValue!);\n            destination.complete();\n          }\n        },\n      });\n      source.subscribe(operatorSubscriber);\n    });\n}\n"
  },
  {
    "path": "packages/rxjs/src/internal/operators/endWith.ts",
    "content": "/** prettier */\nimport { Observable, operate, subscribeToArray } from '@rxjs/observable';\nimport type { OperatorFunction, ValueFromArray } from '../types.js';\n\n/**\n * Returns an observable that will emit all values from the source, then synchronously emit\n * the provided value(s) immediately after the source completes.\n *\n * This is useful for knowing when an observable ends. Particularly when paired with an\n * operator like {@link takeUntil}\n *\n * ![](endWith.png)\n *\n * ## Example\n *\n * Emit values to know when an interval starts and stops. The interval will\n * stop when a user clicks anywhere on the document.\n *\n * ```ts\n * import { interval, map, fromEvent, startWith, takeUntil, endWith } from 'rxjs';\n *\n * const ticker$ = interval(5000).pipe(\n *   map(() => 'tick')\n * );\n *\n * const documentClicks$ = fromEvent(document, 'click');\n *\n * ticker$.pipe(\n *   startWith('interval started'),\n *   takeUntil(documentClicks$),\n *   endWith('interval ended by click')\n * )\n * .subscribe(x => console.log(x));\n *\n * // Result (assuming a user clicks after 15 seconds)\n * // 'interval started'\n * // 'tick'\n * // 'tick'\n * // 'tick'\n * // 'interval ended by click'\n * ```\n *\n * @see {@link startWith}\n * @see {@link concat}\n * @see {@link takeUntil}\n *\n * @param values Items you want the modified Observable to emit last.\n * @return A function that returns an Observable that emits all values from the\n * source, then synchronously emits the provided value(s) immediately after the\n * source completes.\n */\nexport function endWith<T, A extends readonly unknown[] = T[]>(...values: A): OperatorFunction<T, T | ValueFromArray<A>> {\n  return (source) =>\n    new Observable((destination) => {\n      source.subscribe(\n        operate({\n          destination,\n          complete: () => {\n            subscribeToArray(values as readonly ValueFromArray<A>[], destination);\n          },\n        })\n      );\n    });\n}\n"
  },
  {
    "path": "packages/rxjs/src/internal/operators/every.ts",
    "content": "import { Observable, operate } from '@rxjs/observable';\nimport type { Falsy, OperatorFunction } from '../types.js';\n\nexport function every<T>(predicate: BooleanConstructor): OperatorFunction<T, Exclude<T, Falsy> extends never ? false : boolean>;\nexport function every<T>(predicate: (value: T, index: number) => boolean): OperatorFunction<T, boolean>;\n\n/**\n * Returns an Observable that emits whether or not every item of the source satisfies the condition specified.\n *\n * <span class=\"informal\">If all values pass predicate before the source completes, emits true before completion,\n * otherwise emit false, then complete.</span>\n *\n * ![](every.png)\n *\n * ## Example\n *\n * A simple example emitting true if all elements are less than 5, false otherwise\n *\n * ```ts\n * import { of, every } from 'rxjs';\n *\n * of(1, 2, 3, 4, 5, 6)\n *   .pipe(every(x => x < 5))\n *   .subscribe(x => console.log(x)); // -> false\n * ```\n *\n * @param predicate A function for determining if an item meets a specified condition.\n * @param thisArg Optional object to use for `this` in the callback.\n * @return A function that returns an Observable of booleans that determines if\n * all items of the source Observable meet the condition specified.\n */\nexport function every<T>(predicate: (value: T, index: number) => boolean): OperatorFunction<T, boolean> {\n  return (source) =>\n    new Observable((destination) => {\n      let index = 0;\n\n      const subscriber = operate({\n        destination,\n        next: (value: T) => {\n          if (!predicate(value, index++)) {\n            // To prevent re-entrancy issues, we unsubscribe from the\n            // source as soon as possible. Because the `next` right below it\n            // could cause us to re-enter before we get to `complete()`.\n            subscriber.unsubscribe();\n            destination.next(false);\n            destination.complete();\n          }\n        },\n        complete: () => {\n          destination.next(true);\n          destination.complete();\n        },\n      });\n\n      source.subscribe(subscriber);\n    });\n}\n"
  },
  {
    "path": "packages/rxjs/src/internal/operators/exhaustAll.ts",
    "content": "import type { OperatorFunction, ObservableInput, ObservedValueOf } from '../types.js';\nimport { exhaustMap } from './exhaustMap.js';\nimport { identity } from '../util/identity.js';\n\n/**\n * Converts a higher-order Observable into a first-order Observable by dropping\n * inner Observables while the previous inner Observable has not yet completed.\n *\n * <span class=\"informal\">Flattens an Observable-of-Observables by dropping the\n * next inner Observables while the current inner is still executing.</span>\n *\n * ![](exhaustAll.svg)\n *\n * `exhaustAll` subscribes to an Observable that emits Observables, also known as a\n * higher-order Observable. Each time it observes one of these emitted inner\n * Observables, the output Observable begins emitting the items emitted by that\n * inner Observable. So far, it behaves like {@link mergeAll}. However,\n * `exhaustAll` ignores every new inner Observable if the previous Observable has\n * not yet completed. Once that one completes, it will accept and flatten the\n * next inner Observable and repeat this process.\n *\n * ## Example\n *\n * Run a finite timer for each click, only if there is no currently active timer\n *\n * ```ts\n * import { fromEvent, map, interval, take, exhaustAll } from 'rxjs';\n *\n * const clicks = fromEvent(document, 'click');\n * const higherOrder = clicks.pipe(\n *   map(() => interval(1000).pipe(take(5)))\n * );\n * const result = higherOrder.pipe(exhaustAll());\n * result.subscribe(x => console.log(x));\n * ```\n *\n * @see {@link combineLatestAll}\n * @see {@link concatAll}\n * @see {@link switchAll}\n * @see {@link switchMap}\n * @see {@link mergeAll}\n * @see {@link exhaustMap}\n * @see {@link zipAll}\n *\n * @return A function that returns an Observable that takes a source of\n * Observables and propagates the first Observable exclusively until it\n * completes before subscribing to the next.\n */\nexport function exhaustAll<O extends ObservableInput<any>>(): OperatorFunction<O, ObservedValueOf<O>> {\n  return exhaustMap(identity);\n}\n"
  },
  {
    "path": "packages/rxjs/src/internal/operators/exhaustMap.ts",
    "content": "import type { Subscriber} from '@rxjs/observable';\nimport { operate, from, Observable } from '@rxjs/observable';\nimport type { ObservableInput, OperatorFunction, ObservedValueOf } from '../types.js';\n\n/**\n * Projects each source value to an Observable which is merged in the output\n * Observable only if the previous projected Observable has completed.\n *\n * <span class=\"informal\">Maps each value to an Observable, then flattens all of\n * these inner Observables using {@link exhaustAll}.</span>\n *\n * ![](exhaustMap.png)\n *\n * Returns an Observable that emits items based on applying a function that you\n * supply to each item emitted by the source Observable, where that function\n * returns an (so-called \"inner\") Observable. When it projects a source value to\n * an Observable, the output Observable begins emitting the items emitted by\n * that projected Observable. However, `exhaustMap` ignores every new projected\n * Observable if the previous projected Observable has not yet completed. Once\n * that one completes, it will accept and flatten the next projected Observable\n * and repeat this process.\n *\n * ## Example\n *\n * Run a finite timer for each click, only if there is no currently active timer\n *\n * ```ts\n * import { fromEvent, exhaustMap, interval, take } from 'rxjs';\n *\n * const clicks = fromEvent(document, 'click');\n * const result = clicks.pipe(\n *   exhaustMap(() => interval(1000).pipe(take(5)))\n * );\n * result.subscribe(x => console.log(x));\n * ```\n *\n * @see {@link concatMap}\n * @see {@link exhaustAll}\n * @see {@link mergeMap}\n * @see {@link switchMap}\n *\n * @param project A function that, when applied to an item emitted by the source\n * Observable, returns an Observable.\n * @return A function that returns an Observable containing projected\n * Observables of each item of the source, ignoring projected Observables that\n * start before their preceding Observable has completed.\n */\nexport function exhaustMap<T, O extends ObservableInput<any>>(\n  project: (value: T, index: number) => O\n): OperatorFunction<T, ObservedValueOf<O>> {\n  return (source) =>\n    new Observable((destination) => {\n      let index = 0;\n      let innerSub: Subscriber<T> | null = null;\n      let isComplete = false;\n      source.subscribe(\n        operate({\n          destination,\n          next: (outerValue) => {\n            if (!innerSub) {\n              innerSub = operate({\n                destination,\n                complete: () => {\n                  innerSub = null;\n                  isComplete && destination.complete();\n                },\n              });\n              from(project(outerValue, index++)).subscribe(innerSub);\n            }\n          },\n          complete: () => {\n            isComplete = true;\n            !innerSub && destination.complete();\n          },\n        })\n      );\n    });\n}\n"
  },
  {
    "path": "packages/rxjs/src/internal/operators/expand.ts",
    "content": "import { Observable } from '@rxjs/observable';\nimport type { ObservableInput, ObservedValueOf, OperatorFunction, SchedulerLike } from '../types.js';\nimport { mergeInternals } from './mergeInternals.js';\n\nexport function expand<T, O extends ObservableInput<unknown>>(\n  project: (value: T, index: number) => O,\n  concurrent?: number\n): OperatorFunction<T, ObservedValueOf<O>>;\n\n/**\n * Recursively projects each source value to an Observable which is merged in\n * the output Observable.\n *\n * <span class=\"informal\">It's similar to {@link mergeMap}, but applies the\n * projection function to every source value as well as every output value.\n * It's recursive.</span>\n *\n * ![](expand.png)\n *\n * Returns an Observable that emits items based on applying a function that you\n * supply to each item emitted by the source Observable, where that function\n * returns an Observable, and then merging those resulting Observables and\n * emitting the results of this merger. *Expand* will re-emit on the output\n * Observable every source value. Then, each output value is given to the\n * `project` function which returns an inner Observable to be merged on the\n * output Observable. Those output values resulting from the projection are also\n * given to the `project` function to produce new output values. This is how\n * *expand* behaves recursively.\n *\n * ## Example\n *\n * Start emitting the powers of two on every click, at most 10 of them\n *\n * ```ts\n * import { fromEvent, map, expand, of, delay, take } from 'rxjs';\n *\n * const clicks = fromEvent(document, 'click');\n * const powersOfTwo = clicks.pipe(\n *   map(() => 1),\n *   expand(x => of(2 * x).pipe(delay(1000))),\n *   take(10)\n * );\n * powersOfTwo.subscribe(x => console.log(x));\n * ```\n *\n * @see {@link mergeMap}\n * @see {@link mergeScan}\n *\n * @param project A function that, when applied to an item emitted by the source\n * or the output Observable, returns an Observable.\n * @param concurrent Maximum number of input Observables being subscribed to\n * concurrently.\n * @param scheduler The {@link SchedulerLike} to use for subscribing to\n * each projected inner Observable.\n * @return A function that returns an Observable that emits the source values\n * and also result of applying the projection function to each value emitted on\n * the output Observable and merging the results of the Observables obtained\n * from this transformation.\n */\nexport function expand<T, O extends ObservableInput<unknown>>(\n  project: (value: T, index: number) => O,\n  concurrent = Infinity\n): OperatorFunction<T, ObservedValueOf<O>> {\n  concurrent = (concurrent || 0) < 1 ? Infinity : concurrent;\n  return (source) =>\n    new Observable((subscriber) =>\n      mergeInternals(\n        // General merge params\n        source,\n        subscriber,\n\n        // HACK: Cast because TypeScript seems to get confused here.\n        project as (value: T, index: number) => ObservableInput<ObservedValueOf<O>>,\n        concurrent,\n\n        // onBeforeNext\n        undefined,\n\n        // Expand-specific\n        true // Use expand path\n      )\n    );\n}\n"
  },
  {
    "path": "packages/rxjs/src/internal/operators/filter.ts",
    "content": "import type { OperatorFunction, MonoTypeOperatorFunction, TruthyTypesOf } from '../types.js';\nimport { Observable, operate } from '@rxjs/observable';\n\n/** @deprecated Use a closure instead of a `thisArg`. Signatures accepting a `thisArg` will be removed in v8. */\nexport function filter<T, S extends T, A>(predicate: (this: A, value: T, index: number) => value is S, thisArg: A): OperatorFunction<T, S>;\nexport function filter<T, S extends T>(predicate: (value: T, index: number) => value is S): OperatorFunction<T, S>;\nexport function filter<T>(predicate: BooleanConstructor): OperatorFunction<T, TruthyTypesOf<T>>;\n/** @deprecated Use a closure instead of a `thisArg`. Signatures accepting a `thisArg` will be removed in v8. */\nexport function filter<T, A>(predicate: (this: A, value: T, index: number) => boolean, thisArg: A): MonoTypeOperatorFunction<T>;\nexport function filter<T>(predicate: (value: T, index: number) => boolean): MonoTypeOperatorFunction<T>;\n\n/**\n * Filter items emitted by the source Observable by only emitting those that\n * satisfy a specified predicate.\n *\n * <span class=\"informal\">Like\n * [Array.prototype.filter()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter),\n * it only emits a value from the source if it passes a criterion function.</span>\n *\n * ![](filter.png)\n *\n * Similar to the well-known `Array.prototype.filter` method, this operator\n * takes values from the source Observable, passes them through a `predicate`\n * function and only emits those values that yielded `true`.\n *\n * ## Example\n *\n * Emit only click events whose target was a DIV element\n *\n * ```ts\n * import { fromEvent, filter } from 'rxjs';\n *\n * const div = document.createElement('div');\n * div.style.cssText = 'width: 200px; height: 200px; background: #09c;';\n * document.body.appendChild(div);\n *\n * const clicks = fromEvent(document, 'click');\n * const clicksOnDivs = clicks.pipe(filter(ev => (<HTMLElement>ev.target).tagName === 'DIV'));\n * clicksOnDivs.subscribe(x => console.log(x));\n * ```\n *\n * @see {@link distinct}\n * @see {@link distinctUntilChanged}\n * @see {@link distinctUntilKeyChanged}\n * @see {@link ignoreElements}\n * @see {@link partition}\n * @see {@link skip}\n *\n * @param predicate A function that\n * evaluates each value emitted by the source Observable. If it returns `true`,\n * the value is emitted, if `false` the value is not passed to the output\n * Observable. The `index` parameter is the number `i` for the i-th source\n * emission that has happened since the subscription, starting from the number\n * `0`.\n * @param thisArg An optional argument to determine the value of `this`\n * in the `predicate` function.\n * @return A function that returns an Observable that emits items from the\n * source Observable that satisfy the specified `predicate`.\n */\nexport function filter<T>(predicate: (value: T, index: number) => boolean, thisArg?: any): MonoTypeOperatorFunction<T> {\n  return (source) =>\n    new Observable((destination) => {\n      // An index passed to our predicate function on each call.\n      let index = 0;\n\n      // Subscribe to the source, all errors and completions are\n      // forwarded to the consumer.\n      source.subscribe(\n        // Call the predicate with the appropriate `this` context,\n        // if the predicate returns `true`, then send the value\n        // to the consumer.\n        operate({ destination, next: (value) => predicate.call(thisArg, value, index++) && destination.next(value) })\n      );\n    });\n}\n"
  },
  {
    "path": "packages/rxjs/src/internal/operators/finalize.ts",
    "content": "import type { MonoTypeOperatorFunction } from '../types.js';\nimport { Observable } from '@rxjs/observable';\n\n/**\n * Returns an Observable that mirrors the source Observable, but will call a specified function when\n * the source terminates on complete or error.\n * The specified function will also be called when the subscriber explicitly unsubscribes.\n *\n * ## Examples\n *\n * Execute callback function when the observable completes\n *\n * ```ts\n * import { interval, take, finalize } from 'rxjs';\n *\n * // emit value in sequence every 1 second\n * const source = interval(1000);\n * const example = source.pipe(\n *   take(5), //take only the first 5 values\n *   finalize(() => console.log('Sequence complete')) // Execute when the observable completes\n * );\n * const subscribe = example.subscribe(val => console.log(val));\n *\n * // results:\n * // 0\n * // 1\n * // 2\n * // 3\n * // 4\n * // 'Sequence complete'\n * ```\n *\n * Execute callback function when the subscriber explicitly unsubscribes\n *\n * ```ts\n * import { interval, finalize, tap, noop, timer } from 'rxjs';\n *\n * const source = interval(100).pipe(\n *   finalize(() => console.log('[finalize] Called')),\n *   tap({\n *     next: () => console.log('[next] Called'),\n *     error: () => console.log('[error] Not called'),\n *     complete: () => console.log('[tap complete] Not called')\n *   })\n * );\n *\n * const sub = source.subscribe({\n *   next: x => console.log(x),\n *   error: noop,\n *   complete: () => console.log('[complete] Not called')\n * });\n *\n * timer(150).subscribe(() => sub.unsubscribe());\n *\n * // results:\n * // '[next] Called'\n * // 0\n * // '[finalize] Called'\n * ```\n *\n * @param callback Function to be called when source terminates.\n * @return A function that returns an Observable that mirrors the source, but\n * will call the specified function on termination.\n */\nexport function finalize<T>(callback: () => void): MonoTypeOperatorFunction<T> {\n  return (source) =>\n    new Observable((subscriber) => {\n      source.subscribe(subscriber);\n      subscriber.add(callback);\n    });\n}\n"
  },
  {
    "path": "packages/rxjs/src/internal/operators/find.ts",
    "content": "import type { Subscriber} from '@rxjs/observable';\nimport { Observable, operate } from '@rxjs/observable';\nimport type { OperatorFunction, TruthyTypesOf } from '../types.js';\n\nexport function find<T>(predicate: BooleanConstructor): OperatorFunction<T, TruthyTypesOf<T>>;\nexport function find<T, S extends T>(\n  predicate: (value: T, index: number, source: Observable<T>) => value is S\n): OperatorFunction<T, S | undefined>;\nexport function find<T>(predicate: (value: T, index: number, source: Observable<T>) => boolean): OperatorFunction<T, T | undefined>;\n/**\n * Emits only the first value emitted by the source Observable that meets some\n * condition.\n *\n * <span class=\"informal\">Finds the first value that passes some test and emits\n * that.</span>\n *\n * ![](find.png)\n *\n * `find` searches for the first item in the source Observable that matches the\n * specified condition embodied by the `predicate`, and returns the first\n * occurrence in the source. Unlike {@link first}, the `predicate` is required\n * in `find`, and does not emit an error if a valid value is not found\n * (emits `undefined` instead).\n *\n * ## Example\n *\n * Find and emit the first click that happens on a DIV element\n *\n * ```ts\n * import { fromEvent, find } from 'rxjs';\n *\n * const div = document.createElement('div');\n * div.style.cssText = 'width: 200px; height: 200px; background: #09c;';\n * document.body.appendChild(div);\n *\n * const clicks = fromEvent(document, 'click');\n * const result = clicks.pipe(find(ev => (<HTMLElement>ev.target).tagName === 'DIV'));\n * result.subscribe(x => console.log(x));\n * ```\n *\n * @see {@link filter}\n * @see {@link first}\n * @see {@link findIndex}\n * @see {@link take}\n *\n * @param predicate A function called with each item to test for condition matching.\n * @return A function that returns an Observable that emits the first item that\n * matches the condition.\n */\nexport function find<T>(predicate: (value: T, index: number, source: Observable<T>) => boolean): OperatorFunction<T, T | undefined> {\n  return (source) => new Observable((subscriber) => createFind(predicate, 'value', source, subscriber));\n}\n\nexport function createFind<T>(\n  predicate: (value: T, index: number, source: Observable<T>) => boolean,\n  emit: 'value' | 'index',\n  source: Observable<T>,\n  destination: Subscriber<any>\n) {\n  const findIndex = emit === 'index';\n  let index = 0;\n  source.subscribe(\n    operate({\n      destination,\n      next: (value) => {\n        const i = index++;\n        if (predicate(value, i, source)) {\n          destination.next(findIndex ? i : value);\n          destination.complete();\n        }\n      },\n      complete: () => {\n        destination.next(findIndex ? -1 : undefined);\n        destination.complete();\n      },\n    })\n  );\n}\n"
  },
  {
    "path": "packages/rxjs/src/internal/operators/findIndex.ts",
    "content": "import { Observable } from '@rxjs/observable';\nimport type { Falsy, OperatorFunction } from '../types.js';\nimport { createFind } from './find.js';\n\nexport function findIndex<T>(predicate: BooleanConstructor): OperatorFunction<T, T extends Falsy ? -1 : number>;\nexport function findIndex<T>(predicate: (value: T, index: number, source: Observable<T>) => boolean): OperatorFunction<T, number>;\n\n/**\n * Emits only the index of the first value emitted by the source Observable that\n * meets some condition.\n *\n * <span class=\"informal\">It's like {@link find}, but emits the index of the\n * found value, not the value itself.</span>\n *\n * ![](findIndex.png)\n *\n * `findIndex` searches for the first item in the source Observable that matches\n * the specified condition embodied by the `predicate`, and returns the\n * (zero-based) index of the first occurrence in the source. Unlike\n * {@link first}, the `predicate` is required in `findIndex`, and does not emit\n * an error if a valid value is not found.\n *\n * ## Example\n *\n * Emit the index of first click that happens on a DIV element\n *\n * ```ts\n * import { fromEvent, findIndex } from 'rxjs';\n *\n * const div = document.createElement('div');\n * div.style.cssText = 'width: 200px; height: 200px; background: #09c;';\n * document.body.appendChild(div);\n *\n * const clicks = fromEvent(document, 'click');\n * const result = clicks.pipe(findIndex(ev => (<HTMLElement>ev.target).tagName === 'DIV'));\n * result.subscribe(x => console.log(x));\n * ```\n *\n * @see {@link filter}\n * @see {@link find}\n * @see {@link first}\n * @see {@link take}\n *\n * @param predicate A function called with each item to test for condition\n * matching.\n * @return A function that returns an Observable that emits the index of the\n * first item that matches the condition.\n */\nexport function findIndex<T>(predicate: (value: T, index: number, source: Observable<T>) => boolean): OperatorFunction<T, number> {\n  return (source) => new Observable((subscriber) => createFind(predicate, 'index', source, subscriber));\n}\n"
  },
  {
    "path": "packages/rxjs/src/internal/operators/first.ts",
    "content": "import { Observable, operate } from '@rxjs/observable';\nimport { EmptyError } from '../util/EmptyError.js';\nimport type { OperatorFunction, TruthyTypesOf } from '../types.js';\nimport { filter } from './filter.js';\nimport { take } from './take.js';\n\nexport function first<T, D = T>(predicate?: null, defaultValue?: D): OperatorFunction<T, T | D>;\nexport function first<T>(predicate: BooleanConstructor): OperatorFunction<T, TruthyTypesOf<T>>;\nexport function first<T, D>(predicate: BooleanConstructor, defaultValue: D): OperatorFunction<T, TruthyTypesOf<T> | D>;\nexport function first<T, S extends T>(\n  predicate: (value: T, index: number, source: Observable<T>) => value is S,\n  defaultValue?: S\n): OperatorFunction<T, S>;\nexport function first<T, S extends T, D>(\n  predicate: (value: T, index: number, source: Observable<T>) => value is S,\n  defaultValue: D\n): OperatorFunction<T, S | D>;\nexport function first<T, D = T>(\n  predicate: (value: T, index: number, source: Observable<T>) => boolean,\n  defaultValue?: D\n): OperatorFunction<T, T | D>;\n\n/**\n * Emits only the first value (or the first value that meets some condition)\n * emitted by the source Observable.\n *\n * <span class=\"informal\">Emits only the first value. Or emits only the first\n * value that passes some test.</span>\n *\n * ![](first.png)\n *\n * If called with no arguments, `first` emits the first value of the source\n * Observable, then completes. If called with a `predicate` function, `first`\n * emits the first value of the source that matches the specified condition. Emits an error\n * notification if `defaultValue` was not provided and a matching element is not found.\n *\n * ## Examples\n *\n * Emit only the first click that happens on the DOM\n *\n * ```ts\n * import { fromEvent, first } from 'rxjs';\n *\n * const clicks = fromEvent(document, 'click');\n * const result = clicks.pipe(first());\n * result.subscribe(x => console.log(x));\n * ```\n *\n * Emits the first click that happens on a DIV\n *\n * ```ts\n * import { fromEvent, first } from 'rxjs';\n *\n * const div = document.createElement('div');\n * div.style.cssText = 'width: 200px; height: 200px; background: #09c;';\n * document.body.appendChild(div);\n *\n * const clicks = fromEvent(document, 'click');\n * const result = clicks.pipe(first(ev => (<HTMLElement>ev.target).tagName === 'DIV'));\n * result.subscribe(x => console.log(x));\n * ```\n *\n * @see {@link filter}\n * @see {@link find}\n * @see {@link take}\n * @see {@link last}\n *\n * @throws {EmptyError} Delivers an `EmptyError` to the Observer's `error`\n * callback if the Observable completes before any `next` notification was sent.\n * This is how `first()` is different from `take(1)` which completes instead.\n *\n * @param predicate An optional function called with each item to test for condition\n * matching.\n * @param defaultValue The default value emitted in case no valid value was found on\n * the source.\n * @return A function that returns an Observable that emits the first item that\n * matches the condition.\n */\nexport function first<T, D>(\n  predicate?: ((value: T, index: number, source: Observable<T>) => boolean) | null,\n  defaultValue?: D\n): OperatorFunction<T, T | D> {\n  const hasDefaultValue = arguments.length >= 2;\n  return (source) =>\n    new Observable((destination) => {\n      let index = 0;\n      const operatorSubscriber = operate<T, T | D>({\n        destination,\n        next: (value) => {\n          const passed = predicate ? predicate(value, index++, source) : true;\n          if (passed) {\n            // We want to unsubscribe from the source as soon as we know\n            // we can. This will prevent reentrancy issues if calling\n            // `destination.next()` happens to emit another value from source.\n            operatorSubscriber.unsubscribe();\n            destination.next(value);\n            destination.complete();\n          }\n        },\n        complete: () => {\n          if (hasDefaultValue) {\n            destination.next(defaultValue!);\n            destination.complete();\n          } else {\n            destination.error(new EmptyError());\n          }\n        },\n      });\n      source.subscribe(operatorSubscriber);\n    });\n}\n"
  },
  {
    "path": "packages/rxjs/src/internal/operators/groupBy.ts",
    "content": "import { Observable, from, operate } from '@rxjs/observable';\nimport { Subject } from '../Subject.js';\nimport type { ObservableInput, Observer, OperatorFunction, SubjectLike } from '../types.js';\n\nexport interface BasicGroupByOptions<K, T> {\n  element?: undefined;\n  duration?: (grouped: GroupedObservable<K, T>) => ObservableInput<any>;\n  connector?: () => SubjectLike<T>;\n}\n\nexport interface GroupByOptionsWithElement<K, E, T> {\n  element: (value: T) => E;\n  duration?: (grouped: GroupedObservable<K, E>) => ObservableInput<any>;\n  connector?: () => SubjectLike<E>;\n}\n\nexport function groupBy<T, K>(key: (value: T) => K, options: BasicGroupByOptions<K, T>): OperatorFunction<T, GroupedObservable<K, T>>;\n\nexport function groupBy<T, K, E>(\n  key: (value: T) => K,\n  options: GroupByOptionsWithElement<K, E, T>\n): OperatorFunction<T, GroupedObservable<K, E>>;\n\nexport function groupBy<T, K extends T>(\n  key: (value: T) => value is K\n): OperatorFunction<T, GroupedObservable<true, K> | GroupedObservable<false, Exclude<T, K>>>;\n\nexport function groupBy<T, K>(key: (value: T) => K): OperatorFunction<T, GroupedObservable<K, T>>;\n\n/**\n * @deprecated use the options parameter instead.\n */\nexport function groupBy<T, K>(\n  key: (value: T) => K,\n  element: void,\n  duration: (grouped: GroupedObservable<K, T>) => Observable<any>\n): OperatorFunction<T, GroupedObservable<K, T>>;\n\n/**\n * @deprecated use the options parameter instead.\n */\nexport function groupBy<T, K, R>(\n  key: (value: T) => K,\n  element?: (value: T) => R,\n  duration?: (grouped: GroupedObservable<K, R>) => Observable<any>\n): OperatorFunction<T, GroupedObservable<K, R>>;\n\n/**\n * Groups the items emitted by an Observable according to a specified criterion,\n * and emits these grouped items as `GroupedObservables`, one\n * {@link GroupedObservable} per group.\n *\n * ![](groupBy.png)\n *\n * When the Observable emits an item, a key is computed for this item with the key function.\n *\n * If a {@link GroupedObservable} for this key exists, this {@link GroupedObservable} emits. Otherwise, a new\n * {@link GroupedObservable} for this key is created and emits.\n *\n * A {@link GroupedObservable} represents values belonging to the same group represented by a common key. The common\n * key is available as the `key` field of a {@link GroupedObservable} instance.\n *\n * The elements emitted by {@link GroupedObservable}s are by default the items emitted by the Observable, or elements\n * returned by the element function.\n *\n * ## Examples\n *\n * Group objects by `id` and return as array\n *\n * ```ts\n * import { of, groupBy, mergeMap, reduce } from 'rxjs';\n *\n * of(\n *   { id: 1, name: 'JavaScript' },\n *   { id: 2, name: 'Parcel' },\n *   { id: 2, name: 'webpack' },\n *   { id: 1, name: 'TypeScript' },\n *   { id: 3, name: 'TSLint' }\n * ).pipe(\n *   groupBy(p => p.id),\n *   mergeMap(group$ => group$.pipe(reduce((acc, cur) => [...acc, cur], [])))\n * )\n * .subscribe(p => console.log(p));\n *\n * // displays:\n * // [{ id: 1, name: 'JavaScript' }, { id: 1, name: 'TypeScript'}]\n * // [{ id: 2, name: 'Parcel' }, { id: 2, name: 'webpack'}]\n * // [{ id: 3, name: 'TSLint' }]\n * ```\n *\n * Pivot data on the `id` field\n *\n * ```ts\n * import { of, groupBy, mergeMap, reduce, map } from 'rxjs';\n *\n * of(\n *   { id: 1, name: 'JavaScript' },\n *   { id: 2, name: 'Parcel' },\n *   { id: 2, name: 'webpack' },\n *   { id: 1, name: 'TypeScript' },\n *   { id: 3, name: 'TSLint' }\n * ).pipe(\n *   groupBy(p => p.id, { element: p => p.name }),\n *   mergeMap(group$ => group$.pipe(reduce((acc, cur) => [...acc, cur], [`${ group$.key }`]))),\n *   map(arr => ({ id: parseInt(arr[0], 10), values: arr.slice(1) }))\n * )\n * .subscribe(p => console.log(p));\n *\n * // displays:\n * // { id: 1, values: [ 'JavaScript', 'TypeScript' ] }\n * // { id: 2, values: [ 'Parcel', 'webpack' ] }\n * // { id: 3, values: [ 'TSLint' ] }\n * ```\n *\n * @param key A function that extracts the key\n * for each item.\n * @param element A function that extracts the\n * return element for each item.\n * @param duration\n * A function that returns an Observable to determine how long each group should\n * exist.\n * @param connector Factory function to create an\n * intermediate Subject through which grouped elements are emitted.\n * @return A function that returns an Observable that emits GroupedObservables,\n * each of which corresponds to a unique key value and each of which emits\n * those items from the source Observable that share that key value.\n *\n * @deprecated Use the options parameter instead.\n */\nexport function groupBy<T, K, R>(\n  key: (value: T) => K,\n  element?: (value: T) => R,\n  duration?: (grouped: GroupedObservable<K, R>) => Observable<any>,\n  connector?: () => Subject<R>\n): OperatorFunction<T, GroupedObservable<K, R>>;\n\n// Impl\nexport function groupBy<T, K, R>(\n  keySelector: (value: T) => K,\n  elementOrOptions?: ((value: any) => any) | void | BasicGroupByOptions<K, T> | GroupByOptionsWithElement<K, R, T>,\n  duration?: (grouped: GroupedObservable<any, any>) => ObservableInput<any>,\n  connector?: () => SubjectLike<any>\n): OperatorFunction<T, GroupedObservable<K, R>> {\n  return (source) =>\n    new Observable((destination) => {\n      let element: ((value: any) => any) | void;\n      if (!elementOrOptions || typeof elementOrOptions === 'function') {\n        element = elementOrOptions as (value: any) => any;\n      } else {\n        ({ duration, element, connector } = elementOrOptions);\n      }\n\n      // A lookup for the groups that we have so far.\n      const groups = new Map<K, SubjectLike<any>>();\n\n      // Used for notifying all groups and the subscriber in the same way.\n      const notify = (cb: (group: Observer<any>) => void) => {\n        groups.forEach(cb);\n        cb(destination);\n      };\n\n      // Used to handle errors from the source, AND errors that occur during the\n      // next call from the source.\n      const handleError = (err: any) => notify((consumer) => consumer.error(err));\n\n      // Capturing a reference to this, because we need a handle to it\n      // in `createGroupedObservable` below. This is what we use to\n      // subscribe to our source observable. This sometimes needs to be unsubscribed\n      // out-of-band with our `subscriber` which is the downstream subscriber, or destination,\n      // in cases where a user unsubscribes from the main resulting subscription, but\n      // still has groups from this subscription subscribed and would expect values from it\n      // Consider:  `rx(source, groupBy(fn), take(2))`.\n      const groupBySourceSubscriber = operate({\n        destination,\n        next: (value: T) => {\n          // Because we have to notify all groups of any errors that occur in here,\n          // we have to add our own try/catch to ensure that those errors are propagated.\n          // OperatorSubscriber will only send the error to the main subscriber.\n          try {\n            const key = keySelector(value);\n\n            let group = groups.get(key);\n            if (!group) {\n              // Create our group subject\n              groups.set(key, (group = connector ? connector() : new Subject<any>()));\n\n              // Emit the grouped observable. Note that we can't do a simple `asObservable()` here,\n              // because the grouped observable has special semantics around reference counting\n              // to ensure we don't sever our connection to the source prematurely.\n              const grouped = createGroupedObservable(key, group);\n              destination.next(grouped);\n\n              if (duration) {\n                const durationSubscriber = operate({\n                  // Providing the group here ensures that it is disposed of -- via `unsubscribe` --\n                  // when the duration subscription is torn down. That is important, because then\n                  // if someone holds a handle to the grouped observable and tries to subscribe to it\n                  // after the connection to the source has been severed, they will get an\n                  // `ObjectUnsubscribedError` and know they can't possibly get any notifications.\n                  destination: group as any,\n                  next: () => {\n                    // Our duration notified! We can complete the group.\n                    // The group will be removed from the map in the finalization phase.\n                    group!.complete();\n                    durationSubscriber?.unsubscribe();\n                  },\n                  finalize: () => groups.delete(key),\n                });\n\n                // Start our duration notifier.\n                groupBySourceSubscriber.add(from(duration(grouped)).subscribe(durationSubscriber));\n              }\n            }\n\n            // Send the value to our group.\n            group.next(element ? element(value) : value);\n          } catch (err) {\n            handleError(err);\n          }\n        },\n        // Error from the source.\n        error: handleError,\n        // Source completes.\n        complete: () => notify((consumer) => consumer.complete()),\n        // Free up memory.\n        // When the source subscription is _finally_ torn down, release the subjects and keys\n        // in our groups Map, they may be quite large and we don't want to keep them around if we\n        // don't have to.\n        finalize: () => groups.clear(),\n      });\n\n      // Subscribe to the source\n      source.subscribe(groupBySourceSubscriber);\n\n      /**\n       * Creates the actual grouped observable returned.\n       * @param key The key of the group\n       * @param groupSubject The subject that fuels the group\n       */\n      function createGroupedObservable(key: K, groupSubject: SubjectLike<any>) {\n        const result: any = new Observable<T>((groupSubscriber) => groupSubject.subscribe(groupSubscriber));\n        result.key = key;\n        return result;\n      }\n    });\n}\n\n/**\n * An observable of values that is the emitted by the result of a {@link groupBy} operator,\n * contains a `key` property for the grouping.\n */\nexport interface GroupedObservable<K, T> extends Observable<T> {\n  /**\n   * The key value for the grouped notifications.\n   */\n  readonly key: K;\n}\n"
  },
  {
    "path": "packages/rxjs/src/internal/operators/ignoreElements.ts",
    "content": "import type { OperatorFunction } from '../types.js';\nimport { Observable, operate } from '@rxjs/observable';\nimport { noop } from '../util/noop.js';\n\n/**\n * Ignores all items emitted by the source Observable and only passes calls of `complete` or `error`.\n *\n * ![](ignoreElements.png)\n *\n * The `ignoreElements` operator suppresses all items emitted by the source Observable,\n * but allows its termination notification (either `error` or `complete`) to pass through unchanged.\n *\n * If you do not care about the items being emitted by an Observable, but you do want to be notified\n * when it completes or when it terminates with an error, you can apply the `ignoreElements` operator\n * to the Observable, which will ensure that it will never call its observers’ `next` handlers.\n *\n * ## Example\n *\n * Ignore all `next` emissions from the source\n *\n * ```ts\n * import { of, ignoreElements } from 'rxjs';\n *\n * of('you', 'talking', 'to', 'me')\n *   .pipe(ignoreElements())\n *   .subscribe({\n *     next: word => console.log(word),\n *     error: err => console.log('error:', err),\n *     complete: () => console.log('the end'),\n *   });\n *\n * // result:\n * // 'the end'\n * ```\n *\n * @return A function that returns an empty Observable that only calls\n * `complete` or `error`, based on which one is called by the source\n * Observable.\n */\nexport function ignoreElements(): OperatorFunction<unknown, never> {\n  return (source) =>\n    new Observable((destination) => {\n      source.subscribe(operate({ destination, next: noop }));\n    });\n}\n"
  },
  {
    "path": "packages/rxjs/src/internal/operators/isEmpty.ts",
    "content": "import type { OperatorFunction } from '../types.js';\nimport { Observable, operate } from '@rxjs/observable';\n\n/**\n * Emits `false` if the input Observable emits any values, or emits `true` if the\n * input Observable completes without emitting any values.\n *\n * <span class=\"informal\">Tells whether any values are emitted by an Observable.</span>\n *\n * ![](isEmpty.png)\n *\n * `isEmpty` transforms an Observable that emits values into an Observable that\n * emits a single boolean value representing whether or not any values were\n * emitted by the source Observable. As soon as the source Observable emits a\n * value, `isEmpty` will emit a `false` and complete.  If the source Observable\n * completes having not emitted anything, `isEmpty` will emit a `true` and\n * complete.\n *\n * A similar effect could be achieved with {@link count}, but `isEmpty` can emit\n * a `false` value sooner.\n *\n * ## Examples\n *\n * Emit `false` for a non-empty Observable\n *\n * ```ts\n * import { Subject, isEmpty } from 'rxjs';\n *\n * const source = new Subject<string>();\n * const result = source.pipe(isEmpty());\n *\n * source.subscribe(x => console.log(x));\n * result.subscribe(x => console.log(x));\n *\n * source.next('a');\n * source.next('b');\n * source.next('c');\n * source.complete();\n *\n * // Outputs\n * // 'a'\n * // false\n * // 'b'\n * // 'c'\n * ```\n *\n * Emit `true` for an empty Observable\n *\n * ```ts\n * import { EMPTY, isEmpty } from 'rxjs';\n *\n * const result = EMPTY.pipe(isEmpty());\n * result.subscribe(x => console.log(x));\n *\n * // Outputs\n * // true\n * ```\n *\n * @see {@link count}\n * @see {@link EMPTY}\n *\n * @return A function that returns an Observable that emits boolean value\n * indicating whether the source Observable was empty or not.\n */\nexport function isEmpty<T>(): OperatorFunction<T, boolean> {\n  return (source) =>\n    new Observable((destination) => {\n      source.subscribe(\n        operate({\n          destination,\n          next: () => {\n            destination.next(false);\n            destination.complete();\n          },\n          complete: () => {\n            destination.next(true);\n            destination.complete();\n          },\n        })\n      );\n    });\n}\n"
  },
  {
    "path": "packages/rxjs/src/internal/operators/joinAllInternals.ts",
    "content": "import type { Observable } from '@rxjs/observable';\nimport type { ObservableInput, OperatorFunction } from '../types.js';\nimport { identity } from '../util/identity.js';\nimport { mapOneOrManyArgs } from '../util/mapOneOrManyArgs.js';\nimport { pipe } from '../util/pipe.js';\nimport { mergeMap } from './mergeMap.js';\nimport { toArray } from './toArray.js';\n\n/**\n * Collects all of the inner sources from source observable. Then, once the\n * source completes, joins the values using the given static.\n *\n * This is used for {@link combineLatestAll} and {@link zipAll} which both have the\n * same behavior of collecting all inner observables, then operating on them.\n *\n * @param joinFn The type of static join to apply to the sources collected\n * @param project The projection function to apply to the values, if any\n */\nexport function joinAllInternals<T, R>(joinFn: (sources: ObservableInput<T>[]) => Observable<T>, project?: (...args: any[]) => R) {\n  return pipe(\n    // Collect all inner sources into an array, and emit them when the\n    // source completes.\n    toArray() as OperatorFunction<ObservableInput<T>, ObservableInput<T>[]>,\n    // Run the join function on the collected array of inner sources.\n    mergeMap((sources) => joinFn(sources)),\n    // If a projection function was supplied, apply it to each result.\n    project ? mapOneOrManyArgs(project) : (identity as any)\n  );\n}\n"
  },
  {
    "path": "packages/rxjs/src/internal/operators/last.ts",
    "content": "import { Observable, operate } from '@rxjs/observable';\nimport { EmptyError } from '../util/EmptyError.js';\nimport type { OperatorFunction, TruthyTypesOf } from '../types.js';\n\nexport function last<T>(predicate: BooleanConstructor): OperatorFunction<T, TruthyTypesOf<T>>;\nexport function last<T, D>(predicate: BooleanConstructor, defaultValue: D): OperatorFunction<T, TruthyTypesOf<T> | D>;\nexport function last<T, D = T>(predicate?: null, defaultValue?: D): OperatorFunction<T, T | D>;\nexport function last<T, S extends T>(\n  predicate: (value: T, index: number, source: Observable<T>) => value is S,\n  defaultValue?: S\n): OperatorFunction<T, S>;\nexport function last<T, D = T>(\n  predicate: (value: T, index: number, source: Observable<T>) => boolean,\n  defaultValue?: D\n): OperatorFunction<T, T | D>;\n\n/**\n * Returns an Observable that emits only the last item emitted by the source Observable.\n * It optionally takes a predicate function as a parameter, in which case, rather than emitting\n * the last item from the source Observable, the resulting Observable will emit the last item\n * from the source Observable that satisfies the predicate.\n *\n * ![](last.png)\n *\n * It will emit an error notification if the source completes without notification or one that matches\n * the predicate. It returns the last value or if a predicate is provided last value that matches the\n * predicate. It returns the given default value if no notification is emitted or matches the predicate.\n *\n * ## Examples\n *\n * Last alphabet from the sequence\n *\n * ```ts\n * import { from, last } from 'rxjs';\n *\n * const source = from(['x', 'y', 'z']);\n * const result = source.pipe(last());\n *\n * result.subscribe(value => console.log(`Last alphabet: ${ value }`));\n *\n * // Outputs\n * // Last alphabet: z\n * ```\n *\n * Default value when the value in the predicate is not matched\n *\n * ```ts\n * import { from, last } from 'rxjs';\n *\n * const source = from(['x', 'y', 'z']);\n * const result = source.pipe(last(char => char === 'a', 'not found'));\n *\n * result.subscribe(value => console.log(`'a' is ${ value }.`));\n *\n * // Outputs\n * // 'a' is not found.\n * ```\n *\n * @see {@link skip}\n * @see {@link skipUntil}\n * @see {@link skipLast}\n * @see {@link skipWhile}\n * @see {@link first}\n *\n * @throws {EmptyError} Delivers an `EmptyError` to the Observer's `error`\n * callback if the Observable completes before any `next` notification was sent.\n *\n * @param predicate The condition any source emitted item has to satisfy.\n * @param defaultValue An optional default value to provide if last `predicate`\n * isn't met or no values were emitted.\n * @return A function that returns an Observable that emits only the last item\n * satisfying the given condition from the source, or an error notification\n * with an `EmptyError` object if no such items are emitted.\n */\nexport function last<T, D>(\n  predicate?: ((value: T, index: number, source: Observable<T>) => boolean) | null,\n  defaultValue?: D\n): OperatorFunction<T, T | D> {\n  const hasDefaultValue = arguments.length >= 2;\n  return (source: Observable<T>) =>\n    new Observable((destination) => {\n      let index = 0;\n      let found = false;\n      let lastValue: T | D | undefined;\n      source.subscribe(\n        operate({\n          destination,\n          next(value) {\n            if (!predicate || predicate(value, index++, source)) {\n              found = true;\n              lastValue = value;\n            }\n          },\n          complete() {\n            if (found) {\n              destination.next(lastValue!);\n              destination.complete();\n            } else if (hasDefaultValue) {\n              destination.next(defaultValue!);\n              destination.complete();\n            } else {\n              destination.error(new EmptyError());\n            }\n          },\n        })\n      );\n    });\n}\n"
  },
  {
    "path": "packages/rxjs/src/internal/operators/map.ts",
    "content": "import type { OperatorFunction } from '../types.js';\nimport { Observable, operate } from '@rxjs/observable';\n\n/**\n * Applies a given `project` function to each value emitted by the source\n * Observable, and emits the resulting values as an Observable.\n *\n * <span class=\"informal\">Like [Array.prototype.map()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map),\n * it passes each source value through a transformation function to get\n * corresponding output values.</span>\n *\n * ![](map.png)\n *\n * Similar to the well known `Array.prototype.map` function, this operator\n * applies a projection to each value and emits that projection in the output\n * Observable.\n *\n * ## Example\n *\n * Map every click to the `clientX` position of that click\n *\n * ```ts\n * import { fromEvent, map } from 'rxjs';\n *\n * const clicks = fromEvent<PointerEvent>(document, 'click');\n * const positions = clicks.pipe(map(ev => ev.clientX));\n *\n * positions.subscribe(x => console.log(x));\n * ```\n *\n * @see {@link mapTo}\n *\n * @param project The function to apply to each `value` emitted by the source\n * Observable. The `index` parameter is the number `i` for the i-th emission\n * that has happened since the subscription, starting from the number `0`.\n * @return A function that returns an Observable that emits the values from the\n * source Observable transformed by the given `project` function.\n */\nexport function map<T, R>(project: (value: T, index: number) => R): OperatorFunction<T, R> {\n  return (source) =>\n    new Observable((destination) => {\n      // The index of the value from the source. Used with projection.\n      let index = 0;\n      // Subscribe to the source, all errors and completions are sent along\n      // to the consumer.\n      source.subscribe(\n        operate({\n          destination,\n          next: (value: T) => {\n            // Call the projection function with the appropriate this context,\n            // and send the resulting value to the consumer.\n            destination.next(project(value, index++));\n          },\n        })\n      );\n    });\n}\n"
  },
  {
    "path": "packages/rxjs/src/internal/operators/mapTo.ts",
    "content": "import type { OperatorFunction } from '../types.js';\nimport { map } from './map.js';\n\n/** @deprecated To be removed in v9. Use {@link map} instead: `map(() => value)`. */\nexport function mapTo<R>(value: R): OperatorFunction<unknown, R>;\n/**\n * @deprecated Do not specify explicit type parameters. Signatures with type parameters\n * that cannot be inferred will be removed in v8. `mapTo` itself will be removed in v9,\n * use {@link map} instead: `map(() => value)`.\n * */\nexport function mapTo<T, R>(value: R): OperatorFunction<T, R>;\n\n/**\n * Emits the given constant value on the output Observable every time the source\n * Observable emits a value.\n *\n * <span class=\"informal\">Like {@link map}, but it maps every source value to\n * the same output value every time.</span>\n *\n * ![](mapTo.png)\n *\n * Takes a constant `value` as argument, and emits that whenever the source\n * Observable emits a value. In other words, ignores the actual source value,\n * and simply uses the emission moment to know when to emit the given `value`.\n *\n * ## Example\n *\n * Map every click to the string `'Hi'`\n *\n * ```ts\n * import { fromEvent, mapTo } from 'rxjs';\n *\n * const clicks = fromEvent(document, 'click');\n * const greetings = clicks.pipe(mapTo('Hi'));\n *\n * greetings.subscribe(x => console.log(x));\n * ```\n *\n * @see {@link map}\n *\n * @param value The value to map each source value to.\n * @return A function that returns an Observable that emits the given `value`\n * every time the source Observable emits.\n * @deprecated To be removed in v9. Use {@link map} instead: `map(() => value)`.\n */\nexport function mapTo<R>(value: R): OperatorFunction<unknown, R> {\n  return map(() => value);\n}\n"
  },
  {
    "path": "packages/rxjs/src/internal/operators/materialize.ts",
    "content": "import type { OperatorFunction, ObservableNotification } from '../types.js';\nimport { Observable, operate, COMPLETE_NOTIFICATION, errorNotification, nextNotification } from '@rxjs/observable';\n\n/**\n * Represents all of the notifications from the source Observable as `next`\n * emissions marked with their original types within {@link ObservableNotification}\n * objects.\n *\n * <span class=\"informal\">Wraps `next`, `error` and `complete` emissions in\n * {@link ObservableNotification} objects, emitted as `next` on the output Observable.\n * </span>\n *\n * ![](materialize.png)\n *\n * `materialize` returns an Observable that emits a `next` notification for each\n * `next`, `error`, or `complete` emission of the source Observable. When the\n * source Observable emits `complete`, the output Observable will emit `next` as\n * a Notification of type \"complete\", and then it will emit `complete` as well.\n * When the source Observable emits `error`, the output will emit `next` as a\n * Notification of type \"error\", and then `complete`.\n *\n * This operator is useful for producing metadata of the source Observable, to\n * be consumed as `next` emissions. Use it in conjunction with\n * {@link dematerialize}.\n *\n * ## Example\n *\n * Convert a faulty Observable to an Observable of Notifications\n *\n * ```ts\n * import { of, materialize, map } from 'rxjs';\n *\n * const letters = of('a', 'b', 13, 'd');\n * const upperCase = letters.pipe(map((x: any) => x.toUpperCase()));\n * const materialized = upperCase.pipe(materialize());\n *\n * materialized.subscribe(x => console.log(x));\n *\n * // Results in the following:\n * // - Notification { kind: 'N', value: 'A', error: undefined, hasValue: true }\n * // - Notification { kind: 'N', value: 'B', error: undefined, hasValue: true }\n * // - Notification { kind: 'E', value: undefined, error: TypeError { message: x.toUpperCase is not a function }, hasValue: false }\n * ```\n *\n * @see {@link ObservableNotification}\n * @see {@link dematerialize}\n *\n * @return A function that returns an Observable that emits\n * {@link ObservableNotification} objects that wrap the original emissions from the\n * source Observable with metadata.\n */\nexport function materialize<T>(): OperatorFunction<T, ObservableNotification<T>> {\n  return (source) =>\n    new Observable((destination) => {\n      source.subscribe(\n        operate({\n          destination,\n          next: (value) => {\n            destination.next(nextNotification(value));\n          },\n          error: (error) => {\n            destination.next(errorNotification(error));\n            destination.complete();\n          },\n          complete: () => {\n            destination.next(COMPLETE_NOTIFICATION);\n            destination.complete();\n          },\n        })\n      );\n    });\n}\n"
  },
  {
    "path": "packages/rxjs/src/internal/operators/max.ts",
    "content": "import { reduce } from './reduce.js';\nimport type { MonoTypeOperatorFunction } from '../types.js';\nimport { isFunction } from '@rxjs/observable';\n\n/**\n * The `max` operator operates on an Observable that emits numbers (or items that\n * can be compared with a provided function), and when source Observable completes\n * it emits a single item: the item with the largest value.\n *\n * ![](max.png)\n *\n * ## Examples\n *\n * Get the maximal value of a series of numbers\n *\n * ```ts\n * import { of, max } from 'rxjs';\n *\n * of(5, 4, 7, 2, 8)\n *   .pipe(max())\n *   .subscribe(x => console.log(x));\n *\n * // Outputs\n * // 8\n * ```\n *\n * Use a comparer function to get the maximal item\n *\n * ```ts\n * import { of, max } from 'rxjs';\n *\n * of(\n *   { age: 7, name: 'Foo' },\n *   { age: 5, name: 'Bar' },\n *   { age: 9, name: 'Beer' }\n * ).pipe(\n *   max((a, b) => a.age < b.age ? -1 : 1)\n * )\n * .subscribe(x => console.log(x.name));\n *\n * // Outputs\n * // 'Beer'\n * ```\n *\n * @see {@link min}\n *\n * @param comparer Optional comparer function that it will use instead of its\n * default to compare the value of two items.\n * @return A function that returns an Observable that emits item with the\n * largest value.\n */\nexport function max<T>(comparer?: (x: T, y: T) => number): MonoTypeOperatorFunction<T> {\n  return reduce(isFunction(comparer) ? (x, y) => (comparer(x, y) > 0 ? x : y) : (x, y) => (x > y ? x : y));\n}\n"
  },
  {
    "path": "packages/rxjs/src/internal/operators/mergeAll.ts",
    "content": "import { mergeMap } from './mergeMap.js';\nimport { identity } from '../util/identity.js';\nimport type { OperatorFunction, ObservableInput, ObservedValueOf } from '../types.js';\n\n/**\n * Converts a higher-order Observable into a first-order Observable which\n * concurrently delivers all values that are emitted on the inner Observables.\n *\n * <span class=\"informal\">Flattens an Observable-of-Observables.</span>\n *\n * ![](mergeAll.png)\n *\n * `mergeAll` subscribes to an Observable that emits Observables, also known as\n * a higher-order Observable. Each time it observes one of these emitted inner\n * Observables, it subscribes to that and delivers all the values from the\n * inner Observable on the output Observable. The output Observable only\n * completes once all inner Observables have completed. Any error delivered by\n * a inner Observable will be immediately emitted on the output Observable.\n *\n * ## Examples\n *\n * Spawn a new interval Observable for each click event, and blend their outputs as one Observable\n *\n * ```ts\n * import { fromEvent, map, interval, mergeAll } from 'rxjs';\n *\n * const clicks = fromEvent(document, 'click');\n * const higherOrder = clicks.pipe(map(() => interval(1000)));\n * const firstOrder = higherOrder.pipe(mergeAll());\n *\n * firstOrder.subscribe(x => console.log(x));\n * ```\n *\n * Count from 0 to 9 every second for each click, but only allow 2 concurrent timers\n *\n * ```ts\n * import { fromEvent, map, interval, take, mergeAll } from 'rxjs';\n *\n * const clicks = fromEvent(document, 'click');\n * const higherOrder = clicks.pipe(\n *   map(() => interval(1000).pipe(take(10)))\n * );\n * const firstOrder = higherOrder.pipe(mergeAll(2));\n *\n * firstOrder.subscribe(x => console.log(x));\n * ```\n *\n * @see {@link combineLatestAll}\n * @see {@link concatAll}\n * @see {@link exhaustAll}\n * @see {@link merge}\n * @see {@link mergeMap}\n * @see {@link mergeMapTo}\n * @see {@link mergeScan}\n * @see {@link switchAll}\n * @see {@link switchMap}\n * @see {@link zipAll}\n *\n * @param concurrent Maximum number of inner Observables being subscribed to\n * concurrently.\n * @return A function that returns an Observable that emits values coming from\n * all the inner Observables emitted by the source Observable.\n */\nexport function mergeAll<O extends ObservableInput<any>>(concurrent: number = Infinity): OperatorFunction<O, ObservedValueOf<O>> {\n  return mergeMap(identity, concurrent);\n}\n"
  },
  {
    "path": "packages/rxjs/src/internal/operators/mergeInternals.ts",
    "content": "import type { Observable, Subscriber } from '@rxjs/observable';\nimport { from, operate } from '@rxjs/observable';\nimport type { ObservableInput } from '../types.js';\n\n/**\n * A process embodying the general \"merge\" strategy. This is used in\n * `mergeMap` and `mergeScan` because the logic is otherwise nearly identical.\n * @param source The original source observable\n * @param destination The consumer subscriber\n * @param project The projection function to get our inner sources\n * @param concurrent The number of concurrent inner subscriptions\n * @param onBeforeNext Additional logic to apply before nexting to our consumer\n * @param expand If `true` this will perform an \"expand\" strategy, which differs only\n * in that it recurses, and the inner subscription must be schedule-able.\n * @param innerSubScheduler A scheduler to use to schedule inner subscriptions,\n * this is to support the expand strategy, mostly, and should be deprecated\n */\nexport function mergeInternals<T, R>(\n  source: Observable<T>,\n  destination: Subscriber<R>,\n  project: (value: T, index: number) => ObservableInput<R>,\n  concurrent: number,\n  onBeforeNext?: (innerValue: R) => void,\n  expand?: boolean\n) {\n  // Buffered values, in the event of going over our concurrency limit\n  const buffer: T[] = [];\n  // The number of active inner subscriptions.\n  let active = 0;\n  // An index to pass to our accumulator function\n  let index = 0;\n  // Whether or not the outer source has completed.\n  let isComplete = false;\n\n  /**\n   * Checks to see if we can complete our result or not.\n   */\n  const checkComplete = () => {\n    // If the outer has completed, and nothing is left in the buffer,\n    // and we don't have any active inner subscriptions, then we can\n    // Emit the state and complete.\n    if (isComplete && !buffer.length && !active) {\n      destination.complete();\n    }\n  };\n\n  // If we're under our concurrency limit, just start the inner subscription, otherwise buffer and wait.\n  const outerNext = (value: T) => (active < concurrent ? doInnerSub(value) : buffer.push(value));\n\n  const doInnerSub = (value: T) => {\n    // If we're expanding, we need to emit the outer values and the inner values\n    // as the inners will \"become outers\" in a way as they are recursively fed\n    // back to the projection mechanism.\n    expand && destination.next(value as any);\n\n    // Increment the number of active subscriptions so we can track it\n    // against our concurrency limit later.\n    active++;\n\n    // A flag used to show that the inner observable completed.\n    // This is checked during finalization to see if we should\n    // move to the next item in the buffer, if there is on.\n    let innerComplete = false;\n\n    // Start our inner subscription.\n    from(project(value, index++)).subscribe(\n      operate({\n        destination,\n        next: (innerValue) => {\n          // `mergeScan` has additional handling here. For example\n          // taking the inner value and updating state.\n          onBeforeNext?.(innerValue);\n\n          if (expand) {\n            // If we're expanding, then just recurse back to our outer\n            // handler. It will emit the value first thing.\n            outerNext(innerValue as any);\n          } else {\n            // Otherwise, emit the inner value.\n            destination.next(innerValue);\n          }\n        },\n        complete: () => {\n          // Flag that we have completed, so we know to check the buffer\n          // during finalization.\n          innerComplete = true;\n        },\n        finalize: () => {\n          // During finalization, if the inner completed (it wasn't errored or\n          // cancelled), then we want to try the next item in the buffer if\n          // there is one.\n          if (innerComplete) {\n            // We have to wrap this in a try/catch because it happens during\n            // finalization, possibly asynchronously, and we want to pass\n            // any errors that happen (like in a projection function) to\n            // the outer Subscriber.\n            try {\n              // INNER SOURCE COMPLETE\n              // Decrement the active count to ensure that the next time\n              // we try to call `doInnerSub`, the number is accurate.\n              active--;\n              // If we have more values in the buffer, try to process those\n              // Note that this call will increment `active` ahead of the\n              // next conditional, if there were any more inner subscriptions\n              // to start.\n              while (buffer.length && active < concurrent) {\n                doInnerSub(buffer.shift()!);\n              }\n              // Check to see if we can complete, and complete if so.\n              checkComplete();\n            } catch (err) {\n              destination.error(err);\n            }\n          }\n        },\n      })\n    );\n  };\n\n  // Subscribe to our source observable.\n  source.subscribe(\n    operate({\n      destination,\n      next: outerNext,\n      complete: () => {\n        // Outer completed, make a note of it, and check to see if we can complete everything.\n        isComplete = true;\n        checkComplete();\n      },\n    })\n  );\n}\n"
  },
  {
    "path": "packages/rxjs/src/internal/operators/mergeMap.ts",
    "content": "import type { ObservableInput, OperatorFunction, ObservedValueOf } from '../types.js';\nimport { Observable } from '@rxjs/observable';\nimport { mergeInternals } from './mergeInternals.js';\n\n/**\n * Projects each source value to an Observable which is merged in the output\n * Observable.\n *\n * <span class=\"informal\">Maps each value to an Observable, then flattens all of\n * these inner Observables using {@link mergeAll}.</span>\n *\n * ![](mergeMap.png)\n *\n * Returns an Observable that emits items based on applying a function that you\n * supply to each item emitted by the source Observable, where that function\n * returns an Observable, and then merging those resulting Observables and\n * emitting the results of this merger.\n *\n * ## Example\n *\n * Map and flatten each letter to an Observable ticking every 1 second\n *\n * ```ts\n * import { of, mergeMap, interval, map } from 'rxjs';\n *\n * const letters = of('a', 'b', 'c');\n * const result = letters.pipe(\n *   mergeMap(x => interval(1000).pipe(map(i => x + i)))\n * );\n *\n * result.subscribe(x => console.log(x));\n *\n * // Results in the following:\n * // a0\n * // b0\n * // c0\n * // a1\n * // b1\n * // c1\n * // continues to list a, b, c every second with respective ascending integers\n * ```\n *\n * @see {@link concatMap}\n * @see {@link exhaustMap}\n * @see {@link merge}\n * @see {@link mergeAll}\n * @see {@link mergeMapTo}\n * @see {@link mergeScan}\n * @see {@link switchMap}\n *\n * @param project A function that, when applied to an item emitted by the source\n * Observable, returns an Observable.\n * @param concurrent Maximum number of `ObservableInput`s being subscribed to concurrently.\n * @return A function that returns an Observable that emits the result of\n * applying the projection function to each item emitted by the source Observable\n * and merging the results of the Observables obtained from this transformation.\n */\nexport function mergeMap<T, O extends ObservableInput<any>>(\n  project: (value: T, index: number) => O,\n  concurrent: number = Infinity\n): OperatorFunction<T, ObservedValueOf<O>> {\n  return (source) => new Observable((subscriber) => mergeInternals(source, subscriber, project, concurrent));\n}\n"
  },
  {
    "path": "packages/rxjs/src/internal/operators/mergeMapTo.ts",
    "content": "import type { OperatorFunction, ObservedValueOf, ObservableInput } from '../types.js';\nimport { mergeMap } from './mergeMap.js';\n\n/**\n * Projects each source value to the same Observable which is merged multiple\n * times in the output Observable.\n *\n * <span class=\"informal\">It's like {@link mergeMap}, but maps each value always\n * to the same inner Observable.</span>\n *\n * ![](mergeMapTo.png)\n *\n * Maps each source value to the given Observable `innerObservable` regardless\n * of the source value, and then merges those resulting Observables into one\n * single Observable, which is the output Observable.\n *\n * ## Example\n *\n * For each click event, start an interval Observable ticking every 1 second\n *\n * ```ts\n * import { fromEvent, mergeMapTo, interval } from 'rxjs';\n *\n * const clicks = fromEvent(document, 'click');\n * const result = clicks.pipe(mergeMapTo(interval(1000)));\n *\n * result.subscribe(x => console.log(x));\n * ```\n *\n * @see {@link concatMapTo}\n * @see {@link merge}\n * @see {@link mergeAll}\n * @see {@link mergeMap}\n * @see {@link mergeScan}\n * @see {@link switchMapTo}\n *\n * @param innerObservable An `ObservableInput` to replace each value from the\n * source Observable.\n * @param concurrent Maximum number of input Observables being subscribed to\n * concurrently.\n * @return A function that returns an Observable that emits items from the\n * given `innerObservable`.\n * @deprecated Will be removed in v9. Use {@link mergeMap} instead: `mergeMap(() => result)`\n */\nexport function mergeMapTo<O extends ObservableInput<unknown>>(\n  innerObservable: O,\n  concurrent?: number\n): OperatorFunction<unknown, ObservedValueOf<O>> {\n  return mergeMap(() => innerObservable, concurrent);\n}\n"
  },
  {
    "path": "packages/rxjs/src/internal/operators/mergeScan.ts",
    "content": "import type { ObservableInput, OperatorFunction } from '../types.js';\nimport { Observable } from '@rxjs/observable';\nimport { mergeInternals } from './mergeInternals.js';\n\n/**\n * Applies an accumulator function over the source Observable where the\n * accumulator function itself returns an Observable, then each intermediate\n * Observable returned is merged into the output Observable.\n *\n * <span class=\"informal\">It's like {@link scan}, but the Observables returned\n * by the accumulator are merged into the outer Observable.</span>\n *\n * The first parameter of the `mergeScan` is an `accumulator` function which is\n * being called every time the source Observable emits a value. `mergeScan` will\n * subscribe to the value returned by the `accumulator` function and will emit\n * values to the subscriber emitted by inner Observable.\n *\n * The `accumulator` function is being called with three parameters passed to it:\n * `acc`, `value` and `index`. The `acc` parameter is used as the state parameter\n * whose value is initially set to the `seed` parameter (the second parameter\n * passed to the `mergeScan` operator).\n *\n * `mergeScan` internally keeps the value of the `acc` parameter: as long as the\n * source Observable emits without inner Observable emitting, the `acc` will be\n * set to `seed`. The next time the inner Observable emits a value, `mergeScan`\n * will internally remember it and it will be passed to the `accumulator`\n * function as `acc` parameter the next time source emits.\n *\n * The `value` parameter of the `accumulator` function is the value emitted by the\n * source Observable, while the `index` is a number which represent the order of the\n * current emission by the source Observable. It starts with 0.\n *\n * The last parameter to the `mergeScan` is the `concurrent` value which defaults\n * to Infinity. It represents the maximum number of inner Observable subscriptions\n * at a time.\n *\n * ## Example\n *\n * Count the number of click events\n *\n * ```ts\n * import { fromEvent, map, mergeScan, of } from 'rxjs';\n *\n * const click$ = fromEvent(document, 'click');\n * const one$ = click$.pipe(map(() => 1));\n * const seed = 0;\n * const count$ = one$.pipe(\n *   mergeScan((acc, one) => of(acc + one), seed)\n * );\n *\n * count$.subscribe(x => console.log(x));\n *\n * // Results:\n * // 1\n * // 2\n * // 3\n * // 4\n * // ...and so on for each click\n * ```\n *\n * @see {@link scan}\n * @see {@link switchScan}\n *\n * @param accumulator The accumulator function called on each source value.\n * @param seed The initial accumulation value.\n * @param concurrent Maximum number of input Observables being subscribed to\n * concurrently.\n * @return A function that returns an Observable of the accumulated values.\n */\nexport function mergeScan<T, R>(\n  accumulator: (acc: R, value: T, index: number) => ObservableInput<R>,\n  seed: R,\n  concurrent = Infinity\n): OperatorFunction<T, R> {\n  return (source) =>\n    new Observable((subscriber) => {\n      // The accumulated state.\n      let state = seed;\n\n      mergeInternals(\n        source,\n        subscriber,\n        (value, index) => accumulator(state, value, index),\n        concurrent,\n        (value) => {\n          state = value;\n        },\n        false\n      );\n\n      return () => {\n        state = null!;\n      };\n    });\n}\n"
  },
  {
    "path": "packages/rxjs/src/internal/operators/mergeWith.ts",
    "content": "import { Observable, from } from '@rxjs/observable';\nimport { mergeAll } from '../operators/mergeAll.js';\nimport type { ObservableInputTuple, OperatorFunction } from '../types.js';\n\n/**\n * Merge the values from all observables to a single observable result.\n *\n * Creates an observable, that when subscribed to, subscribes to the source\n * observable, and all other sources provided as arguments. All values from\n * every source are emitted from the resulting subscription.\n *\n * When all sources complete, the resulting observable will complete.\n *\n * When any source errors, the resulting observable will error.\n *\n * ## Example\n *\n * Joining all outputs from multiple user input event streams\n *\n * ```ts\n * import { fromEvent, map, mergeWith } from 'rxjs';\n *\n * const clicks$ = fromEvent(document, 'click').pipe(map(() => 'click'));\n * const mousemoves$ = fromEvent(document, 'mousemove').pipe(map(() => 'mousemove'));\n * const dblclicks$ = fromEvent(document, 'dblclick').pipe(map(() => 'dblclick'));\n *\n * mousemoves$\n *   .pipe(mergeWith(clicks$, dblclicks$))\n *   .subscribe(x => console.log(x));\n *\n * // result (assuming user interactions)\n * // 'mousemove'\n * // 'mousemove'\n * // 'mousemove'\n * // 'click'\n * // 'click'\n * // 'dblclick'\n * ```\n *\n * @see {@link merge}\n *\n * @param otherSources the sources to combine the current source with.\n * @return A function that returns an Observable that merges the values from\n * all given Observables.\n */\nexport function mergeWith<T, A extends readonly unknown[]>(\n  ...otherSources: [...ObservableInputTuple<A>]\n): OperatorFunction<T, T | A[number]> {\n  return (source) =>\n    new Observable((subscriber) => {\n      mergeAll()(from([source, ...otherSources])).subscribe(subscriber);\n    });\n}\n"
  },
  {
    "path": "packages/rxjs/src/internal/operators/min.ts",
    "content": "import { reduce } from './reduce.js';\nimport type { MonoTypeOperatorFunction } from '../types.js';\nimport { isFunction } from '@rxjs/observable';\n\n/**\n * The `min` operator operates on an Observable that emits numbers (or items that\n * can be compared with a provided function), and when source Observable completes\n * it emits a single item: the item with the smallest value.\n *\n * ![](min.png)\n *\n * ## Examples\n *\n * Get the minimal value of a series of numbers\n *\n * ```ts\n * import { of, min } from 'rxjs';\n *\n * of(5, 4, 7, 2, 8)\n *   .pipe(min())\n *   .subscribe(x => console.log(x));\n *\n * // Outputs\n * // 2\n * ```\n *\n * Use a comparer function to get the minimal item\n *\n * ```ts\n * import { of, min } from 'rxjs';\n *\n * of(\n *   { age: 7, name: 'Foo' },\n *   { age: 5, name: 'Bar' },\n *   { age: 9, name: 'Beer' }\n * ).pipe(\n *   min((a, b) => a.age < b.age ? -1 : 1)\n * )\n * .subscribe(x => console.log(x.name));\n *\n * // Outputs\n * // 'Bar'\n * ```\n *\n * @see {@link max}\n *\n * @param comparer Optional comparer function that it will use instead of its\n * default to compare the value of two items.\n * @return A function that returns an Observable that emits item with the\n * smallest value.\n */\nexport function min<T>(comparer?: (x: T, y: T) => number): MonoTypeOperatorFunction<T> {\n  return reduce(isFunction(comparer) ? (x, y) => (comparer(x, y) < 0 ? x : y) : (x, y) => (x < y ? x : y));\n}\n"
  },
  {
    "path": "packages/rxjs/src/internal/operators/observeOn.ts",
    "content": "import type { MonoTypeOperatorFunction, SchedulerLike } from '../types.js';\nimport { executeSchedule } from '../util/executeSchedule.js';\nimport { Observable, operate } from '@rxjs/observable';\n\n/**\n * Re-emits all notifications from source Observable with specified scheduler.\n *\n * <span class=\"informal\">Ensure a specific scheduler is used, from outside of an Observable.</span>\n *\n * `observeOn` is an operator that accepts a scheduler as a first parameter, which will be used to reschedule\n * notifications emitted by the source Observable. It might be useful, if you do not have control over\n * internal scheduler of a given Observable, but want to control when its values are emitted nevertheless.\n *\n * Returned Observable emits the same notifications (nexted values, complete and error events) as the source Observable,\n * but rescheduled with provided scheduler. Note that this doesn't mean that source Observables internal\n * scheduler will be replaced in any way. Original scheduler still will be used, but when the source Observable emits\n * notification, it will be immediately scheduled again - this time with scheduler passed to `observeOn`.\n * An anti-pattern would be calling `observeOn` on Observable that emits lots of values synchronously, to split\n * that emissions into asynchronous chunks. For this to happen, scheduler would have to be passed into the source\n * Observable directly (usually into the operator that creates it). `observeOn` simply delays notifications a\n * little bit more, to ensure that they are emitted at expected moments.\n *\n * As a matter of fact, `observeOn` accepts second parameter, which specifies in milliseconds with what delay notifications\n * will be emitted. The main difference between {@link delay} operator and `observeOn` is that `observeOn`\n * will delay all notifications - including error notifications - while `delay` will pass through error\n * from source Observable immediately when it is emitted. In general it is highly recommended to use `delay` operator\n * for any kind of delaying of values in the stream, while using `observeOn` to specify which scheduler should be used\n * for notification emissions in general.\n *\n * ## Example\n *\n * Ensure values in subscribe are called just before browser repaint\n *\n * ```ts\n * import { interval, observeOn, animationFrameScheduler } from 'rxjs';\n *\n * const someDiv = document.createElement('div');\n * someDiv.style.cssText = 'width: 200px;background: #09c';\n * document.body.appendChild(someDiv);\n * const intervals = interval(10);      // Intervals are scheduled\n *                                      // with async scheduler by default...\n * intervals.pipe(\n *   observeOn(animationFrameScheduler) // ...but we will observe on animationFrameScheduler\n * )                                    // scheduler to ensure smooth animation.\n * .subscribe(val => {\n *   someDiv.style.height = val + 'px';\n * });\n * ```\n *\n * @see {@link delay}\n *\n * @param scheduler Scheduler that will be used to reschedule notifications from source Observable.\n * @param delay Number of milliseconds that states with what delay every notification should be rescheduled.\n * @return A function that returns an Observable that emits the same\n * notifications as the source Observable, but with provided scheduler.\n */\nexport function observeOn<T>(scheduler: SchedulerLike, delay = 0): MonoTypeOperatorFunction<T> {\n  return (source) =>\n    new Observable((destination) => {\n      source.subscribe(\n        operate({\n          destination,\n          next: (value) => executeSchedule(destination, scheduler, () => destination.next(value), delay),\n          error: (err) => executeSchedule(destination, scheduler, () => destination.error(err), delay),\n          complete: () => executeSchedule(destination, scheduler, () => destination.complete(), delay),\n        })\n      );\n    });\n}\n"
  },
  {
    "path": "packages/rxjs/src/internal/operators/onErrorResumeNextWith.ts",
    "content": "import type { ObservableInputTuple, OperatorFunction } from '../types.js';\nimport { argsOrArgArray } from '../util/argsOrArgArray.js';\nimport { onErrorResumeNext as oERNCreate } from '../observable/onErrorResumeNext.js';\n\nexport function onErrorResumeNextWith<T, A extends readonly unknown[]>(\n  sources: [...ObservableInputTuple<A>]\n): OperatorFunction<T, T | A[number]>;\nexport function onErrorResumeNextWith<T, A extends readonly unknown[]>(\n  ...sources: [...ObservableInputTuple<A>]\n): OperatorFunction<T, T | A[number]>;\n\n/**\n * When any of the provided Observable emits an complete or error notification, it immediately subscribes to the next one\n * that was passed.\n *\n * <span class=\"informal\">Execute series of Observables, subscribes to next one on error or complete.</span>\n *\n * ![](onErrorResumeNext.png)\n *\n * `onErrorResumeNext` is an operator that accepts a series of Observables, provided either directly as\n * arguments or as an array. If no single Observable is provided, returned Observable will simply behave the same\n * as the source.\n *\n * `onErrorResumeNext` returns an Observable that starts by subscribing and re-emitting values from the source Observable.\n * When its stream of values ends - no matter if Observable completed or emitted an error - `onErrorResumeNext`\n * will subscribe to the first Observable that was passed as an argument to the method. It will start re-emitting\n * its values as well and - again - when that stream ends, `onErrorResumeNext` will proceed to subscribing yet another\n * Observable in provided series, no matter if previous Observable completed or ended with an error. This will\n * be happening until there is no more Observables left in the series, at which point returned Observable will\n * complete - even if the last subscribed stream ended with an error.\n *\n * `onErrorResumeNext` can be therefore thought of as version of {@link concatWith} operator, which is more permissive\n * when it comes to the errors emitted by its input Observables. While `concat` subscribes to the next Observable\n * in series only if previous one successfully completed, `onErrorResumeNext` subscribes even if it ended with\n * an error.\n *\n * Note that you do not get any access to errors emitted by the Observables. In particular do not\n * expect these errors to appear in error callback passed to {@link Observable#subscribe}. If you want to take\n * specific actions based on what error was emitted by an Observable, you should try out {@link catchError} instead.\n *\n *\n * ## Example\n *\n * Subscribe to the next Observable after map fails\n *\n * ```ts\n * import { of, onErrorResumeNext, map } from 'rxjs';\n *\n * of(1, 2, 3, 0)\n *   .pipe(\n *     map(x => {\n *       if (x === 0) {\n *         throw Error();\n *       }\n *\n *       return 10 / x;\n *     }),\n *     onErrorResumeNext(of(1, 2, 3))\n *   )\n *   .subscribe({\n *     next: val => console.log(val),\n *     error: err => console.log(err),          // Will never be called.\n *     complete: () => console.log('that\\'s it!')\n *   });\n *\n * // Logs:\n * // 10\n * // 5\n * // 3.3333333333333335\n * // 1\n * // 2\n * // 3\n * // 'that's it!'\n * ```\n *\n * @see {@link concat}\n * @see {@link catchError}\n *\n * @param sources `ObservableInput`s passed either directly or as an array.\n * @return A function that returns an Observable that emits values from source\n * Observable, but - if it errors - subscribes to the next passed Observable\n * and so on, until it completes or runs out of Observables.\n */\nexport function onErrorResumeNextWith<T, A extends readonly unknown[]>(\n  ...sources: [[...ObservableInputTuple<A>]] | [...ObservableInputTuple<A>]\n): OperatorFunction<T, T | A[number]> {\n  // For some reason, TS 4.1 RC gets the inference wrong here and infers the\n  // result to be `A[number][]` - completely dropping the ObservableInput part\n  // of the type. This makes no sense whatsoever. As a workaround, the type is\n  // asserted explicitly.\n  const nextSources = argsOrArgArray(sources) as unknown as ObservableInputTuple<A>;\n\n  return (source) => oERNCreate(source, ...nextSources);\n}\n"
  },
  {
    "path": "packages/rxjs/src/internal/operators/pairwise.ts",
    "content": "import type { OperatorFunction } from '../types.js';\nimport { Observable, operate } from '@rxjs/observable';\n\n/**\n * Groups pairs of consecutive emissions together and emits them as an array of\n * two values.\n *\n * <span class=\"informal\">Puts the current value and previous value together as\n * an array, and emits that.</span>\n *\n * ![](pairwise.png)\n *\n * The Nth emission from the source Observable will cause the output Observable\n * to emit an array [(N-1)th, Nth] of the previous and the current value, as a\n * pair. For this reason, `pairwise` emits on the second and subsequent\n * emissions from the source Observable, but not on the first emission, because\n * there is no previous value in that case.\n *\n * ## Example\n *\n * On every click (starting from the second), emit the relative distance to the previous click\n *\n * ```ts\n * import { fromEvent, pairwise, map } from 'rxjs';\n *\n * const clicks = fromEvent<PointerEvent>(document, 'click');\n * const pairs = clicks.pipe(pairwise());\n * const distance = pairs.pipe(\n *   map(([first, second]) => {\n *     const x0 = first.clientX;\n *     const y0 = first.clientY;\n *     const x1 = second.clientX;\n *     const y1 = second.clientY;\n *     return Math.sqrt(Math.pow(x0 - x1, 2) + Math.pow(y0 - y1, 2));\n *   })\n * );\n *\n * distance.subscribe(x => console.log(x));\n * ```\n *\n * @see {@link buffer}\n * @see {@link bufferCount}\n *\n * @return A function that returns an Observable of pairs (as arrays) of\n * consecutive values from the source Observable.\n */\nexport function pairwise<T>(): OperatorFunction<T, [T, T]> {\n  return (source) =>\n    new Observable((destination) => {\n      let prev: T;\n      let hasPrev = false;\n      source.subscribe(\n        operate({\n          destination,\n          next: (value) => {\n            const p = prev;\n            prev = value;\n            hasPrev && destination.next([p, value]);\n            hasPrev = true;\n          },\n        })\n      );\n    });\n}\n"
  },
  {
    "path": "packages/rxjs/src/internal/operators/partition.ts",
    "content": "import { not } from '../util/not.js';\nimport { filter } from './filter.js';\nimport type { Observable } from '@rxjs/observable';\nimport type { UnaryFunction } from '../types.js';\n\n/**\n * Splits the source Observable into two, one with values that satisfy a\n * predicate, and another with values that don't satisfy the predicate.\n *\n * <span class=\"informal\">It's like {@link filter}, but returns two Observables:\n * one like the output of {@link filter}, and the other with values that did not\n * pass the condition.</span>\n *\n * ![](partition.png)\n *\n * `partition` outputs an array with two Observables that partition the values\n * from the source Observable through the given `predicate` function. The first\n * Observable in that array emits source values for which the predicate argument\n * returns true. The second Observable emits source values for which the\n * predicate returns false. The first behaves like {@link filter} and the second\n * behaves like {@link filter} with the predicate negated.\n *\n * ## Example\n *\n * Partition click events into those on DIV elements and those elsewhere\n *\n * ```ts\n * import { fromEvent } from 'rxjs';\n * import { partition } from 'rxjs/operators';\n *\n * const div = document.createElement('div');\n * div.style.cssText = 'width: 200px; height: 200px; background: #09c;';\n * document.body.appendChild(div);\n *\n * const clicks = fromEvent(document, 'click');\n * const [clicksOnDivs, clicksElsewhere] = clicks.pipe(partition(ev => (<HTMLElement>ev.target).tagName === 'DIV'));\n *\n * clicksOnDivs.subscribe(x => console.log('DIV clicked: ', x));\n * clicksElsewhere.subscribe(x => console.log('Other clicked: ', x));\n * ```\n *\n * @see {@link filter}\n *\n * @param predicate A function that evaluates each value emitted by the source\n * Observable. If it returns `true`, the value is emitted on the first Observable\n * in the returned array, if `false` the value is emitted on the second Observable\n * in the array. The `index` parameter is the number `i` for the i-th source\n * emission that has happened since the subscription, starting from the number `0`.\n * @param thisArg An optional argument to determine the value of `this` in the\n * `predicate` function.\n * @return A function that returns an array with two Observables: one with\n * values that passed the predicate, and another with values that did not pass\n * the predicate.\n * @deprecated Replaced with the {@link partition} static creation function. Will be removed in v8.\n */\nexport function partition<T>(\n  predicate: (value: T, index: number) => boolean,\n  thisArg?: any\n): UnaryFunction<Observable<T>, [Observable<T>, Observable<T>]> {\n  return (source: Observable<T>) =>\n    [filter(predicate, thisArg)(source), filter(not(predicate, thisArg))(source)] as [Observable<T>, Observable<T>];\n}\n"
  },
  {
    "path": "packages/rxjs/src/internal/operators/raceWith.ts",
    "content": "import type { OperatorFunction, ObservableInputTuple } from '../types.js';\nimport { raceInit } from '../observable/race.js';\nimport { Observable } from '@rxjs/observable';\nimport { identity } from '../util/identity.js';\n\n/**\n * Creates an Observable that mirrors the first source Observable to emit a next,\n * error or complete notification from the combination of the Observable to which\n * the operator is applied and supplied Observables.\n *\n * ## Example\n *\n * ```ts\n * import { interval, map, raceWith } from 'rxjs';\n *\n * const obs1 = interval(7000).pipe(map(() => 'slow one'));\n * const obs2 = interval(3000).pipe(map(() => 'fast one'));\n * const obs3 = interval(5000).pipe(map(() => 'medium one'));\n *\n * obs1\n *   .pipe(raceWith(obs2, obs3))\n *   .subscribe(winner => console.log(winner));\n *\n * // Outputs\n * // a series of 'fast one'\n * ```\n *\n * @param otherSources Sources used to race for which Observable emits first.\n * @return A function that returns an Observable that mirrors the output of the\n * first Observable to emit an item.\n */\nexport function raceWith<T, A extends readonly unknown[]>(\n  ...otherSources: [...ObservableInputTuple<A>]\n): OperatorFunction<T, T | A[number]> {\n  return !otherSources.length\n    ? identity\n    : (source) =>\n        new Observable((subscriber) => {\n          raceInit<T | A[number]>([source, ...otherSources])(subscriber);\n        });\n}\n"
  },
  {
    "path": "packages/rxjs/src/internal/operators/reduce.ts",
    "content": "import { scanInternals } from './scanInternals.js';\nimport type { OperatorFunction } from '../types.js';\nimport { Observable } from '@rxjs/observable';\n\nexport function reduce<V, A = V>(accumulator: (acc: A | V, value: V, index: number) => A): OperatorFunction<V, V | A>;\nexport function reduce<V, A>(accumulator: (acc: A, value: V, index: number) => A, seed: A): OperatorFunction<V, A>;\nexport function reduce<V, A, S = A>(accumulator: (acc: A | S, value: V, index: number) => A, seed: S): OperatorFunction<V, A>;\n\n/**\n * Applies an accumulator function over the source Observable, and returns the\n * accumulated result when the source completes, given an optional seed value.\n *\n * <span class=\"informal\">Combines together all values emitted on the source,\n * using an accumulator function that knows how to join a new source value into\n * the accumulation from the past.</span>\n *\n * ![](reduce.png)\n *\n * Like\n * [Array.prototype.reduce()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/reduce),\n * `reduce` applies an `accumulator` function against an accumulation and each\n * value of the source Observable (from the past) to reduce it to a single\n * value, emitted on the output Observable. Note that `reduce` will only emit\n * one value, only when the source Observable completes. It is equivalent to\n * applying operator {@link scan} followed by operator {@link last}.\n *\n * Returns an Observable that applies a specified `accumulator` function to each\n * item emitted by the source Observable. If a `seed` value is specified, then\n * that value will be used as the initial value for the accumulator. If no seed\n * value is specified, the first item of the source is used as the seed.\n *\n * ## Example\n *\n * Count the number of click events that happened in 5 seconds\n *\n * ```ts\n * import { fromEvent, takeUntil, interval, map, reduce } from 'rxjs';\n *\n * const clicksInFiveSeconds = fromEvent(document, 'click')\n *   .pipe(takeUntil(interval(5000)));\n *\n * const ones = clicksInFiveSeconds.pipe(map(() => 1));\n * const seed = 0;\n * const count = ones.pipe(reduce((acc, one) => acc + one, seed));\n *\n * count.subscribe(x => console.log(x));\n * ```\n *\n * @see {@link count}\n * @see {@link expand}\n * @see {@link mergeScan}\n * @see {@link scan}\n *\n * @param accumulator The accumulator function called on each source value.\n * @param seed The initial accumulation value.\n * @return A function that returns an Observable that emits a single value that\n * is the result of accumulating the values emitted by the source Observable.\n */\nexport function reduce<V, A>(accumulator: (acc: V | A, value: V, index: number) => A, seed?: any): OperatorFunction<V, V | A> {\n  const hasSeed = arguments.length >= 2;\n  return (source) => new Observable((subscriber) => scanInternals(accumulator, seed, hasSeed, false, true, source, subscriber));\n}\n"
  },
  {
    "path": "packages/rxjs/src/internal/operators/repeat.ts",
    "content": "import type { Subscription} from '@rxjs/observable';\nimport { Observable, operate, from } from '@rxjs/observable';\nimport { EMPTY } from '../observable/empty.js';\nimport type { MonoTypeOperatorFunction, ObservableInput } from '../types.js';\nimport { timer } from '../observable/timer.js';\n\nexport interface RepeatConfig {\n  /**\n   * The number of times to repeat the source. Defaults to `Infinity`.\n   */\n  count?: number;\n\n  /**\n   * If a `number`, will delay the repeat of the source by that number of milliseconds.\n   * If a function, it will provide the number of times the source has been subscribed to,\n   * and the return value should be a valid observable input that will notify when the source\n   * should be repeated. If the notifier observable is empty, the result will complete.\n   */\n  delay?: number | ((count: number) => ObservableInput<any>);\n}\n\n/**\n * Returns an Observable that will resubscribe to the source stream when the source stream completes.\n *\n * <span class=\"informal\">Repeats all values emitted on the source. It's like {@link retry}, but for non error cases.</span>\n *\n * ![](repeat.png)\n *\n * Repeat will output values from a source until the source completes, then it will resubscribe to the\n * source a specified number of times, with a specified delay. Repeat can be particularly useful in\n * combination with closing operators like {@link take}, {@link takeUntil}, {@link first}, or {@link takeWhile},\n * as it can be used to restart a source again from scratch.\n *\n * Repeat is very similar to {@link retry}, where {@link retry} will resubscribe to the source in the error case, but\n * `repeat` will resubscribe if the source completes.\n *\n * Note that `repeat` will _not_ catch errors. Use {@link retry} for that.\n *\n * - `repeat(0)` returns an empty observable\n * - `repeat()` will repeat forever\n * - `repeat({ delay: 200 })` will repeat forever, with a delay of 200ms between repetitions.\n * - `repeat({ count: 2, delay: 400 })` will repeat twice, with a delay of 400ms between repetitions.\n * - `repeat({ delay: (count) => timer(count * 1000) })` will repeat forever, but will have a delay that grows by one second for each repetition.\n *\n * ## Example\n *\n * Repeat a message stream\n *\n * ```ts\n * import { of, repeat } from 'rxjs';\n *\n * const source = of('Repeat message');\n * const result = source.pipe(repeat(3));\n *\n * result.subscribe(x => console.log(x));\n *\n * // Results\n * // 'Repeat message'\n * // 'Repeat message'\n * // 'Repeat message'\n * ```\n *\n * Repeat 3 values, 2 times\n *\n * ```ts\n * import { interval, take, repeat } from 'rxjs';\n *\n * const source = interval(1000);\n * const result = source.pipe(take(3), repeat(2));\n *\n * result.subscribe(x => console.log(x));\n *\n * // Results every second\n * // 0\n * // 1\n * // 2\n * // 0\n * // 1\n * // 2\n * ```\n *\n * Defining two complex repeats with delays on the same source.\n * Note that the second repeat cannot be called until the first\n * repeat as exhausted it's count.\n *\n * ```ts\n * import { defer, of, repeat } from 'rxjs';\n *\n * const source = defer(() => {\n *    return of(`Hello, it is ${new Date()}`)\n * });\n *\n * source.pipe(\n *    // Repeat 3 times with a delay of 1 second between repetitions\n *    repeat({\n *      count: 3,\n *      delay: 1000,\n *    }),\n *\n *    // *Then* repeat forever, but with an exponential step-back\n *    // maxing out at 1 minute.\n *    repeat({\n *      delay: (count) => timer(Math.min(60000, 2 ^ count * 1000))\n *    })\n * )\n * ```\n *\n * @see {@link repeatWhen}\n * @see {@link retry}\n *\n * @param countOrConfig Either the number of times the source Observable items are repeated\n * (a count of 0 will yield an empty Observable) or a {@link RepeatConfig} object.\n */\nexport function repeat<T>(countOrConfig?: number | RepeatConfig): MonoTypeOperatorFunction<T> {\n  let count = Infinity;\n  let delay: RepeatConfig['delay'];\n\n  if (countOrConfig != null) {\n    if (typeof countOrConfig === 'object') {\n      ({ count = Infinity, delay } = countOrConfig);\n    } else {\n      count = countOrConfig;\n    }\n  }\n\n  return count <= 0\n    ? () => EMPTY\n    : (source) =>\n        new Observable((destination) => {\n          let soFar = 0;\n          let sourceSub: Subscription | null;\n\n          const resubscribe = () => {\n            sourceSub?.unsubscribe();\n            sourceSub = null;\n            if (delay != null) {\n              const notifier = typeof delay === 'number' ? timer(delay) : from(delay(soFar));\n              const notifierSubscriber = operate({\n                destination,\n                next: () => {\n                  notifierSubscriber.unsubscribe();\n                  subscribeToSource();\n                },\n              });\n              notifier.subscribe(notifierSubscriber);\n            } else {\n              subscribeToSource();\n            }\n          };\n\n          const subscribeToSource = () => {\n            let syncUnsub = false;\n            sourceSub = source.subscribe(\n              operate({\n                destination,\n                complete: () => {\n                  if (++soFar < count) {\n                    if (sourceSub) {\n                      resubscribe();\n                    } else {\n                      syncUnsub = true;\n                    }\n                  } else {\n                    destination.complete();\n                  }\n                },\n              })\n            );\n\n            if (syncUnsub) {\n              resubscribe();\n            }\n          };\n\n          subscribeToSource();\n        });\n}\n"
  },
  {
    "path": "packages/rxjs/src/internal/operators/repeatWhen.ts",
    "content": "import type { Subscription} from '@rxjs/observable';\nimport { Observable, from, operate } from '@rxjs/observable';\nimport { Subject } from '../Subject.js';\nimport type { MonoTypeOperatorFunction, ObservableInput } from '../types.js';\n\n/**\n * Returns an Observable that mirrors the source Observable with the exception of a `complete`. If the source\n * Observable calls `complete`, this method will emit to the Observable returned from `notifier`. If that Observable\n * calls `complete` or `error`, then this method will call `complete` or `error` on the child subscription. Otherwise\n * this method will resubscribe to the source Observable.\n *\n * ![](repeatWhen.png)\n *\n * ## Example\n *\n * Repeat a message stream on click\n *\n * ```ts\n * import { of, fromEvent, repeatWhen } from 'rxjs';\n *\n * const source = of('Repeat message');\n * const documentClick$ = fromEvent(document, 'click');\n *\n * const result = source.pipe(repeatWhen(() => documentClick$));\n *\n * result.subscribe(data => console.log(data))\n * ```\n *\n * @see {@link repeat}\n * @see {@link retry}\n * @see {@link retryWhen}\n *\n * @param notifier Function that receives an Observable of notifications with\n * which a user can `complete` or `error`, aborting the repetition.\n * @return A function that returns an Observable that mirrors the source\n * Observable with the exception of a `complete`.\n * @deprecated Will be removed in v9 or v10. Use {@link repeat}'s {@link RepeatConfig#delay delay} option instead.\n * Instead of `repeatWhen(() => notify$)`, use: `repeat({ delay: () => notify$ })`.\n */\nexport function repeatWhen<T>(notifier: (notifications: Observable<void>) => ObservableInput<any>): MonoTypeOperatorFunction<T> {\n  return (source) =>\n    new Observable((destination) => {\n      let innerSub: Subscription | null;\n      let syncResub = false;\n      let completions$: Subject<void>;\n      let isNotifierComplete = false;\n      let isMainComplete = false;\n\n      /**\n       * Checks to see if we can complete the result, completes it, and returns `true` if it was completed.\n       */\n      const checkComplete = () => isMainComplete && isNotifierComplete && (destination.complete(), true);\n      /**\n       * Gets the subject to send errors through. If it doesn't exist,\n       * we know we need to setup the notifier.\n       */\n      const getCompletionSubject = () => {\n        if (!completions$) {\n          completions$ = new Subject();\n\n          // If the call to `notifier` throws, it will be caught by the OperatorSubscriber\n          // In the main subscription -- in `subscribeForRepeatWhen`.\n          from(notifier(completions$)).subscribe(\n            operate({\n              destination,\n              next: () => {\n                if (innerSub) {\n                  subscribeForRepeatWhen();\n                } else {\n                  // If we don't have an innerSub yet, that's because the inner subscription\n                  // call hasn't even returned yet. We've arrived here synchronously.\n                  // So we flag that we want to resub, such that we can ensure finalization\n                  // happens before we resubscribe.\n                  syncResub = true;\n                }\n              },\n              complete: () => {\n                isNotifierComplete = true;\n                checkComplete();\n              },\n            })\n          );\n        }\n        return completions$;\n      };\n\n      const subscribeForRepeatWhen = () => {\n        isMainComplete = false;\n\n        innerSub = source.subscribe(\n          operate({\n            destination,\n            complete: () => {\n              isMainComplete = true;\n              // Check to see if we are complete, and complete if so.\n              // If we are not complete. Get the subject. This calls the `notifier` function.\n              // If that function fails, it will throw and `.next()` will not be reached on this\n              // line. The thrown error is caught by the _complete handler in this\n              // `OperatorSubscriber` and handled appropriately.\n              !checkComplete() && getCompletionSubject().next();\n            },\n          })\n        );\n\n        if (syncResub) {\n          // Ensure that the inner subscription is torn down before\n          // moving on to the next subscription in the synchronous case.\n          // If we don't do this here, all inner subscriptions will not be\n          // torn down until the entire observable is done.\n          innerSub.unsubscribe();\n          // It is important to null this out. Not only to free up memory, but\n          // to make sure code above knows we are in a subscribing state to\n          // handle synchronous resubscription.\n          innerSub = null;\n          // We may need to do this multiple times, so reset the flags.\n          syncResub = false;\n          // Resubscribe\n          subscribeForRepeatWhen();\n        }\n      };\n\n      // Start the subscription\n      subscribeForRepeatWhen();\n    });\n}\n"
  },
  {
    "path": "packages/rxjs/src/internal/operators/retry.ts",
    "content": "import type { MonoTypeOperatorFunction, ObservableInput } from '../types.js';\nimport type { Subscription} from '@rxjs/observable';\nimport { Observable, operate, from } from '@rxjs/observable';\nimport { identity } from '../util/identity.js';\nimport { timer } from '../observable/timer.js';\n\n/**\n * The {@link retry} operator configuration object. `retry` either accepts a `number`\n * or an object described by this interface.\n */\nexport interface RetryConfig {\n  /**\n   * The maximum number of times to retry. If `count` is omitted, `retry` will try to\n   * resubscribe on errors infinite number of times.\n   */\n  count?: number;\n  /**\n   * The number of milliseconds to delay before retrying, OR a function to\n   * return a notifier for delaying. If a function is given, that function should\n   * return a notifier that, when it emits will retry the source. If the notifier\n   * completes _without_ emitting, the resulting observable will complete without error,\n   * if the notifier errors, the error will be pushed to the result.\n   */\n  delay?: number | ((error: any, retryCount: number) => ObservableInput<any>);\n  /**\n   * Whether or not to reset the retry counter when the retried subscription\n   * emits its first value.\n   */\n  resetOnSuccess?: boolean;\n}\n\nexport function retry<T>(count?: number): MonoTypeOperatorFunction<T>;\nexport function retry<T>(config: RetryConfig): MonoTypeOperatorFunction<T>;\n\n/**\n * Returns an Observable that mirrors the source Observable with the exception of an `error`.\n *\n * If the source Observable calls `error`, this method will resubscribe to the source Observable for a maximum of\n * `count` resubscriptions rather than propagating the `error` call.\n *\n * ![](retry.png)\n *\n * The number of retries is determined by the `count` parameter. It can be set either by passing a number to\n * `retry` function or by setting `count` property when `retry` is configured using {@link RetryConfig}. If\n * `count` is omitted, `retry` will try to resubscribe on errors infinite number of times.\n *\n * Any and all items emitted by the source Observable will be emitted by the resulting Observable, even those\n * emitted during failed subscriptions. For example, if an Observable fails at first but emits `[1, 2]` then\n * succeeds the second time and emits: `[1, 2, 3, 4, 5, complete]` then the complete stream of emissions and\n * notifications would be: `[1, 2, 1, 2, 3, 4, 5, complete]`.\n *\n * ## Example\n *\n * ```ts\n * import { interval, mergeMap, throwError, of, retry } from 'rxjs';\n *\n * const source = interval(1000);\n * const result = source.pipe(\n *   mergeMap(val => val > 5 ? throwError(() => 'Error!') : of(val)),\n *   retry(2) // retry 2 times on error\n * );\n *\n * result.subscribe({\n *   next: value => console.log(value),\n *   error: err => console.log(`${ err }: Retried 2 times then quit!`)\n * });\n *\n * // Output:\n * // 0..1..2..3..4..5..\n * // 0..1..2..3..4..5..\n * // 0..1..2..3..4..5..\n * // 'Error!: Retried 2 times then quit!'\n * ```\n *\n * @see {@link retryWhen}\n *\n * @param configOrCount Either number of retry attempts before failing or a\n * {@link RetryConfig} object.\n * @return A function that returns an Observable that will resubscribe to the\n * source stream when the source stream errors, at most `count` times.\n */\nexport function retry<T>(configOrCount: number | RetryConfig = Infinity): MonoTypeOperatorFunction<T> {\n  let config: RetryConfig;\n  if (configOrCount && typeof configOrCount === 'object') {\n    config = configOrCount;\n  } else {\n    config = {\n      count: configOrCount as number,\n    };\n  }\n  const { count = Infinity, delay, resetOnSuccess: resetOnSuccess = false } = config;\n\n  return count <= 0\n    ? identity\n    : (source) =>\n        new Observable((destination) => {\n          let soFar = 0;\n          let innerSub: Subscription | null;\n          const subscribeForRetry = () => {\n            let syncUnsub = false;\n            innerSub = source.subscribe(\n              operate({\n                destination,\n                next: (value) => {\n                  // If we're resetting on success\n                  if (resetOnSuccess) {\n                    soFar = 0;\n                  }\n                  destination.next(value);\n                },\n                error: (err) => {\n                  if (soFar++ < count) {\n                    // We are still under our retry count\n                    const resub = () => {\n                      if (innerSub) {\n                        innerSub.unsubscribe();\n                        innerSub = null;\n                        subscribeForRetry();\n                      } else {\n                        syncUnsub = true;\n                      }\n                    };\n\n                    if (delay != null) {\n                      // The user specified a retry delay.\n                      // They gave us a number, use a timer, otherwise, it's a function,\n                      // and we're going to call it to get a notifier.\n                      const notifier = typeof delay === 'number' ? timer(delay) : from(delay(err, soFar));\n                      const notifierSubscriber = operate({\n                        destination,\n                        next: () => {\n                          // After we get the first notification, we\n                          // unsubscribe from the notifier, because we don't want anymore\n                          // and we resubscribe to the source.\n                          notifierSubscriber.unsubscribe();\n                          resub();\n                        },\n                        complete: () => {\n                          // The notifier completed without emitting.\n                          // The author is telling us they want to complete.\n                          destination.complete();\n                        },\n                      });\n                      notifier.subscribe(notifierSubscriber);\n                    } else {\n                      // There was no notifier given. Just resub immediately.\n                      resub();\n                    }\n                  } else {\n                    // We're past our maximum number of retries.\n                    // Just send along the error.\n                    destination.error(err);\n                  }\n                },\n              })\n            );\n            if (syncUnsub) {\n              innerSub.unsubscribe();\n              innerSub = null;\n              subscribeForRetry();\n            }\n          };\n          subscribeForRetry();\n        });\n}\n"
  },
  {
    "path": "packages/rxjs/src/internal/operators/retryWhen.ts",
    "content": "import type { Subscription} from '@rxjs/observable';\nimport { Observable, from, operate } from '@rxjs/observable';\nimport { Subject } from '../Subject.js';\nimport type { MonoTypeOperatorFunction, ObservableInput } from '../types.js';\n\n/**\n * Returns an Observable that mirrors the source Observable with the exception of an `error`. If the source Observable\n * calls `error`, this method will emit the Throwable that caused the error to the `ObservableInput` returned from `notifier`.\n * If that Observable calls `complete` or `error` then this method will call `complete` or `error` on the child\n * subscription. Otherwise this method will resubscribe to the source Observable.\n *\n * ![](retryWhen.png)\n *\n * Retry an observable sequence on error based on custom criteria.\n *\n * ## Example\n *\n * ```ts\n * import { interval, map, retryWhen, tap, delayWhen, timer } from 'rxjs';\n *\n * const source = interval(1000);\n * const result = source.pipe(\n *   map(value => {\n *     if (value > 5) {\n *       // error will be picked up by retryWhen\n *       throw value;\n *     }\n *     return value;\n *   }),\n *   retryWhen(errors =>\n *     errors.pipe(\n *       // log error message\n *       tap(value => console.log(`Value ${ value } was too high!`)),\n *       // restart in 5 seconds\n *       delayWhen(value => timer(value * 1000))\n *     )\n *   )\n * );\n *\n * result.subscribe(value => console.log(value));\n *\n * // results:\n * // 0\n * // 1\n * // 2\n * // 3\n * // 4\n * // 5\n * // 'Value 6 was too high!'\n * // - Wait 5 seconds then repeat\n * ```\n *\n * @see {@link retry}\n *\n * @param notifier Function that receives an Observable of notifications with which a\n * user can `complete` or `error`, aborting the retry.\n * @return A function that returns an Observable that mirrors the source\n * Observable with the exception of an `error`.\n * @deprecated Will be removed in v9 or v10. Use {@link retry}'s {@link RetryConfig#delay delay} option instead.\n * Instead of `retryWhen(() => notify$)`, use: `retry({ delay: () => notify$ })`.\n */\nexport function retryWhen<T>(notifier: (errors: Observable<any>) => ObservableInput<any>): MonoTypeOperatorFunction<T> {\n  return (source) =>\n    new Observable((destination) => {\n      let innerSub: Subscription | null;\n      let syncResub = false;\n      let errors$: Subject<any>;\n\n      const subscribeForRetryWhen = () => {\n        innerSub = source.subscribe(\n          operate({\n            destination,\n            error: (err) => {\n              if (!errors$) {\n                errors$ = new Subject();\n                from(notifier(errors$)).subscribe(\n                  operate({\n                    destination,\n                    next: () =>\n                      // If we have an innerSub, this was an asynchronous call, kick off the retry.\n                      // Otherwise, if we don't have an innerSub yet, that's because the inner subscription\n                      // call hasn't even returned yet. We've arrived here synchronously.\n                      // So we flag that we want to resub, such that we can ensure finalization\n                      // happens before we resubscribe.\n                      innerSub ? subscribeForRetryWhen() : (syncResub = true),\n                  })\n                );\n              }\n              if (errors$) {\n                // We have set up the notifier without error.\n                errors$.next(err);\n              }\n            },\n          })\n        );\n\n        if (syncResub) {\n          // Ensure that the inner subscription is torn down before\n          // moving on to the next subscription in the synchronous case.\n          // If we don't do this here, all inner subscriptions will not be\n          // torn down until the entire observable is done.\n          innerSub.unsubscribe();\n          innerSub = null;\n          // We may need to do this multiple times, so reset the flag.\n          syncResub = false;\n          // Resubscribe\n          subscribeForRetryWhen();\n        }\n      };\n\n      // Start the subscription\n      subscribeForRetryWhen();\n    });\n}\n"
  },
  {
    "path": "packages/rxjs/src/internal/operators/sample.ts",
    "content": "import { Observable, from, operate } from '@rxjs/observable';\nimport type { MonoTypeOperatorFunction, ObservableInput } from '../types.js';\nimport { noop } from '../util/noop.js';\n\n/**\n * Emits the most recently emitted value from the source Observable whenever\n * another Observable, the `notifier`, emits.\n *\n * <span class=\"informal\">It's like {@link sampleTime}, but samples whenever\n * the `notifier` `ObservableInput` emits something.</span>\n *\n * ![](sample.png)\n *\n * Whenever the `notifier` `ObservableInput` emits a value, `sample`\n * looks at the source Observable and emits whichever value it has most recently\n * emitted since the previous sampling, unless the source has not emitted\n * anything since the previous sampling. The `notifier` is subscribed to as soon\n * as the output Observable is subscribed.\n *\n * ## Example\n *\n * On every click, sample the most recent `seconds` timer\n *\n * ```ts\n * import { fromEvent, interval, sample } from 'rxjs';\n *\n * const seconds = interval(1000);\n * const clicks = fromEvent(document, 'click');\n * const result = seconds.pipe(sample(clicks));\n *\n * result.subscribe(x => console.log(x));\n * ```\n *\n * @see {@link audit}\n * @see {@link debounce}\n * @see {@link sampleTime}\n * @see {@link throttle}\n *\n * @param notifier The `ObservableInput` to use for sampling the\n * source Observable.\n * @return A function that returns an Observable that emits the results of\n * sampling the values emitted by the source Observable whenever the notifier\n * Observable emits value or completes.\n */\nexport function sample<T>(notifier: ObservableInput<any>): MonoTypeOperatorFunction<T> {\n  return (source) =>\n    new Observable((destination) => {\n      let hasValue = false;\n      let lastValue: T | null = null;\n      source.subscribe(\n        operate({\n          destination,\n          next: (value) => {\n            hasValue = true;\n            lastValue = value;\n          },\n        })\n      );\n      from(notifier).subscribe(\n        operate({\n          destination,\n          next: () => {\n            if (hasValue) {\n              hasValue = false;\n              const value = lastValue!;\n              lastValue = null;\n              destination.next(value);\n            }\n          },\n          complete: noop,\n        })\n      );\n    });\n}\n"
  },
  {
    "path": "packages/rxjs/src/internal/operators/sampleTime.ts",
    "content": "import { asyncScheduler } from '../scheduler/async.js';\nimport type { MonoTypeOperatorFunction, SchedulerLike } from '../types.js';\nimport { sample } from './sample.js';\nimport { interval } from '../observable/interval.js';\n\n/**\n * Emits the most recently emitted value from the source Observable within\n * periodic time intervals.\n *\n * <span class=\"informal\">Samples the source Observable at periodic time\n * intervals, emitting what it samples.</span>\n *\n * ![](sampleTime.png)\n *\n * `sampleTime` periodically looks at the source Observable and emits whichever\n * value it has most recently emitted since the previous sampling, unless the\n * source has not emitted anything since the previous sampling. The sampling\n * happens periodically in time every `period` milliseconds (or the time unit\n * defined by the optional `scheduler` argument). The sampling starts as soon as\n * the output Observable is subscribed.\n *\n * ## Example\n *\n * Every second, emit the most recent click at most once\n *\n * ```ts\n * import { fromEvent, sampleTime } from 'rxjs';\n *\n * const clicks = fromEvent(document, 'click');\n * const result = clicks.pipe(sampleTime(1000));\n *\n * result.subscribe(x => console.log(x));\n * ```\n *\n * @see {@link auditTime}\n * @see {@link debounceTime}\n * @see {@link delay}\n * @see {@link sample}\n * @see {@link throttleTime}\n *\n * @param period The sampling period expressed in milliseconds or the time unit\n * determined internally by the optional `scheduler`.\n * @param scheduler The {@link SchedulerLike} to use for managing the timers\n * that handle the sampling.\n * @return A function that returns an Observable that emits the results of\n * sampling the values emitted by the source Observable at the specified time\n * interval.\n */\nexport function sampleTime<T>(period: number, scheduler: SchedulerLike = asyncScheduler): MonoTypeOperatorFunction<T> {\n  return sample(interval(period, scheduler));\n}\n"
  },
  {
    "path": "packages/rxjs/src/internal/operators/scan.ts",
    "content": "import { Observable } from '@rxjs/observable';\nimport type { OperatorFunction } from '../types.js';\nimport { scanInternals } from './scanInternals.js';\n\nexport function scan<V, A = V>(accumulator: (acc: A | V, value: V, index: number) => A): OperatorFunction<V, V | A>;\nexport function scan<V, A>(accumulator: (acc: A, value: V, index: number) => A, seed: A): OperatorFunction<V, A>;\nexport function scan<V, A, S>(accumulator: (acc: A | S, value: V, index: number) => A, seed: S): OperatorFunction<V, A>;\n\n// TODO: link to a \"redux pattern\" section in the guide (location TBD)\n\n/**\n * Useful for encapsulating and managing state. Applies an accumulator (or \"reducer function\")\n * to each value from the source after an initial state is established -- either via\n * a `seed` value (second argument), or from the first value from the source.\n *\n * <span class=\"informal\">It's like {@link reduce}, but emits the current\n * accumulation state after each update</span>\n *\n * ![](scan.png)\n *\n * This operator maintains an internal state and emits it after processing each value as follows:\n *\n * 1. First value arrives\n *   - If a `seed` value was supplied (as the second argument to `scan`), let `state = seed` and `value = firstValue`.\n *   - If NO `seed` value was supplied (no second argument), let `state = firstValue` and go to 3.\n * 2. Let `state = accumulator(state, value)`.\n *   - If an error is thrown by `accumulator`, notify the consumer of an error. The process ends.\n * 3. Emit `state`.\n * 4. Next value arrives, let `value = nextValue`, go to 2.\n *\n * ## Examples\n *\n * An average of previous numbers. This example shows how\n * not providing a `seed` can prime the stream with the\n * first value from the source.\n *\n * ```ts\n * import { of, scan, map } from 'rxjs';\n *\n * const numbers$ = of(1, 2, 3);\n *\n * numbers$\n *   .pipe(\n *     // Get the sum of the numbers coming in.\n *     scan((total, n) => total + n),\n *     // Get the average by dividing the sum by the total number\n *     // received so far (which is 1 more than the zero-based index).\n *     map((sum, index) => sum / (index + 1))\n *   )\n *   .subscribe(console.log);\n * ```\n *\n * The Fibonacci sequence. This example shows how you can use\n * a seed to prime accumulation process. Also... you know... Fibonacci.\n * So important to like, computers and stuff that its whiteboarded\n * in job interviews. Now you can show them the Rx version! (Please don't, haha)\n *\n * ```ts\n * import { interval, scan, map, startWith } from 'rxjs';\n *\n * const firstTwoFibs = [0, 1];\n * // An endless stream of Fibonacci numbers.\n * const fibonacci$ = interval(1000).pipe(\n *   // Scan to get the fibonacci numbers (after 0, 1)\n *   scan(([a, b]) => [b, a + b], firstTwoFibs),\n *   // Get the second number in the tuple, it's the one you calculated\n *   map(([, n]) => n),\n *   // Start with our first two digits :)\n *   startWith(...firstTwoFibs)\n * );\n *\n * fibonacci$.subscribe(console.log);\n * ```\n *\n * @see {@link expand}\n * @see {@link mergeScan}\n * @see {@link reduce}\n * @see {@link switchScan}\n *\n * @param accumulator A \"reducer function\". This will be called for each value after an initial state is\n * acquired.\n * @param seed The initial state. If this is not provided, the first value from the source will\n * be used as the initial state, and emitted without going through the accumulator. All subsequent values\n * will be processed by the accumulator function. If this is provided, all values will go through\n * the accumulator function.\n * @return A function that returns an Observable of the accumulated values.\n */\nexport function scan<V, A, S>(accumulator: (acc: V | A | S, value: V, index: number) => A, seed?: S): OperatorFunction<V, V | A> {\n  // providing a seed of `undefined` *should* be valid and trigger\n  // hasSeed! so don't use `seed !== undefined` checks!\n  // For this reason, we have to check it here at the original call site\n  // otherwise inside Operator/Subscriber we won't know if `undefined`\n  // means they didn't provide anything or if they literally provided `undefined`\n  const hasSeed = arguments.length >= 2;\n  return (source) => new Observable((subscriber) => scanInternals(accumulator, seed as S, hasSeed, true, false, source, subscriber));\n}\n"
  },
  {
    "path": "packages/rxjs/src/internal/operators/scanInternals.ts",
    "content": "import type { Observable, Subscriber} from '@rxjs/observable';\nimport { operate } from '@rxjs/observable';\n\n/**\n * A basic scan operation. This is used for `scan` and `reduce`.\n * @param accumulator The accumulator to use\n * @param seed The seed value for the state to accumulate\n * @param hasSeed Whether or not a seed was provided\n * @param emitOnNext Whether or not to emit the state on next\n * @param emitBeforeComplete Whether or not to emit the before completion\n */\n\nexport function scanInternals<V, A, S>(\n  accumulator: (acc: V | A | S, value: V, index: number) => A,\n  seed: S,\n  hasSeed: boolean,\n  emitOnNext: boolean,\n  emitBeforeComplete: boolean,\n  source: Observable<V>,\n  destination: Subscriber<any>\n) {\n  // Whether or not we have state yet. This will only be\n  // false before the first value arrives if we didn't get\n  // a seed value.\n  let hasState = hasSeed;\n  // The state that we're tracking, starting with the seed,\n  // if there is one, and then updated by the return value\n  // from the accumulator on each emission.\n  let state: any = seed;\n  // An index to pass to the accumulator function.\n  let index = 0;\n\n  // Subscribe to our source. All errors and completions are passed through.\n  source.subscribe(\n    operate({\n      destination,\n      next: (value) => {\n        // Always increment the index.\n        const i = index++;\n        // Set the state\n        state = hasState\n          ? // We already have state, so we can get the new state from the accumulator\n            accumulator(state, value, i)\n          : // We didn't have state yet, a seed value was not provided, so\n\n            // we set the state to the first value, and mark that we have state now\n            ((hasState = true), value);\n\n        // Maybe send it to the consumer.\n        emitOnNext && destination.next(state);\n      },\n      // If an onComplete was given, call it, otherwise\n      // just pass through the complete notification to the consumer.\n      complete: emitBeforeComplete\n        ? () => {\n            hasState && destination.next(state);\n            destination.complete();\n          }\n        : undefined,\n    })\n  );\n}\n"
  },
  {
    "path": "packages/rxjs/src/internal/operators/sequenceEqual.ts",
    "content": "import type { OperatorFunction, ObservableInput } from '../types.js';\nimport { Observable, operate, from } from '@rxjs/observable';\n\n/**\n * Compares all values of two observables in sequence using an optional comparator function\n * and returns an observable of a single boolean value representing whether or not the two sequences\n * are equal.\n *\n * <span class=\"informal\">Checks to see of all values emitted by both observables are equal, in order.</span>\n *\n * ![](sequenceEqual.png)\n *\n * `sequenceEqual` subscribes to source observable and `compareTo` `ObservableInput` (that internally\n * gets converted to an observable) and buffers incoming values from each observable. Whenever either\n * observable emits a value, the value is buffered and the buffers are shifted and compared from the bottom\n * up; If any value pair doesn't match, the returned observable will emit `false` and complete. If one of the\n * observables completes, the operator will wait for the other observable to complete; If the other\n * observable emits before completing, the returned observable will emit `false` and complete. If one observable never\n * completes or emits after the other completes, the returned observable will never complete.\n *\n * ## Example\n *\n * Figure out if the Konami code matches\n *\n * ```ts\n * import { from, fromEvent, map, bufferCount, mergeMap, sequenceEqual } from 'rxjs';\n *\n * const codes = from([\n *   'ArrowUp',\n *   'ArrowUp',\n *   'ArrowDown',\n *   'ArrowDown',\n *   'ArrowLeft',\n *   'ArrowRight',\n *   'ArrowLeft',\n *   'ArrowRight',\n *   'KeyB',\n *   'KeyA',\n *   'Enter', // no start key, clearly.\n * ]);\n *\n * const keys = fromEvent<KeyboardEvent>(document, 'keyup').pipe(map(e => e.code));\n * const matches = keys.pipe(\n *   bufferCount(11, 1),\n *   mergeMap(last11 => from(last11).pipe(sequenceEqual(codes)))\n * );\n * matches.subscribe(matched => console.log('Successful cheat at Contra? ', matched));\n * ```\n *\n * @see {@link combineLatest}\n * @see {@link zip}\n * @see {@link withLatestFrom}\n *\n * @param compareTo The `ObservableInput` sequence to compare the source sequence to.\n * @param comparator An optional function to compare each value pair.\n *\n * @return A function that returns an Observable that emits a single boolean\n * value representing whether or not the values emitted by the source\n * Observable and provided `ObservableInput` were equal in sequence.\n */\nexport function sequenceEqual<T>(\n  compareTo: ObservableInput<T>,\n  comparator: (a: T, b: T) => boolean = (a, b) => a === b\n): OperatorFunction<T, boolean> {\n  return (source) =>\n    new Observable((destination) => {\n      // The state for the source observable\n      const aState = createState<T>();\n      // The state for the compareTo observable;\n      const bState = createState<T>();\n\n      /** A utility to emit and complete */\n      const emit = (isEqual: boolean) => {\n        destination.next(isEqual);\n        destination.complete();\n      };\n\n      /**\n       * Creates a subscriber that subscribes to one of the sources, and compares its collected\n       * state -- `selfState` -- to the other source's collected state -- `otherState`. This\n       * is used for both streams.\n       */\n      const createSubscriber = (selfState: SequenceState<T>, otherState: SequenceState<T>) => {\n        const sequenceEqualSubscriber = operate<T, boolean>({\n          destination,\n          next: (a) => {\n            const { buffer, complete } = otherState;\n            if (buffer.length === 0) {\n              // If there's no values in the other buffer\n              // and the other stream is complete, we know\n              // this isn't a match, because we got one more value.\n              // Otherwise, we push onto our buffer, so when the other\n              // stream emits, it can pull this value off our buffer and check it\n              // at the appropriate time.\n              complete ? emit(false) : selfState.buffer.push(a);\n            } else {\n              // If the other stream *does* have values in its buffer,\n              // pull the oldest one off so we can compare it to what we\n              // just got. If it wasn't a match, emit `false` and complete.\n              !comparator(a, buffer.shift()!) && emit(false);\n            }\n          },\n          complete: () => {\n            // Or observable completed\n            selfState.complete = true;\n            const { complete, buffer } = otherState;\n            // If the other observable is also complete, and there's\n            // still stuff left in their buffer, it doesn't match, if their\n            // buffer is empty, then it does match. This is because we can't\n            // possibly get more values here anymore.\n            complete && emit(buffer.length === 0);\n            // Be sure to clean up our stream as soon as possible if we can.\n            sequenceEqualSubscriber?.unsubscribe();\n          },\n        });\n\n        return sequenceEqualSubscriber;\n      };\n\n      // Subscribe to each source.\n      source.subscribe(createSubscriber(aState, bState));\n      from(compareTo).subscribe(createSubscriber(bState, aState));\n    });\n}\n\n/**\n * A simple structure for the data used to test each sequence\n */\ninterface SequenceState<T> {\n  /** A temporary store for arrived values before they are checked */\n  buffer: T[];\n  /** Whether or not the sequence source has completed. */\n  complete: boolean;\n}\n\n/**\n * Creates a simple structure that is used to represent\n * data used to test each sequence.\n */\nfunction createState<T>(): SequenceState<T> {\n  return {\n    buffer: [],\n    complete: false,\n  };\n}\n"
  },
  {
    "path": "packages/rxjs/src/internal/operators/share.ts",
    "content": "import type { Subscription } from '@rxjs/observable';\nimport { Observable, Subscriber, from } from '@rxjs/observable';\nimport { Subject } from '../Subject.js';\nimport type { MonoTypeOperatorFunction, ObservableInput, SubjectLike } from '../types.js';\n\nexport interface ShareConfig<T> {\n  /**\n   * The factory used to create the subject that will connect the source observable to\n   * multicast consumers.\n   */\n  connector?: () => SubjectLike<T>;\n  /**\n   * If `true`, the resulting observable will reset internal state on error from source and return to a \"cold\" state. This\n   * allows the resulting observable to be \"retried\" in the event of an error.\n   * If `false`, when an error comes from the source it will push the error into the connecting subject, and the subject\n   * will remain the connecting subject, meaning the resulting observable will not go \"cold\" again, and subsequent retries\n   * or resubscriptions will resubscribe to that same subject. In all cases, RxJS subjects will emit the same error again, however\n   * {@link ReplaySubject} will also push its buffered values before pushing the error.\n   * It is also possible to pass a notifier factory returning an `ObservableInput` instead which grants more fine-grained\n   * control over how and when the reset should happen. This allows behaviors like conditional or delayed resets.\n   */\n  resetOnError?: boolean | ((error: any) => ObservableInput<any>);\n  /**\n   * If `true`, the resulting observable will reset internal state on completion from source and return to a \"cold\" state. This\n   * allows the resulting observable to be \"repeated\" after it is done.\n   * If `false`, when the source completes, it will push the completion through the connecting subject, and the subject\n   * will remain the connecting subject, meaning the resulting observable will not go \"cold\" again, and subsequent repeats\n   * or resubscriptions will resubscribe to that same subject.\n   * It is also possible to pass a notifier factory returning an `ObservableInput` instead which grants more fine-grained\n   * control over how and when the reset should happen. This allows behaviors like conditional or delayed resets.\n   */\n  resetOnComplete?: boolean | (() => ObservableInput<any>);\n  /**\n   * If `true`, when the number of subscribers to the resulting observable reaches zero due to those subscribers unsubscribing, the\n   * internal state will be reset and the resulting observable will return to a \"cold\" state. This means that the next\n   * time the resulting observable is subscribed to, a new subject will be created and the source will be subscribed to\n   * again.\n   * If `false`, when the number of subscribers to the resulting observable reaches zero due to unsubscription, the subject\n   * will remain connected to the source, and new subscriptions to the result will be connected through that same subject.\n   * It is also possible to pass a notifier factory returning an `ObservableInput` instead which grants more fine-grained\n   * control over how and when the reset should happen. This allows behaviors like conditional or delayed resets.\n   */\n  resetOnRefCountZero?: boolean | (() => ObservableInput<any>);\n}\n\nexport function share<T>(): MonoTypeOperatorFunction<T>;\n\nexport function share<T>(options: ShareConfig<T>): MonoTypeOperatorFunction<T>;\n\n/**\n * Returns a new Observable that multicasts (shares) the original Observable. As long as there is at least one\n * Subscriber this Observable will be subscribed and emitting data. When all subscribers have unsubscribed it will\n * unsubscribe from the source Observable. Because the Observable is multicasting it makes the stream `hot`.\n *\n * The subscription to the underlying source Observable can be reset (unsubscribe and resubscribe for new subscribers),\n * if the subscriber count to the shared observable drops to 0, or if the source Observable errors or completes. It is\n * possible to use notifier factories for the resets to allow for behaviors like conditional or delayed resets. Please\n * note that resetting on error or complete of the source Observable does not behave like a transparent retry or restart\n * of the source because the error or complete will be forwarded to all subscribers and their subscription will be\n * closed. Only new subscribers after a reset on error or complete happened will cause a fresh subscription to the\n * source. To achieve transparent retries or restarts pipe the source through appropriate operators before sharing.\n *\n * ![](share.png)\n *\n * ## Example\n *\n * Generate new multicast Observable from the `source` Observable value\n *\n * ```ts\n * import { interval, tap, map, take, share } from 'rxjs';\n *\n * const source = interval(1000).pipe(\n *   tap(x => console.log('Processing: ', x)),\n *   map(x => x * x),\n *   take(6),\n *   share()\n * );\n *\n * source.subscribe(x => console.log('subscription 1: ', x));\n * source.subscribe(x => console.log('subscription 2: ', x));\n *\n * // Logs:\n * // Processing: 0\n * // subscription 1: 0\n * // subscription 2: 0\n * // Processing: 1\n * // subscription 1: 1\n * // subscription 2: 1\n * // Processing: 2\n * // subscription 1: 4\n * // subscription 2: 4\n * // Processing: 3\n * // subscription 1: 9\n * // subscription 2: 9\n * // Processing: 4\n * // subscription 1: 16\n * // subscription 2: 16\n * // Processing: 5\n * // subscription 1: 25\n * // subscription 2: 25\n * ```\n *\n * ## Example with notifier factory: Delayed reset\n *\n * ```ts\n * import { interval, take, share, timer } from 'rxjs';\n *\n * const source = interval(1000).pipe(\n *   take(3),\n *   share({\n *     resetOnRefCountZero: () => timer(1000)\n *   })\n * );\n *\n * const subscriptionOne = source.subscribe(x => console.log('subscription 1: ', x));\n * setTimeout(() => subscriptionOne.unsubscribe(), 1300);\n *\n * setTimeout(() => source.subscribe(x => console.log('subscription 2: ', x)), 1700);\n *\n * setTimeout(() => source.subscribe(x => console.log('subscription 3: ', x)), 5000);\n *\n * // Logs:\n * // subscription 1:  0\n * // (subscription 1 unsubscribes here)\n * // (subscription 2 subscribes here ~400ms later, source was not reset)\n * // subscription 2:  1\n * // subscription 2:  2\n * // (subscription 2 unsubscribes here)\n * // (subscription 3 subscribes here ~2000ms later, source did reset before)\n * // subscription 3:  0\n * // subscription 3:  1\n * // subscription 3:  2\n * ```\n *\n * @see {@link shareReplay}\n *\n * @return A function that returns an Observable that mirrors the source.\n */\nexport function share<T>(options: ShareConfig<T> = {}): MonoTypeOperatorFunction<T> {\n  const { connector = () => new Subject<T>(), resetOnError = true, resetOnComplete = true, resetOnRefCountZero = true } = options;\n\n  return (source) => {\n    let connection: Subscriber<T> | undefined;\n    let resetConnection: Subscription | undefined;\n    let subject: SubjectLike<T> | undefined;\n    let refCount = 0;\n    let hasCompleted = false;\n    let hasErrored = false;\n\n    const cancelReset = () => {\n      resetConnection?.unsubscribe();\n      resetConnection = undefined;\n    };\n    // Used to reset the internal state to a \"cold\"\n    // state, as though it had never been subscribed to.\n    const reset = () => {\n      cancelReset();\n      connection = subject = undefined;\n      hasCompleted = hasErrored = false;\n    };\n    const resetAndUnsubscribe = () => {\n      // We need to capture the connection before\n      // we reset (if we need to reset).\n      const conn = connection;\n      reset();\n      conn?.unsubscribe();\n    };\n\n    return new Observable((subscriber) => {\n      refCount++;\n      if (!hasErrored && !hasCompleted) {\n        cancelReset();\n      }\n\n      // Create the subject if we don't have one yet. Grab a local reference to\n      // it as well, which avoids non-null assertions when using it and, if we\n      // connect to it now, then error/complete need a reference after it was\n      // reset.\n      const dest = (subject = subject ?? connector());\n\n      // Add the finalization directly to the subscriber - instead of returning it -\n      // so that the handling of the subscriber's unsubscription will be wired\n      // up _before_ the subscription to the source occurs. This is done so that\n      // the assignment to the source connection's `closed` property will be seen\n      // by synchronous firehose sources.\n      subscriber.add(() => {\n        refCount--;\n\n        // If we're resetting on refCount === 0, and it's 0, we only want to do\n        // that on \"unsubscribe\", really. Resetting on error or completion is a different\n        // configuration.\n        if (refCount === 0 && !hasErrored && !hasCompleted) {\n          resetConnection = handleReset(resetAndUnsubscribe, resetOnRefCountZero);\n        }\n      });\n\n      // The following line adds the subscription to the subscriber passed.\n      // Basically, `subscriber === dest.subscribe(subscriber)` is `true`.\n      dest.subscribe(subscriber);\n\n      if (\n        !connection &&\n        // Check this shareReplay is still activate - it can be reset to 0\n        // and be \"unsubscribed\" _before_ it actually subscribes.\n        // If we were to subscribe then, it'd leak and get stuck.\n        refCount > 0\n      ) {\n        // We need to create a subscriber here - rather than pass an observer and\n        // assign the returned subscription to connection - because it's possible\n        // for reentrant subscriptions to the shared observable to occur and in\n        // those situations we want connection to be already-assigned so that we\n        // don't create another connection to the source.\n        connection = new Subscriber({\n          next: (value: T) => dest.next(value),\n          error: (err: any) => {\n            hasErrored = true;\n            cancelReset();\n            resetConnection = handleReset(reset, resetOnError, err);\n            dest.error(err);\n          },\n          complete: () => {\n            hasCompleted = true;\n            cancelReset();\n            resetConnection = handleReset(reset, resetOnComplete);\n            dest.complete();\n          },\n        });\n        from(source).subscribe(connection);\n      }\n    });\n  };\n}\n\nfunction handleReset<T extends unknown[] = never[]>(\n  reset: () => void,\n  on: boolean | ((...args: T) => ObservableInput<any>),\n  ...args: T\n): Subscription | undefined {\n  if (on === true) {\n    reset();\n    return;\n  }\n\n  if (on === false) {\n    return;\n  }\n\n  const onSubscriber = new Subscriber({\n    next: () => {\n      onSubscriber.unsubscribe();\n      reset();\n    },\n  });\n\n  return from(on(...args)).subscribe(onSubscriber);\n}\n"
  },
  {
    "path": "packages/rxjs/src/internal/operators/shareReplay.ts",
    "content": "import { ReplaySubject } from '../ReplaySubject.js';\nimport type { MonoTypeOperatorFunction, SchedulerLike } from '../types.js';\nimport { share } from './share.js';\n\nexport interface ShareReplayConfig {\n  bufferSize?: number;\n  windowTime?: number;\n  refCount: boolean;\n  scheduler?: SchedulerLike;\n}\n\nexport function shareReplay<T>(config: ShareReplayConfig): MonoTypeOperatorFunction<T>;\nexport function shareReplay<T>(bufferSize?: number, windowTime?: number, scheduler?: SchedulerLike): MonoTypeOperatorFunction<T>;\n\n/**\n * Share source and replay specified number of emissions on subscription.\n *\n * This operator is a specialization of `replay` that connects to a source observable\n * and multicasts through a `ReplaySubject` constructed with the specified arguments.\n * A successfully completed source will stay cached in the `shareReplay`ed observable forever,\n * but an errored source can be retried.\n *\n * ## Why use `shareReplay`?\n *\n * You generally want to use `shareReplay` when you have side-effects or taxing computations\n * that you do not wish to be executed amongst multiple subscribers.\n * It may also be valuable in situations where you know you will have late subscribers to\n * a stream that need access to previously emitted values.\n * This ability to replay values on subscription is what differentiates {@link share} and `shareReplay`.\n *\n * ## Reference counting\n *\n * By default `shareReplay` will use `refCount` of false, meaning that it will _not_ unsubscribe the\n * source when the reference counter drops to zero, i.e. the inner `ReplaySubject` will _not_ be unsubscribed\n * (and potentially run for ever).\n * This is the default as it is expected that `shareReplay` is often used to keep around expensive to setup\n * observables which we want to keep running instead of having to do the expensive setup again.\n *\n * As of RXJS version 6.4.0 a new overload signature was added to allow for manual control over what\n * happens when the operators internal reference counter drops to zero.\n * If `refCount` is true, the source will be unsubscribed from once the reference count drops to zero, i.e.\n * the inner `ReplaySubject` will be unsubscribed. All new subscribers will receive value emissions from a\n * new `ReplaySubject` which in turn will cause a new subscription to the source observable.\n *\n * ## Examples\n *\n * Example with a third subscriber coming late to the party\n *\n * ```ts\n * import { interval, take, shareReplay } from 'rxjs';\n *\n * const shared$ = interval(2000).pipe(\n *   take(6),\n *   shareReplay(3)\n * );\n *\n * shared$.subscribe(x => console.log('sub A: ', x));\n * shared$.subscribe(y => console.log('sub B: ', y));\n *\n * setTimeout(() => {\n *   shared$.subscribe(y => console.log('sub C: ', y));\n * }, 11000);\n *\n * // Logs:\n * // (after ~2000 ms)\n * // sub A: 0\n * // sub B: 0\n * // (after ~4000 ms)\n * // sub A: 1\n * // sub B: 1\n * // (after ~6000 ms)\n * // sub A: 2\n * // sub B: 2\n * // (after ~8000 ms)\n * // sub A: 3\n * // sub B: 3\n * // (after ~10000 ms)\n * // sub A: 4\n * // sub B: 4\n * // (after ~11000 ms, sub C gets the last 3 values)\n * // sub C: 2\n * // sub C: 3\n * // sub C: 4\n * // (after ~12000 ms)\n * // sub A: 5\n * // sub B: 5\n * // sub C: 5\n * ```\n *\n * Example for `refCount` usage\n *\n * ```ts\n * import { Observable, tap, interval, shareReplay, take } from 'rxjs';\n *\n * const log = <T>(name: string, source: Observable<T>) => source.pipe(\n *   tap({\n *     subscribe: () => console.log(`${ name }: subscribed`),\n *     next: value => console.log(`${ name }: ${ value }`),\n *     complete: () => console.log(`${ name }: completed`),\n *     finalize: () => console.log(`${ name }: unsubscribed`)\n *   })\n * );\n *\n * const obs$ = log('source', interval(1000));\n *\n * const shared$ = log('shared', obs$.pipe(\n *   shareReplay({ bufferSize: 1, refCount: true }),\n *   take(2)\n * ));\n *\n * shared$.subscribe(x => console.log('sub A: ', x));\n * shared$.subscribe(y => console.log('sub B: ', y));\n *\n * // PRINTS:\n * // shared: subscribed <-- reference count = 1\n * // source: subscribed\n * // shared: subscribed <-- reference count = 2\n * // source: 0\n * // shared: 0\n * // sub A: 0\n * // shared: 0\n * // sub B: 0\n * // source: 1\n * // shared: 1\n * // sub A: 1\n * // shared: completed <-- take(2) completes the subscription for sub A\n * // shared: unsubscribed <-- reference count = 1\n * // shared: 1\n * // sub B: 1\n * // shared: completed <-- take(2) completes the subscription for sub B\n * // shared: unsubscribed <-- reference count = 0\n * // source: unsubscribed <-- replaySubject unsubscribes from source observable because the reference count dropped to 0 and refCount is true\n *\n * // In case of refCount being false, the unsubscribe is never called on the source and the source would keep on emitting, even if no subscribers\n * // are listening.\n * // source: 2\n * // source: 3\n * // source: 4\n * // ...\n * ```\n *\n * @see {@link connectable}\n * @see {@link share}\n *\n * @param configOrBufferSize Maximum element count of the replay buffer or {@link ShareReplayConfig configuration}\n * object.\n * @param windowTime Maximum time length of the replay buffer in milliseconds.\n * @param scheduler Scheduler where connected observers within the selector function\n * will be invoked on.\n * @return A function that returns an Observable sequence that contains the\n * elements of a sequence produced by multicasting the source sequence within a\n * selector function.\n */\nexport function shareReplay<T>(\n  configOrBufferSize?: ShareReplayConfig | number,\n  windowTime?: number,\n  scheduler?: SchedulerLike\n): MonoTypeOperatorFunction<T> {\n  let bufferSize: number;\n  let refCount = false;\n  if (configOrBufferSize && typeof configOrBufferSize === 'object') {\n    ({ bufferSize = Infinity, windowTime = Infinity, refCount = false, scheduler } = configOrBufferSize);\n  } else {\n    bufferSize = (configOrBufferSize ?? Infinity) as number;\n  }\n  return share<T>({\n    connector: () => new ReplaySubject(bufferSize, windowTime, scheduler),\n    resetOnError: true,\n    resetOnComplete: false,\n    resetOnRefCountZero: refCount,\n  });\n}\n"
  },
  {
    "path": "packages/rxjs/src/internal/operators/single.ts",
    "content": "import { Observable, operate } from '@rxjs/observable';\nimport { EmptyError } from '../util/EmptyError.js';\n\nimport type { MonoTypeOperatorFunction, OperatorFunction, TruthyTypesOf } from '../types.js';\nimport { SequenceError } from '../util/SequenceError.js';\nimport { NotFoundError } from '../util/NotFoundError.js';\n\nexport function single<T>(predicate: BooleanConstructor): OperatorFunction<T, TruthyTypesOf<T>>;\nexport function single<T>(predicate?: (value: T, index: number, source: Observable<T>) => boolean): MonoTypeOperatorFunction<T>;\n\n/**\n * Returns an observable that asserts that only one value is\n * emitted from the observable that matches the predicate. If no\n * predicate is provided, then it will assert that the observable\n * only emits one value.\n *\n * If the source Observable did not emit `next` before completion, it\n * will emit an {@link EmptyError} to the Observer's `error` callback.\n *\n * In the event that two values are found that match the predicate,\n * or when there are two values emitted and no predicate, it will\n * emit a {@link SequenceError} to the Observer's `error` callback.\n *\n * In the event that no values match the predicate, if one is provided,\n * it will emit a {@link NotFoundError} to the Observer's `error` callback.\n *\n * ## Example\n *\n * Expect only `name` beginning with `'B'`\n *\n * ```ts\n * import { of, single } from 'rxjs';\n *\n * const source1 = of(\n *  { name: 'Ben' },\n *  { name: 'Tracy' },\n *  { name: 'Laney' },\n *  { name: 'Lily' }\n * );\n *\n * source1\n *   .pipe(single(x => x.name.startsWith('B')))\n *   .subscribe(x => console.log(x));\n * // Emits 'Ben'\n *\n *\n * const source2 = of(\n *  { name: 'Ben' },\n *  { name: 'Tracy' },\n *  { name: 'Bradley' },\n *  { name: 'Lincoln' }\n * );\n *\n * source2\n *   .pipe(single(x => x.name.startsWith('B')))\n *   .subscribe({ error: err => console.error(err) });\n * // Error emitted: SequenceError('Too many values match')\n *\n *\n * const source3 = of(\n *  { name: 'Laney' },\n *  { name: 'Tracy' },\n *  { name: 'Lily' },\n *  { name: 'Lincoln' }\n * );\n *\n * source3\n *   .pipe(single(x => x.name.startsWith('B')))\n *   .subscribe({ error: err => console.error(err) });\n * // Error emitted: NotFoundError('No values match')\n * ```\n *\n * @see {@link first}\n * @see {@link find}\n * @see {@link findIndex}\n * @see {@link elementAt}\n *\n * @throws {NotFoundError} Delivers a `NotFoundError` to the Observer's `error`\n * callback if the Observable completes before any `next` notification was sent.\n * @throws {SequenceError} Delivers a `SequenceError` if more than one value is\n * emitted that matches the provided predicate. If no predicate is provided, it\n * will deliver a `SequenceError` if more than one value comes from the source.\n * @throws {EmptyError} Delivers an `EmptyError` if no values were `next`ed prior\n * to completion.\n *\n * @param predicate A predicate function to evaluate items emitted by the source\n * Observable.\n * @return A function that returns an Observable that emits the single item\n * emitted by the source Observable that matches the predicate.\n */\nexport function single<T>(predicate?: (value: T, index: number, source: Observable<T>) => boolean): MonoTypeOperatorFunction<T> {\n  return (source) =>\n    new Observable((destination) => {\n      let hasValue = false;\n      let singleValue: T;\n      let seenValue = false;\n      let index = 0;\n      source.subscribe(\n        operate({\n          destination,\n          next: (value) => {\n            seenValue = true;\n            if (!predicate || predicate(value, index++, source)) {\n              hasValue && destination.error(new SequenceError('Too many matching values'));\n              hasValue = true;\n              singleValue = value;\n            }\n          },\n          complete: () => {\n            if (hasValue) {\n              destination.next(singleValue);\n              destination.complete();\n            } else {\n              destination.error(seenValue ? new NotFoundError('No matching values') : new EmptyError());\n            }\n          },\n        })\n      );\n    });\n}\n"
  },
  {
    "path": "packages/rxjs/src/internal/operators/skip.ts",
    "content": "import type { MonoTypeOperatorFunction } from '../types.js';\nimport { filter } from './filter.js';\n\n/**\n * Returns an Observable that skips the first `count` items emitted by the source Observable.\n *\n * ![](skip.png)\n *\n * Skips the values until the sent notifications are equal or less than provided skip count. It raises\n * an error if skip count is equal or more than the actual number of emits and source raises an error.\n *\n * ## Example\n *\n * Skip the values before the emission\n *\n * ```ts\n * import { interval, skip } from 'rxjs';\n *\n * // emit every half second\n * const source = interval(500);\n * // skip the first 10 emitted values\n * const result = source.pipe(skip(10));\n *\n * result.subscribe(value => console.log(value));\n * // output: 10...11...12...13...\n * ```\n *\n * @see {@link last}\n * @see {@link skipWhile}\n * @see {@link skipUntil}\n * @see {@link skipLast}\n *\n * @param count The number of times, items emitted by source Observable should be skipped.\n * @return A function that returns an Observable that skips the first `count`\n * values emitted by the source Observable.\n */\nexport function skip<T>(count: number): MonoTypeOperatorFunction<T> {\n  return filter((_, index) => count <= index);\n}\n"
  },
  {
    "path": "packages/rxjs/src/internal/operators/skipLast.ts",
    "content": "import type { MonoTypeOperatorFunction } from '../types.js';\nimport { identity } from '../util/identity.js';\nimport { Observable, operate } from '@rxjs/observable';\n\n/**\n * Skip a specified number of values before the completion of an observable.\n *\n * ![](skipLast.png)\n *\n * Returns an observable that will emit values as soon as it can, given a number of\n * skipped values. For example, if you `skipLast(3)` on a source, when the source\n * emits its fourth value, the first value the source emitted will finally be emitted\n * from the returned observable, as it is no longer part of what needs to be skipped.\n *\n * All values emitted by the result of `skipLast(N)` will be delayed by `N` emissions,\n * as each value is held in a buffer until enough values have been emitted that that\n * the buffered value may finally be sent to the consumer.\n *\n * After subscribing, unsubscribing will not result in the emission of the buffered\n * skipped values.\n *\n * ## Example\n *\n * Skip the last 2 values of an observable with many values\n *\n * ```ts\n * import { of, skipLast } from 'rxjs';\n *\n * const numbers = of(1, 2, 3, 4, 5);\n * const skipLastTwo = numbers.pipe(skipLast(2));\n * skipLastTwo.subscribe(x => console.log(x));\n *\n * // Results in:\n * // 1 2 3\n * // (4 and 5 are skipped)\n * ```\n *\n * @see {@link skip}\n * @see {@link skipUntil}\n * @see {@link skipWhile}\n * @see {@link take}\n *\n * @param skipCount Number of elements to skip from the end of the source Observable.\n * @return A function that returns an Observable that skips the last `count`\n * values emitted by the source Observable.\n */\nexport function skipLast<T>(skipCount: number): MonoTypeOperatorFunction<T> {\n  return skipCount <= 0\n    ? // For skipCounts less than or equal to zero, we are just mirroring the source.\n      identity\n    : (source) =>\n        new Observable((destination) => {\n          // A ring buffer to hold the values while we wait to see\n          // if we can emit it or it's part of the \"skipped\" last values.\n          // Note that it is the _same size_ as the skip count.\n          let ring: T[] = new Array(skipCount);\n          // The number of values seen so far. This is used to get\n          // the index of the current value when it arrives.\n          let seen = 0;\n          source.subscribe(\n            operate({\n              destination,\n              next: (value) => {\n                // Get the index of the value we have right now\n                // relative to all other values we've seen, then\n                // increment `seen`. This ensures we've moved to\n                // the next slot in our ring buffer.\n                const valueIndex = seen++;\n                if (valueIndex < skipCount) {\n                  // If we haven't seen enough values to fill our buffer yet,\n                  // Then we aren't to a number of seen values where we can\n                  // emit anything, so let's just start by filling the ring buffer.\n                  ring[valueIndex] = value;\n                } else {\n                  // We are traversing over the ring array in such\n                  // a way that when we get to the end, we loop back\n                  // and go to the start.\n                  const index = valueIndex % skipCount;\n                  // Pull the oldest value out so we can emit it,\n                  // and stuff the new value in it's place.\n                  const oldValue = ring[index];\n                  ring[index] = value;\n                  // Emit the old value. It is important that this happens\n                  // after we swap the value in the buffer, if it happens\n                  // before we swap the value in the buffer, then a synchronous\n                  // source can get the buffer out of whack.\n                  destination.next(oldValue);\n                }\n              },\n            })\n          );\n\n          return () => {\n            // Release our values in memory\n            ring = null!;\n          };\n        });\n}\n"
  },
  {
    "path": "packages/rxjs/src/internal/operators/skipUntil.ts",
    "content": "import type { MonoTypeOperatorFunction, ObservableInput } from '../types.js';\nimport { Observable, operate, from } from '@rxjs/observable';\nimport { noop } from '../util/noop.js';\n\n/**\n * Returns an Observable that skips items emitted by the source Observable until a second Observable emits an item.\n *\n * The `skipUntil` operator causes the observable stream to skip the emission of values until the passed in observable\n * emits the first value. This can be particularly useful in combination with user interactions, responses of HTTP\n * requests or waiting for specific times to pass by.\n *\n * ![](skipUntil.png)\n *\n * Internally, the `skipUntil` operator subscribes to the passed in `notifier` `ObservableInput` (which gets converted\n * to an Observable) in order to recognize the emission of its first value. When `notifier` emits next, the operator\n * unsubscribes from it and starts emitting the values of the *source* observable until it completes or errors. It\n * will never let the *source* observable emit any values if the `notifier` completes or throws an error without\n * emitting a value before.\n *\n * ## Example\n *\n * In the following example, all emitted values of the interval observable are skipped until the user clicks anywhere\n * within the page\n *\n * ```ts\n * import { interval, fromEvent, skipUntil } from 'rxjs';\n *\n * const intervalObservable = interval(1000);\n * const click = fromEvent(document, 'click');\n *\n * const emitAfterClick = intervalObservable.pipe(\n *   skipUntil(click)\n * );\n * // clicked at 4.6s. output: 5...6...7...8........ or\n * // clicked at 7.3s. output: 8...9...10..11.......\n * emitAfterClick.subscribe(value => console.log(value));\n * ```\n *\n * @see {@link last}\n * @see {@link skip}\n * @see {@link skipWhile}\n * @see {@link skipLast}\n *\n * @param notifier An `ObservableInput` that has to emit an item before the source Observable elements begin to\n * be mirrored by the resulting Observable.\n * @return A function that returns an Observable that skips items from the\n * source Observable until the `notifier` Observable emits an item, then emits the\n * remaining items.\n */\nexport function skipUntil<T>(notifier: ObservableInput<any>): MonoTypeOperatorFunction<T> {\n  return (source) =>\n    new Observable((destination) => {\n      let taking = false;\n\n      const skipSubscriber = operate({\n        destination,\n        next: () => {\n          skipSubscriber?.unsubscribe();\n          taking = true;\n        },\n        complete: noop,\n      });\n\n      from(notifier).subscribe(skipSubscriber);\n\n      source.subscribe(operate({ destination, next: (value) => taking && destination.next(value) }));\n    });\n}\n"
  },
  {
    "path": "packages/rxjs/src/internal/operators/skipWhile.ts",
    "content": "import type { Falsy, MonoTypeOperatorFunction, OperatorFunction } from '../types.js';\nimport { Observable, operate } from '@rxjs/observable';\n\nexport function skipWhile<T>(predicate: BooleanConstructor): OperatorFunction<T, Extract<T, Falsy> extends never ? never : T>;\nexport function skipWhile<T>(predicate: (value: T, index: number) => true): OperatorFunction<T, never>;\nexport function skipWhile<T>(predicate: (value: T, index: number) => boolean): MonoTypeOperatorFunction<T>;\n\n/**\n * Returns an Observable that skips all items emitted by the source Observable as long as a specified condition holds\n * true, but emits all further source items as soon as the condition becomes false.\n *\n * ![](skipWhile.png)\n *\n * Skips all the notifications with a truthy predicate. It will not skip the notifications when the predicate is falsy.\n * It can also be skipped using index. Once the predicate is true, it will not be called again.\n *\n * ## Example\n *\n * Skip some super heroes\n *\n * ```ts\n * import { from, skipWhile } from 'rxjs';\n *\n * const source = from(['Green Arrow', 'SuperMan', 'Flash', 'SuperGirl', 'Black Canary'])\n * // Skip the heroes until SuperGirl\n * const example = source.pipe(skipWhile(hero => hero !== 'SuperGirl'));\n * // output: SuperGirl, Black Canary\n * example.subscribe(femaleHero => console.log(femaleHero));\n * ```\n *\n * Skip values from the array until index 5\n *\n * ```ts\n * import { from, skipWhile } from 'rxjs';\n *\n * const source = from([1, 2, 3, 4, 5, 6, 7, 9, 10]);\n * const example = source.pipe(skipWhile((_, i) => i !== 5));\n * // output: 6, 7, 9, 10\n * example.subscribe(value => console.log(value));\n * ```\n *\n * @see {@link last}\n * @see {@link skip}\n * @see {@link skipUntil}\n * @see {@link skipLast}\n *\n * @param predicate A function to test each item emitted from the source Observable.\n * @return A function that returns an Observable that begins emitting items\n * emitted by the source Observable when the specified predicate becomes false.\n */\nexport function skipWhile<T>(predicate: (value: T, index: number) => boolean): MonoTypeOperatorFunction<T> {\n  return (source) =>\n    new Observable((destination) => {\n      let taking = false;\n      let index = 0;\n      source.subscribe(\n        operate({ destination, next: (value) => (taking || (taking = !predicate(value, index++))) && destination.next(value) })\n      );\n    });\n}\n"
  },
  {
    "path": "packages/rxjs/src/internal/operators/startWith.ts",
    "content": "import { Observable, subscribeToArray, operate } from '@rxjs/observable';\nimport type { OperatorFunction, ValueFromArray } from '../types.js';\n\nexport function startWith<T>(value: null): OperatorFunction<T, T | null>;\nexport function startWith<T>(value: undefined): OperatorFunction<T, T | undefined>;\nexport function startWith<T, A extends readonly unknown[] = T[]>(...values: A): OperatorFunction<T, T | ValueFromArray<A>>;\n\n/**\n * Returns an observable that, at the moment of subscription, will synchronously emit all\n * values provided to this operator, then subscribe to the source and mirror all of its emissions\n * to subscribers.\n *\n * This is a useful way to know when subscription has occurred on an existing observable.\n *\n * <span class=\"informal\">First emits its arguments in order, and then any\n * emissions from the source.</span>\n *\n * ![](startWith.png)\n *\n * ## Examples\n *\n * Emit a value when a timer starts.\n *\n * ```ts\n * import { timer, map, startWith } from 'rxjs';\n *\n * timer(1000)\n *   .pipe(\n *     map(() => 'timer emit'),\n *     startWith('timer start')\n *   )\n *   .subscribe(x => console.log(x));\n *\n * // results:\n * // 'timer start'\n * // 'timer emit'\n * ```\n *\n * @param values Items you want the modified Observable to emit first.\n * @return A function that returns an Observable that synchronously emits\n * provided values before subscribing to the source Observable.\n *\n * @see {@link endWith}\n * @see {@link finalize}\n * @see {@link concat}\n */\nexport function startWith<T, D>(...values: D[]): OperatorFunction<T, T | D> {\n  return (source) =>\n    new Observable((destination) => {\n      subscribeToArray(values, operate({ destination, complete: () => source.subscribe(destination) }));\n    });\n}\n"
  },
  {
    "path": "packages/rxjs/src/internal/operators/subscribeOn.ts",
    "content": "import type { MonoTypeOperatorFunction, SchedulerLike } from '../types.js';\nimport { Observable } from '@rxjs/observable';\n\n/**\n * Asynchronously subscribes Observers to this Observable on the specified {@link SchedulerLike}.\n *\n * With `subscribeOn` you can decide what type of scheduler a specific Observable will be using when it is subscribed to.\n *\n * Schedulers control the speed and order of emissions to observers from an Observable stream.\n *\n * ![](subscribeOn.png)\n *\n * ## Example\n *\n * Given the following code:\n *\n * ```ts\n * import { of, merge } from 'rxjs';\n *\n * const a = of(1, 2, 3);\n * const b = of(4, 5, 6);\n *\n * merge(a, b).subscribe(console.log);\n *\n * // Outputs\n * // 1\n * // 2\n * // 3\n * // 4\n * // 5\n * // 6\n * ```\n *\n * Both Observable `a` and `b` will emit their values directly and synchronously once they are subscribed to.\n *\n * If we instead use the `subscribeOn` operator declaring that we want to use the {@link asyncScheduler} for values emitted by Observable `a`:\n *\n * ```ts\n * import { of, subscribeOn, asyncScheduler, merge } from 'rxjs';\n *\n * const a = of(1, 2, 3).pipe(subscribeOn(asyncScheduler));\n * const b = of(4, 5, 6);\n *\n * merge(a, b).subscribe(console.log);\n *\n * // Outputs\n * // 4\n * // 5\n * // 6\n * // 1\n * // 2\n * // 3\n * ```\n *\n * The reason for this is that Observable `b` emits its values directly and synchronously like before\n * but the emissions from `a` are scheduled on the event loop because we are now using the {@link asyncScheduler} for that specific Observable.\n *\n * @param scheduler The {@link SchedulerLike} to perform subscription actions on.\n * @param delay A delay to pass to the scheduler to delay subscriptions\n * @return A function that returns an Observable modified so that its\n * subscriptions happen on the specified {@link SchedulerLike}.\n */\nexport function subscribeOn<T>(scheduler: SchedulerLike, delay: number = 0): MonoTypeOperatorFunction<T> {\n  return (source) =>\n    new Observable((subscriber) => {\n      subscriber.add(scheduler.schedule(() => source.subscribe(subscriber), delay));\n    });\n}\n"
  },
  {
    "path": "packages/rxjs/src/internal/operators/switchAll.ts",
    "content": "import type { OperatorFunction, ObservableInput, ObservedValueOf } from '../types.js';\nimport { switchMap } from './switchMap.js';\nimport { identity } from '../util/identity.js';\n\n/**\n * Converts a higher-order Observable into a first-order Observable\n * producing values only from the most recent observable sequence\n *\n * <span class=\"informal\">Flattens an Observable-of-Observables.</span>\n *\n * ![](switchAll.png)\n *\n * `switchAll` subscribes to a source that is an observable of observables, also known as a\n * \"higher-order observable\" (or `Observable<Observable<T>>`). It subscribes to the most recently\n * provided \"inner observable\" emitted by the source, unsubscribing from any previously subscribed\n * to inner observable, such that only the most recent inner observable may be subscribed to at\n * any point in time. The resulting observable returned by `switchAll` will only complete if the\n * source observable completes, *and* any currently subscribed to inner observable also has completed,\n * if there are any.\n *\n * ## Examples\n *\n * Spawn a new interval observable for each click event, but for every new\n * click, cancel the previous interval and subscribe to the new one\n *\n * ```ts\n * import { fromEvent, tap, map, interval, switchAll } from 'rxjs';\n *\n * const clicks = fromEvent(document, 'click').pipe(tap(() => console.log('click')));\n * const source = clicks.pipe(map(() => interval(1000)));\n *\n * source\n *   .pipe(switchAll())\n *   .subscribe(x => console.log(x));\n *\n * // Output\n * // click\n * // 0\n * // 1\n * // 2\n * // 3\n * // ...\n * // click\n * // 0\n * // 1\n * // 2\n * // ...\n * // click\n * // ...\n * ```\n *\n * @see {@link combineLatestAll}\n * @see {@link concatAll}\n * @see {@link exhaustAll}\n * @see {@link switchMap}\n * @see {@link switchMapTo}\n * @see {@link mergeAll}\n *\n * @return A function that returns an Observable that converts a higher-order\n * Observable into a first-order Observable producing values only from the most\n * recent Observable sequence.\n */\nexport function switchAll<O extends ObservableInput<any>>(): OperatorFunction<O, ObservedValueOf<O>> {\n  return switchMap(identity);\n}\n"
  },
  {
    "path": "packages/rxjs/src/internal/operators/switchMap.ts",
    "content": "import type { Subscriber} from '@rxjs/observable';\nimport { Observable, from, operate } from '@rxjs/observable';\nimport type { ObservableInput, OperatorFunction, ObservedValueOf } from '../types.js';\n\n/**\n * Projects each source value to an Observable which is merged in the output\n * Observable, emitting values only from the most recently projected Observable.\n *\n * <span class=\"informal\">Maps each value to an Observable, then flattens all of\n * these inner Observables using {@link switchAll}.</span>\n *\n * ![](switchMap.png)\n *\n * Returns an Observable that emits items based on applying a function that you\n * supply to each item emitted by the source Observable, where that function\n * returns an (so-called \"inner\") Observable. Each time it observes one of these\n * inner Observables, the output Observable begins emitting the items emitted by\n * that inner Observable. When a new inner Observable is emitted, `switchMap`\n * stops emitting items from the earlier-emitted inner Observable and begins\n * emitting items from the new one. It continues to behave like this for\n * subsequent inner Observables.\n *\n * ## Example\n *\n * Generate new Observable according to source Observable values\n *\n * ```ts\n * import { of, switchMap } from 'rxjs';\n *\n * const switched = of(1, 2, 3).pipe(switchMap(x => of(x, x ** 2, x ** 3)));\n * switched.subscribe(x => console.log(x));\n * // outputs\n * // 1\n * // 1\n * // 1\n * // 2\n * // 4\n * // 8\n * // 3\n * // 9\n * // 27\n * ```\n *\n * Restart an interval Observable on every click event\n *\n * ```ts\n * import { fromEvent, switchMap, interval } from 'rxjs';\n *\n * const clicks = fromEvent(document, 'click');\n * const result = clicks.pipe(switchMap(() => interval(1000)));\n * result.subscribe(x => console.log(x));\n * ```\n *\n * @see {@link concatMap}\n * @see {@link exhaustMap}\n * @see {@link mergeMap}\n * @see {@link switchAll}\n * @see {@link switchMapTo}\n *\n * @param project A function that, when applied to an item emitted by the source\n * Observable, returns an Observable.\n * @return A function that returns an Observable that emits the result of\n * applying the projection function to each item emitted by the source Observable\n * and taking only the values from the most recently projected inner Observable.\n */\nexport function switchMap<T, O extends ObservableInput<any>>(\n  project: (value: T, index: number) => O\n): OperatorFunction<T, ObservedValueOf<O>> {\n  return (source) =>\n    new Observable((destination) => {\n      let innerSubscriber: Subscriber<ObservedValueOf<O>> | null = null;\n      let index = 0;\n      // Whether or not the source subscription has completed\n      let isComplete = false;\n\n      // We only complete the result if the source is complete AND we don't have an active inner subscription.\n      // This is called both when the source completes and when the inners complete.\n      const checkComplete = () => isComplete && !innerSubscriber && destination.complete();\n\n      source.subscribe(\n        operate({\n          destination,\n          next: (value) => {\n            // Cancel the previous inner subscription if there was one\n            innerSubscriber?.unsubscribe();\n            const outerIndex = index++;\n            // Start the next inner subscription\n            from(project(value, outerIndex)).subscribe(\n              (innerSubscriber = operate({\n                destination,\n                complete: () => {\n                  // The inner has completed. Null out the inner subscriber to\n                  // free up memory and to signal that we have no inner subscription\n                  // currently.\n                  innerSubscriber = null!;\n                  checkComplete();\n                },\n              }))\n            );\n          },\n          complete: () => {\n            isComplete = true;\n            checkComplete();\n          },\n        })\n      );\n    });\n}\n"
  },
  {
    "path": "packages/rxjs/src/internal/operators/switchMapTo.ts",
    "content": "import { switchMap } from './switchMap.js';\nimport type { ObservableInput, OperatorFunction, ObservedValueOf } from '../types.js';\n\n/**\n * Projects each source value to the same Observable which is flattened multiple\n * times with {@link switchMap} in the output Observable.\n *\n * <span class=\"informal\">It's like {@link switchMap}, but maps each value\n * always to the same inner Observable.</span>\n *\n * ![](switchMapTo.png)\n *\n * Maps each source value to the given Observable `innerObservable` regardless\n * of the source value, and then flattens those resulting Observables into one\n * single Observable, which is the output Observable. The output Observables\n * emits values only from the most recently emitted instance of\n * `innerObservable`.\n *\n * ## Example\n *\n * Restart an interval Observable on every click event\n *\n * ```ts\n * import { fromEvent, switchMapTo, interval } from 'rxjs';\n *\n * const clicks = fromEvent(document, 'click');\n * const result = clicks.pipe(switchMapTo(interval(1000)));\n * result.subscribe(x => console.log(x));\n * ```\n *\n * @see {@link concatMapTo}\n * @see {@link switchAll}\n * @see {@link switchMap}\n * @see {@link mergeMapTo}\n *\n * @param innerObservable An `ObservableInput` to replace each value from the\n * source Observable.\n * @return A function that returns an Observable that emits items from the\n * given `innerObservable` every time a value is emitted on the source Observable,\n * and taking only the values from the most recently projected inner Observable.\n * @deprecated Will be removed in v9. Use {@link switchMap} instead: `switchMap(() => result)`\n */\nexport function switchMapTo<O extends ObservableInput<unknown>>(innerObservable: O): OperatorFunction<unknown, ObservedValueOf<O>> {\n  return switchMap(() => innerObservable);\n}\n"
  },
  {
    "path": "packages/rxjs/src/internal/operators/switchScan.ts",
    "content": "import type { ObservableInput, ObservedValueOf, OperatorFunction } from '../types.js';\nimport { switchMap } from './switchMap.js';\nimport { Observable, operate } from '@rxjs/observable';\n\n// TODO: Generate a marble diagram for these docs.\n\n/**\n * Applies an accumulator function over the source Observable where the\n * accumulator function itself returns an Observable, emitting values\n * only from the most recently returned Observable.\n *\n * <span class=\"informal\">It's like {@link mergeScan}, but only the most recent\n * Observable returned by the accumulator is merged into the outer Observable.</span>\n *\n * @see {@link scan}\n * @see {@link mergeScan}\n * @see {@link switchMap}\n *\n * @param accumulator\n * The accumulator function called on each source value.\n * @param seed The initial accumulation value.\n * @return A function that returns an observable of the accumulated values.\n */\nexport function switchScan<T, R, O extends ObservableInput<any>>(\n  accumulator: (acc: R, value: T, index: number) => O,\n  seed: R\n): OperatorFunction<T, ObservedValueOf<O>> {\n  return (source) =>\n    new Observable((destination) => {\n      // The state we will keep up to date to pass into our\n      // accumulator function at each new value from the source.\n      let state = seed;\n\n      // Use `switchMap` on our `source` to do the work of creating\n      // this operator. Note the backwards order here of `switchMap()(source)`\n      // to avoid needing to use `pipe` unnecessarily\n      switchMap(\n        // On each value from the source, call the accumulator with\n        // our previous state, the value and the index.\n        (value: T, index) => accumulator(state, value, index)\n      )(source).subscribe(\n        operate({\n          destination,\n          next: (innerValue) => {\n            // Update our state with the flattened value.\n            state = innerValue;\n            destination.next(innerValue);\n          },\n        })\n      );\n\n      return () => {\n        // Release state on finalization\n        state = null!;\n      };\n    });\n}\n"
  },
  {
    "path": "packages/rxjs/src/internal/operators/take.ts",
    "content": "import type { MonoTypeOperatorFunction } from '../types.js';\nimport { EMPTY } from '../observable/empty.js';\nimport { Observable, operate } from '@rxjs/observable';\n\n/**\n * Emits only the first `count` values emitted by the source Observable.\n *\n * <span class=\"informal\">Takes the first `count` values from the source, then\n * completes.</span>\n *\n * ![](take.png)\n *\n * `take` returns an Observable that emits only the first `count` values emitted\n * by the source Observable. If the source emits fewer than `count` values then\n * all of its values are emitted. After that, it completes, regardless if the\n * source completes.\n *\n * ## Example\n *\n * Take the first 5 seconds of an infinite 1-second interval Observable\n *\n * ```ts\n * import { interval, take } from 'rxjs';\n *\n * const intervalCount = interval(1000);\n * const takeFive = intervalCount.pipe(take(5));\n * takeFive.subscribe(x => console.log(x));\n *\n * // Logs:\n * // 0\n * // 1\n * // 2\n * // 3\n * // 4\n * ```\n *\n * @see {@link takeLast}\n * @see {@link takeUntil}\n * @see {@link takeWhile}\n * @see {@link skip}\n *\n * @param count The maximum number of `next` values to emit.\n * @return A function that returns an Observable that emits only the first\n * `count` values emitted by the source Observable, or all of the values from\n * the source if the source emits fewer than `count` values.\n */\nexport function take<T>(count: number): MonoTypeOperatorFunction<T> {\n  return count <= 0\n    ? // If we are taking no values, that's empty.\n      () => EMPTY\n    : (source) =>\n        new Observable((destination) => {\n          let seen = 0;\n          const operatorSubscriber = operate<T, T>({\n            destination,\n            next: (value) => {\n              if (++seen < count) {\n                destination.next(value);\n              } else {\n                operatorSubscriber.unsubscribe();\n                destination.next(value);\n                destination.complete();\n              }\n            },\n          });\n          source.subscribe(operatorSubscriber);\n        });\n}\n"
  },
  {
    "path": "packages/rxjs/src/internal/operators/takeLast.ts",
    "content": "import { EMPTY } from '../observable/empty.js';\nimport type { MonoTypeOperatorFunction } from '../types.js';\nimport { Observable, operate } from '@rxjs/observable';\n\n/**\n * Waits for the source to complete, then emits the last N values from the source,\n * as specified by the `count` argument.\n *\n * ![](takeLast.png)\n *\n * `takeLast` results in an observable that will hold values up to `count` values in memory,\n * until the source completes. It then pushes all values in memory to the consumer, in the\n * order they were received from the source, then notifies the consumer that it is\n * complete.\n *\n * If for some reason the source completes before the `count` supplied to `takeLast` is reached,\n * all values received until that point are emitted, and then completion is notified.\n *\n * **Warning**: Using `takeLast` with an observable that never completes will result\n * in an observable that never emits a value.\n *\n * ## Example\n *\n * Take the last 3 values of an Observable with many values\n *\n * ```ts\n * import { range, takeLast } from 'rxjs';\n *\n * const many = range(1, 100);\n * const lastThree = many.pipe(takeLast(3));\n * lastThree.subscribe(x => console.log(x));\n * ```\n *\n * @see {@link take}\n * @see {@link takeUntil}\n * @see {@link takeWhile}\n * @see {@link skip}\n *\n * @param count The maximum number of values to emit from the end of\n * the sequence of values emitted by the source Observable.\n * @return A function that returns an Observable that emits at most the last\n * `count` values emitted by the source Observable.\n */\nexport function takeLast<T>(count: number): MonoTypeOperatorFunction<T> {\n  return count <= 0\n    ? () => EMPTY\n    : (source) =>\n        new Observable((destination) => {\n          // This is a ring buffer that will hold our values\n          let ring = new Array<T>(count);\n          // This counter is how we track where we are at in the ring buffer.\n          let counter = 0;\n          source.subscribe(\n            operate({\n              destination,\n              next: (value) => {\n                ring[counter++ % count] = value;\n              },\n              complete: () => {\n                // We need to loop through our ring buffer.\n                // If we haven't filled the buffer yet, we can start at zero.\n                const start = count <= counter ? counter : 0;\n                // Only need to emit however many values we've seen,\n                // up to the expected count\n                const total = Math.min(count, counter);\n                for (let n = 0; n < total; n++) {\n                  // The tricky bit here is we're incrementing `n`, and moving\n                  // through our ring buffer, starting at the `start` index we\n                  // found above. The `% count` will \"wrap\" us around to read\n                  // the remaining values, if necessary.\n                  destination.next(ring[(start + n) % count]);\n                }\n                // All done. This will also trigger clean up.\n                destination.complete();\n              },\n              finalize: () => {\n                // During finalization release the values in our buffer.\n                ring = null!;\n              },\n            })\n          );\n        });\n}\n"
  },
  {
    "path": "packages/rxjs/src/internal/operators/takeUntil.ts",
    "content": "import type { MonoTypeOperatorFunction, ObservableInput } from '../types.js';\nimport { Observable, operate, from } from '@rxjs/observable';\nimport { noop } from '../util/noop.js';\n\n/**\n * Emits the values emitted by the source Observable until a `notifier`\n * Observable emits a value.\n *\n * <span class=\"informal\">Lets values pass until a second Observable,\n * `notifier`, emits a value. Then, it completes.</span>\n *\n * ![](takeUntil.png)\n *\n * `takeUntil` subscribes and begins mirroring the source Observable. It also\n * monitors a second Observable, `notifier` that you provide. If the `notifier`\n * emits a value, the output Observable stops mirroring the source Observable\n * and completes. If the `notifier` doesn't emit any value and completes\n * then `takeUntil` will pass all values.\n *\n * ## Example\n *\n * Tick every second until the first click happens\n *\n * ```ts\n * import { interval, fromEvent, takeUntil } from 'rxjs';\n *\n * const source = interval(1000);\n * const clicks = fromEvent(document, 'click');\n * const result = source.pipe(takeUntil(clicks));\n * result.subscribe(x => console.log(x));\n * ```\n *\n * @see {@link take}\n * @see {@link takeLast}\n * @see {@link takeWhile}\n * @see {@link skip}\n *\n * @param notifier The `ObservableInput` whose first emitted value will cause the output\n * Observable of `takeUntil` to stop emitting values from the source Observable.\n * @return A function that returns an Observable that emits the values from the\n * source Observable until `notifier` emits its first value.\n */\nexport function takeUntil<T>(notifier: ObservableInput<any>): MonoTypeOperatorFunction<T> {\n  return (source) =>\n    new Observable((destination) => {\n      from(notifier).subscribe(operate({ destination, next: () => destination.complete(), complete: noop }));\n      !destination.closed && source.subscribe(destination);\n    });\n}\n"
  },
  {
    "path": "packages/rxjs/src/internal/operators/takeWhile.ts",
    "content": "import type { OperatorFunction, MonoTypeOperatorFunction, TruthyTypesOf } from '../types.js';\nimport { Observable, operate } from '@rxjs/observable';\n\nexport function takeWhile<T>(predicate: BooleanConstructor, inclusive: true): MonoTypeOperatorFunction<T>;\nexport function takeWhile<T>(predicate: BooleanConstructor, inclusive: false): OperatorFunction<T, TruthyTypesOf<T>>;\nexport function takeWhile<T>(predicate: BooleanConstructor): OperatorFunction<T, TruthyTypesOf<T>>;\nexport function takeWhile<T, S extends T>(predicate: (value: T, index: number) => value is S): OperatorFunction<T, S>;\nexport function takeWhile<T, S extends T>(predicate: (value: T, index: number) => value is S, inclusive: false): OperatorFunction<T, S>;\nexport function takeWhile<T>(predicate: (value: T, index: number) => boolean, inclusive?: boolean): MonoTypeOperatorFunction<T>;\n\n/**\n * Emits values emitted by the source Observable so long as each value satisfies\n * the given `predicate`, and then completes as soon as this `predicate` is not\n * satisfied.\n *\n * <span class=\"informal\">Takes values from the source only while they pass the\n * condition given. When the first value does not satisfy, it completes.</span>\n *\n * ![](takeWhile.png)\n *\n * `takeWhile` subscribes and begins mirroring the source Observable. Each value\n * emitted on the source is given to the `predicate` function which returns a\n * boolean, representing a condition to be satisfied by the source values. The\n * output Observable emits the source values until such time as the `predicate`\n * returns false, at which point `takeWhile` stops mirroring the source\n * Observable and completes the output Observable.\n *\n * ## Example\n *\n * Emit click events only while the clientX property is greater than 200\n *\n * ```ts\n * import { fromEvent, takeWhile } from 'rxjs';\n *\n * const clicks = fromEvent<PointerEvent>(document, 'click');\n * const result = clicks.pipe(takeWhile(ev => ev.clientX > 200));\n * result.subscribe(x => console.log(x));\n * ```\n *\n * @see {@link take}\n * @see {@link takeLast}\n * @see {@link takeUntil}\n * @see {@link skip}\n *\n * @param predicate A function that evaluates a value emitted by the source\n * Observable and returns a boolean. Also takes the (zero-based) index as the\n * second argument.\n * @param inclusive When set to `true` the value that caused `predicate` to\n * return `false` will also be emitted.\n * @return A function that returns an Observable that emits values from the\n * source Observable so long as each value satisfies the condition defined by\n * the `predicate`, then completes.\n */\nexport function takeWhile<T>(predicate: (value: T, index: number) => boolean, inclusive = false): MonoTypeOperatorFunction<T> {\n  return (source) =>\n    new Observable((destination) => {\n      let index = 0;\n      const operatorSubscriber = operate({\n        destination,\n        next: (value: T) => {\n          if (predicate(value, index++)) {\n            destination.next(value);\n          } else {\n            operatorSubscriber.unsubscribe();\n            if (inclusive) {\n              destination.next(value);\n            }\n            destination.complete();\n          }\n        },\n      });\n\n      source.subscribe(operatorSubscriber);\n    });\n}\n"
  },
  {
    "path": "packages/rxjs/src/internal/operators/tap.ts",
    "content": "import type { MonoTypeOperatorFunction, Observer } from '../types.js';\nimport { Observable, operate, isFunction } from '@rxjs/observable';\nimport { identity } from '../util/identity.js';\n\n/**\n * An extension to the {@link Observer} interface used only by the {@link tap} operator.\n *\n * It provides a useful set of callbacks a user can register to do side-effects in\n * cases other than what the usual {@link Observer} callbacks are\n * ({@link guide/glossary-and-semantics#next next},\n * {@link guide/glossary-and-semantics#error error} and/or\n * {@link guide/glossary-and-semantics#complete complete}).\n *\n * ## Example\n *\n * ```ts\n * import { fromEvent, switchMap, tap, interval, take } from 'rxjs';\n *\n * const source$ = fromEvent(document, 'click');\n * const result$ = source$.pipe(\n *   switchMap((_, i) => i % 2 === 0\n *     ? fromEvent(document, 'mousemove').pipe(\n *         tap({\n *           subscribe: () => console.log('Subscribed to the mouse move events after click #' + i),\n *           unsubscribe: () => console.log('Mouse move events #' + i + ' unsubscribed'),\n *           finalize: () => console.log('Mouse move events #' + i + ' finalized')\n *         })\n *       )\n *     : interval(1_000).pipe(\n *         take(5),\n *         tap({\n *           subscribe: () => console.log('Subscribed to the 1-second interval events after click #' + i),\n *           unsubscribe: () => console.log('1-second interval events #' + i + ' unsubscribed'),\n *           finalize: () => console.log('1-second interval events #' + i + ' finalized')\n *         })\n *       )\n *   )\n * );\n *\n * const subscription = result$.subscribe({\n *   next: console.log\n * });\n *\n * setTimeout(() => {\n *   console.log('Unsubscribe after 60 seconds');\n *   subscription.unsubscribe();\n * }, 60_000);\n * ```\n */\nexport interface TapObserver<T> extends Observer<T> {\n  /**\n   * The callback that `tap` operator invokes at the moment when the source Observable\n   * gets subscribed to.\n   */\n  subscribe: () => void;\n  /**\n   * The callback that `tap` operator invokes when an explicit\n   * {@link guide/glossary-and-semantics#unsubscription unsubscribe} happens. It won't get invoked on\n   * `error` or `complete` events.\n   */\n  unsubscribe: () => void;\n  /**\n   * The callback that `tap` operator invokes when any kind of\n   * {@link guide/glossary-and-semantics#finalization finalization} happens - either when\n   * the source Observable `error`s or `complete`s or when it gets explicitly unsubscribed\n   * by the user. There is no difference in using this callback or the {@link finalize}\n   * operator, but if you're already using `tap` operator, you can use this callback\n   * instead. You'd get the same result in either case.\n   */\n  finalize: () => void;\n}\n\n/**\n * Used to perform side-effects for notifications from the source observable\n *\n * <span class=\"informal\">Used when you want to affect outside state with a notification without altering the notification</span>\n *\n * ![](tap.png)\n *\n * Tap is designed to allow the developer a designated place to perform side effects. While you _could_ perform side-effects\n * inside of a `map` or a `mergeMap`, that would make their mapping functions impure, which isn't always a big deal, but will\n * make it so you can't do things like memoize those functions. The `tap` operator is designed solely for such side-effects to\n * help you remove side-effects from other operations.\n *\n * For any notification, next, error, or complete, `tap` will call the appropriate callback you have provided to it, via a function\n * reference, or a partial observer, then pass that notification down the stream.\n *\n * The observable returned by `tap` is an exact mirror of the source, with one exception: Any error that occurs -- synchronously -- in a handler\n * provided to `tap` will be emitted as an error from the returned observable.\n *\n * > Be careful! You can mutate objects as they pass through the `tap` operator's handlers.\n *\n * The most common use of `tap` is actually for debugging. You can place a `tap(console.log)` anywhere\n * in your observable `pipe`, log out the notifications as they are emitted by the source returned by the previous\n * operation.\n *\n * ## Examples\n *\n * Check a random number before it is handled. Below is an observable that will use a random number between 0 and 1,\n * and emit `'big'` or `'small'` depending on the size of that number. But we wanted to log what the original number\n * was, so we have added a `tap(console.log)`.\n *\n * ```ts\n * import { of, tap, map } from 'rxjs';\n *\n * of(Math.random()).pipe(\n *   tap(console.log),\n *   map(n => n > 0.5 ? 'big' : 'small')\n * ).subscribe(console.log);\n * ```\n *\n * Using `tap` to analyze a value and force an error. Below is an observable where in our system we only\n * want to emit numbers 3 or less we get from another source. We can force our observable to error\n * using `tap`.\n *\n * ```ts\n * import { of, tap } from 'rxjs';\n *\n * const source = of(1, 2, 3, 4, 5);\n *\n * source.pipe(\n *   tap(n => {\n *     if (n > 3) {\n *       throw new TypeError(`Value ${ n } is greater than 3`);\n *     }\n *   })\n * )\n * .subscribe({ next: console.log, error: err => console.log(err.message) });\n * ```\n *\n * We want to know when an observable completes before moving on to the next observable. The system\n * below will emit a random series of `'X'` characters from 3 different observables in sequence. The\n * only way we know when one observable completes and moves to the next one, in this case, is because\n * we have added a `tap` with the side effect of logging to console.\n *\n * ```ts\n * import { of, concatMap, interval, take, map, tap } from 'rxjs';\n *\n * of(1, 2, 3).pipe(\n *   concatMap(n => interval(1000).pipe(\n *     take(Math.round(Math.random() * 10)),\n *     map(() => 'X'),\n *     tap({ complete: () => console.log(`Done with ${ n }`) })\n *   ))\n * )\n * .subscribe(console.log);\n * ```\n *\n * @see {@link finalize}\n * @see {@link TapObserver}\n *\n * @param observerOrNext A next handler or partial observer\n * @return A function that returns an Observable identical to the source, but\n * runs the specified Observer or callback(s) for each item.\n */\nexport function tap<T>(observerOrNext?: Partial<TapObserver<T>> | ((value: T) => void) | null): MonoTypeOperatorFunction<T> {\n  // Just need to see if it's a function or a partial observer.\n  const tapObserver: Partial<TapObserver<T>> | null | undefined = isFunction(observerOrNext) ? { next: observerOrNext } : observerOrNext;\n\n  return tapObserver\n    ? (source) =>\n        new Observable((destination) => {\n          tapObserver.subscribe?.();\n          let isUnsub = true;\n          source.subscribe(\n            operate({\n              destination,\n              next: (value) => {\n                tapObserver.next?.(value);\n                destination.next(value);\n              },\n              error: (err) => {\n                isUnsub = false;\n                tapObserver.error?.(err);\n                destination.error(err);\n              },\n              complete: () => {\n                isUnsub = false;\n                tapObserver.complete?.();\n                destination.complete();\n              },\n              finalize: () => {\n                if (isUnsub) {\n                  tapObserver.unsubscribe?.();\n                }\n                tapObserver.finalize?.();\n              },\n            })\n          );\n        })\n    : // Tap was called with no valid tap observer or handler\n      // (e.g. `tap(null)` or `tap()`)\n      // so we're going to just mirror the source.\n      identity;\n}\n"
  },
  {
    "path": "packages/rxjs/src/internal/operators/throttle.ts",
    "content": "import type { Subscription } from '@rxjs/observable';\nimport { Observable, operate, from } from '@rxjs/observable';\nimport type { MonoTypeOperatorFunction, ObservableInput } from '../types.js';\n\n/**\n * An object interface used by {@link throttle} or {@link throttleTime} that ensure\n * configuration options of these operators.\n *\n * @see {@link throttle}\n * @see {@link throttleTime}\n */\nexport interface ThrottleConfig {\n  /**\n   * If `true`, the resulting Observable will emit the first value from the source\n   * Observable at the **start** of the \"throttling\" process (when starting an\n   * internal timer that prevents other emissions from the source to pass through).\n   * If `false`, it will not emit the first value from the source Observable at the\n   * start of the \"throttling\" process.\n   *\n   * If not provided, defaults to: `true`.\n   */\n  leading?: boolean;\n  /**\n   * If `true`, the resulting Observable will emit the last value from the source\n   * Observable at the **end** of the \"throttling\" process (when ending an internal\n   * timer that prevents other emissions from the source to pass through).\n   * If `false`, it will not emit the last value from the source Observable at the\n   * end of the \"throttling\" process.\n   *\n   * If not provided, defaults to: `false`.\n   */\n  trailing?: boolean;\n}\n\n/**\n * Emits a value from the source Observable, then ignores subsequent source\n * values for a duration determined by another Observable, then repeats this\n * process.\n *\n * <span class=\"informal\">It's like {@link throttleTime}, but the silencing\n * duration is determined by a second Observable.</span>\n *\n * ![](throttle.svg)\n *\n * `throttle` emits the source Observable values on the output Observable\n * when its internal timer is disabled, and ignores source values when the timer\n * is enabled. Initially, the timer is disabled. As soon as the first source\n * value arrives, it is forwarded to the output Observable, and then the timer\n * is enabled by calling the `durationSelector` function with the source value,\n * which returns the \"duration\" Observable. When the duration Observable emits a\n * value, the timer is disabled, and this process repeats for the\n * next source value.\n *\n * ## Example\n *\n * Emit clicks at a rate of at most one click per second\n *\n * ```ts\n * import { fromEvent, throttle, interval } from 'rxjs';\n *\n * const clicks = fromEvent(document, 'click');\n * const result = clicks.pipe(throttle(() => interval(1000)));\n *\n * result.subscribe(x => console.log(x));\n * ```\n *\n * @see {@link audit}\n * @see {@link debounce}\n * @see {@link delayWhen}\n * @see {@link sample}\n * @see {@link throttleTime}\n *\n * @param durationSelector A function that receives a value from the source\n * Observable, for computing the silencing duration for each source value,\n * returned as an `ObservableInput`.\n * @param config A configuration object to define `leading` and `trailing`\n * behavior. Defaults to `{ leading: true, trailing: false }`.\n * @return A function that returns an Observable that performs the throttle\n * operation to limit the rate of emissions from the source.\n */\nexport function throttle<T>(durationSelector: (value: T) => ObservableInput<any>, config?: ThrottleConfig): MonoTypeOperatorFunction<T> {\n  return (source) =>\n    new Observable((destination) => {\n      const { leading = true, trailing = false } = config ?? {};\n      let hasValue = false;\n      let sendValue: T | null = null;\n      let throttled: Subscription | null = null;\n      let isComplete = false;\n\n      const endThrottling = () => {\n        throttled?.unsubscribe();\n        throttled = null;\n        if (trailing) {\n          send();\n          isComplete && destination.complete();\n        }\n      };\n\n      const cleanupThrottling = () => {\n        throttled = null;\n        isComplete && destination.complete();\n      };\n\n      const startThrottle = (value: T) =>\n        (throttled = from(durationSelector(value)).subscribe(operate({ destination, next: endThrottling, complete: cleanupThrottling })));\n\n      const send = () => {\n        if (hasValue) {\n          // Ensure we clear out our value and hasValue flag\n          // before we emit, otherwise reentrant code can cause\n          // issues here.\n          hasValue = false;\n          const value = sendValue!;\n          sendValue = null;\n          // Emit the value.\n          destination.next(value);\n          !isComplete && startThrottle(value);\n        }\n      };\n\n      source.subscribe(\n        operate({\n          destination,\n          // Regarding the presence of throttled.closed in the following\n          // conditions, if a synchronous duration selector is specified - weird,\n          // but legal - an already-closed subscription will be assigned to\n          // throttled, so the subscription's closed property needs to be checked,\n          // too.\n          next: (value) => {\n            hasValue = true;\n            sendValue = value;\n            !(throttled && !throttled.closed) && (leading ? send() : startThrottle(value));\n          },\n          complete: () => {\n            isComplete = true;\n            !(trailing && hasValue && throttled && !throttled.closed) && destination.complete();\n          },\n        })\n      );\n    });\n}\n"
  },
  {
    "path": "packages/rxjs/src/internal/operators/throttleTime.ts",
    "content": "import { asyncScheduler } from '../scheduler/async.js';\nimport type { ThrottleConfig } from './throttle.js';\nimport { throttle } from './throttle.js';\nimport type { MonoTypeOperatorFunction, SchedulerLike } from '../types.js';\nimport { timer } from '../observable/timer.js';\n\n/**\n * Emits a value from the source Observable, then ignores subsequent source\n * values for `duration` milliseconds, then repeats this process.\n *\n * <span class=\"informal\">Lets a value pass, then ignores source values for the\n * next `duration` milliseconds.</span>\n *\n * ![](throttleTime.png)\n *\n * `throttleTime` emits the source Observable values on the output Observable\n * when its internal timer is disabled, and ignores source values when the timer\n * is enabled. Initially, the timer is disabled. As soon as the first source\n * value arrives, it is forwarded to the output Observable, and then the timer\n * is enabled. After `duration` milliseconds (or the time unit determined\n * internally by the optional `scheduler`) has passed, the timer is disabled,\n * and this process repeats for the next source value. Optionally takes a\n * {@link SchedulerLike} for managing timers.\n *\n * ## Examples\n *\n * ### Limit click rate\n *\n * Emit clicks at a rate of at most one click per second\n *\n * ```ts\n * import { fromEvent, throttleTime } from 'rxjs';\n *\n * const clicks = fromEvent(document, 'click');\n * const result = clicks.pipe(throttleTime(1000));\n *\n * result.subscribe(x => console.log(x));\n * ```\n *\n * @see {@link auditTime}\n * @see {@link debounceTime}\n * @see {@link delay}\n * @see {@link sampleTime}\n * @see {@link throttle}\n *\n * @param duration Time to wait before emitting another value after\n * emitting the last value, measured in milliseconds or the time unit determined\n * internally by the optional `scheduler`.\n * @param scheduler The {@link SchedulerLike} to use for\n * managing the timers that handle the throttling. Defaults to {@link asyncScheduler}.\n * @param config A configuration object to define `leading` and\n * `trailing` behavior. Defaults to `{ leading: true, trailing: false }`.\n * @return A function that returns an Observable that performs the throttle\n * operation to limit the rate of emissions from the source.\n */\nexport function throttleTime<T>(\n  duration: number,\n  scheduler: SchedulerLike = asyncScheduler,\n  config?: ThrottleConfig\n): MonoTypeOperatorFunction<T> {\n  const duration$ = timer(duration, scheduler);\n  return throttle(() => duration$, config);\n}\n"
  },
  {
    "path": "packages/rxjs/src/internal/operators/throwIfEmpty.ts",
    "content": "import { EmptyError } from '../util/EmptyError.js';\nimport type { MonoTypeOperatorFunction } from '../types.js';\nimport { Observable, operate } from '@rxjs/observable';\n\n/**\n * If the source observable completes without emitting a value, it will emit\n * an error. The error will be created at that time by the optional\n * `errorFactory` argument, otherwise, the error will be {@link EmptyError}.\n *\n * ![](throwIfEmpty.png)\n *\n * ## Example\n *\n * Throw an error if the document wasn't clicked within 1 second\n *\n * ```ts\n * import { fromEvent, takeUntil, timer, throwIfEmpty } from 'rxjs';\n *\n * const click$ = fromEvent(document, 'click');\n *\n * click$.pipe(\n *   takeUntil(timer(1000)),\n *   throwIfEmpty(() => new Error('The document was not clicked within 1 second'))\n * )\n * .subscribe({\n *   next() {\n *    console.log('The document was clicked');\n *   },\n *   error(err) {\n *     console.error(err.message);\n *   }\n * });\n * ```\n *\n * @param errorFactory A factory function called to produce the\n * error to be thrown when the source observable completes without emitting a\n * value.\n * @return A function that returns an Observable that throws an error if the\n * source Observable completed without emitting.\n */\nexport function throwIfEmpty<T>(errorFactory: () => any = defaultErrorFactory): MonoTypeOperatorFunction<T> {\n  return (source) =>\n    new Observable((destination) => {\n      let hasValue = false;\n      source.subscribe(\n        operate({\n          destination,\n          next: (value) => {\n            hasValue = true;\n            destination.next(value);\n          },\n          complete: () => (hasValue ? destination.complete() : destination.error(errorFactory())),\n        })\n      );\n    });\n}\n\nfunction defaultErrorFactory() {\n  return new EmptyError();\n}\n"
  },
  {
    "path": "packages/rxjs/src/internal/operators/timeInterval.ts",
    "content": "import { asyncScheduler } from '../scheduler/async.js';\nimport type { SchedulerLike, OperatorFunction } from '../types.js';\nimport { Observable, operate } from '@rxjs/observable';\n\n/**\n * Emits an object containing the current value, and the time that has\n * passed between emitting the current value and the previous value, which is\n * calculated by using the provided `scheduler`'s `now()` method to retrieve\n * the current time at each emission, then calculating the difference. The `scheduler`\n * defaults to {@link asyncScheduler}, so by default, the `interval` will be in\n * milliseconds.\n *\n * <span class=\"informal\">Convert an Observable that emits items into one that\n * emits indications of the amount of time elapsed between those emissions.</span>\n *\n * ![](timeInterval.png)\n *\n * ## Example\n *\n * Emit interval between current value with the last value\n *\n * ```ts\n * import { interval, timeInterval } from 'rxjs';\n *\n * const seconds = interval(1000);\n *\n * seconds\n *   .pipe(timeInterval())\n *   .subscribe(value => console.log(value));\n *\n * // NOTE: The values will never be this precise,\n * // intervals created with `interval` or `setInterval`\n * // are non-deterministic.\n *\n * // { value: 0, interval: 1000 }\n * // { value: 1, interval: 1000 }\n * // { value: 2, interval: 1000 }\n * ```\n *\n * @param scheduler Scheduler used to get the current time.\n * @return A function that returns an Observable that emits information about\n * value and interval.\n */\nexport function timeInterval<T>(scheduler: SchedulerLike = asyncScheduler): OperatorFunction<T, TimeInterval<T>> {\n  return (source) =>\n    new Observable((destination) => {\n      let last = scheduler.now();\n      source.subscribe(\n        operate({\n          destination,\n          next: (value) => {\n            const now = scheduler.now();\n            const interval = now - last;\n            last = now;\n            destination.next(new TimeInterval(value, interval));\n          },\n        })\n      );\n    });\n}\n\n// TODO(benlesh): make this an interface, export the interface, but not the implemented class,\n// there's no reason users should be manually creating this type.\n\nexport class TimeInterval<T> {\n  /**\n   * @deprecated Internal implementation detail, do not construct directly. Will be made an interface in v8.\n   */\n  constructor(public value: T, public interval: number) {}\n}\n"
  },
  {
    "path": "packages/rxjs/src/internal/operators/timeout.ts",
    "content": "import { asyncScheduler } from '../scheduler/async.js';\nimport type { MonoTypeOperatorFunction, SchedulerLike, OperatorFunction, ObservableInput, ObservedValueOf } from '../types.js';\nimport { isValidDate } from '../util/isDate.js';\nimport type { Subscription} from '@rxjs/observable';\nimport { Observable, from, operate } from '@rxjs/observable';\nimport { executeSchedule } from '../util/executeSchedule.js';\n\nexport interface TimeoutConfig<T, O extends ObservableInput<unknown> = ObservableInput<T>, M = unknown> {\n  /**\n   * The time allowed between values from the source before timeout is triggered.\n   */\n  each?: number;\n\n  /**\n   * The relative time as a `number` in milliseconds, or a specific time as a `Date` object,\n   * by which the first value must arrive from the source before timeout is triggered.\n   */\n  first?: number | Date;\n\n  /**\n   * The scheduler to use with time-related operations within this operator. Defaults to {@link asyncScheduler}\n   */\n  scheduler?: SchedulerLike;\n\n  /**\n   * A factory used to create observable to switch to when timeout occurs. Provides\n   * a {@link TimeoutInfo} about the source observable's emissions and what delay or\n   * exact time triggered the timeout.\n   */\n  with?: (info: TimeoutInfo<T, M>) => O;\n\n  /**\n   * Optional additional metadata you can provide to code that handles\n   * the timeout, will be provided through the {@link TimeoutError}.\n   * This can be used to help identify the source of a timeout or pass along\n   * other information related to the timeout.\n   */\n  meta?: M;\n}\n\nexport interface TimeoutInfo<T, M = unknown> {\n  /** Optional metadata that was provided to the timeout configuration. */\n  readonly meta: M;\n  /** The number of messages seen before the timeout */\n  readonly seen: number;\n  /** The last message seen */\n  readonly lastValue: T | null;\n}\n\n/**\n * An error thrown by the {@link timeout} operator.\n *\n * Provided so users can use as a type and do quality comparisons.\n * We recommend you do not subclass this or create instances of this class directly.\n * If you have need of a error representing a timeout, you should\n * create your own error class and use that.\n *\n * @see {@link timeout}\n */\nexport class TimeoutError<T, M> extends Error {\n  /**\n   * @param info The information provided to the error by the timeout\n   * operation that created the error. Will be `null` if\n   * used directly in non-RxJS code with an empty constructor.\n   * (Note that using this constructor directly is not recommended,\n   * you should create your own errors)\n   *  @deprecated Internal implementation detail. Do not construct error instances.\n   * Cannot be tagged as internal: https://github.com/ReactiveX/rxjs/issues/6269\n   */\n  constructor(public info: TimeoutInfo<T, M> | null = null) {\n    super('Timeout has occurred');\n    this.name = 'TimeoutError';\n  }\n}\n\n/**\n * If `with` is provided, this will return an observable that will switch to a different observable if the source\n * does not push values within the specified time parameters.\n *\n * <span class=\"informal\">The most flexible option for creating a timeout behavior.</span>\n *\n * The first thing to know about the configuration is if you do not provide a `with` property to the configuration,\n * when timeout conditions are met, this operator will emit a {@link TimeoutError}. Otherwise, it will use the factory\n * function provided by `with`, and switch your subscription to the result of that. Timeout conditions are provided by\n * the settings in `first` and `each`.\n *\n * The `first` property can be either a `Date` for a specific time, a `number` for a time period relative to the\n * point of subscription, or it can be skipped. This property is to check timeout conditions for the arrival of\n * the first value from the source _only_. The timings of all subsequent values  from the source will be checked\n * against the time period provided by `each`, if it was provided.\n *\n * The `each` property can be either a `number` or skipped. If a value for `each` is provided, it represents the amount of\n * time the resulting observable will wait between the arrival of values from the source before timing out. Note that if\n * `first` is _not_ provided, the value from `each` will be used to check timeout conditions for the arrival of the first\n * value and all subsequent values. If `first` _is_ provided, `each` will only be use to check all values after the first.\n *\n * ## Examples\n *\n * Emit a custom error if there is too much time between values\n *\n * ```ts\n * import { interval, timeout, throwError } from 'rxjs';\n *\n * class CustomTimeoutError extends Error {\n *   constructor() {\n *     super('It was too slow');\n *     this.name = 'CustomTimeoutError';\n *   }\n * }\n *\n * const slow$ = interval(900);\n *\n * slow$.pipe(\n *   timeout({\n *     each: 1000,\n *     with: () => throwError(() => new CustomTimeoutError())\n *   })\n * )\n * .subscribe({\n *   error: console.error\n * });\n * ```\n *\n * Switch to a faster observable if your source is slow.\n *\n * ```ts\n * import { interval, timeout } from 'rxjs';\n *\n * const slow$ = interval(900);\n * const fast$ = interval(500);\n *\n * slow$.pipe(\n *   timeout({\n *     each: 1000,\n *     with: () => fast$,\n *   })\n * )\n * .subscribe(console.log);\n * ```\n * @param config The configuration for the timeout.\n */\nexport function timeout<T, O extends ObservableInput<unknown>, M = unknown>(\n  config: TimeoutConfig<T, O, M> & { with: (info: TimeoutInfo<T, M>) => O }\n): OperatorFunction<T, T | ObservedValueOf<O>>;\n\n/**\n * Returns an observable that will error or switch to a different observable if the source does not push values\n * within the specified time parameters.\n *\n * <span class=\"informal\">The most flexible option for creating a timeout behavior.</span>\n *\n * The first thing to know about the configuration is if you do not provide a `with` property to the configuration,\n * when timeout conditions are met, this operator will emit a {@link TimeoutError}. Otherwise, it will use the factory\n * function provided by `with`, and switch your subscription to the result of that. Timeout conditions are provided by\n * the settings in `first` and `each`.\n *\n * The `first` property can be either a `Date` for a specific time, a `number` for a time period relative to the\n * point of subscription, or it can be skipped. This property is to check timeout conditions for the arrival of\n * the first value from the source _only_. The timings of all subsequent values  from the source will be checked\n * against the time period provided by `each`, if it was provided.\n *\n * The `each` property can be either a `number` or skipped. If a value for `each` is provided, it represents the amount of\n * time the resulting observable will wait between the arrival of values from the source before timing out. Note that if\n * `first` is _not_ provided, the value from `each` will be used to check timeout conditions for the arrival of the first\n * value and all subsequent values. If `first` _is_ provided, `each` will only be use to check all values after the first.\n *\n * ### Handling TimeoutErrors\n *\n * If no `with` property was provided, subscriptions to the resulting observable may emit an error of {@link TimeoutError}.\n * The timeout error provides useful information you can examine when you're handling the error. The most common way to handle\n * the error would be with {@link catchError}, although you could use {@link tap} or just the error handler in your `subscribe` call\n * directly, if your error handling is only a side effect (such as notifying the user, or logging).\n *\n * In this case, you would check the error for `instanceof TimeoutError` to validate that the error was indeed from `timeout`, and\n * not from some other source. If it's not from `timeout`, you should probably rethrow it if you're in a `catchError`.\n *\n * ## Examples\n *\n * Emit a {@link TimeoutError} if the first value, and _only_ the first value, does not arrive within 5 seconds\n *\n * ```ts\n * import { interval, timeout } from 'rxjs';\n *\n * // A random interval that lasts between 0 and 10 seconds per tick\n * const source$ = interval(Math.round(Math.random() * 10_000));\n *\n * source$.pipe(\n *   timeout({ first: 5_000 })\n * )\n * .subscribe({\n *   next: console.log,\n *   error: console.error\n * });\n * ```\n *\n * Emit a {@link TimeoutError} if the source waits longer than 5 seconds between any two values or the first value\n * and subscription.\n *\n * ```ts\n * import { timer, timeout, expand } from 'rxjs';\n *\n * const getRandomTime = () => Math.round(Math.random() * 10_000);\n *\n * // An observable that waits a random amount of time between each delivered value\n * const source$ = timer(getRandomTime())\n *   .pipe(expand(() => timer(getRandomTime())));\n *\n * source$\n *   .pipe(timeout({ each: 5_000 }))\n *   .subscribe({\n *     next: console.log,\n *     error: console.error\n *   });\n * ```\n *\n * Emit a {@link TimeoutError} if the source does not emit before 7 seconds, _or_ if the source waits longer than\n * 5 seconds between any two values after the first.\n *\n * ```ts\n * import { timer, timeout, expand } from 'rxjs';\n *\n * const getRandomTime = () => Math.round(Math.random() * 10_000);\n *\n * // An observable that waits a random amount of time between each delivered value\n * const source$ = timer(getRandomTime())\n *   .pipe(expand(() => timer(getRandomTime())));\n *\n * source$\n *   .pipe(timeout({ first: 7_000, each: 5_000 }))\n *   .subscribe({\n *     next: console.log,\n *     error: console.error\n *   });\n * ```\n */\nexport function timeout<T, M = unknown>(config: Omit<TimeoutConfig<T, any, M>, 'with'>): OperatorFunction<T, T>;\n\n/**\n * Returns an observable that will error if the source does not push its first value before the specified time passed as a `Date`.\n * This is functionally the same as `timeout({ first: someDate })`.\n *\n * <span class=\"informal\">Errors if the first value doesn't show up before the given date and time</span>\n *\n * ![](timeout.png)\n *\n * @param first The date to at which the resulting observable will timeout if the source observable\n * does not emit at least one value.\n * @param scheduler The scheduler to use. Defaults to {@link asyncScheduler}.\n */\nexport function timeout<T>(first: Date, scheduler?: SchedulerLike): MonoTypeOperatorFunction<T>;\n\n/**\n * Returns an observable that will error if the source does not push a value within the specified time in milliseconds.\n * This is functionally the same as `timeout({ each: milliseconds })`.\n *\n * <span class=\"informal\">Errors if it waits too long between any value</span>\n *\n * ![](timeout.png)\n *\n * @param each The time allowed between each pushed value from the source before the resulting observable\n * will timeout.\n * @param scheduler The scheduler to use. Defaults to {@link asyncScheduler}.\n */\nexport function timeout<T>(each: number, scheduler?: SchedulerLike): MonoTypeOperatorFunction<T>;\n\n/**\n *\n * Errors if Observable does not emit a value in given time span.\n *\n * <span class=\"informal\">Timeouts on Observable that doesn't emit values fast enough.</span>\n *\n * ![](timeout.png)\n *\n * @see {@link timeoutWith}\n *\n * @return A function that returns an Observable that mirrors behaviour of the\n * source Observable, unless timeout happens when it throws an error.\n */\nexport function timeout<T, O extends ObservableInput<any>, M>(\n  config: number | Date | TimeoutConfig<T, O, M>,\n  schedulerArg?: SchedulerLike\n): OperatorFunction<T, T | ObservedValueOf<O>> {\n  // Intentionally terse code.\n  // If the first argument is a valid `Date`, then we use it as the `first` config.\n  // Otherwise, if the first argument is a `number`, then we use it as the `each` config.\n  // Otherwise, it can be assumed the first argument is the configuration object itself, and\n  // we destructure that into what we're going to use, setting important defaults as we do.\n  // NOTE: The default for `scheduler` will be the `scheduler` argument if it exists, or\n  // it will default to the `asyncScheduler`.\n  const {\n    first,\n    each,\n    with: _with = timeoutErrorFactory,\n    scheduler = schedulerArg ?? asyncScheduler,\n    meta = null!,\n  } = (isValidDate(config) ? { first: config } : typeof config === 'number' ? { each: config } : config) as TimeoutConfig<T, O, M>;\n\n  if (first == null && each == null) {\n    // Ensure timeout was provided at runtime.\n    throw new TypeError('No timeout provided.');\n  }\n\n  return (source) =>\n    new Observable((destination) => {\n      // This subscription encapsulates our subscription to the\n      // source for this operator. We're capturing it separately,\n      // because if there is a `with` observable to fail over to,\n      // we want to unsubscribe from our original subscription, and\n      // hand of the subscription to that one.\n      // eslint-disable-next-line prefer-const\n      let originalSourceSubscription: Subscription;\n      // The subscription for our timeout timer. This changes\n      // every time we get a new value.\n      let timerSubscription: Subscription | void;\n      // A bit of state we pass to our with and error factories to\n      // tell what the last value we saw was.\n      let lastValue: T | null = null;\n      // A bit of state we pass to the with and error factories to\n      // tell how many values we have seen so far.\n      let seen = 0;\n      const startTimer = (delay: number) => {\n        timerSubscription = executeSchedule(\n          destination,\n          scheduler,\n          () => {\n            try {\n              originalSourceSubscription.unsubscribe();\n              from(\n                _with!({\n                  meta,\n                  lastValue,\n                  seen,\n                })\n              ).subscribe(destination);\n            } catch (err) {\n              destination.error(err);\n            }\n          },\n          delay\n        );\n      };\n\n      originalSourceSubscription = source.subscribe(\n        operate({\n          destination,\n          next: (value: T) => {\n            // clear the timer so we can emit and start another one.\n            timerSubscription?.unsubscribe();\n            seen++;\n            // Emit\n            destination.next((lastValue = value));\n            // null | undefined are both < 0. Thanks, JavaScript.\n            each! > 0 && startTimer(each!);\n          },\n          finalize: () => {\n            timerSubscription?.unsubscribe();\n            // Be sure not to hold the last value in memory after unsubscription\n            // it could be quite large.\n            lastValue = null;\n          },\n        })\n      );\n\n      // Intentionally terse code.\n      // If we've `seen` a value, that means the \"first\" clause was met already, if it existed.\n      //   it also means that a timer was already started for \"each\" (in the next handler above).\n      // If `first` was provided, and it's a number, then use it.\n      // If `first` was provided and it's not a number, it's a Date, and we get the difference between it and \"now\".\n      // If `first` was not provided at all, then our first timer will be the value from `each`.\n      !seen && startTimer(first != null ? (typeof first === 'number' ? first : +first - scheduler!.now()) : each!);\n    });\n}\n\n/**\n * The default function to use to emit an error when timeout occurs and a `with` function\n * is not specified.\n * @param info The information about the timeout to pass along to the error\n */\nfunction timeoutErrorFactory(info: TimeoutInfo<any>): Observable<never> {\n  throw new TimeoutError(info);\n}\n"
  },
  {
    "path": "packages/rxjs/src/internal/operators/timeoutWith.ts",
    "content": "import { asyncScheduler } from '../scheduler/async.js';\nimport { isValidDate } from '../util/isDate.js';\nimport type { ObservableInput, OperatorFunction, SchedulerLike } from '../types.js';\nimport { timeout } from './timeout.js';\n\n/** @deprecated Replaced with {@link timeout}. Instead of `timeoutWith(someDate, a$, scheduler)`, use the configuration object\n * `timeout({ first: someDate, with: () => a$, scheduler })`. Will be removed in v8. */\nexport function timeoutWith<T, R>(dueBy: Date, switchTo: ObservableInput<R>, scheduler?: SchedulerLike): OperatorFunction<T, T | R>;\n/** @deprecated Replaced with {@link timeout}. Instead of `timeoutWith(100, a$, scheduler)`, use the configuration object\n *  `timeout({ each: 100, with: () => a$, scheduler })`. Will be removed in v8. */\nexport function timeoutWith<T, R>(waitFor: number, switchTo: ObservableInput<R>, scheduler?: SchedulerLike): OperatorFunction<T, T | R>;\n\n/**\n * When the passed timespan elapses before the source emits any given value, it will unsubscribe from the source,\n * and switch the subscription to another observable.\n *\n * <span class=\"informal\">Used to switch to a different observable if your source is being slow.</span>\n *\n * Useful in cases where:\n *\n * - You want to switch to a different source that may be faster.\n * - You want to notify a user that the data stream is slow.\n * - You want to emit a custom error rather than the {@link TimeoutError} emitted\n *   by the default usage of {@link timeout}.\n *\n * If the first parameter is passed as Date and the time of the Date arrives before the first value arrives from the source,\n * it will unsubscribe from the source and switch the subscription to another observable.\n *\n * <span class=\"informal\">Use Date object to switch to a different observable if the first value doesn't arrive by a specific time.</span>\n *\n * Can be used to set a timeout only for the first value, however it's recommended to use the {@link timeout} operator with\n * the `first` configuration to get the same effect.\n *\n * ## Examples\n *\n * Fallback to a faster observable\n *\n * ```ts\n * import { interval, timeoutWith } from 'rxjs';\n *\n * const slow$ = interval(1000);\n * const faster$ = interval(500);\n *\n * slow$\n *   .pipe(timeoutWith(900, faster$))\n *   .subscribe(console.log);\n * ```\n *\n * Emit your own custom timeout error\n *\n * ```ts\n * import { interval, timeoutWith, throwError } from 'rxjs';\n *\n * class CustomTimeoutError extends Error {\n *   constructor() {\n *     super('It was too slow');\n *     this.name = 'CustomTimeoutError';\n *   }\n * }\n *\n * const slow$ = interval(1000);\n *\n * slow$\n *   .pipe(timeoutWith(900, throwError(() => new CustomTimeoutError())))\n *   .subscribe({\n *     error: err => console.error(err.message)\n *   });\n * ```\n *\n * @see {@link timeout}\n *\n * @param due When passed a number, used as the time (in milliseconds) allowed between each value from the source before timeout\n * is triggered. When passed a Date, used as the exact time at which the timeout will be triggered if the first value does not arrive.\n * @param withObservable The observable to switch to when timeout occurs.\n * @param scheduler The scheduler to use with time-related operations within this operator. Defaults to {@link asyncScheduler}\n * @return A function that returns an Observable that mirrors behaviour of the\n * source Observable, unless timeout happens when it starts emitting values\n * from the `ObservableInput` passed as a second parameter.\n * @deprecated Replaced with {@link timeout}. Instead of `timeoutWith(100, a$, scheduler)`, use {@link timeout} with the configuration\n * object: `timeout({ each: 100, with: () => a$, scheduler })`. Instead of `timeoutWith(someDate, a$, scheduler)`, use {@link timeout}\n * with the configuration object: `timeout({ first: someDate, with: () => a$, scheduler })`. Will be removed in v8.\n */\nexport function timeoutWith<T, R>(\n  due: number | Date,\n  withObservable: ObservableInput<R>,\n  scheduler?: SchedulerLike\n): OperatorFunction<T, T | R> {\n  let first: number | Date | undefined;\n  let each: number | undefined;\n  let _with: () => ObservableInput<R>;\n  scheduler = scheduler ?? asyncScheduler;\n\n  if (isValidDate(due)) {\n    first = due;\n  } else if (typeof due === 'number') {\n    each = due;\n  }\n\n  if (withObservable) {\n    _with = () => withObservable;\n  } else {\n    throw new TypeError('No observable provided to switch to');\n  }\n\n  if (first == null && each == null) {\n    // Ensure timeout was provided at runtime.\n    throw new TypeError('No timeout provided.');\n  }\n\n  return timeout<T, ObservableInput<R>>({\n    first,\n    each,\n    scheduler,\n    with: _with,\n  });\n}\n"
  },
  {
    "path": "packages/rxjs/src/internal/operators/timestamp.ts",
    "content": "import type { OperatorFunction, TimestampProvider, Timestamp } from '../types.js';\nimport { dateTimestampProvider } from '../scheduler/dateTimestampProvider.js';\nimport { map } from './map.js';\n\n/**\n * Attaches a timestamp to each item emitted by an observable indicating when it was emitted\n *\n * The `timestamp` operator maps the *source* observable stream to an object of type\n * `{value: T, timestamp: R}`. The properties are generically typed. The `value` property contains the value\n * and type of the *source* observable. The `timestamp` is generated by the schedulers `now` function. By\n * default, it uses the `asyncScheduler` which simply returns `Date.now()` (milliseconds since 1970/01/01\n * 00:00:00:000) and therefore is of type `number`.\n *\n * ![](timestamp.png)\n *\n * ## Example\n *\n * In this example there is a timestamp attached to the document's click events\n *\n * ```ts\n * import { fromEvent, timestamp } from 'rxjs';\n *\n * const clickWithTimestamp = fromEvent(document, 'click').pipe(\n *   timestamp()\n * );\n *\n * // Emits data of type { value: PointerEvent, timestamp: number }\n * clickWithTimestamp.subscribe(data => {\n *   console.log(data);\n * });\n * ```\n *\n * @param timestampProvider An object with a `now()` method used to get the current timestamp.\n * @return A function that returns an Observable that attaches a timestamp to\n * each item emitted by the source Observable indicating when it was emitted.\n */\nexport function timestamp<T>(timestampProvider: TimestampProvider = dateTimestampProvider): OperatorFunction<T, Timestamp<T>> {\n  return map((value: T) => ({ value, timestamp: timestampProvider.now() }));\n}\n"
  },
  {
    "path": "packages/rxjs/src/internal/operators/toArray.ts",
    "content": "import { reduce } from './reduce.js';\nimport type { OperatorFunction } from '../types.js';\nimport { Observable } from '@rxjs/observable';\n\nconst arrReducer = (arr: any[], value: any) => (arr.push(value), arr);\n\n/**\n * Collects all source emissions and emits them as an array when the source completes.\n *\n * <span class=\"informal\">Get all values inside an array when the source completes</span>\n *\n * ![](toArray.png)\n *\n * `toArray` will wait until the source Observable completes before emitting\n * the array containing all emissions. When the source Observable errors no\n * array will be emitted.\n *\n * ## Example\n *\n * ```ts\n * import { interval, take, toArray } from 'rxjs';\n *\n * const source = interval(1000);\n * const example = source.pipe(\n *   take(10),\n *   toArray()\n * );\n *\n * example.subscribe(value => console.log(value));\n *\n * // output: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]\n * ```\n *\n * @return A function that returns an Observable that emits an array of items\n * emitted by the source Observable when source completes.\n */\nexport function toArray<T>(): OperatorFunction<T, T[]> {\n  // Because arrays are mutable, and we're mutating the array in this\n  // reducer process, we have to encapsulate the creation of the initial\n  // array within the returned operator function.\n  return (source) =>\n    new Observable((subscriber) => {\n      reduce(arrReducer, [] as T[])(source).subscribe(subscriber);\n    });\n}\n"
  },
  {
    "path": "packages/rxjs/src/internal/operators/window.ts",
    "content": "import { Observable, from, operate } from '@rxjs/observable';\nimport type { OperatorFunction, ObservableInput } from '../types.js';\nimport { Subject } from '../Subject.js';\nimport { noop } from '../util/noop.js';\n\n/**\n * Branch out the source Observable values as a nested Observable whenever\n * `windowBoundaries` emits.\n *\n * <span class=\"informal\">It's like {@link buffer}, but emits a nested Observable\n * instead of an array.</span>\n *\n * ![](window.png)\n *\n * Returns an Observable that emits windows of items it collects from the source\n * Observable. The output Observable emits connected, non-overlapping\n * windows. It emits the current window and opens a new one whenever the\n * `windowBoundaries` emits an item. `windowBoundaries` can be any type that\n * `ObservableInput` accepts. It internally gets converted to an Observable.\n * Because each window is an Observable, the output is a higher-order Observable.\n *\n * ## Example\n *\n * In every window of 1 second each, emit at most 2 click events\n *\n * ```ts\n * import { fromEvent, interval, window, map, take, mergeAll } from 'rxjs';\n *\n * const clicks = fromEvent(document, 'click');\n * const sec = interval(1000);\n * const result = clicks.pipe(\n *   window(sec),\n *   map(win => win.pipe(take(2))), // take at most 2 emissions from each window\n *   mergeAll()                     // flatten the Observable-of-Observables\n * );\n * result.subscribe(x => console.log(x));\n * ```\n *\n * @see {@link windowCount}\n * @see {@link windowTime}\n * @see {@link windowToggle}\n * @see {@link windowWhen}\n * @see {@link buffer}\n *\n * @param windowBoundaries An `ObservableInput` that completes the\n * previous window and starts a new window.\n * @return A function that returns an Observable of windows, which are\n * Observables emitting values of the source Observable.\n */\nexport function window<T>(windowBoundaries: ObservableInput<any>): OperatorFunction<T, Observable<T>> {\n  return (source) =>\n    new Observable((destination) => {\n      let windowSubject: Subject<T> = new Subject<T>();\n\n      destination.next(windowSubject.asObservable());\n\n      const errorHandler = (err: any) => {\n        windowSubject.error(err);\n        destination.error(err);\n      };\n\n      // Subscribe to our source\n      source.subscribe(\n        operate({\n          destination,\n          next: (value) => windowSubject?.next(value),\n          complete: () => {\n            windowSubject.complete();\n            destination.complete();\n          },\n          error: errorHandler,\n        })\n      );\n\n      // Subscribe to the window boundaries.\n      from(windowBoundaries).subscribe(\n        operate({\n          destination,\n          next: () => {\n            windowSubject.complete();\n            destination.next((windowSubject = new Subject()));\n          },\n          complete: noop,\n          error: errorHandler,\n        })\n      );\n\n      return () => {\n        // Unsubscribing the subject ensures that anyone who has captured\n        // a reference to this window that tries to use it after it can\n        // no longer get values from the source will get an ObjectUnsubscribedError.\n        windowSubject?.unsubscribe();\n        windowSubject = null!;\n      };\n    });\n}\n"
  },
  {
    "path": "packages/rxjs/src/internal/operators/windowCount.ts",
    "content": "import { Observable, operate } from '@rxjs/observable';\nimport { Subject } from '../Subject.js';\nimport type { OperatorFunction } from '../types.js';\n\n/**\n * Branch out the source Observable values as a nested Observable with each\n * nested Observable emitting at most `windowSize` values.\n *\n * <span class=\"informal\">It's like {@link bufferCount}, but emits a nested\n * Observable instead of an array.</span>\n *\n * ![](windowCount.png)\n *\n * Returns an Observable that emits windows of items it collects from the source\n * Observable. The output Observable emits windows every `startWindowEvery`\n * items, each containing no more than `windowSize` items. When the source\n * Observable completes or encounters an error, the output Observable emits\n * the current window and propagates the notification from the source\n * Observable. If `startWindowEvery` is not provided, then new windows are\n * started immediately at the start of the source and when each window completes\n * with size `windowSize`.\n *\n * ## Examples\n *\n * Ignore every 3rd click event, starting from the first one\n *\n * ```ts\n * import { fromEvent, windowCount, map, skip, mergeAll } from 'rxjs';\n *\n * const clicks = fromEvent(document, 'click');\n * const result = clicks.pipe(\n *   windowCount(3),\n *   map(win => win.pipe(skip(1))), // skip first of every 3 clicks\n *   mergeAll()                     // flatten the Observable-of-Observables\n * );\n * result.subscribe(x => console.log(x));\n * ```\n *\n * Ignore every 3rd click event, starting from the third one\n *\n * ```ts\n * import { fromEvent, windowCount, mergeAll } from 'rxjs';\n *\n * const clicks = fromEvent(document, 'click');\n * const result = clicks.pipe(\n *   windowCount(2, 3),\n *   mergeAll() // flatten the Observable-of-Observables\n * );\n * result.subscribe(x => console.log(x));\n * ```\n *\n * @see {@link window}\n * @see {@link windowTime}\n * @see {@link windowToggle}\n * @see {@link windowWhen}\n * @see {@link bufferCount}\n *\n * @param windowSize The maximum number of values emitted by each window.\n * @param startWindowEvery Interval at which to start a new window. For example\n * if `startWindowEvery` is `2`, then a new window will be started on every\n * other value from the source. A new window is started at the beginning of the\n * source by default.\n * @return A function that returns an Observable of windows, which in turn are\n * Observable of values.\n */\nexport function windowCount<T>(windowSize: number, startWindowEvery: number = 0): OperatorFunction<T, Observable<T>> {\n  const startEvery = startWindowEvery > 0 ? startWindowEvery : windowSize;\n\n  return (source) =>\n    new Observable((destination) => {\n      let windows = [new Subject<T>()];\n      let starts: number[] = [];\n      let count = 0;\n\n      // Open the first window.\n      destination.next(windows[0].asObservable());\n\n      source.subscribe(\n        operate({\n          destination,\n          next: (value: T) => {\n            // Emit the value through all current windows.\n            // We don't need to create a new window yet, we\n            // do that as soon as we close one.\n            for (const window of windows) {\n              window.next(value);\n            }\n            // Here we're using the size of the window array to figure\n            // out if the oldest window has emitted enough values. We can do this\n            // because the size of the window array is a function of the values\n            // seen by the subscription. If it's time to close it, we complete\n            // it and remove it.\n            const c = count - windowSize + 1;\n            if (c >= 0 && c % startEvery === 0) {\n              windows.shift()!.complete();\n            }\n\n            // Look to see if the next count tells us it's time to open a new window.\n            // TODO: We need to figure out if this really makes sense. We're technically\n            // emitting windows *before* we have a value to emit them for. It's probably\n            // more expected that we should be emitting the window when the start\n            // count is reached -- not before.\n            if (++count % startEvery === 0) {\n              const window = new Subject<T>();\n              windows.push(window);\n              destination.next(window.asObservable());\n            }\n          },\n          error: (err) => {\n            while (windows.length > 0) {\n              windows.shift()!.error(err);\n            }\n            destination.error(err);\n          },\n          complete: () => {\n            while (windows.length > 0) {\n              windows.shift()!.complete();\n            }\n            destination.complete();\n          },\n          finalize: () => {\n            starts = null!;\n            windows = null!;\n          },\n        })\n      );\n    });\n}\n"
  },
  {
    "path": "packages/rxjs/src/internal/operators/windowTime.ts",
    "content": "import { Subject } from '../Subject.js';\nimport { asyncScheduler } from '../scheduler/async.js';\nimport { Observable, operate, Subscription } from '@rxjs/observable';\nimport type { Observer, OperatorFunction, SchedulerLike } from '../types.js';\nimport { arrRemove } from '../util/arrRemove.js';\nimport { popScheduler } from '../util/args.js';\nimport { executeSchedule } from '../util/executeSchedule.js';\n\nexport function windowTime<T>(windowTimeSpan: number, scheduler?: SchedulerLike): OperatorFunction<T, Observable<T>>;\nexport function windowTime<T>(\n  windowTimeSpan: number,\n  windowCreationInterval: number,\n  scheduler?: SchedulerLike\n): OperatorFunction<T, Observable<T>>;\nexport function windowTime<T>(\n  windowTimeSpan: number,\n  windowCreationInterval: number | null | void,\n  maxWindowSize: number,\n  scheduler?: SchedulerLike\n): OperatorFunction<T, Observable<T>>;\n\n/**\n * Branch out the source Observable values as a nested Observable periodically\n * in time.\n *\n * <span class=\"informal\">It's like {@link bufferTime}, but emits a nested\n * Observable instead of an array.</span>\n *\n * ![](windowTime.png)\n *\n * Returns an Observable that emits windows of items it collects from the source\n * Observable. The output Observable starts a new window periodically, as\n * determined by the `windowCreationInterval` argument. It emits each window\n * after a fixed timespan, specified by the `windowTimeSpan` argument. When the\n * source Observable completes or encounters an error, the output Observable\n * emits the current window and propagates the notification from the source\n * Observable. If `windowCreationInterval` is not provided, the output\n * Observable starts a new window when the previous window of duration\n * `windowTimeSpan` completes. If `maxWindowCount` is provided, each window\n * will emit at most fixed number of values. Window will complete immediately\n * after emitting last value and next one still will open as specified by\n * `windowTimeSpan` and `windowCreationInterval` arguments.\n *\n * ## Examples\n *\n * In every window of 1 second each, emit at most 2 click events\n *\n * ```ts\n * import { fromEvent, windowTime, map, take, mergeAll } from 'rxjs';\n *\n * const clicks = fromEvent(document, 'click');\n * const result = clicks.pipe(\n *   windowTime(1000),\n *   map(win => win.pipe(take(2))), // take at most 2 emissions from each window\n *   mergeAll()                     // flatten the Observable-of-Observables\n * );\n * result.subscribe(x => console.log(x));\n * ```\n *\n * Every 5 seconds start a window 1 second long, and emit at most 2 click events per window\n *\n * ```ts\n * import { fromEvent, windowTime, map, take, mergeAll } from 'rxjs';\n *\n * const clicks = fromEvent(document, 'click');\n * const result = clicks.pipe(\n *   windowTime(1000, 5000),\n *   map(win => win.pipe(take(2))), // take at most 2 emissions from each window\n *   mergeAll()                     // flatten the Observable-of-Observables\n * );\n * result.subscribe(x => console.log(x));\n * ```\n *\n * Same as example above but with `maxWindowCount` instead of `take`\n *\n * ```ts\n * import { fromEvent, windowTime, mergeAll } from 'rxjs';\n *\n * const clicks = fromEvent(document, 'click');\n * const result = clicks.pipe(\n *   windowTime(1000, 5000, 2), // take at most 2 emissions from each window\n *   mergeAll()                 // flatten the Observable-of-Observables\n * );\n * result.subscribe(x => console.log(x));\n * ```\n *\n * @see {@link window}\n * @see {@link windowCount}\n * @see {@link windowToggle}\n * @see {@link windowWhen}\n * @see {@link bufferTime}\n *\n * @param windowTimeSpan The amount of time, in milliseconds, to fill each window.\n * @param windowCreationInterval The interval at which to start new\n * windows.\n * @param maxWindowSize Max number of\n * values each window can emit before completion.\n * @param scheduler The scheduler on which to schedule the\n * intervals that determine window boundaries.\n * @return A function that returns an Observable of windows, which in turn are\n * Observables.\n */\nexport function windowTime<T>(windowTimeSpan: number, ...otherArgs: any[]): OperatorFunction<T, Observable<T>> {\n  const scheduler = popScheduler(otherArgs) ?? asyncScheduler;\n  const windowCreationInterval = (otherArgs[0] as number) ?? null;\n  const maxWindowSize = (otherArgs[1] as number) || Infinity;\n\n  return (source) =>\n    new Observable((destination) => {\n      // The active windows, their related subscriptions, and removal functions.\n      let windowRecords: WindowRecord<T>[] | null = [];\n      // If true, it means that every time we close a window, we want to start a new window.\n      // This is only really used for when *just* the time span is passed.\n      let restartOnClose = false;\n\n      const closeWindow = (record: { window: Subject<T>; subs: Subscription }) => {\n        const { window, subs } = record;\n        window.complete();\n        subs.unsubscribe();\n        arrRemove(windowRecords, record);\n        restartOnClose && startWindow();\n      };\n\n      /**\n       * Called every time we start a new window. This also does\n       * the work of scheduling the job to close the window.\n       */\n      const startWindow = () => {\n        if (windowRecords) {\n          const subs = new Subscription();\n          destination.add(subs);\n          const window = new Subject<T>();\n          const record = {\n            window,\n            subs,\n            seen: 0,\n          };\n          windowRecords.push(record);\n          destination.next(window.asObservable());\n          executeSchedule(subs, scheduler, () => closeWindow(record), windowTimeSpan);\n        }\n      };\n\n      if (windowCreationInterval !== null && windowCreationInterval >= 0) {\n        // The user passed both a windowTimeSpan (required), and a creation interval\n        // That means we need to start new window on the interval, and those windows need\n        // to wait the required time span before completing.\n        executeSchedule(destination, scheduler, startWindow, windowCreationInterval, true);\n      } else {\n        restartOnClose = true;\n      }\n\n      startWindow();\n\n      /**\n       * We need to loop over a copy of the window records several times in this operator.\n       * This is to save bytes over the wire more than anything.\n       * The reason we copy the array is that reentrant code could mutate the array while\n       * we are iterating over it.\n       */\n      const loop = (cb: (record: WindowRecord<T>) => void) => windowRecords!.slice().forEach(cb);\n\n      /**\n       * Used to notify all of the windows and the subscriber in the same way\n       * in the error and complete handlers.\n       */\n      const terminate = (cb: (consumer: Observer<any>) => void) => {\n        loop(({ window }) => cb(window));\n        cb(destination);\n        destination.unsubscribe();\n      };\n\n      source.subscribe(\n        operate({\n          destination,\n          next: (value: T) => {\n            // Notify all windows of the value.\n            loop((record) => {\n              record.window.next(value);\n              // If the window is over the max size, we need to close it.\n              maxWindowSize <= ++record.seen && closeWindow(record);\n            });\n          },\n          // Notify the windows and the downstream subscriber of the error and clean up.\n          error: (err) => terminate((consumer) => consumer.error(err)),\n          // Complete the windows and the downstream subscriber and clean up.\n          complete: () => terminate((consumer) => consumer.complete()),\n        })\n      );\n\n      // Additional finalization. This will be called when the\n      // destination tears down. Other finalizations are registered implicitly\n      // above via subscription.\n      return () => {\n        // Ensure that the buffer is released.\n        windowRecords = null!;\n      };\n    });\n}\n\ninterface WindowRecord<T> {\n  seen: number;\n  window: Subject<T>;\n  subs: Subscription;\n}\n"
  },
  {
    "path": "packages/rxjs/src/internal/operators/windowToggle.ts",
    "content": "import { Observable, Subscription, from, operate } from '@rxjs/observable';\nimport { Subject } from '../Subject.js';\nimport type { ObservableInput, OperatorFunction } from '../types.js';\nimport { noop } from '../util/noop.js';\nimport { arrRemove } from '../util/arrRemove.js';\n\n/**\n * Branch out the source Observable values as a nested Observable starting from\n * an emission from `openings` and ending when the output of `closingSelector`\n * emits.\n *\n * <span class=\"informal\">It's like {@link bufferToggle}, but emits a nested\n * Observable instead of an array.</span>\n *\n * ![](windowToggle.png)\n *\n * Returns an Observable that emits windows of items it collects from the source\n * Observable. The output Observable emits windows that contain those items\n * emitted by the source Observable between the time when the `openings`\n * Observable emits an item and when the Observable returned by\n * `closingSelector` emits an item.\n *\n * ## Example\n *\n * Every other second, emit the click events from the next 500ms\n *\n * ```ts\n * import { fromEvent, interval, windowToggle, EMPTY, mergeAll } from 'rxjs';\n *\n * const clicks = fromEvent(document, 'click');\n * const openings = interval(1000);\n * const result = clicks.pipe(\n *   windowToggle(openings, i => i % 2 ? interval(500) : EMPTY),\n *   mergeAll()\n * );\n * result.subscribe(x => console.log(x));\n * ```\n *\n * @see {@link window}\n * @see {@link windowCount}\n * @see {@link windowTime}\n * @see {@link windowWhen}\n * @see {@link bufferToggle}\n *\n * @param openings An observable of notifications to start new windows.\n * @param closingSelector A function that takes the value emitted by the\n * `openings` observable and returns an Observable, which, when it emits a next\n * notification, signals that the associated window should complete.\n * @return A function that returns an Observable of windows, which in turn are\n * Observables.\n */\nexport function windowToggle<T, O>(\n  openings: ObservableInput<O>,\n  closingSelector: (openValue: O) => ObservableInput<any>\n): OperatorFunction<T, Observable<T>> {\n  return (source) =>\n    new Observable((destination) => {\n      const windows: Subject<T>[] = [];\n\n      const handleError = (err: any) => {\n        while (0 < windows.length) {\n          windows.shift()!.error(err);\n        }\n        destination.error(err);\n      };\n\n      from(openings).subscribe(\n        operate({\n          destination,\n          next: (openValue) => {\n            const window = new Subject<T>();\n            windows.push(window);\n            const closingSubscription = new Subscription();\n            const closeWindow = () => {\n              arrRemove(windows, window);\n              window.complete();\n              closingSubscription.unsubscribe();\n            };\n\n            let closingNotifier: Observable<any>;\n            try {\n              closingNotifier = from(closingSelector(openValue));\n            } catch (err) {\n              handleError(err);\n              return;\n            }\n\n            // TODO: We should probably make this `.asObservable()`, but we've historically\n            // had windows throw an `ObjectUnsubscribedError` if you try to subscribe to them\n            // late. We should probably change that: (https://github.com/ReactiveX/rxjs/issues/7200)\n            destination.next(window);\n\n            closingSubscription.add(\n              closingNotifier.subscribe(\n                operate({\n                  destination,\n                  next: closeWindow,\n                  error: handleError,\n                  complete: noop,\n                })\n              )\n            );\n          },\n          complete: noop,\n        })\n      );\n\n      // Subscribe to the source to get things started.\n      source.subscribe(\n        operate({\n          destination,\n          next: (value: T) => {\n            // Copy the windows array before we emit to\n            // make sure we don't have issues with reentrant code.\n            const windowsCopy = windows.slice();\n            for (const window of windowsCopy) {\n              window.next(value);\n            }\n          },\n          error: handleError,\n          complete: () => {\n            // Complete all of our windows before we complete.\n            while (0 < windows.length) {\n              windows.shift()!.complete();\n            }\n            destination.complete();\n          },\n          finalize: () => {\n            // Add this finalization so that all window subjects are\n            // disposed of. This way, if a user tries to subscribe\n            // to a window *after* the outer subscription has been unsubscribed,\n            // they will get an error, instead of waiting forever to\n            // see if a value arrives.\n            while (0 < windows.length) {\n              windows.shift()!.unsubscribe();\n            }\n          },\n        })\n      );\n    });\n}\n"
  },
  {
    "path": "packages/rxjs/src/internal/operators/windowWhen.ts",
    "content": "import type { Subscriber} from '@rxjs/observable';\nimport { operate, Observable, from } from '@rxjs/observable';\nimport { Subject } from '../Subject.js';\nimport type { ObservableInput, OperatorFunction } from '../types.js';\nimport { noop } from '../util/noop.js';\n\n/**\n * Branch out the source Observable values as a nested Observable using a\n * factory function of closing Observables to determine when to start a new\n * window.\n *\n * <span class=\"informal\">It's like {@link bufferWhen}, but emits a nested\n * Observable instead of an array.</span>\n *\n * ![](windowWhen.svg)\n *\n * Returns an Observable that emits Observable windows of items it collects from\n * the source Observable. The output Observable emits connected, non-overlapping\n * windows. It emits the current window immediately when subscribing to the source\n * Observable and opens a new one whenever the Observable produced by the specified\n * `closingSelector` function emits `next`. When an Observable returned by the\n * `closingSelector` emits `next`, the previous window completes and a new window\n * is emitted to the output subscriber.\n *\n * ## Example\n *\n * Emit only the first two clicks events in every window of [1-5] random seconds\n *\n * ```ts\n * import { fromEvent, windowWhen, interval, map, take, mergeAll } from 'rxjs';\n *\n * const clicks = fromEvent(document, 'click');\n * const result = clicks.pipe(\n *   windowWhen(() => interval(1000 + Math.random() * 4000)),\n *   map(win => win.pipe(take(2))), // take at most 2 emissions from each window\n *   mergeAll()                     // flatten the Observable-of-Observables\n * );\n * result.subscribe(x => console.log(x));\n * ```\n *\n * @see {@link window}\n * @see {@link windowCount}\n * @see {@link windowTime}\n * @see {@link windowToggle}\n * @see {@link bufferWhen}\n *\n * @param closingSelector A function that takes no arguments and returns an\n * {@link ObservableInput} (that gets converted to Observable) that signals\n * when to close the previous window and start a new one. Note that a value (any value) must be\n * observed to signal window closure.\n * @return A function that returns an Observable of windows, which in turn are\n * Observables.\n */\nexport function windowWhen<T>(closingSelector: () => ObservableInput<any>): OperatorFunction<T, Observable<T>> {\n  return (source) =>\n    new Observable((destination) => {\n      let window: Subject<T> | null;\n      let closingSubscriber: Subscriber<any> | undefined;\n\n      /**\n       * When we get an error, we have to notify both the\n       * destination subscriber and the window.\n       */\n      const handleError = (err: any) => {\n        window!.error(err);\n        destination.error(err);\n      };\n\n      /**\n       * Called every time we need to open a window.\n       * Recursive, as it will start the closing notifier, which\n       * inevitably *should* call openWindow -- but may not if\n       * it is a \"never\" observable.\n       */\n      const openWindow = () => {\n        // We need to clean up our closing subscription,\n        // we only cared about the first next or complete notification.\n        closingSubscriber?.unsubscribe();\n\n        // Close our window before starting a new one.\n        window?.complete();\n\n        // Start the new window.\n        window = new Subject<T>();\n        destination.next(window.asObservable());\n\n        // Get our closing notifier.\n        let closingNotifier: Observable<any>;\n        try {\n          closingNotifier = from(closingSelector());\n        } catch (err) {\n          handleError(err);\n          return;\n        }\n\n        // Subscribe to the closing notifier, be sure\n        // to capture the subscriber (aka Subscription)\n        // so we can clean it up when we close the window\n        // and open a new one.\n        closingNotifier.subscribe(\n          (closingSubscriber = operate({\n            destination,\n            next: openWindow,\n            error: handleError,\n            complete: noop,\n          }))\n        );\n      };\n\n      // Start the first window.\n      openWindow();\n\n      // Subscribe to the source\n      source.subscribe(\n        operate({\n          destination,\n          next: (value) => window!.next(value),\n          error: handleError,\n          complete: () => {\n            // The source completed, close the window and complete.\n            window!.complete();\n            destination.complete();\n          },\n          finalize: () => {\n            // Be sure to clean up our closing subscription\n            // when this tears down.\n            closingSubscriber?.unsubscribe();\n            window = null!;\n          },\n        })\n      );\n    });\n}\n"
  },
  {
    "path": "packages/rxjs/src/internal/operators/withLatestFrom.ts",
    "content": "import type { OperatorFunction, ObservableInputTuple } from '../types.js';\nimport { Observable, operate, from } from '@rxjs/observable';\nimport { identity } from '../util/identity.js';\nimport { noop } from '../util/noop.js';\nimport { popResultSelector } from '../util/args.js';\n\nexport function withLatestFrom<T, O extends unknown[]>(...inputs: [...ObservableInputTuple<O>]): OperatorFunction<T, [T, ...O]>;\n\nexport function withLatestFrom<T, O extends unknown[], R>(\n  ...inputs: [...ObservableInputTuple<O>, (...value: [T, ...O]) => R]\n): OperatorFunction<T, R>;\n\n/**\n * Combines the source Observable with other Observables to create an Observable\n * whose values are calculated from the latest values of each, only when the\n * source emits.\n *\n * <span class=\"informal\">Whenever the source Observable emits a value, it\n * computes a formula using that value plus the latest values from other input\n * Observables, then emits the output of that formula.</span>\n *\n * ![](withLatestFrom.png)\n *\n * `withLatestFrom` combines each value from the source Observable (the\n * instance) with the latest values from the other input Observables only when\n * the source emits a value, optionally using a `project` function to determine\n * the value to be emitted on the output Observable. All input Observables must\n * emit at least one value before the output Observable will emit a value.\n *\n * ## Example\n *\n * On every click event, emit an array with the latest timer event plus the click event\n *\n * ```ts\n * import { fromEvent, interval, withLatestFrom } from 'rxjs';\n *\n * const clicks = fromEvent(document, 'click');\n * const timer = interval(1000);\n * const result = clicks.pipe(withLatestFrom(timer));\n * result.subscribe(x => console.log(x));\n * ```\n *\n * @see {@link combineLatest}\n *\n * @param inputs An input Observable to combine with the source Observable. More\n * than one input Observables may be given as argument. If the last parameter is\n * a function, it will be used as a projection function for combining values\n * together. When the function is called, it receives all values in order of the\n * Observables passed, where the first parameter is a value from the source\n * Observable. (e.g.\n * `a.pipe(withLatestFrom(b, c), map(([a1, b1, c1]) => a1 + b1 + c1))`). If this\n * is not passed, arrays will be emitted on the output Observable.\n * @return A function that returns an Observable of projected values from the\n * most recent values from each input Observable, or an array of the most\n * recent values from each input Observable.\n */\nexport function withLatestFrom<T, R>(...inputs: any[]): OperatorFunction<T, R | any[]> {\n  const project = popResultSelector(inputs) as ((...args: any[]) => R) | undefined;\n\n  return (source) =>\n    new Observable((destination) => {\n      const len = inputs.length;\n      const otherValues = new Array(len);\n      // An array of whether or not the other sources have emitted. Matched with them by index.\n      // TODO: At somepoint, we should investigate the performance implications here, and look\n      // into using a `Set()` and checking the `size` to see if we're ready.\n      let hasValue = inputs.map(() => false);\n      // Flipped true when we have at least one value from all other sources and\n      // we are ready to start emitting values.\n      let ready = false;\n\n      // Other sources. Note that here we are not checking `subscriber.closed`,\n      // this causes all inputs to be subscribed to, even if nothing can be emitted\n      // from them. This is an important distinction because subscription constitutes\n      // a side-effect.\n      for (let i = 0; i < len; i++) {\n        from(inputs[i]).subscribe(\n          operate({\n            destination,\n            next: (value) => {\n              otherValues[i] = value;\n              if (!ready && !hasValue[i]) {\n                // If we're not ready yet, flag to show this observable has emitted.\n                hasValue[i] = true;\n                // Intentionally terse code.\n                // If all of our other observables have emitted, set `ready` to `true`,\n                // so we know we can start emitting values, then clean up the `hasValue` array,\n                // because we don't need it anymore.\n                (ready = hasValue.every(identity)) && (hasValue = null!);\n              }\n            },\n            // Completing one of the other sources has\n            // no bearing on the completion of our result.\n            complete: noop,\n          })\n        );\n      }\n\n      // Source subscription\n      source.subscribe(\n        operate({\n          destination,\n          next: (value) => {\n            if (ready) {\n              // We have at least one value from the other sources. Go ahead and emit.\n              const values = [value, ...otherValues];\n              destination.next(project ? project(...values) : values);\n            }\n          },\n        })\n      );\n    });\n}\n"
  },
  {
    "path": "packages/rxjs/src/internal/operators/zipAll.ts",
    "content": "import type { OperatorFunction, ObservableInput } from '../types.js';\nimport { zip } from '../observable/zip.js';\nimport { joinAllInternals } from './joinAllInternals.js';\n\n/**\n * Collects all observable inner sources from the source, once the source completes,\n * it will subscribe to all inner sources, combining their values by index and emitting\n * them.\n *\n * @see {@link zipWith}\n * @see {@link zip}\n */\nexport function zipAll<T>(): OperatorFunction<ObservableInput<T>, T[]>;\nexport function zipAll<T>(): OperatorFunction<any, T[]>;\nexport function zipAll<T, R>(project: (...values: T[]) => R): OperatorFunction<ObservableInput<T>, R>;\nexport function zipAll<R>(project: (...values: Array<any>) => R): OperatorFunction<any, R>;\n\nexport function zipAll<T, R>(project?: (...values: T[]) => R) {\n  return joinAllInternals(zip, project);\n}\n"
  },
  {
    "path": "packages/rxjs/src/internal/operators/zipWith.ts",
    "content": "import type { ObservableInputTuple, OperatorFunction, Cons } from '../types.js';\nimport { Observable } from '@rxjs/observable';\nimport { zip } from '../observable/zip.js';\n\n/**\n * Subscribes to the source, and the observable inputs provided as arguments, and combines their values, by index, into arrays.\n *\n * What is meant by \"combine by index\": The first value from each will be made into a single array, then emitted,\n * then the second value from each will be combined into a single array and emitted, then the third value\n * from each will be combined into a single array and emitted, and so on.\n *\n * This will continue until it is no longer able to combine values of the same index into an array.\n *\n * After the last value from any one completed source is emitted in an array, the resulting observable will complete,\n * as there is no way to continue \"zipping\" values together by index.\n *\n * Use-cases for this operator are limited. There are memory concerns if one of the streams is emitting\n * values at a much faster rate than the others. Usage should likely be limited to streams that emit\n * at a similar pace, or finite streams of known length.\n *\n * In many cases, authors want `combineLatestWith` and not `zipWith`.\n *\n * @param otherInputs other observable inputs to collate values from.\n * @return A function that returns an Observable that emits items by index\n * combined from the source Observable and provided Observables, in form of an\n * array.\n */\nexport function zipWith<T, A extends readonly unknown[]>(...otherInputs: [...ObservableInputTuple<A>]): OperatorFunction<T, Cons<T, A>> {\n  return (source) =>\n    new Observable((subscriber) => {\n      zip<[T, ...A]>(source, ...otherInputs).subscribe(subscriber);\n    });\n}\n"
  },
  {
    "path": "packages/rxjs/src/internal/scheduled/scheduleArray.ts",
    "content": "import { Observable } from '@rxjs/observable';\nimport type { SchedulerLike } from '../types.js';\nimport { executeSchedule } from '../util/executeSchedule.js';\n\nexport function scheduleArray<T>(input: ArrayLike<T>, scheduler: SchedulerLike) {\n  return new Observable<T>((subscriber) => {\n    // The current array index.\n    let i = 0;\n    const emit = () => {\n      // If we have hit the end of the array, complete.\n      if (i === input.length) {\n        subscriber.complete();\n      } else {\n        // Otherwise, next the value at the current index,\n        // then increment our index.\n        subscriber.next(input[i++]);\n        executeSchedule(subscriber, scheduler, emit);\n      }\n    };\n\n    // Start iterating over the array like on a schedule.\n    return executeSchedule(subscriber, scheduler, emit);\n  });\n}\n"
  },
  {
    "path": "packages/rxjs/src/internal/scheduled/scheduleAsyncIterable.ts",
    "content": "import type { SchedulerLike } from '../types.js';\nimport { Observable } from '@rxjs/observable';\nimport { executeSchedule } from '../util/executeSchedule.js';\n\nexport function scheduleAsyncIterable<T>(input: AsyncIterable<T>, scheduler: SchedulerLike) {\n  if (!input) {\n    throw new Error('Iterable cannot be null');\n  }\n  return new Observable<T>((subscriber) => {\n    executeSchedule(subscriber, scheduler, () => {\n      const iterator = input[Symbol.asyncIterator]();\n      executeSchedule(\n        subscriber,\n        scheduler,\n        () => {\n          iterator.next().then((result) => {\n            if (result.done) {\n              // This will remove the subscriptions from\n              // the parent subscription.\n              subscriber.complete();\n            } else {\n              subscriber.next(result.value);\n            }\n          });\n        },\n        0,\n        true\n      );\n    });\n  });\n}\n"
  },
  {
    "path": "packages/rxjs/src/internal/scheduled/scheduleIterable.ts",
    "content": "import { Observable, isFunction } from '@rxjs/observable';\nimport type { SchedulerLike } from '../types.js';\nimport { iterator as Symbol_iterator } from '../symbol/iterator.js';\nimport { executeSchedule } from '../util/executeSchedule.js';\n\n/**\n * Used in {@link scheduled} to create an observable from an Iterable.\n * @param input The iterable to create an observable from\n * @param scheduler The scheduler to use\n */\nexport function scheduleIterable<T>(input: Iterable<T>, scheduler: SchedulerLike) {\n  return new Observable<T>((subscriber) => {\n    let iterator: Iterator<T, T>;\n\n    // Schedule the initial creation of the iterator from\n    // the iterable. This is so the code in the iterable is\n    // not called until the scheduled job fires.\n    executeSchedule(subscriber, scheduler, () => {\n      // Create the iterator.\n      iterator = (input as any)[Symbol_iterator]();\n\n      executeSchedule(\n        subscriber,\n        scheduler,\n        () => {\n          let value: T;\n          let done: boolean | undefined;\n          try {\n            // Pull the value out of the iterator\n            ({ value, done } = iterator.next());\n          } catch (err) {\n            // We got an error while pulling from the iterator\n            subscriber.error(err);\n            return;\n          }\n\n          if (done) {\n            // If it is \"done\" we just complete. This mimics the\n            // behavior of JavaScript's `for..of` consumption of\n            // iterables, which will not emit the value from an iterator\n            // result of `{ done: true: value: 'here' }`.\n            subscriber.complete();\n          } else {\n            // The iterable is not done, emit the value.\n            subscriber.next(value);\n          }\n        },\n        0,\n        true\n      );\n    });\n\n    // During finalization, if we see this iterator has a `return` method,\n    // then we know it is a Generator, and not just an Iterator. So we call\n    // the `return()` function. This will ensure that any `finally { }` blocks\n    // inside of the generator we can hit will be hit properly.\n    return () => isFunction(iterator?.return) && iterator.return();\n  });\n}\n"
  },
  {
    "path": "packages/rxjs/src/internal/scheduled/scheduleObservable.ts",
    "content": "import { from } from '@rxjs/observable';\nimport { observeOn } from '../operators/observeOn.js';\nimport { subscribeOn } from '../operators/subscribeOn.js';\nimport type { InteropObservable, SchedulerLike } from '../types.js';\n\nexport function scheduleObservable<T>(input: InteropObservable<T>, scheduler: SchedulerLike) {\n  return from(input).pipe(subscribeOn(scheduler), observeOn(scheduler));\n}\n"
  },
  {
    "path": "packages/rxjs/src/internal/scheduled/schedulePromise.ts",
    "content": "import { from } from '@rxjs/observable';\nimport { observeOn } from '../operators/observeOn.js';\nimport { subscribeOn } from '../operators/subscribeOn.js';\nimport type { SchedulerLike } from '../types.js';\n\nexport function schedulePromise<T>(input: PromiseLike<T>, scheduler: SchedulerLike) {\n  return from(input).pipe(subscribeOn(scheduler), observeOn(scheduler));\n}\n"
  },
  {
    "path": "packages/rxjs/src/internal/scheduled/scheduleReadableStreamLike.ts",
    "content": "import type { SchedulerLike, ReadableStreamLike } from '../types.js';\nimport type { Observable} from '@rxjs/observable';\nimport { readableStreamLikeToAsyncGenerator } from '@rxjs/observable';\nimport { scheduleAsyncIterable } from './scheduleAsyncIterable.js';\n\nexport function scheduleReadableStreamLike<T>(input: ReadableStreamLike<T>, scheduler: SchedulerLike): Observable<T> {\n  return scheduleAsyncIterable(readableStreamLikeToAsyncGenerator(input), scheduler);\n}\n"
  },
  {
    "path": "packages/rxjs/src/internal/scheduled/scheduled.ts",
    "content": "import { scheduleObservable } from './scheduleObservable.js';\nimport { schedulePromise } from './schedulePromise.js';\nimport { scheduleArray } from './scheduleArray.js';\nimport { scheduleIterable } from './scheduleIterable.js';\nimport { scheduleAsyncIterable } from './scheduleAsyncIterable.js';\nimport type { InteropObservable, ObservableInput, SchedulerLike } from '../types.js';\nimport type { Observable} from '@rxjs/observable';\nimport { ObservableInputType, getObservableInputType } from '@rxjs/observable';\nimport { scheduleReadableStreamLike } from './scheduleReadableStreamLike.js';\n\n/**\n * Converts from a common {@link ObservableInput} type to an observable where subscription and emissions\n * are scheduled on the provided scheduler.\n *\n * @see {@link from}\n * @see {@link of}\n *\n * @param input The observable, array, promise, iterable, etc you would like to schedule\n * @param scheduler The scheduler to use to schedule the subscription and emissions from\n * the returned observable.\n */\nexport function scheduled<T>(input: ObservableInput<T>, scheduler: SchedulerLike): Observable<T> {\n  const type = getObservableInputType(input);\n  switch (type) {\n    case ObservableInputType.Own:\n    case ObservableInputType.InteropObservable:\n      return scheduleObservable(input as InteropObservable<T>, scheduler);\n    case ObservableInputType.Promise:\n      return schedulePromise(input as Promise<T>, scheduler);\n    case ObservableInputType.ArrayLike:\n      return scheduleArray(input as ArrayLike<T>, scheduler);\n    case ObservableInputType.Iterable:\n      return scheduleIterable(input as Iterable<T>, scheduler);\n    case ObservableInputType.AsyncIterable:\n      return scheduleAsyncIterable(input as AsyncIterable<T>, scheduler);\n    case ObservableInputType.ReadableStreamLike:\n      return scheduleReadableStreamLike(input as ReadableStream<T>, scheduler);\n  }\n}\n"
  },
  {
    "path": "packages/rxjs/src/internal/scheduler/Action.ts",
    "content": "import type { Scheduler } from '../Scheduler.js';\nimport { Subscription } from '@rxjs/observable';\nimport type { SchedulerAction } from '../types.js';\n\n/**\n * A unit of work to be executed in a `scheduler`. An action is typically\n * created from within a {@link SchedulerLike} and an RxJS user does not need to concern\n * themselves about creating and manipulating an Action.\n *\n * ```ts\n * class Action<T> extends Subscription {\n *   new (scheduler: Scheduler, work: (state?: T) => void);\n *   schedule(state?: T, delay: number = 0): Subscription;\n * }\n * ```\n */\nexport class Action<T> extends Subscription {\n  constructor(scheduler: Scheduler, work: (this: SchedulerAction<T>, state?: T) => void) {\n    super();\n  }\n  /**\n   * Schedules this action on its parent {@link SchedulerLike} for execution. May be passed\n   * some context object, `state`. May happen at some point in the future,\n   * according to the `delay` parameter, if specified.\n   * @param state Some contextual data that the `work` function uses when called by the\n   * Scheduler.\n   * @param delay Time to wait before executing the work, where the time unit is implicit\n   * and defined by the Scheduler.\n   * @return A subscription in order to be able to unsubscribe the scheduled work.\n   */\n  public schedule(state?: T, delay: number = 0): Subscription {\n    return this;\n  }\n}\n"
  },
  {
    "path": "packages/rxjs/src/internal/scheduler/AnimationFrameAction.ts",
    "content": "import { AsyncAction } from './AsyncAction.js';\nimport type { AnimationFrameScheduler } from './AnimationFrameScheduler.js';\nimport type { SchedulerAction } from '../types.js';\nimport { animationFrameProvider } from './animationFrameProvider.js';\nimport type { TimerHandle } from './timerHandle.js';\n\nexport class AnimationFrameAction<T> extends AsyncAction<T> {\n  constructor(protected scheduler: AnimationFrameScheduler, protected work: (this: SchedulerAction<T>, state?: T) => void) {\n    super(scheduler, work);\n  }\n\n  protected requestAsyncId(scheduler: AnimationFrameScheduler, id?: TimerHandle, delay: number = 0): TimerHandle {\n    // If delay is greater than 0, request as an async action.\n    if (delay !== null && delay > 0) {\n      return super.requestAsyncId(scheduler, id, delay);\n    }\n    // Push the action to the end of the scheduler queue.\n    scheduler.actions.push(this);\n    // If an animation frame has already been requested, don't request another\n    // one. If an animation frame hasn't been requested yet, request one. Return\n    // the current animation frame request id.\n    return scheduler._scheduled || (scheduler._scheduled = animationFrameProvider.requestAnimationFrame(() => scheduler.flush(undefined)));\n  }\n\n  protected recycleAsyncId(scheduler: AnimationFrameScheduler, id?: TimerHandle, delay: number = 0): TimerHandle | undefined {\n    // If delay exists and is greater than 0, or if the delay is null (the\n    // action wasn't rescheduled) but was originally scheduled as an async\n    // action, then recycle as an async action.\n    if (delay != null ? delay > 0 : this.delay > 0) {\n      return super.recycleAsyncId(scheduler, id, delay);\n    }\n    // If the scheduler queue has no remaining actions with the same async id,\n    // cancel the requested animation frame and set the scheduled flag to\n    // undefined so the next AnimationFrameAction will request its own.\n    const { actions } = scheduler;\n    if (id != null && actions[actions.length - 1]?.id !== id) {\n      animationFrameProvider.cancelAnimationFrame(id as number);\n      scheduler._scheduled = undefined;\n    }\n    // Return undefined so the action knows to request a new async id if it's rescheduled.\n    return undefined;\n  }\n}\n"
  },
  {
    "path": "packages/rxjs/src/internal/scheduler/AnimationFrameScheduler.ts",
    "content": "import type { AsyncAction } from './AsyncAction.js';\nimport { AsyncScheduler } from './AsyncScheduler.js';\n\nexport class AnimationFrameScheduler extends AsyncScheduler {\n  public flush(action?: AsyncAction<any>): void {\n    this._active = true;\n    // The async id that effects a call to flush is stored in _scheduled.\n    // Before executing an action, it's necessary to check the action's async\n    // id to determine whether it's supposed to be executed in the current\n    // flush.\n    // Previous implementations of this method used a count to determine this,\n    // but that was unsound, as actions that are unsubscribed - i.e. cancelled -\n    // are removed from the actions array and that can shift actions that are\n    // scheduled to be executed in a subsequent flush into positions at which\n    // they are executed within the current flush.\n    const flushId = this._scheduled;\n    this._scheduled = undefined;\n\n    const { actions } = this;\n    let error: any;\n    action = action || actions.shift()!;\n\n    do {\n      if ((error = action.execute(action.state, action.delay))) {\n        break;\n      }\n    } while ((action = actions[0]) && action.id === flushId && actions.shift());\n\n    this._active = false;\n\n    if (error) {\n      while ((action = actions[0]) && action.id === flushId && actions.shift()) {\n        action.unsubscribe();\n      }\n      throw error;\n    }\n  }\n}\n"
  },
  {
    "path": "packages/rxjs/src/internal/scheduler/AsapAction.ts",
    "content": "import { AsyncAction } from './AsyncAction.js';\nimport type { AsapScheduler } from './AsapScheduler.js';\nimport type { SchedulerAction } from '../types.js';\nimport { immediateProvider } from './immediateProvider.js';\nimport type { TimerHandle } from './timerHandle.js';\n\nexport class AsapAction<T> extends AsyncAction<T> {\n  constructor(protected scheduler: AsapScheduler, protected work: (this: SchedulerAction<T>, state?: T) => void) {\n    super(scheduler, work);\n  }\n\n  protected requestAsyncId(scheduler: AsapScheduler, id?: TimerHandle, delay: number = 0): TimerHandle {\n    // If delay is greater than 0, request as an async action.\n    if (delay !== null && delay > 0) {\n      return super.requestAsyncId(scheduler, id, delay);\n    }\n    // Push the action to the end of the scheduler queue.\n    scheduler.actions.push(this);\n    // If a microtask has already been scheduled, don't schedule another\n    // one. If a microtask hasn't been scheduled yet, schedule one now. Return\n    // the current scheduled microtask id.\n    return scheduler._scheduled || (scheduler._scheduled = immediateProvider.setImmediate(scheduler.flush.bind(scheduler, undefined)));\n  }\n\n  protected recycleAsyncId(scheduler: AsapScheduler, id?: TimerHandle, delay: number = 0): TimerHandle | undefined {\n    // If delay exists and is greater than 0, or if the delay is null (the\n    // action wasn't rescheduled) but was originally scheduled as an async\n    // action, then recycle as an async action.\n    if (delay != null ? delay > 0 : this.delay > 0) {\n      return super.recycleAsyncId(scheduler, id, delay);\n    }\n    // If the scheduler queue has no remaining actions with the same async id,\n    // cancel the requested microtask and set the scheduled flag to undefined\n    // so the next AsapAction will request its own.\n    const { actions } = scheduler;\n    if (id != null && actions[actions.length - 1]?.id !== id) {\n      immediateProvider.clearImmediate(id);\n      if (scheduler._scheduled === id) {\n        scheduler._scheduled = undefined;\n      }\n    }\n    // Return undefined so the action knows to request a new async id if it's rescheduled.\n    return undefined;\n  }\n}\n"
  },
  {
    "path": "packages/rxjs/src/internal/scheduler/AsapScheduler.ts",
    "content": "import type { AsyncAction } from './AsyncAction.js';\nimport { AsyncScheduler } from './AsyncScheduler.js';\n\nexport class AsapScheduler extends AsyncScheduler {\n  public flush(action?: AsyncAction<any>): void {\n    this._active = true;\n    // The async id that effects a call to flush is stored in _scheduled.\n    // Before executing an action, it's necessary to check the action's async\n    // id to determine whether it's supposed to be executed in the current\n    // flush.\n    // Previous implementations of this method used a count to determine this,\n    // but that was unsound, as actions that are unsubscribed - i.e. cancelled -\n    // are removed from the actions array and that can shift actions that are\n    // scheduled to be executed in a subsequent flush into positions at which\n    // they are executed within the current flush.\n    const flushId = this._scheduled;\n    this._scheduled = undefined;\n\n    const { actions } = this;\n    let error: any;\n    action = action || actions.shift()!;\n\n    do {\n      if ((error = action.execute(action.state, action.delay))) {\n        break;\n      }\n    } while ((action = actions[0]) && action.id === flushId && actions.shift());\n\n    this._active = false;\n\n    if (error) {\n      while ((action = actions[0]) && action.id === flushId && actions.shift()) {\n        action.unsubscribe();\n      }\n      throw error;\n    }\n  }\n}\n"
  },
  {
    "path": "packages/rxjs/src/internal/scheduler/AsyncAction.ts",
    "content": "import { Action } from './Action.js';\nimport type { SchedulerAction } from '../types.js';\nimport type { Subscription } from '@rxjs/observable';\nimport type { AsyncScheduler } from './AsyncScheduler.js';\nimport { intervalProvider } from './intervalProvider.js';\nimport { arrRemove } from '../util/arrRemove.js';\nimport type { TimerHandle } from './timerHandle.js';\n\nexport class AsyncAction<T> extends Action<T> {\n  public id: TimerHandle | undefined;\n  public state?: T;\n  public delay!: number;\n  protected pending: boolean = false;\n\n  constructor(protected scheduler: AsyncScheduler, protected work: (this: SchedulerAction<T>, state?: T) => void) {\n    super(scheduler, work);\n  }\n\n  public schedule(state?: T, delay: number = 0): Subscription {\n    if (this.closed) {\n      return this;\n    }\n\n    // Always replace the current state with the new state.\n    this.state = state;\n\n    const id = this.id;\n    const scheduler = this.scheduler;\n\n    //\n    // Important implementation note:\n    //\n    // Actions only execute once by default, unless rescheduled from within the\n    // scheduled callback. This allows us to implement single and repeat\n    // actions via the same code path, without adding API surface area, as well\n    // as mimic traditional recursion but across asynchronous boundaries.\n    //\n    // However, JS runtimes and timers distinguish between intervals achieved by\n    // serial `setTimeout` calls vs. a single `setInterval` call. An interval of\n    // serial `setTimeout` calls can be individually delayed, which delays\n    // scheduling the next `setTimeout`, and so on. `setInterval` attempts to\n    // guarantee the interval callback will be invoked more precisely to the\n    // interval period, regardless of load.\n    //\n    // Therefore, we use `setInterval` to schedule single and repeat actions.\n    // If the action reschedules itself with the same delay, the interval is not\n    // canceled. If the action doesn't reschedule, or reschedules with a\n    // different delay, the interval will be canceled after scheduled callback\n    // execution.\n    //\n    if (id != null) {\n      this.id = this.recycleAsyncId(scheduler, id, delay);\n    }\n\n    // Set the pending flag indicating that this action has been scheduled, or\n    // has recursively rescheduled itself.\n    this.pending = true;\n\n    this.delay = delay;\n    // If this action has already an async Id, don't request a new one.\n    this.id = this.id ?? this.requestAsyncId(scheduler, this.id, delay);\n\n    return this;\n  }\n\n  protected requestAsyncId(scheduler: AsyncScheduler, _id?: TimerHandle, delay: number = 0): TimerHandle {\n    return intervalProvider.setInterval(scheduler.flush.bind(scheduler, this), delay);\n  }\n\n  protected recycleAsyncId(_scheduler: AsyncScheduler, id?: TimerHandle, delay: number | null = 0): TimerHandle | undefined {\n    // If this action is rescheduled with the same delay time, don't clear the interval id.\n    if (delay != null && this.delay === delay && this.pending === false) {\n      return id;\n    }\n    // Otherwise, if the action's delay time is different from the current delay,\n    // or the action has been rescheduled before it's executed, clear the interval id\n    if (id != null) {\n      intervalProvider.clearInterval(id);\n    }\n\n    return undefined;\n  }\n\n  /**\n   * Immediately executes this action and the `work` it contains.\n   */\n  public execute(state: T, delay: number): any {\n    if (this.closed) {\n      return new Error('executing a cancelled action');\n    }\n\n    this.pending = false;\n    const error = this._execute(state, delay);\n    if (error) {\n      return error;\n    } else if (this.pending === false && this.id != null) {\n      // Dequeue if the action didn't reschedule itself. Don't call\n      // unsubscribe(), because the action could reschedule later.\n      // For example:\n      // ```\n      // scheduler.schedule(function doWork(counter) {\n      //   /* ... I'm a busy worker bee ... */\n      //   var originalAction = this;\n      //   /* wait 100ms before rescheduling the action */\n      //   setTimeout(function () {\n      //     originalAction.schedule(counter + 1);\n      //   }, 100);\n      // }, 1000);\n      // ```\n      this.id = this.recycleAsyncId(this.scheduler, this.id, null);\n    }\n  }\n\n  protected _execute(state: T, _delay: number): any {\n    let errored: boolean = false;\n    let errorValue: any;\n    try {\n      this.work(state);\n    } catch (e) {\n      errored = true;\n      // HACK: Since code elsewhere is relying on the \"truthiness\" of the\n      // return here, we can't have it return \"\" or 0 or false.\n      // TODO: Clean this up when we refactor schedulers mid-version-8 or so.\n      errorValue = e ? e : new Error('Scheduled action threw falsy error');\n    }\n    if (errored) {\n      this.unsubscribe();\n      return errorValue;\n    }\n  }\n\n  unsubscribe() {\n    if (!this.closed) {\n      const { id, scheduler } = this;\n      const { actions } = scheduler;\n\n      this.work = this.state = this.scheduler = null!;\n      this.pending = false;\n\n      arrRemove(actions, this);\n      if (id != null) {\n        this.id = this.recycleAsyncId(scheduler, id, null);\n      }\n\n      this.delay = null!;\n      super.unsubscribe();\n    }\n  }\n}\n"
  },
  {
    "path": "packages/rxjs/src/internal/scheduler/AsyncScheduler.ts",
    "content": "import { Scheduler } from '../Scheduler.js';\nimport type { Action } from './Action.js';\nimport type { AsyncAction } from './AsyncAction.js';\nimport type { TimerHandle } from './timerHandle.js';\n\nexport class AsyncScheduler extends Scheduler {\n  public actions: Array<AsyncAction<any>> = [];\n  /**\n   * A flag to indicate whether the Scheduler is currently executing a batch of\n   * queued actions.\n   * @internal\n   */\n  public _active: boolean = false;\n  /**\n   * An internal ID used to track the latest asynchronous task such as those\n   * coming from `setTimeout`, `setInterval`, `requestAnimationFrame`, and\n   * others.\n   * @internal\n   */\n  public _scheduled: TimerHandle | undefined;\n\n  constructor(SchedulerAction: typeof Action, now: () => number = Scheduler.now) {\n    super(SchedulerAction, now);\n  }\n\n  public flush(action: AsyncAction<any>): void {\n    const { actions } = this;\n\n    if (this._active) {\n      actions.push(action);\n      return;\n    }\n\n    let error: any;\n    this._active = true;\n\n    do {\n      if ((error = action.execute(action.state, action.delay))) {\n        break;\n      }\n    } while ((action = actions.shift()!)); // exhaust the scheduler queue\n\n    this._active = false;\n\n    if (error) {\n      while ((action = actions.shift()!)) {\n        action.unsubscribe();\n      }\n      throw error;\n    }\n  }\n}\n"
  },
  {
    "path": "packages/rxjs/src/internal/scheduler/QueueAction.ts",
    "content": "import { AsyncAction } from './AsyncAction.js';\nimport type { Subscription } from '@rxjs/observable';\nimport type { QueueScheduler } from './QueueScheduler.js';\nimport type { SchedulerAction } from '../types.js';\nimport type { TimerHandle } from './timerHandle.js';\n\nexport class QueueAction<T> extends AsyncAction<T> {\n  constructor(protected scheduler: QueueScheduler, protected work: (this: SchedulerAction<T>, state?: T) => void) {\n    super(scheduler, work);\n  }\n\n  public schedule(state?: T, delay: number = 0): Subscription {\n    if (delay > 0) {\n      return super.schedule(state, delay);\n    }\n    this.delay = delay;\n    this.state = state;\n    this.scheduler.flush(this);\n    return this;\n  }\n\n  public execute(state: T, delay: number): any {\n    return delay > 0 || this.closed ? super.execute(state, delay) : this._execute(state, delay);\n  }\n\n  protected requestAsyncId(scheduler: QueueScheduler, id?: TimerHandle, delay: number = 0): TimerHandle {\n    // If delay exists and is greater than 0, or if the delay is null (the\n    // action wasn't rescheduled) but was originally scheduled as an async\n    // action, then recycle as an async action.\n\n    if ((delay != null && delay > 0) || (delay == null && this.delay > 0)) {\n      return super.requestAsyncId(scheduler, id, delay);\n    }\n\n    // Otherwise flush the scheduler starting with this action.\n    scheduler.flush(this);\n\n    // HACK: In the past, this was returning `void`. However, `void` isn't a valid\n    // `TimerHandle`, and generally the return value here isn't really used. So the\n    // compromise is to return `0` which is both \"falsy\" and a valid `TimerHandle`,\n    // as opposed to refactoring every other instanceo of `requestAsyncId`.\n    return 0;\n  }\n}\n"
  },
  {
    "path": "packages/rxjs/src/internal/scheduler/QueueScheduler.ts",
    "content": "import { AsyncScheduler } from './AsyncScheduler.js';\n\nexport class QueueScheduler extends AsyncScheduler {}\n"
  },
  {
    "path": "packages/rxjs/src/internal/scheduler/VirtualTimeScheduler.ts",
    "content": "import { AsyncAction } from './AsyncAction.js';\nimport { Subscription } from '@rxjs/observable';\nimport { AsyncScheduler } from './AsyncScheduler.js';\nimport type { SchedulerAction } from '../types.js';\nimport type { TimerHandle } from './timerHandle.js';\n\nexport class VirtualTimeScheduler extends AsyncScheduler {\n  /** @deprecated Not used in VirtualTimeScheduler directly. Will be removed in v8. */\n  static frameTimeFactor = 10;\n\n  /**\n   * The current frame for the state of the virtual scheduler instance. The difference\n   * between two \"frames\" is synonymous with the passage of \"virtual time units\". So if\n   * you record `scheduler.frame` to be `1`, then later, observe `scheduler.frame` to be at `11`,\n   * that means `10` virtual time units have passed.\n   */\n  public frame: number = 0;\n\n  /**\n   * Used internally to examine the current virtual action index being processed.\n   * @deprecated Internal implementation detail, do not use directly. Will be made internal in v8.\n   */\n  public index: number = -1;\n\n  /**\n   * This creates an instance of a `VirtualTimeScheduler`. Experts only. The signature of\n   * this constructor is likely to change in the long run.\n   *\n   * @param schedulerActionCtor The type of Action to initialize when initializing actions during scheduling.\n   * @param maxFrames The maximum number of frames to process before stopping. Used to prevent endless flush cycles.\n   */\n  constructor(schedulerActionCtor: typeof AsyncAction = VirtualAction as any, public maxFrames: number = Infinity) {\n    super(schedulerActionCtor, () => this.frame);\n  }\n\n  /**\n   * Prompt the Scheduler to execute all of its queued actions, therefore\n   * clearing its queue.\n   */\n  public flush(): void {\n    const { actions, maxFrames } = this;\n    let error: any;\n    let action: AsyncAction<any> | undefined;\n\n    while ((action = actions[0]) && action.delay <= maxFrames) {\n      actions.shift();\n      this.frame = action.delay;\n\n      if ((error = action.execute(action.state, action.delay))) {\n        break;\n      }\n    }\n\n    if (error) {\n      while ((action = actions.shift())) {\n        action.unsubscribe();\n      }\n      throw error;\n    }\n  }\n}\n\nexport class VirtualAction<T> extends AsyncAction<T> {\n  protected active: boolean = true;\n\n  constructor(\n    protected scheduler: VirtualTimeScheduler,\n    protected work: (this: SchedulerAction<T>, state?: T) => void,\n    protected index: number = (scheduler.index += 1)\n  ) {\n    super(scheduler, work);\n    this.index = scheduler.index = index;\n  }\n\n  public schedule(state?: T, delay: number = 0): Subscription {\n    if (Number.isFinite(delay)) {\n      if (!this.id) {\n        return super.schedule(state, delay);\n      }\n      this.active = false;\n      // If an action is rescheduled, we save allocations by mutating its state,\n      // pushing it to the end of the scheduler queue, and recycling the action.\n      // But since the VirtualTimeScheduler is used for testing, VirtualActions\n      // must be immutable so they can be inspected later.\n      const action = new VirtualAction(this.scheduler, this.work);\n      this.add(action);\n      return action.schedule(state, delay);\n    } else {\n      // If someone schedules something with Infinity, it'll never happen. So we\n      // don't even schedule it.\n      return Subscription.EMPTY;\n    }\n  }\n\n  protected requestAsyncId(scheduler: VirtualTimeScheduler, id?: any, delay: number = 0): TimerHandle {\n    this.delay = scheduler.frame + delay;\n    const { actions } = scheduler;\n    actions.push(this);\n    (actions as Array<VirtualAction<T>>).sort(VirtualAction.sortActions);\n    return 1;\n  }\n\n  protected recycleAsyncId(scheduler: VirtualTimeScheduler, id?: any, delay: number = 0): TimerHandle | undefined {\n    return undefined;\n  }\n\n  protected _execute(state: T, delay: number): any {\n    if (this.active === true) {\n      return super._execute(state, delay);\n    }\n  }\n\n  private static sortActions<T>(a: VirtualAction<T>, b: VirtualAction<T>) {\n    if (a.delay === b.delay) {\n      if (a.index === b.index) {\n        return 0;\n      } else if (a.index > b.index) {\n        return 1;\n      } else {\n        return -1;\n      }\n    } else if (a.delay > b.delay) {\n      return 1;\n    } else {\n      return -1;\n    }\n  }\n}\n"
  },
  {
    "path": "packages/rxjs/src/internal/scheduler/animationFrame.ts",
    "content": "import { AnimationFrameAction } from './AnimationFrameAction.js';\nimport { AnimationFrameScheduler } from './AnimationFrameScheduler.js';\n\n/**\n *\n * Animation Frame Scheduler\n *\n * <span class=\"informal\">Perform task when `window.requestAnimationFrame` would fire</span>\n *\n * When `animationFrameScheduler` scheduler is used with delay, it will fall back to {@link asyncScheduler}\n * scheduler behaviour.\n *\n * Without delay, `animationFrameScheduler` scheduler can be used to create smooth browser animations.\n * It makes sure scheduled task will happen just before next browser content repaint,\n * thus performing animations as efficiently as possible.\n *\n * ## Example\n * Schedule div height animation\n * ```ts\n * // html: <div style=\"background: #0ff;\"></div>\n * import { animationFrameScheduler } from 'rxjs';\n *\n * const div = document.querySelector('div');\n *\n * animationFrameScheduler.schedule(function(height) {\n *   div.style.height = height + \"px\";\n *\n *   this.schedule(height + 1);  // `this` references currently executing Action,\n *                               // which we reschedule with new state\n * }, 0, 0);\n *\n * // You will see a div element growing in height\n * ```\n */\n\nexport const animationFrameScheduler = new AnimationFrameScheduler(AnimationFrameAction);\n"
  },
  {
    "path": "packages/rxjs/src/internal/scheduler/animationFrameProvider.ts",
    "content": "import { Subscription } from '@rxjs/observable';\n\ninterface AnimationFrameProvider {\n  schedule(callback: FrameRequestCallback): Subscription;\n  requestAnimationFrame: typeof requestAnimationFrame;\n  cancelAnimationFrame: typeof cancelAnimationFrame;\n  delegate:\n    | {\n        requestAnimationFrame: typeof requestAnimationFrame;\n        cancelAnimationFrame: typeof cancelAnimationFrame;\n      }\n    | undefined;\n}\n\nexport const animationFrameProvider: AnimationFrameProvider = {\n  // When accessing the delegate, use the variable rather than `this` so that\n  // the functions can be called without being bound to the provider.\n  schedule(callback) {\n    let request = requestAnimationFrame;\n    let cancel: typeof cancelAnimationFrame | undefined = cancelAnimationFrame;\n    const { delegate } = animationFrameProvider;\n    if (delegate) {\n      request = delegate.requestAnimationFrame;\n      cancel = delegate.cancelAnimationFrame;\n    }\n    const handle = request((timestamp) => {\n      // Clear the cancel function. The request has been fulfilled, so\n      // attempting to cancel the request upon unsubscription would be\n      // pointless.\n      cancel = undefined;\n      callback(timestamp);\n    });\n    return new Subscription(() => cancel?.(handle));\n  },\n  requestAnimationFrame(...args) {\n    const { delegate } = animationFrameProvider;\n    return (delegate?.requestAnimationFrame || requestAnimationFrame)(...args);\n  },\n  cancelAnimationFrame(...args) {\n    const { delegate } = animationFrameProvider;\n    return (delegate?.cancelAnimationFrame || cancelAnimationFrame)(...args);\n  },\n  delegate: undefined,\n};\n"
  },
  {
    "path": "packages/rxjs/src/internal/scheduler/asap.ts",
    "content": "import { AsapAction } from './AsapAction.js';\nimport { AsapScheduler } from './AsapScheduler.js';\n\n/**\n *\n * Asap Scheduler\n *\n * <span class=\"informal\">Perform task as fast as it can be performed asynchronously</span>\n *\n * `asapScheduler` scheduler behaves the same as {@link asyncScheduler} scheduler when you use it to delay task\n * in time. If however you set delay to `0`, `asap` will wait for current synchronously executing\n * code to end and then it will try to execute given task as fast as possible.\n *\n * `asapScheduler` scheduler will do its best to minimize time between end of currently executing code\n * and start of scheduled task. This makes it best candidate for performing so called \"deferring\".\n * Traditionally this was achieved by calling `setTimeout(deferredTask, 0)`, but that technique involves\n * some (although minimal) unwanted delay.\n *\n * Note that using `asapScheduler` scheduler does not necessarily mean that your task will be first to process\n * after currently executing code. In particular, if some task was also scheduled with `asapScheduler` before,\n * that task will execute first. That being said, if you need to schedule task asynchronously, but\n * as soon as possible, `asapScheduler` scheduler is your best bet.\n *\n * ## Example\n * Compare async and asap scheduler<\n * ```ts\n * import { asapScheduler, asyncScheduler } from 'rxjs';\n *\n * asyncScheduler.schedule(() => console.log('async')); // scheduling 'async' first...\n * asapScheduler.schedule(() => console.log('asap'));\n *\n * // Logs:\n * // \"asap\"\n * // \"async\"\n * // ... but 'asap' goes first!\n * ```\n */\n\nexport const asapScheduler = new AsapScheduler(AsapAction);\n"
  },
  {
    "path": "packages/rxjs/src/internal/scheduler/async.ts",
    "content": "import { AsyncAction } from './AsyncAction.js';\nimport { AsyncScheduler } from './AsyncScheduler.js';\n\n/**\n *\n * Async Scheduler\n *\n * <span class=\"informal\">Schedule task as if you used setTimeout(task, duration)</span>\n *\n * `asyncScheduler` scheduler schedules tasks asynchronously, by putting them on the JavaScript\n * event loop queue. It is best used to delay tasks in time or to schedule tasks repeating\n * in intervals.\n *\n * If you just want to \"defer\" task, that is to perform it right after currently\n * executing synchronous code ends (commonly achieved by `setTimeout(deferredTask, 0)`),\n * better choice will be the {@link asapScheduler} scheduler.\n *\n * ## Examples\n * Use async scheduler to delay task\n * ```ts\n * import { asyncScheduler } from 'rxjs';\n *\n * const task = () => console.log('it works!');\n *\n * asyncScheduler.schedule(task, 2000);\n *\n * // After 2 seconds logs:\n * // \"it works!\"\n * ```\n *\n * Use async scheduler to repeat task in intervals\n * ```ts\n * import { asyncScheduler } from 'rxjs';\n *\n * function task(state) {\n *   console.log(state);\n *   this.schedule(state + 1, 1000); // `this` references currently executing Action,\n *                                   // which we reschedule with new state and delay\n * }\n *\n * asyncScheduler.schedule(task, 3000, 0);\n *\n * // Logs:\n * // 0 after 3s\n * // 1 after 4s\n * // 2 after 5s\n * // 3 after 6s\n * ```\n */\n\nexport const asyncScheduler = new AsyncScheduler(AsyncAction);\n"
  },
  {
    "path": "packages/rxjs/src/internal/scheduler/dateTimestampProvider.ts",
    "content": "import type { TimestampProvider } from '../types.js';\n\ninterface DateTimestampProvider extends TimestampProvider {\n  delegate: TimestampProvider | undefined;\n}\n\nexport const dateTimestampProvider: DateTimestampProvider = {\n  now() {\n    // Use the variable rather than `this` so that the function can be called\n    // without being bound to the provider.\n    return (dateTimestampProvider.delegate || Date).now();\n  },\n  delegate: undefined,\n};\n"
  },
  {
    "path": "packages/rxjs/src/internal/scheduler/immediateProvider.ts",
    "content": "import { Immediate } from '../util/Immediate.js';\nimport type { TimerHandle } from './timerHandle.js';\nconst { setImmediate, clearImmediate } = Immediate;\n\ntype SetImmediateFunction = (handler: () => void, ...args: any[]) => TimerHandle;\ntype ClearImmediateFunction = (handle: TimerHandle) => void;\n\ninterface ImmediateProvider {\n  setImmediate: SetImmediateFunction;\n  clearImmediate: ClearImmediateFunction;\n  delegate:\n    | {\n        setImmediate: SetImmediateFunction;\n        clearImmediate: ClearImmediateFunction;\n      }\n    | undefined;\n}\n\nexport const immediateProvider: ImmediateProvider = {\n  // When accessing the delegate, use the variable rather than `this` so that\n  // the functions can be called without being bound to the provider.\n  setImmediate(...args) {\n    const { delegate } = immediateProvider;\n    return (delegate?.setImmediate || setImmediate)(...args);\n  },\n  clearImmediate(handle) {\n    const { delegate } = immediateProvider;\n    return (delegate?.clearImmediate || clearImmediate)(handle as any);\n  },\n  delegate: undefined,\n};\n"
  },
  {
    "path": "packages/rxjs/src/internal/scheduler/intervalProvider.ts",
    "content": "import type { TimerHandle } from './timerHandle.js';\ntype SetIntervalFunction = (handler: () => void, timeout?: number, ...args: any[]) => TimerHandle;\ntype ClearIntervalFunction = (handle: TimerHandle) => void;\n\ninterface IntervalProvider {\n  setInterval: SetIntervalFunction;\n  clearInterval: ClearIntervalFunction;\n  delegate:\n    | {\n        setInterval: SetIntervalFunction;\n        clearInterval: ClearIntervalFunction;\n      }\n    | undefined;\n}\n\nexport const intervalProvider: IntervalProvider = {\n  // When accessing the delegate, use the variable rather than `this` so that\n  // the functions can be called without being bound to the provider.\n  setInterval(handler: () => void, timeout?: number, ...args) {\n    const { delegate } = intervalProvider;\n    if (delegate?.setInterval) {\n      return delegate.setInterval(handler, timeout, ...args);\n    }\n    return setInterval(handler, timeout, ...args);\n  },\n  clearInterval(handle) {\n    const { delegate } = intervalProvider;\n    return (delegate?.clearInterval || clearInterval)(handle as any);\n  },\n  delegate: undefined,\n};\n"
  },
  {
    "path": "packages/rxjs/src/internal/scheduler/performanceTimestampProvider.ts",
    "content": "import type { TimestampProvider } from '../types.js';\n\ninterface PerformanceTimestampProvider extends TimestampProvider {\n  delegate: TimestampProvider | undefined;\n}\n\nexport const performanceTimestampProvider: PerformanceTimestampProvider = {\n  now() {\n    // Use the variable rather than `this` so that the function can be called\n    // without being bound to the provider.\n    return (performanceTimestampProvider.delegate || performance).now();\n  },\n  delegate: undefined,\n};\n"
  },
  {
    "path": "packages/rxjs/src/internal/scheduler/queue.ts",
    "content": "import { QueueAction } from './QueueAction.js';\nimport { QueueScheduler } from './QueueScheduler.js';\n\n/**\n *\n * Queue Scheduler\n *\n * <span class=\"informal\">Put every next task on a queue, instead of executing it immediately</span>\n *\n * `queueScheduler` scheduler, when used with delay, behaves the same as {@link asyncScheduler} scheduler.\n *\n * When used without delay, it schedules given task synchronously - executes it right when\n * it is scheduled. However when called recursively, that is when inside the scheduled task,\n * another task is scheduled with queue scheduler, instead of executing immediately as well,\n * that task will be put on a queue and wait for current one to finish.\n *\n * This means that when you execute task with `queueScheduler` scheduler, you are sure it will end\n * before any other task scheduled with that scheduler will start.\n *\n * ## Examples\n * Schedule recursively first, then do something\n * ```ts\n * import { queueScheduler } from 'rxjs';\n *\n * queueScheduler.schedule(() => {\n *   queueScheduler.schedule(() => console.log('second')); // will not happen now, but will be put on a queue\n *\n *   console.log('first');\n * });\n *\n * // Logs:\n * // \"first\"\n * // \"second\"\n * ```\n *\n * Reschedule itself recursively\n * ```ts\n * import { queueScheduler } from 'rxjs';\n *\n * queueScheduler.schedule(function(state) {\n *   if (state !== 0) {\n *     console.log('before', state);\n *     this.schedule(state - 1); // `this` references currently executing Action,\n *                               // which we reschedule with new state\n *     console.log('after', state);\n *   }\n * }, 0, 3);\n *\n * // In scheduler that runs recursively, you would expect:\n * // \"before\", 3\n * // \"before\", 2\n * // \"before\", 1\n * // \"after\", 1\n * // \"after\", 2\n * // \"after\", 3\n *\n * // But with queue it logs:\n * // \"before\", 3\n * // \"after\", 3\n * // \"before\", 2\n * // \"after\", 2\n * // \"before\", 1\n * // \"after\", 1\n * ```\n */\n\nexport const queueScheduler = new QueueScheduler(QueueAction);\n"
  },
  {
    "path": "packages/rxjs/src/internal/scheduler/timeoutProvider.ts",
    "content": "import type { TimerHandle } from './timerHandle.js';\ntype SetTimeoutFunction = (handler: () => void, timeout?: number, ...args: any[]) => TimerHandle;\ntype ClearTimeoutFunction = (handle: TimerHandle) => void;\n\ninterface TimeoutProvider {\n  setTimeout: SetTimeoutFunction;\n  clearTimeout: ClearTimeoutFunction;\n  delegate:\n    | {\n        setTimeout: SetTimeoutFunction;\n        clearTimeout: ClearTimeoutFunction;\n      }\n    | undefined;\n}\n\nexport const timeoutProvider: TimeoutProvider = {\n  // When accessing the delegate, use the variable rather than `this` so that\n  // the functions can be called without being bound to the provider.\n  setTimeout(handler: () => void, timeout?: number, ...args) {\n    const { delegate } = timeoutProvider;\n    if (delegate?.setTimeout) {\n      return delegate.setTimeout(handler, timeout, ...args);\n    }\n    return setTimeout(handler, timeout, ...args);\n  },\n  clearTimeout(handle) {\n    const { delegate } = timeoutProvider;\n    return (delegate?.clearTimeout || clearTimeout)(handle as any);\n  },\n  delegate: undefined,\n};\n"
  },
  {
    "path": "packages/rxjs/src/internal/scheduler/timerHandle.ts",
    "content": "export type TimerHandle = number | ReturnType<typeof setTimeout>;\n"
  },
  {
    "path": "packages/rxjs/src/internal/symbol/iterator.ts",
    "content": "export function getSymbolIterator(): symbol {\n  if (typeof Symbol !== 'function' || !Symbol.iterator) {\n    return '@@iterator' as any;\n  }\n\n  return Symbol.iterator;\n}\n\nexport const iterator = getSymbolIterator();\n"
  },
  {
    "path": "packages/rxjs/src/internal/testing/ColdObservable.ts",
    "content": "import type { Subscriber} from '@rxjs/observable';\nimport { Observable, Subscription } from '@rxjs/observable';\nimport type { TestMessage } from './TestMessage.js';\nimport { observeNotification } from '../Notification.js';\nimport type { SchedulerLike, TeardownLogic } from '../types.js';\nimport type { SubscriptionLog } from './subscription-logging.js';\nimport { logSubscribedFrame, logUnsubscribedFrame } from './subscription-logging.js';\n\nexport class ColdObservable<T> extends Observable<T> {\n  public subscriptions: SubscriptionLog[] = [];\n  logSubscribedFrame = logSubscribedFrame;\n  logUnsubscribedFrame = logUnsubscribedFrame;\n\n  protected _subscribe(subscriber: Subscriber<any>): TeardownLogic {\n    const index = this.logSubscribedFrame();\n    const subscription = new Subscription();\n    subscription.add(\n      new Subscription(() => {\n        this.logUnsubscribedFrame(index);\n      })\n    );\n    this.scheduleMessages(subscriber);\n    return subscription;\n  }\n\n  constructor(public messages: TestMessage[], public scheduler: SchedulerLike) {\n    super();\n  }\n\n  scheduleMessages(subscriber: Subscriber<any>) {\n    const messagesLength = this.messages.length;\n    for (let i = 0; i < messagesLength; i++) {\n      const message = this.messages[i];\n      subscriber.add(\n        this.scheduler.schedule(\n          (state) => {\n            const {\n              message: { notification },\n              subscriber: destination,\n            } = state!;\n            observeNotification(notification, destination);\n          },\n          message.frame,\n          { message, subscriber }\n        )\n      );\n    }\n  }\n}\n"
  },
  {
    "path": "packages/rxjs/src/internal/testing/HotObservable.ts",
    "content": "import { Subject } from '../Subject.js';\nimport type { Subscriber} from '@rxjs/observable';\nimport { Subscription } from '@rxjs/observable';\nimport type { Scheduler } from '../Scheduler.js';\nimport type { TestMessage } from './TestMessage.js';\nimport { observeNotification } from '../Notification.js';\nimport type { SubscriptionLog } from './subscription-logging.js';\nimport { logSubscribedFrame, logUnsubscribedFrame } from './subscription-logging.js';\n\nexport class HotObservable<T> extends Subject<T> {\n  public subscriptions: SubscriptionLog[] = [];\n\n  logSubscribedFrame = logSubscribedFrame;\n\n  logUnsubscribedFrame = logUnsubscribedFrame;\n\n  constructor(public messages: TestMessage[], public scheduler: Scheduler) {\n    super();\n  }\n\n  /** @internal */\n  protected _subscribe(subscriber: Subscriber<any>): Subscription {\n    const index = this.logSubscribedFrame();\n    const subscription = new Subscription();\n    subscription.add(\n      new Subscription(() => {\n        this.logUnsubscribedFrame(index);\n      })\n    );\n    subscription.add(super._subscribe(subscriber));\n    return subscription;\n  }\n\n  setup() {\n    for (const { notification, frame } of this.messages) {\n      this.scheduler.schedule(() => {\n        observeNotification(notification, this);\n      }, frame);\n    }\n  }\n}\n"
  },
  {
    "path": "packages/rxjs/src/internal/testing/TestMessage.ts",
    "content": "import type { ObservableNotification } from '../types.js';\n\nexport interface TestMessage {\n  frame: number;\n  notification: ObservableNotification<any>;\n  isGhost?: boolean;\n}\n"
  },
  {
    "path": "packages/rxjs/src/internal/testing/TestScheduler.ts",
    "content": "import { Subscription } from '@rxjs/observable';\nimport { Observable, COMPLETE_NOTIFICATION, errorNotification, nextNotification } from '@rxjs/observable';\nimport { ColdObservable } from './ColdObservable.js';\nimport { HotObservable } from './HotObservable.js';\nimport type { TestMessage } from './TestMessage.js';\nimport { SubscriptionLog } from './subscription-logging.js';\nimport { VirtualTimeScheduler, VirtualAction } from '../scheduler/VirtualTimeScheduler.js';\nimport type { ObservableNotification } from '../types.js';\nimport { dateTimestampProvider } from '../scheduler/dateTimestampProvider.js';\nimport { performanceTimestampProvider } from '../scheduler/performanceTimestampProvider.js';\nimport { animationFrameProvider } from '../scheduler/animationFrameProvider.js';\nimport type { TimerHandle } from '../scheduler/timerHandle.js';\nimport { immediateProvider } from '../scheduler/immediateProvider.js';\nimport { intervalProvider } from '../scheduler/intervalProvider.js';\nimport { timeoutProvider } from '../scheduler/timeoutProvider.js';\n\nconst defaultMaxFrame: number = 750;\n\nexport interface RunHelpers {\n  cold: typeof TestScheduler.prototype.createColdObservable;\n  hot: typeof TestScheduler.prototype.createHotObservable;\n  flush: typeof TestScheduler.prototype.flush;\n  time: typeof TestScheduler.prototype.createTime;\n  expectObservable: typeof TestScheduler.prototype.expectObservable;\n  expectSubscriptions: typeof TestScheduler.prototype.expectSubscriptions;\n  animate: (marbles: string) => void;\n}\n\ninterface FlushableTest {\n  ready: boolean;\n  actual?: any[];\n  expected?: any[];\n}\n\nexport type observableToBeFn = (marbles: string, values?: any, errorValue?: any) => void;\nexport type subscriptionLogsToBeFn = (marbles: string | string[]) => void;\n\nexport class TestScheduler extends VirtualTimeScheduler {\n  /**\n   * The number of virtual time units each character in a marble diagram represents. If\n   * the test scheduler is being used in \"run mode\", via the `run` method, this is temporarily\n   * set to `1` for the duration of the `run` block, then set back to whatever value it was.\n   */\n  static frameTimeFactor = 10;\n\n  /**\n   * @deprecated Internal implementation detail, do not use directly. Will be made internal in v8.\n   */\n  public readonly hotObservables: HotObservable<any>[] = [];\n\n  /**\n   * @deprecated Internal implementation detail, do not use directly. Will be made internal in v8.\n   */\n  public readonly coldObservables: ColdObservable<any>[] = [];\n\n  /**\n   * Test meta data to be processed during `flush()`\n   */\n  private flushTests: FlushableTest[] = [];\n\n  /**\n   * Indicates whether the TestScheduler instance is operating in \"run mode\",\n   * meaning it's processing a call to `run()`\n   */\n  private runMode = false;\n\n  /**\n   *\n   * @param assertDeepEqual A function to set up your assertion for your test harness\n   */\n  constructor(public assertDeepEqual: (actual: any, expected: any) => boolean | void) {\n    super(VirtualAction, defaultMaxFrame);\n  }\n\n  createTime(marbles: string): number {\n    const indexOf = this.runMode ? marbles.trim().indexOf('|') : marbles.indexOf('|');\n    if (indexOf === -1) {\n      throw new Error('marble diagram for time should have a completion marker \"|\"');\n    }\n    return indexOf * TestScheduler.frameTimeFactor;\n  }\n\n  /**\n   * @param marbles A diagram in the marble DSL. Letters map to keys in `values` if provided.\n   * @param values Values to use for the letters in `marbles`. If omitted, the letters themselves are used.\n   * @param error The error to use for the `#` marble (if present).\n   */\n  createColdObservable<T = string>(marbles: string, values?: { [marble: string]: T }, error?: any): ColdObservable<T> {\n    if (marbles.indexOf('^') !== -1) {\n      throw new Error('cold observable cannot have subscription offset \"^\"');\n    }\n    if (marbles.indexOf('!') !== -1) {\n      throw new Error('cold observable cannot have unsubscription marker \"!\"');\n    }\n    const messages = TestScheduler.parseMarbles(marbles, values, error, undefined, this.runMode);\n    const cold = new ColdObservable<T>(messages, this);\n    this.coldObservables.push(cold);\n    return cold;\n  }\n\n  /**\n   * @param marbles A diagram in the marble DSL. Letters map to keys in `values` if provided.\n   * @param values Values to use for the letters in `marbles`. If omitted, the letters themselves are used.\n   * @param error The error to use for the `#` marble (if present).\n   */\n  createHotObservable<T = string>(marbles: string, values?: { [marble: string]: T }, error?: any): HotObservable<T> {\n    if (marbles.indexOf('!') !== -1) {\n      throw new Error('hot observable cannot have unsubscription marker \"!\"');\n    }\n    const messages = TestScheduler.parseMarbles(marbles, values, error, undefined, this.runMode);\n    const subject = new HotObservable<T>(messages, this);\n    this.hotObservables.push(subject);\n    return subject;\n  }\n\n  private materializeInnerObservable(observable: Observable<any>, outerFrame: number): TestMessage[] {\n    const messages: TestMessage[] = [];\n    observable.subscribe({\n      next: (value) => {\n        messages.push({ frame: this.frame - outerFrame, notification: nextNotification(value) });\n      },\n      error: (error) => {\n        messages.push({ frame: this.frame - outerFrame, notification: errorNotification(error) });\n      },\n      complete: () => {\n        messages.push({ frame: this.frame - outerFrame, notification: COMPLETE_NOTIFICATION });\n      },\n    });\n    return messages;\n  }\n\n  expectObservable<T>(observable: Observable<T>, subscriptionMarbles: string | null = null) {\n    const actual: TestMessage[] = [];\n    const flushTest: FlushableTest = { actual, ready: false };\n    const subscriptionParsed = TestScheduler.parseMarblesAsSubscriptions(subscriptionMarbles, this.runMode);\n    const subscriptionFrame = subscriptionParsed.subscribedFrame === Infinity ? 0 : subscriptionParsed.subscribedFrame;\n    const unsubscriptionFrame = subscriptionParsed.unsubscribedFrame;\n    const subscription = new Subscription();\n\n    this.schedule(() => {\n      subscription.add(\n        observable.subscribe({\n          next: (x) => {\n            // Support Observable-of-Observables\n            const value = x instanceof Observable ? this.materializeInnerObservable(x, this.frame) : x;\n            actual.push({ frame: this.frame, notification: nextNotification(value) });\n          },\n          error: (error) => {\n            actual.push({ frame: this.frame, notification: errorNotification(error) });\n          },\n          complete: () => {\n            actual.push({ frame: this.frame, notification: COMPLETE_NOTIFICATION });\n          },\n        })\n      );\n    }, subscriptionFrame);\n\n    if (unsubscriptionFrame !== Infinity) {\n      this.schedule(() => subscription.unsubscribe(), unsubscriptionFrame);\n    }\n\n    this.flushTests.push(flushTest);\n    const { runMode } = this;\n\n    return {\n      toBe(marbles: string, values?: any, errorValue?: any) {\n        flushTest.ready = true;\n        flushTest.expected = TestScheduler.parseMarbles(marbles, values, errorValue, true, runMode);\n      },\n      toEqual: (other: Observable<T>) => {\n        flushTest.ready = true;\n        flushTest.expected = [];\n        this.schedule(() => {\n          subscription.add(\n            other.subscribe({\n              next: (x) => {\n                // Support Observable-of-Observables\n                const value = x instanceof Observable ? this.materializeInnerObservable(x, this.frame) : x;\n                flushTest.expected!.push({ frame: this.frame, notification: nextNotification(value) });\n              },\n              error: (error) => {\n                flushTest.expected!.push({ frame: this.frame, notification: errorNotification(error) });\n              },\n              complete: () => {\n                flushTest.expected!.push({ frame: this.frame, notification: COMPLETE_NOTIFICATION });\n              },\n            })\n          );\n        }, subscriptionFrame);\n      },\n    };\n  }\n\n  expectSubscriptions(actualSubscriptionLogs: SubscriptionLog[]): { toBe: subscriptionLogsToBeFn } {\n    const flushTest: FlushableTest = { actual: actualSubscriptionLogs, ready: false };\n    this.flushTests.push(flushTest);\n    const { runMode } = this;\n    return {\n      toBe(marblesOrMarblesArray: string | string[]) {\n        const marblesArray: string[] = typeof marblesOrMarblesArray === 'string' ? [marblesOrMarblesArray] : marblesOrMarblesArray;\n        flushTest.ready = true;\n        flushTest.expected = marblesArray\n          .map((marbles) => TestScheduler.parseMarblesAsSubscriptions(marbles, runMode))\n          .filter((marbles) => marbles.subscribedFrame !== Infinity);\n      },\n    };\n  }\n\n  flush() {\n    const hotObservables = this.hotObservables;\n    while (hotObservables.length > 0) {\n      hotObservables.shift()!.setup();\n    }\n\n    super.flush();\n\n    this.flushTests = this.flushTests.filter((test) => {\n      if (test.ready) {\n        this.assertDeepEqual(test.actual, test.expected);\n        return false;\n      }\n      return true;\n    });\n  }\n\n  static parseMarblesAsSubscriptions(marbles: string | null, runMode = false): SubscriptionLog {\n    if (typeof marbles !== 'string') {\n      return new SubscriptionLog(Infinity);\n    }\n    // Spreading the marbles into an array leverages ES2015's support for emoji\n    // characters when iterating strings.\n    const characters = [...marbles];\n    const len = characters.length;\n    let groupStart = -1;\n    let subscriptionFrame = Infinity;\n    let unsubscriptionFrame = Infinity;\n    let frame = 0;\n\n    for (let i = 0; i < len; i++) {\n      let nextFrame = frame;\n      const advanceFrameBy = (count: number) => {\n        nextFrame += count * this.frameTimeFactor;\n      };\n      const c = characters[i];\n      switch (c) {\n        case ' ':\n          // Whitespace no longer advances time\n          if (!runMode) {\n            advanceFrameBy(1);\n          }\n          break;\n        case '-':\n          advanceFrameBy(1);\n          break;\n        case '(':\n          groupStart = frame;\n          advanceFrameBy(1);\n          break;\n        case ')':\n          groupStart = -1;\n          advanceFrameBy(1);\n          break;\n        case '^':\n          if (subscriptionFrame !== Infinity) {\n            throw new Error(\"found a second subscription point '^' in a \" + 'subscription marble diagram. There can only be one.');\n          }\n          subscriptionFrame = groupStart > -1 ? groupStart : frame;\n          advanceFrameBy(1);\n          break;\n        case '!':\n          if (unsubscriptionFrame !== Infinity) {\n            throw new Error(\"found a second unsubscription point '!' in a \" + 'subscription marble diagram. There can only be one.');\n          }\n          unsubscriptionFrame = groupStart > -1 ? groupStart : frame;\n          break;\n        default:\n          // time progression syntax\n          if (runMode && c.match(/^[0-9]$/)) {\n            // Time progression must be preceded by at least one space\n            // if it's not at the beginning of the diagram\n            if (i === 0 || characters[i - 1] === ' ') {\n              const buffer = characters.slice(i).join('');\n              const match = buffer.match(/^([0-9]+(?:\\.[0-9]+)?)(ms|s|m) /);\n              if (match) {\n                i += match[0].length - 1;\n                const duration = parseFloat(match[1]);\n                const unit = match[2];\n                let durationInMs: number;\n\n                switch (unit) {\n                  case 'ms':\n                    durationInMs = duration;\n                    break;\n                  case 's':\n                    durationInMs = duration * 1000;\n                    break;\n                  case 'm':\n                    durationInMs = duration * 1000 * 60;\n                    break;\n                  default:\n                    break;\n                }\n\n                advanceFrameBy(durationInMs! / this.frameTimeFactor);\n                break;\n              }\n            }\n          }\n\n          throw new Error(\"there can only be '^' and '!' markers in a \" + \"subscription marble diagram. Found instead '\" + c + \"'.\");\n      }\n\n      frame = nextFrame;\n    }\n\n    if (unsubscriptionFrame < 0) {\n      return new SubscriptionLog(subscriptionFrame);\n    } else {\n      return new SubscriptionLog(subscriptionFrame, unsubscriptionFrame);\n    }\n  }\n\n  static parseMarbles(\n    marbles: string,\n    values?: any,\n    errorValue?: any,\n    materializeInnerObservables: boolean = false,\n    runMode = false\n  ): TestMessage[] {\n    if (marbles.indexOf('!') !== -1) {\n      throw new Error('conventional marble diagrams cannot have the ' + 'unsubscription marker \"!\"');\n    }\n    // Spreading the marbles into an array leverages ES2015's support for emoji\n    // characters when iterating strings.\n    const characters = [...marbles];\n    const len = characters.length;\n    const testMessages: TestMessage[] = [];\n    const subIndex = runMode ? marbles.replace(/^[ ]+/, '').indexOf('^') : marbles.indexOf('^');\n    let frame = subIndex === -1 ? 0 : subIndex * -this.frameTimeFactor;\n    const getValue =\n      typeof values !== 'object'\n        ? (x: any) => x\n        : (x: any) => {\n            // Support Observable-of-Observables\n            if (materializeInnerObservables && values[x] instanceof ColdObservable) {\n              return values[x].messages;\n            }\n            return values[x];\n          };\n    let groupStart = -1;\n\n    for (let i = 0; i < len; i++) {\n      let nextFrame = frame;\n      const advanceFrameBy = (count: number) => {\n        nextFrame += count * this.frameTimeFactor;\n      };\n\n      let notification: ObservableNotification<any> | undefined;\n      const c = characters[i];\n      switch (c) {\n        case ' ':\n          // Whitespace no longer advances time\n          if (!runMode) {\n            advanceFrameBy(1);\n          }\n          break;\n        case '-':\n          advanceFrameBy(1);\n          break;\n        case '(':\n          groupStart = frame;\n          advanceFrameBy(1);\n          break;\n        case ')':\n          groupStart = -1;\n          advanceFrameBy(1);\n          break;\n        case '|':\n          notification = COMPLETE_NOTIFICATION;\n          advanceFrameBy(1);\n          break;\n        case '^':\n          advanceFrameBy(1);\n          break;\n        case '#':\n          notification = errorNotification(errorValue || 'error');\n          advanceFrameBy(1);\n          break;\n        default:\n          // Might be time progression syntax, or a value literal\n          if (runMode && c.match(/^[0-9]$/)) {\n            // Time progression must be preceded by at least one space\n            // if it's not at the beginning of the diagram\n            if (i === 0 || characters[i - 1] === ' ') {\n              const buffer = characters.slice(i).join('');\n              const match = buffer.match(/^([0-9]+(?:\\.[0-9]+)?)(ms|s|m) /);\n              if (match) {\n                i += match[0].length - 1;\n                const duration = parseFloat(match[1]);\n                const unit = match[2];\n                let durationInMs: number;\n\n                switch (unit) {\n                  case 'ms':\n                    durationInMs = duration;\n                    break;\n                  case 's':\n                    durationInMs = duration * 1000;\n                    break;\n                  case 'm':\n                    durationInMs = duration * 1000 * 60;\n                    break;\n                  default:\n                    break;\n                }\n\n                advanceFrameBy(durationInMs! / this.frameTimeFactor);\n                break;\n              }\n            }\n          }\n\n          notification = nextNotification(getValue(c));\n          advanceFrameBy(1);\n          break;\n      }\n\n      if (notification) {\n        testMessages.push({ frame: groupStart > -1 ? groupStart : frame, notification });\n      }\n\n      frame = nextFrame;\n    }\n    return testMessages;\n  }\n\n  private createAnimator() {\n    if (!this.runMode) {\n      throw new Error('animate() must only be used in run mode');\n    }\n\n    // The TestScheduler assigns a delegate to the provider that's used for\n    // requestAnimationFrame (rAF). The delegate works in conjunction with the\n    // animate run helper to coordinate the invocation of any rAF callbacks,\n    // that are effected within tests, with the animation frames specified by\n    // the test's author - in the marbles that are passed to the animate run\n    // helper. This allows the test's author to write deterministic tests and\n    // gives the author full control over when - or if - animation frames are\n    // 'painted'.\n\n    let lastHandle = 0;\n    let map: Map<number, FrameRequestCallback> | undefined;\n\n    const delegate = {\n      requestAnimationFrame(callback: FrameRequestCallback) {\n        if (!map) {\n          throw new Error('animate() was not called within run()');\n        }\n        const handle = ++lastHandle;\n        map.set(handle, callback);\n        return handle;\n      },\n      cancelAnimationFrame(handle: number) {\n        if (!map) {\n          throw new Error('animate() was not called within run()');\n        }\n        map.delete(handle);\n      },\n    };\n\n    const animate = (marbles: string) => {\n      if (map) {\n        throw new Error('animate() must not be called more than once within run()');\n      }\n      if (/[|#]/.test(marbles)) {\n        throw new Error('animate() must not complete or error');\n      }\n      map = new Map<number, FrameRequestCallback>();\n      const messages = TestScheduler.parseMarbles(marbles, undefined, undefined, undefined, true);\n      for (const message of messages) {\n        this.schedule(() => {\n          const now = this.now();\n          // Capture the callbacks within the queue and clear the queue\n          // before enumerating the callbacks, as callbacks might\n          // reschedule themselves. (And, yeah, we're using a Map to represent\n          // the queue, but the values are guaranteed to be returned in\n          // insertion order, so it's all good. Trust me, I've read the docs.)\n          const callbacks = Array.from(map!.values());\n          map!.clear();\n          for (const callback of callbacks) {\n            callback(now);\n          }\n        }, message.frame);\n      }\n    };\n\n    return { animate, delegate };\n  }\n\n  private createDelegates() {\n    // When in run mode, the TestScheduler provides alternate implementations\n    // of set/clearImmediate and set/clearInterval. These implementations are\n    // consumed by the scheduler implementations via the providers. This is\n    // done to effect deterministic asap and async scheduler behavior so that\n    // all of the schedulers are testable in 'run mode'. Prior to v7,\n    // delegation occurred at the scheduler level. That is, the asap and\n    // animation frame schedulers were identical in behavior to the async\n    // scheduler. Now, when in run mode, asap actions are prioritized over\n    // async actions and animation frame actions are coordinated using the\n    // animate run helper.\n\n    let lastHandle = 0;\n    const scheduleLookup = new Map<\n      TimerHandle,\n      {\n        due: number;\n        duration: number;\n        handle: TimerHandle;\n        handler: () => void;\n        subscription: Subscription;\n        type: 'immediate' | 'interval' | 'timeout';\n      }\n    >();\n\n    const run = () => {\n      // Whenever a scheduled run is executed, it must run a single immediate\n      // or interval action - with immediate actions being prioritized over\n      // interval and timeout actions.\n      const now = this.now();\n      const scheduledRecords = Array.from(scheduleLookup.values());\n      const scheduledRecordsDue = scheduledRecords.filter(({ due }) => due <= now);\n      const dueImmediates = scheduledRecordsDue.filter(({ type }) => type === 'immediate');\n      if (dueImmediates.length > 0) {\n        const { handle, handler } = dueImmediates[0];\n        scheduleLookup.delete(handle);\n        handler();\n        return;\n      }\n      const dueIntervals = scheduledRecordsDue.filter(({ type }) => type === 'interval');\n      if (dueIntervals.length > 0) {\n        const firstDueInterval = dueIntervals[0];\n        const { duration, handler } = firstDueInterval;\n        firstDueInterval.due = now + duration;\n        // The interval delegate must behave like setInterval, so run needs to\n        // be rescheduled. This will continue until the clearInterval delegate\n        // unsubscribes and deletes the handle from the map.\n        firstDueInterval.subscription = this.schedule(run, duration);\n        handler();\n        return;\n      }\n      const dueTimeouts = scheduledRecordsDue.filter(({ type }) => type === 'timeout');\n      if (dueTimeouts.length > 0) {\n        const { handle, handler } = dueTimeouts[0];\n        scheduleLookup.delete(handle);\n        handler();\n        return;\n      }\n      throw new Error('Expected a due immediate or interval');\n    };\n\n    // The following objects are the delegates that replace conventional\n    // runtime implementations with TestScheduler implementations.\n    //\n    // The immediate delegate is depended upon by the asapScheduler.\n    //\n    // The interval delegate is depended upon by the asyncScheduler.\n    //\n    // The timeout delegate is not depended upon by any scheduler, but it's\n    // included here because the onUnhandledError and onStoppedNotification\n    // configuration points use setTimeout to avoid producer interference. It's\n    // inclusion allows for the testing of these configuration points.\n\n    const immediate = {\n      setImmediate: (handler: () => void) => {\n        const handle = ++lastHandle;\n        scheduleLookup.set(handle, {\n          due: this.now(),\n          duration: 0,\n          handle,\n          handler,\n          subscription: this.schedule(run, 0),\n          type: 'immediate',\n        });\n        return handle;\n      },\n      clearImmediate: (handle: TimerHandle) => {\n        const value = scheduleLookup.get(handle);\n        if (value) {\n          value.subscription.unsubscribe();\n          scheduleLookup.delete(handle);\n        }\n      },\n    };\n\n    const interval = {\n      setInterval: (handler: () => void, duration = 0) => {\n        const handle = ++lastHandle;\n        scheduleLookup.set(handle, {\n          due: this.now() + duration,\n          duration,\n          handle,\n          handler,\n          subscription: this.schedule(run, duration),\n          type: 'interval',\n        });\n        return handle;\n      },\n      clearInterval: (handle: TimerHandle) => {\n        const value = scheduleLookup.get(handle);\n        if (value) {\n          value.subscription.unsubscribe();\n          scheduleLookup.delete(handle);\n        }\n      },\n    };\n\n    const timeout = {\n      setTimeout: (handler: () => void, duration = 0) => {\n        const handle = ++lastHandle;\n        scheduleLookup.set(handle, {\n          due: this.now() + duration,\n          duration,\n          handle,\n          handler,\n          subscription: this.schedule(run, duration),\n          type: 'timeout',\n        });\n        return handle;\n      },\n      clearTimeout: (handle: TimerHandle) => {\n        const value = scheduleLookup.get(handle);\n        if (value) {\n          value.subscription.unsubscribe();\n          scheduleLookup.delete(handle);\n        }\n      },\n    };\n\n    return { immediate, interval, timeout };\n  }\n\n  /**\n   * The `run` method performs the test in 'run mode' - in which schedulers\n   * used within the test automatically delegate to the `TestScheduler`. That\n   * is, in 'run mode' there is no need to explicitly pass a `TestScheduler`\n   * instance to observable creators or operators.\n   *\n   * @see {@link /guide/testing/marble-testing}\n   */\n  run<T>(callback: (helpers: RunHelpers) => T): T {\n    const prevFrameTimeFactor = TestScheduler.frameTimeFactor;\n    const prevMaxFrames = this.maxFrames;\n\n    TestScheduler.frameTimeFactor = 1;\n    this.maxFrames = Infinity;\n    this.runMode = true;\n\n    const animator = this.createAnimator();\n    const delegates = this.createDelegates();\n\n    animationFrameProvider.delegate = animator.delegate;\n    dateTimestampProvider.delegate = this;\n    immediateProvider.delegate = delegates.immediate;\n    intervalProvider.delegate = delegates.interval;\n    timeoutProvider.delegate = delegates.timeout;\n    performanceTimestampProvider.delegate = this;\n\n    const helpers: RunHelpers = {\n      cold: this.createColdObservable.bind(this),\n      hot: this.createHotObservable.bind(this),\n      flush: this.flush.bind(this),\n      time: this.createTime.bind(this),\n      expectObservable: this.expectObservable.bind(this),\n      expectSubscriptions: this.expectSubscriptions.bind(this),\n      animate: animator.animate,\n    };\n    try {\n      const ret = callback(helpers);\n      this.flush();\n      return ret;\n    } finally {\n      TestScheduler.frameTimeFactor = prevFrameTimeFactor;\n      this.maxFrames = prevMaxFrames;\n      this.runMode = false;\n      animationFrameProvider.delegate = undefined;\n      dateTimestampProvider.delegate = undefined;\n      immediateProvider.delegate = undefined;\n      intervalProvider.delegate = undefined;\n      timeoutProvider.delegate = undefined;\n      performanceTimestampProvider.delegate = undefined;\n    }\n  }\n}\n"
  },
  {
    "path": "packages/rxjs/src/internal/testing/subscription-logging.ts",
    "content": "interface SubscriptionLoggingProps {\n  subscriptions: SubscriptionLog[];\n  scheduler: { now(): number };\n}\n\nexport class SubscriptionLog {\n  constructor(public subscribedFrame: number, public unsubscribedFrame: number = Infinity) {}\n}\n\nexport function logUnsubscribedFrame(this: SubscriptionLoggingProps, index: number) {\n  const subscriptionLogs = this.subscriptions;\n  const oldSubscriptionLog = subscriptionLogs[index];\n  subscriptionLogs[index] = new SubscriptionLog(oldSubscriptionLog.subscribedFrame, this.scheduler.now());\n}\n\nexport function logSubscribedFrame(this: SubscriptionLoggingProps): number {\n  this.subscriptions.push(new SubscriptionLog(this.scheduler.now()));\n  return this.subscriptions.length - 1;\n}\n"
  },
  {
    "path": "packages/rxjs/src/internal/types.ts",
    "content": "// https://github.com/microsoft/TypeScript/issues/40462#issuecomment-689879308\n/// <reference lib=\"esnext.asynciterable\" />\n\nimport type { Observable, Subscription } from '@rxjs/observable';\n\n/**\n * Note: This will add Symbol.observable globally for all TypeScript users,\n * however, we are no longer polyfilling Symbol.observable\n */\ndeclare global {\n  interface SymbolConstructor {\n    readonly observable: symbol;\n  }\n}\n\n/* OPERATOR INTERFACES */\n\n/**\n * A function type interface that describes a function that accepts one parameter `T`\n * and returns another parameter `R`.\n *\n * Usually used to describe {@link OperatorFunction} - it always takes a single\n * parameter (the source Observable) and returns another Observable.\n */\nexport interface UnaryFunction<T, R> {\n  (source: T): R;\n}\n\nexport interface OperatorFunction<T, R> extends UnaryFunction<Observable<T>, Observable<R>> {}\n\nexport type FactoryOrValue<T> = T | (() => T);\n\n/**\n * A function type interface that describes a function that accepts and returns a parameter of the same type.\n *\n * Used to describe {@link OperatorFunction} with the only one type: `OperatorFunction<T, T>`.\n *\n */\nexport interface MonoTypeOperatorFunction<T> extends OperatorFunction<T, T> {}\n\n/**\n * A value and the time at which it was emitted.\n *\n * Emitted by the `timestamp` operator\n *\n * @see {@link timestamp}\n */\nexport interface Timestamp<T> {\n  value: T;\n  /**\n   * The timestamp. By default, this is in epoch milliseconds.\n   * Could vary based on the timestamp provider passed to the operator.\n   */\n  timestamp: number;\n}\n\n/**\n * A value emitted and the amount of time since the last value was emitted.\n *\n * Emitted by the `timeInterval` operator.\n *\n * @see {@link timeInterval}\n */\nexport interface TimeInterval<T> {\n  value: T;\n\n  /**\n   * The amount of time between this value's emission and the previous value's emission.\n   * If this is the first emitted value, then it will be the amount of time since subscription\n   * started.\n   */\n  interval: number;\n}\n\n/* SUBSCRIPTION INTERFACES */\n\nexport interface Unsubscribable {\n  unsubscribe(): void;\n}\n\nexport type TeardownLogic = Subscription | Unsubscribable | (() => void) | void;\n\nexport interface SubscriptionLike extends Unsubscribable {\n  unsubscribe(): void;\n  readonly closed: boolean;\n}\n\n/* OBSERVABLE INTERFACES */\n\nexport interface Subscribable<T> {\n  subscribe(observer: Partial<Observer<T>>): Unsubscribable;\n}\n\n/**\n * Valid types that can be converted to observables.\n */\nexport type ObservableInput<T> =\n  | Observable<T>\n  | InteropObservable<T>\n  | AsyncIterable<T>\n  | PromiseLike<T>\n  | ArrayLike<T>\n  | Iterable<T>\n  | ReadableStreamLike<T>;\n\n/**\n * An object that implements the `Symbol.observable` interface.\n */\nexport interface InteropObservable<T> {\n  [Symbol.observable]: () => Subscribable<T>;\n}\n\n/* NOTIFICATIONS */\n\n/**\n * A notification representing a \"next\" from an observable.\n * Can be used with {@link dematerialize}.\n */\nexport interface NextNotification<T> {\n  /** The kind of notification. Always \"N\" */\n  kind: 'N';\n  /** The value of the notification. */\n  value: T;\n}\n\n/**\n * A notification representing an \"error\" from an observable.\n * Can be used with {@link dematerialize}.\n */\nexport interface ErrorNotification {\n  /** The kind of notification. Always \"E\" */\n  kind: 'E';\n  error: any;\n}\n\n/**\n * A notification representing a \"completion\" from an observable.\n * Can be used with {@link dematerialize}.\n */\nexport interface CompleteNotification {\n  kind: 'C';\n}\n\n/**\n * Valid observable notification types.\n */\nexport type ObservableNotification<T> = NextNotification<T> | ErrorNotification | CompleteNotification;\n\n/* OBSERVER INTERFACES */\n\nexport interface NextObserver<T> {\n  closed?: boolean;\n  next: (value: T) => void;\n  error?: (err: any) => void;\n  complete?: () => void;\n}\n\nexport interface ErrorObserver<T> {\n  closed?: boolean;\n  next?: (value: T) => void;\n  error: (err: any) => void;\n  complete?: () => void;\n}\n\nexport interface CompletionObserver<T> {\n  closed?: boolean;\n  next?: (value: T) => void;\n  error?: (err: any) => void;\n  complete: () => void;\n}\n\nexport type PartialObserver<T> = NextObserver<T> | ErrorObserver<T> | CompletionObserver<T>;\n\n/**\n * An object interface that defines a set of callback functions a user can use to get\n * notified of any set of {@link Observable}\n * {@link guide/glossary-and-semantics#notification notification} events.\n *\n * For more info, please refer to {@link guide/observer this guide}.\n */\nexport interface Observer<T> {\n  /**\n   * A callback function that gets called by the producer during the subscription when\n   * the producer \"has\" the `value`. It won't be called if `error` or `complete` callback\n   * functions have been called, nor after the consumer has unsubscribed.\n   *\n   * For more info, please refer to {@link guide/glossary-and-semantics#next this guide}.\n   */\n  next: (value: T) => void;\n  /**\n   * A callback function that gets called by the producer if and when it encountered a\n   * problem of any kind. The errored value will be provided through the `err` parameter.\n   * This callback can't be called more than one time, it can't be called if the\n   * `complete` callback function have been called previously, nor it can't be called if\n   * the consumer has unsubscribed.\n   *\n   * For more info, please refer to {@link guide/glossary-and-semantics#error this guide}.\n   */\n  error: (err: any) => void;\n  /**\n   * A callback function that gets called by the producer if and when it has no more\n   * values to provide (by calling `next` callback function). This means that no error\n   * has happened. This callback can't be called more than one time, it can't be called\n   * if the `error` callback function have been called previously, nor it can't be called\n   * if the consumer has unsubscribed.\n   *\n   * For more info, please refer to {@link guide/glossary-and-semantics#complete this guide}.\n   */\n  complete: () => void;\n}\n\nexport interface SubjectLike<T> extends Observer<T>, Subscribable<T> {}\n\n/* SCHEDULER INTERFACES */\n\nexport interface SchedulerLike extends TimestampProvider {\n  schedule<T>(work: (this: SchedulerAction<T>, state: T) => void, delay: number, state: T): Subscription;\n  schedule<T>(work: (this: SchedulerAction<T>, state?: T) => void, delay: number, state?: T): Subscription;\n  schedule<T>(work: (this: SchedulerAction<T>, state?: T) => void, delay?: number, state?: T): Subscription;\n}\n\nexport interface SchedulerAction<T> extends Subscription {\n  schedule(state?: T, delay?: number): Subscription;\n}\n\n/**\n * This is a type that provides a method to allow RxJS to create a numeric timestamp\n */\nexport interface TimestampProvider {\n  /**\n   * Returns a timestamp as a number.\n   *\n   * This is used by types like `ReplaySubject` or operators like `timestamp` to calculate\n   * the amount of time passed between events.\n   */\n  now(): number;\n}\n\n/**\n * Extracts the type from an `ObservableInput<any>`. If you have\n * `O extends ObservableInput<any>` and you pass in `Observable<number>`, or\n * `Promise<number>`, etc, it will type as `number`.\n */\nexport type ObservedValueOf<O> = O extends ObservableInput<infer T> ? T : never;\n\n/**\n * Extracts a union of element types from an `ObservableInput<any>[]`.\n * If you have `O extends ObservableInput<any>[]` and you pass in\n * `Observable<string>[]` or `Promise<string>[]` you would get\n * back a type of `string`.\n * If you pass in `[Observable<string>, Observable<number>]` you would\n * get back a type of `string | number`.\n */\nexport type ObservedValueUnionFromArray<X> = X extends Array<ObservableInput<infer T>> ? T : never;\n\n/**\n * Extracts a tuple of element types from an `ObservableInput<any>[]`.\n * If you have `O extends ObservableInput<any>[]` and you pass in\n * `[Observable<string>, Observable<number>]` you would get back a type\n * of `[string, number]`.\n */\nexport type ObservedValueTupleFromArray<X> = { [K in keyof X]: ObservedValueOf<X[K]> };\n\n/**\n * Used to infer types from arguments to functions like {@link forkJoin}.\n * So that you can have `forkJoin([Observable<A>, PromiseLike<B>]): Observable<[A, B]>`\n * et al.\n */\nexport type ObservableInputTuple<T> = {\n  [K in keyof T]: ObservableInput<T[K]>;\n};\n\n/**\n * Constructs a new tuple with the specified type at the head.\n * If you declare `Cons<A, [B, C]>` you will get back `[A, B, C]`.\n */\nexport type Cons<X, Y extends readonly any[]> = ((arg: X, ...rest: Y) => any) extends (...args: infer U) => any ? U : never;\n\n/**\n * Extracts the head of a tuple.\n * If you declare `Head<[A, B, C]>` you will get back `A`.\n */\nexport type Head<X extends readonly any[]> = ((...args: X) => any) extends (arg: infer U, ...rest: any[]) => any ? U : never;\n\n/**\n * Extracts the tail of a tuple.\n * If you declare `Tail<[A, B, C]>` you will get back `[B, C]`.\n */\nexport type Tail<X extends readonly any[]> = ((...args: X) => any) extends (arg: any, ...rest: infer U) => any ? U : never;\n\n/**\n * Extracts the generic value from an Array type.\n * If you have `T extends Array<any>`, and pass a `string[]` to it,\n * `ValueFromArray<T>` will return the actual type of `string`.\n */\nexport type ValueFromArray<A extends readonly unknown[]> = A extends Array<infer T> ? T : never;\n\n/**\n * Gets the value type from an {@link ObservableNotification}, if possible.\n */\nexport type ValueFromNotification<T> = T extends { kind: 'N' | 'E' | 'C' }\n  ? T extends NextNotification<any>\n    ? T extends { value: infer V }\n      ? V\n      : undefined\n    : never\n  : never;\n\n/**\n * A simple type to represent a gamut of \"falsy\" values... with a notable exception:\n * `NaN` is \"falsy\" however, it is not and cannot be typed via TypeScript. See\n * comments here: https://github.com/microsoft/TypeScript/issues/28682#issuecomment-707142417\n */\nexport type Falsy = null | undefined | false | 0 | -0 | 0n | '';\n\nexport type TruthyTypesOf<T> = T extends Falsy ? never : T;\n\n/**\n * The base signature RxJS will look for to identify and use\n * a [ReadableStream](https://streams.spec.whatwg.org/#rs-class)\n * as an {@link ObservableInput} source.\n */\nexport type ReadableStreamLike<T> = Pick<ReadableStream<T>, 'getReader'>;\n\n/**\n * An observable with a `connect` method that is used to create a subscription\n * to an underlying source, connecting it with all consumers via a multicast.\n */\nexport interface Connectable<T> extends Observable<T> {\n  /**\n   * (Idempotent) Calling this method will connect the underlying source observable to all subscribed consumers\n   * through an underlying {@link Subject}.\n   * @returns A subscription, that when unsubscribed, will \"disconnect\" the source from the connector subject,\n   * severing notifications to all consumers.\n   */\n  connect(): Subscription;\n}\n"
  },
  {
    "path": "packages/rxjs/src/internal/util/ArgumentOutOfRangeError.ts",
    "content": "/**\n * An error thrown when an element was queried at a certain index of an\n * Observable, but no such index or position exists in that sequence.\n *\n * @see {@link elementAt}\n * @see {@link take}\n * @see {@link takeLast}\n */\nexport class ArgumentOutOfRangeError extends Error {\n  /**\n   * @deprecated Internal implementation detail. Do not construct error instances.\n   * Cannot be tagged as internal: https://github.com/ReactiveX/rxjs/issues/6269\n   */\n  constructor() {\n    super('argument out of range');\n    this.name = 'ArgumentOutOfRangeError';\n  }\n}\n"
  },
  {
    "path": "packages/rxjs/src/internal/util/EmptyError.ts",
    "content": "/**\n * An error thrown when an Observable or a sequence was queried but has no\n * elements.\n *\n * @see {@link first}\n * @see {@link last}\n * @see {@link single}\n * @see {@link firstValueFrom}\n * @see {@link lastValueFrom}\n */\nexport class EmptyError extends Error {\n  /**\n   * @deprecated Internal implementation detail. Do not construct error instances.\n   * Cannot be tagged as internal: https://github.com/ReactiveX/rxjs/issues/6269\n   */\n  constructor() {\n    super('no elements in sequence');\n    this.name = 'EmptyError';\n  }\n}\n"
  },
  {
    "path": "packages/rxjs/src/internal/util/Immediate.ts",
    "content": "let nextHandle = 1;\n// The promise needs to be created lazily otherwise it won't be patched by Zones\nlet resolved: Promise<any>;\nconst activeHandles: { [key: number]: any } = {};\n\n/**\n * Finds the handle in the list of active handles, and removes it.\n * Returns `true` if found, `false` otherwise. Used both to clear\n * Immediate scheduled tasks, and to identify if a task should be scheduled.\n */\nfunction findAndClearHandle(handle: number): boolean {\n  if (handle in activeHandles) {\n    delete activeHandles[handle];\n    return true;\n  }\n  return false;\n}\n\n/**\n * Helper functions to schedule and unschedule microtasks.\n */\nexport const Immediate = {\n  setImmediate(cb: () => void): number {\n    const handle = nextHandle++;\n    activeHandles[handle] = true;\n    if (!resolved) {\n      resolved = Promise.resolve();\n    }\n    resolved.then(() => findAndClearHandle(handle) && cb());\n    return handle;\n  },\n\n  clearImmediate(handle: number): void {\n    findAndClearHandle(handle);\n  },\n};\n\n/**\n * Used for internal testing purposes only. Do not export from library.\n */\nexport const TestTools = {\n  pending() {\n    return Object.keys(activeHandles).length;\n  }\n};\n"
  },
  {
    "path": "packages/rxjs/src/internal/util/NotFoundError.ts",
    "content": "/**\n * An error thrown when a value or values are missing from an\n * observable sequence.\n *\n * @see {@link operators/single}\n */\nexport class NotFoundError extends Error {\n  /**\n   * @deprecated Internal implementation detail. Do not construct error instances.\n   * Cannot be tagged as internal: https://github.com/ReactiveX/rxjs/issues/6269\n   */\n  constructor(message: string) {\n    super(message);\n    this.name = 'NotFoundError';\n  }\n}\n"
  },
  {
    "path": "packages/rxjs/src/internal/util/SequenceError.ts",
    "content": "/**\n * An error thrown when something is wrong with the sequence of\n * values arriving on the observable.\n *\n * @see {@link operators/single}\n */\nexport class SequenceError extends Error {\n  /**\n   * @deprecated Internal implementation detail. Do not construct error instances.\n   * Cannot be tagged as internal: https://github.com/ReactiveX/rxjs/issues/6269\n   */\n  constructor(message: string) {\n    super(message);\n    this.name = 'SequenceError';\n  }\n}\n"
  },
  {
    "path": "packages/rxjs/src/internal/util/args.ts",
    "content": "import type { SchedulerLike } from '../types.js';\nimport { isFunction } from '@rxjs/observable';\nimport { isScheduler } from './isScheduler.js';\n\nfunction last<T>(arr: T[]): T | undefined {\n  return arr[arr.length - 1];\n}\n\nexport function popResultSelector(args: any[]): ((...args: unknown[]) => unknown) | undefined {\n  return isFunction(last(args)) ? args.pop() : undefined;\n}\n\nexport function popScheduler(args: any[]): SchedulerLike | undefined {\n  return isScheduler(last(args)) ? args.pop() : undefined;\n}\n\nexport function popNumber(args: any[], defaultValue: number): number {\n  return typeof last(args) === 'number' ? args.pop()! : defaultValue;\n}\n"
  },
  {
    "path": "packages/rxjs/src/internal/util/argsArgArrayOrObject.ts",
    "content": "const { isArray } = Array;\nconst { getPrototypeOf, prototype: objectProto, keys: getKeys } = Object;\n\n/**\n * Used in functions where either a list of arguments, a single array of arguments, or a\n * dictionary of arguments can be returned. Returns an object with an `args` property with\n * the arguments in an array, if it is a dictionary, it will also return the `keys` in another\n * property.\n */\nexport function argsArgArrayOrObject<T, O extends Record<string, T>>(args: T[] | [O] | [T[]]): { args: T[]; keys: string[] | null } {\n  if (args.length === 1) {\n    const first = args[0];\n    const result = arrayOrObject(first);\n    if (result) {\n      return result;\n    }\n  }\n\n  return { args: args as T[], keys: null };\n}\n\nexport function arrayOrObject<T, O extends Record<string, T>>(first: T | T[] | O) {\n  if (isArray(first)) {\n    return { args: first, keys: null };\n  }\n  if (isPOJO(first)) {\n    const keys = getKeys(first);\n    return {\n      args: keys.map((key) => first[key]),\n      keys,\n    };\n  }\n  return null;\n}\n\nfunction isPOJO(obj: any): obj is object {\n  return obj && typeof obj === 'object' && getPrototypeOf(obj) === objectProto;\n}\n"
  },
  {
    "path": "packages/rxjs/src/internal/util/argsOrArgArray.ts",
    "content": "const { isArray } = Array;\n\n/**\n * Used in operators and functions that accept either a list of arguments, or an array of arguments\n * as a single argument.\n */\nexport function argsOrArgArray<T>(args: (T | T[])[]): T[] {\n  return args.length === 1 && isArray(args[0]) ? args[0] : (args as T[]);\n}\n"
  },
  {
    "path": "packages/rxjs/src/internal/util/arrRemove.ts",
    "content": "/**\n * Removes an item from an array, mutating it.\n * @param arr The array to remove the item from\n * @param item The item to remove\n */\nexport function arrRemove<T>(arr: T[] | undefined | null, item: T) {\n  if (arr) {\n    const index = arr.indexOf(item);\n    0 <= index && arr.splice(index, 1);\n  }\n}\n"
  },
  {
    "path": "packages/rxjs/src/internal/util/createObject.ts",
    "content": "export function createObject(keys: string[], values: any[]) {\n  return keys.reduce((result, key, i) => ((result[key] = values[i]), result), {} as any);\n}\n"
  },
  {
    "path": "packages/rxjs/src/internal/util/executeSchedule.ts",
    "content": "import type { Subscription } from '@rxjs/observable';\nimport type { SchedulerAction, SchedulerLike } from '../types.js';\n\nexport function executeSchedule(\n  parentSubscription: Subscription,\n  scheduler: SchedulerLike,\n  work: () => void,\n  delay = 0,\n  repeat = false\n): Subscription | void {\n  if (!parentSubscription.closed) {\n    const scheduleSubscription = scheduler.schedule(function (this: SchedulerAction<any>) {\n      work();\n      if (repeat) {\n        parentSubscription.add(this.schedule(null, delay));\n      } else {\n        this.unsubscribe();\n      }\n    }, delay);\n\n    parentSubscription.add(scheduleSubscription);\n\n    if (!repeat) {\n      // Because user-land scheduler implementations are unlikely to properly reuse\n      // Actions for repeat scheduling, we can't trust that the returned subscription\n      // will control repeat subscription scenarios. So we're trying to avoid using them\n      // incorrectly within this library.\n      return scheduleSubscription;\n    }\n  }\n}\n"
  },
  {
    "path": "packages/rxjs/src/internal/util/identity.ts",
    "content": "/**\n * This function takes one parameter and just returns it. Simply put,\n * this is like `<T>(x: T): T => x`.\n *\n * ## Examples\n *\n * This is useful in some cases when using things like `mergeMap`\n *\n * ```ts\n * import { interval, take, map, range, mergeMap, identity } from 'rxjs';\n *\n * const source$ = interval(1000).pipe(take(5));\n *\n * const result$ = source$.pipe(\n *   map(i => range(i)),\n *   mergeMap(identity) // same as mergeMap(x => x)\n * );\n *\n * result$.subscribe({\n *   next: console.log\n * });\n * ```\n *\n * Or when you want to selectively apply an operator\n *\n * ```ts\n * import { interval, take, identity } from 'rxjs';\n *\n * const shouldLimit = () => Math.random() < 0.5;\n *\n * const source$ = interval(1000);\n *\n * const result$ = source$.pipe(shouldLimit() ? take(5) : identity);\n *\n * result$.subscribe({\n *   next: console.log\n * });\n * ```\n *\n * @param x Any value that is returned by this function\n * @returns The value passed as the first parameter to this function\n */\nexport function identity<T>(x: T): T {\n  return x;\n}\n"
  },
  {
    "path": "packages/rxjs/src/internal/util/isDate.ts",
    "content": "/**\n * Checks to see if a value is not only a `Date` object,\n * but a *valid* `Date` object that can be converted to a\n * number. For example, `new Date('blah')` is indeed an\n * `instanceof Date`, however it cannot be converted to a\n * number.\n */\nexport function isValidDate(value: any): value is Date {\n  return value instanceof Date && !isNaN(value as any);\n}\n"
  },
  {
    "path": "packages/rxjs/src/internal/util/isScheduler.ts",
    "content": "import type { SchedulerLike } from '../types.js';\nimport { isFunction } from '@rxjs/observable';\n\nexport function isScheduler(value: any): value is SchedulerLike {\n  return value && isFunction(value.schedule);\n}\n"
  },
  {
    "path": "packages/rxjs/src/internal/util/mapOneOrManyArgs.ts",
    "content": "import type { OperatorFunction } from '../types.js';\nimport { map } from '../operators/map.js';\n\nconst { isArray } = Array;\n\nfunction callOrApply<T, R>(fn: (...values: T[]) => R, args: T | T[]): R {\n  return isArray(args) ? fn(...args) : fn(args);\n}\n\n/**\n * Used in several -- mostly deprecated -- situations where we need to\n * apply a list of arguments or a single argument to a result selector.\n */\nexport function mapOneOrManyArgs<T, R>(fn: (...values: T[]) => R): OperatorFunction<T | T[], R> {\n  return map((args) => callOrApply(fn, args));\n}\n"
  },
  {
    "path": "packages/rxjs/src/internal/util/noop.ts",
    "content": "export function noop() { }\n"
  },
  {
    "path": "packages/rxjs/src/internal/util/not.ts",
    "content": "export function not<T>(pred: (value: T, index: number) => boolean, thisArg: any): (value: T, index: number) => boolean {\n  return (value: T, index: number) => !pred.call(thisArg, value, index); \n}"
  },
  {
    "path": "packages/rxjs/src/internal/util/pipe.ts",
    "content": "import type { UnaryFunction } from '../types.js';\n\nexport function pipe(): <T>(x: T) => T;\nexport function pipe<T, A>(fn1: UnaryFunction<T, A>): UnaryFunction<T, A>;\nexport function pipe<T, A, B>(fn1: UnaryFunction<T, A>, fn2: UnaryFunction<A, B>): UnaryFunction<T, B>;\nexport function pipe<T, A, B, C>(fn1: UnaryFunction<T, A>, fn2: UnaryFunction<A, B>, fn3: UnaryFunction<B, C>): UnaryFunction<T, C>;\nexport function pipe<T, A, B, C, D>(\n  fn1: UnaryFunction<T, A>,\n  fn2: UnaryFunction<A, B>,\n  fn3: UnaryFunction<B, C>,\n  fn4: UnaryFunction<C, D>\n): UnaryFunction<T, D>;\nexport function pipe<T, A, B, C, D, E>(\n  fn1: UnaryFunction<T, A>,\n  fn2: UnaryFunction<A, B>,\n  fn3: UnaryFunction<B, C>,\n  fn4: UnaryFunction<C, D>,\n  fn5: UnaryFunction<D, E>\n): UnaryFunction<T, E>;\nexport function pipe<T, A, B, C, D, E, F>(\n  fn1: UnaryFunction<T, A>,\n  fn2: UnaryFunction<A, B>,\n  fn3: UnaryFunction<B, C>,\n  fn4: UnaryFunction<C, D>,\n  fn5: UnaryFunction<D, E>,\n  fn6: UnaryFunction<E, F>\n): UnaryFunction<T, F>;\nexport function pipe<T, A, B, C, D, E, F, G>(\n  fn1: UnaryFunction<T, A>,\n  fn2: UnaryFunction<A, B>,\n  fn3: UnaryFunction<B, C>,\n  fn4: UnaryFunction<C, D>,\n  fn5: UnaryFunction<D, E>,\n  fn6: UnaryFunction<E, F>,\n  fn7: UnaryFunction<F, G>\n): UnaryFunction<T, G>;\nexport function pipe<T, A, B, C, D, E, F, G, H>(\n  fn1: UnaryFunction<T, A>,\n  fn2: UnaryFunction<A, B>,\n  fn3: UnaryFunction<B, C>,\n  fn4: UnaryFunction<C, D>,\n  fn5: UnaryFunction<D, E>,\n  fn6: UnaryFunction<E, F>,\n  fn7: UnaryFunction<F, G>,\n  fn8: UnaryFunction<G, H>\n): UnaryFunction<T, H>;\nexport function pipe<T, A, B, C, D, E, F, G, H, I>(\n  fn1: UnaryFunction<T, A>,\n  fn2: UnaryFunction<A, B>,\n  fn3: UnaryFunction<B, C>,\n  fn4: UnaryFunction<C, D>,\n  fn5: UnaryFunction<D, E>,\n  fn6: UnaryFunction<E, F>,\n  fn7: UnaryFunction<F, G>,\n  fn8: UnaryFunction<G, H>,\n  fn9: UnaryFunction<H, I>\n): UnaryFunction<T, I>;\nexport function pipe<T, A, B, C, D, E, F, G, H, I>(\n  fn1: UnaryFunction<T, A>,\n  fn2: UnaryFunction<A, B>,\n  fn3: UnaryFunction<B, C>,\n  fn4: UnaryFunction<C, D>,\n  fn5: UnaryFunction<D, E>,\n  fn6: UnaryFunction<E, F>,\n  fn7: UnaryFunction<F, G>,\n  fn8: UnaryFunction<G, H>,\n  fn9: UnaryFunction<H, I>,\n  ...fns: UnaryFunction<any, any>[]\n): UnaryFunction<T, unknown>;\n\n/**\n * pipe() can be called on one or more functions, each of which can take one argument (\"UnaryFunction\")\n * and uses it to return a value.\n * It returns a function that takes one argument, passes it to the first UnaryFunction, and then\n * passes the result to the next one, passes that result to the next one, and so on.\n */\nexport function pipe(...fns: Array<UnaryFunction<any, any>>): UnaryFunction<any, any> {\n  return fns.length === 1 ? fns[0] : (input: any) => fns.reduce(pipeReducer, input);\n}\n\nfunction pipeReducer(prev: any, fn: UnaryFunction<any, any>): any {\n  return fn(prev);\n}\n"
  },
  {
    "path": "packages/rxjs/src/internal/util/rx.ts",
    "content": "import type { Observable} from '@rxjs/observable';\nimport { from } from '@rxjs/observable';\nimport type { ObservableInput, UnaryFunction } from '../types.js';\n\nexport function rx<A>(source: ObservableInput<A>): Observable<A>;\nexport function rx<A, B>(source: ObservableInput<A>, fn2: UnaryFunction<Observable<A>, B>): B;\nexport function rx<A, B, C>(source: ObservableInput<A>, fn2: UnaryFunction<Observable<A>, B>, fn3: UnaryFunction<B, C>): C;\nexport function rx<A, B, C, D>(\n  source: ObservableInput<A>,\n  fn2: UnaryFunction<Observable<A>, B>,\n  fn3: UnaryFunction<B, C>,\n  fn4: UnaryFunction<C, D>\n): D;\nexport function rx<A, B, C, D, E>(\n  source: ObservableInput<A>,\n  fn2: UnaryFunction<Observable<A>, B>,\n  fn3: UnaryFunction<B, C>,\n  fn4: UnaryFunction<C, D>,\n  fn5: UnaryFunction<D, E>\n): E;\nexport function rx<A, B, C, D, E, F>(\n  source: ObservableInput<A>,\n  fn2: UnaryFunction<Observable<A>, B>,\n  fn3: UnaryFunction<B, C>,\n  fn4: UnaryFunction<C, D>,\n  fn5: UnaryFunction<D, E>,\n  fn6: UnaryFunction<E, F>\n): F;\nexport function rx<A, B, C, D, E, F, G>(\n  source: ObservableInput<A>,\n  fn2: UnaryFunction<Observable<A>, B>,\n  fn3: UnaryFunction<B, C>,\n  fn4: UnaryFunction<C, D>,\n  fn5: UnaryFunction<D, E>,\n  fn6: UnaryFunction<E, F>,\n  fn7: UnaryFunction<F, G>\n): G;\nexport function rx<A, B, C, D, E, F, G, H>(\n  source: ObservableInput<A>,\n  fn2: UnaryFunction<Observable<A>, B>,\n  fn3: UnaryFunction<B, C>,\n  fn4: UnaryFunction<C, D>,\n  fn5: UnaryFunction<D, E>,\n  fn6: UnaryFunction<E, F>,\n  fn7: UnaryFunction<F, G>,\n  fn8: UnaryFunction<G, H>\n): H;\nexport function rx<A, B, C, D, E, F, G, H, I>(\n  source: ObservableInput<A>,\n  fn2: UnaryFunction<Observable<A>, B>,\n  fn3: UnaryFunction<B, C>,\n  fn4: UnaryFunction<C, D>,\n  fn5: UnaryFunction<D, E>,\n  fn6: UnaryFunction<E, F>,\n  fn7: UnaryFunction<F, G>,\n  fn8: UnaryFunction<G, H>,\n  fn9: UnaryFunction<H, I>\n): I;\nexport function rx<A, B, C, D, E, F, G, H, I>(\n  source: ObservableInput<A>,\n  fn2: UnaryFunction<Observable<A>, B>,\n  fn3: UnaryFunction<B, C>,\n  fn4: UnaryFunction<C, D>,\n  fn5: UnaryFunction<D, E>,\n  fn6: UnaryFunction<E, F>,\n  fn7: UnaryFunction<F, G>,\n  fn8: UnaryFunction<G, H>,\n  fn9: UnaryFunction<H, I>,\n  ...fns: UnaryFunction<unknown, unknown>[]\n): unknown;\n\n/**\n * Converts the first argument to an observable, then passes that observable to the function in the second argument.\n * The result of _that_ function is then passed to the function in the third argument, and so on. This continues until\n * all functions have been called, and the result of the last function is returned.\n *\n * This means it can be used for anything involving unary functions, just so long as the first unary function accepts an observable as its argument,\n * and as long as the first argument to `rx()` is a valid {@link ObservableInput}.\n *\n * This is the same as an ordinary functional {@link pipe}, except it has an implicit `from` as the second argument.\n *\n * The following are equivalent:\n *\n * ```ts\n * // Where `source` is any valid `ObservableInput`.\n * // A (observable, promise, array, async iterable, etc.)\n * rx(source, map(x => x + 1), filter(x => x % 2 === 0));\n * pipe(map(x => x + 1), filter(x => x % 2 === 0))(from(source));\n * pipe(from, map(x => x + 1), filter(x => x % 2 === 0))(source);\n * ```\n *\n * Furthermore, `rx` can be used to create an observable and pipe it in any number of ways. For example:\n *\n * ```ts\n * const subscription = rx(\n *   of(1, 2, 3),\n *   source => source.subscribe(x => console.log(x)),\n * );\n *\n * // or even something like this:\n * const promise = rx(\n *   of(1, 2, 3),\n *   async (source) => {\n *     const result = [];\n *     await source.forEach(x => result.push(x));\n *     return result;\n *   },\n * });\n * ````\n *\n * @param source Any valid observable source.\n * @param fns Any number of unary functions, starting with a unary function that accepts an observable as its only argument.\n * @returns The result of the last function, or an observable if no functions are provided for the second argument and beyond.\n */\nexport function rx(source: ObservableInput<unknown>, ...fns: UnaryFunction<any, unknown>[]): unknown {\n  return fns.reduce(pipeReducer, from(source));\n}\n\nfunction pipeReducer(prev: any, fn: UnaryFunction<any, any>) {\n  return fn(prev);\n}\n"
  },
  {
    "path": "packages/rxjs/src/internal/util/throwUnobservableError.ts",
    "content": "/**\n * Creates the TypeError to throw if an invalid object is passed to `from` or `scheduled`.\n * @param input The object that was passed.\n */\nexport function createInvalidObservableTypeError(input: any) {\n  // TODO: We should create error codes that can be looked up, so this can be less verbose.\n  return new TypeError(\n    `You provided ${\n      input !== null && typeof input === 'object' ? 'an invalid object' : `'${input}'`\n    } where a stream was expected. You can provide an Observable, Promise, ReadableStream, Array, AsyncIterable, or Iterable.`\n  );\n}\n"
  },
  {
    "path": "packages/rxjs/src/internal/util/workarounds.ts",
    "content": "// Instead of using any - or another less-than-ideal type - to workaround a\n// TypeScript problem or bug, create a type alias and use that instead.\n// Wherever possible, use a TypeScript issue number in the type - something\n// like TS_18757 - or use a descriptive name and leave a detailed comment\n// alongside the type alias.\n\nexport {};\n"
  },
  {
    "path": "packages/rxjs/src/operators/index.ts",
    "content": "/* Operator exports */\nexport { audit } from '../internal/operators/audit.js';\nexport { auditTime } from '../internal/operators/auditTime.js';\nexport { buffer } from '../internal/operators/buffer.js';\nexport { bufferCount } from '../internal/operators/bufferCount.js';\nexport { bufferTime } from '../internal/operators/bufferTime.js';\nexport { bufferToggle } from '../internal/operators/bufferToggle.js';\nexport { bufferWhen } from '../internal/operators/bufferWhen.js';\nexport { catchError } from '../internal/operators/catchError.js';\nexport { combineLatestAll } from '../internal/operators/combineLatestAll.js';\nexport { combineLatestWith } from '../internal/operators/combineLatestWith.js';\nexport { concatAll } from '../internal/operators/concatAll.js';\nexport { concatMap } from '../internal/operators/concatMap.js';\nexport { concatMapTo } from '../internal/operators/concatMapTo.js';\nexport { concatWith } from '../internal/operators/concatWith.js';\nexport type { ConnectConfig } from '../internal/operators/connect.js';\nexport { connect } from '../internal/operators/connect.js';\nexport { count } from '../internal/operators/count.js';\nexport { debounce } from '../internal/operators/debounce.js';\nexport { debounceTime } from '../internal/operators/debounceTime.js';\nexport { defaultIfEmpty } from '../internal/operators/defaultIfEmpty.js';\nexport { delay } from '../internal/operators/delay.js';\nexport { delayWhen } from '../internal/operators/delayWhen.js';\nexport { dematerialize } from '../internal/operators/dematerialize.js';\nexport { distinct } from '../internal/operators/distinct.js';\nexport { distinctUntilChanged } from '../internal/operators/distinctUntilChanged.js';\nexport { distinctUntilKeyChanged } from '../internal/operators/distinctUntilKeyChanged.js';\nexport { elementAt } from '../internal/operators/elementAt.js';\nexport { endWith } from '../internal/operators/endWith.js';\nexport { every } from '../internal/operators/every.js';\nexport { exhaustAll } from '../internal/operators/exhaustAll.js';\nexport { exhaustMap } from '../internal/operators/exhaustMap.js';\nexport { expand } from '../internal/operators/expand.js';\nexport { filter } from '../internal/operators/filter.js';\nexport { finalize } from '../internal/operators/finalize.js';\nexport { find } from '../internal/operators/find.js';\nexport { findIndex } from '../internal/operators/findIndex.js';\nexport { first } from '../internal/operators/first.js';\nexport type { BasicGroupByOptions, GroupByOptionsWithElement } from '../internal/operators/groupBy.js';\nexport { groupBy } from '../internal/operators/groupBy.js';\nexport { ignoreElements } from '../internal/operators/ignoreElements.js';\nexport { isEmpty } from '../internal/operators/isEmpty.js';\nexport { last } from '../internal/operators/last.js';\nexport { map } from '../internal/operators/map.js';\nexport { mapTo } from '../internal/operators/mapTo.js';\nexport { materialize } from '../internal/operators/materialize.js';\nexport { max } from '../internal/operators/max.js';\nexport { mergeAll } from '../internal/operators/mergeAll.js';\nexport { mergeMap } from '../internal/operators/mergeMap.js';\nexport { mergeMapTo } from '../internal/operators/mergeMapTo.js';\nexport { mergeScan } from '../internal/operators/mergeScan.js';\nexport { mergeWith } from '../internal/operators/mergeWith.js';\nexport { min } from '../internal/operators/min.js';\nexport { observeOn } from '../internal/operators/observeOn.js';\nexport { onErrorResumeNextWith } from '../internal/operators/onErrorResumeNextWith.js';\nexport { pairwise } from '../internal/operators/pairwise.js';\nexport { partition } from '../internal/operators/partition.js';\nexport { raceWith } from '../internal/operators/raceWith.js';\nexport { reduce } from '../internal/operators/reduce.js';\nexport type { RepeatConfig } from '../internal/operators/repeat.js';\nexport { repeat } from '../internal/operators/repeat.js';\nexport { repeatWhen } from '../internal/operators/repeatWhen.js';\nexport type { RetryConfig } from '../internal/operators/retry.js';\nexport { retry } from '../internal/operators/retry.js';\nexport { retryWhen } from '../internal/operators/retryWhen.js';\nexport { sample } from '../internal/operators/sample.js';\nexport { sampleTime } from '../internal/operators/sampleTime.js';\nexport { scan } from '../internal/operators/scan.js';\nexport { sequenceEqual } from '../internal/operators/sequenceEqual.js';\nexport type { ShareConfig } from '../internal/operators/share.js';\nexport { share } from '../internal/operators/share.js';\nexport type { ShareReplayConfig } from '../internal/operators/shareReplay.js';\nexport { shareReplay } from '../internal/operators/shareReplay.js';\nexport { single } from '../internal/operators/single.js';\nexport { skip } from '../internal/operators/skip.js';\nexport { skipLast } from '../internal/operators/skipLast.js';\nexport { skipUntil } from '../internal/operators/skipUntil.js';\nexport { skipWhile } from '../internal/operators/skipWhile.js';\nexport { startWith } from '../internal/operators/startWith.js';\nexport { subscribeOn } from '../internal/operators/subscribeOn.js';\nexport { switchAll } from '../internal/operators/switchAll.js';\nexport { switchMap } from '../internal/operators/switchMap.js';\nexport { switchMapTo } from '../internal/operators/switchMapTo.js';\nexport { switchScan } from '../internal/operators/switchScan.js';\nexport { take } from '../internal/operators/take.js';\nexport { takeLast } from '../internal/operators/takeLast.js';\nexport { takeUntil } from '../internal/operators/takeUntil.js';\nexport { takeWhile } from '../internal/operators/takeWhile.js';\nexport type { TapObserver } from '../internal/operators/tap.js';\nexport { tap } from '../internal/operators/tap.js';\nexport type { ThrottleConfig } from '../internal/operators/throttle.js';\nexport { throttle } from '../internal/operators/throttle.js';\nexport { throttleTime } from '../internal/operators/throttleTime.js';\nexport { throwIfEmpty } from '../internal/operators/throwIfEmpty.js';\nexport { timeInterval } from '../internal/operators/timeInterval.js';\nexport type { TimeoutConfig, TimeoutInfo } from '../internal/operators/timeout.js';\nexport { timeout } from '../internal/operators/timeout.js';\nexport { timeoutWith } from '../internal/operators/timeoutWith.js';\nexport { timestamp } from '../internal/operators/timestamp.js';\nexport { toArray } from '../internal/operators/toArray.js';\nexport { window } from '../internal/operators/window.js';\nexport { windowCount } from '../internal/operators/windowCount.js';\nexport { windowTime } from '../internal/operators/windowTime.js';\nexport { windowToggle } from '../internal/operators/windowToggle.js';\nexport { windowWhen } from '../internal/operators/windowWhen.js';\nexport { withLatestFrom } from '../internal/operators/withLatestFrom.js';\nexport { zipAll } from '../internal/operators/zipAll.js';\nexport { zipWith } from '../internal/operators/zipWith.js';\n"
  },
  {
    "path": "packages/rxjs/src/testing/index.ts",
    "content": "export type { RunHelpers } from '../internal/testing/TestScheduler.js';\nexport { TestScheduler } from '../internal/testing/TestScheduler.js';\n"
  },
  {
    "path": "packages/rxjs/src/tsconfig.base.json",
    "content": "{\n  \"extends\": \"../tsconfig.json\",\n  \"compilerOptions\": {\n    \"noEmit\": false,\n    \"baseUrl\": \".\",\n    \"paths\": {\n      \"rxjs\": [\"./\"],\n      \"rxjs/*\": [\"./*\"]\n    }\n  },\n  \"include\": [\"./**/*.ts\"],\n  \"exclude\": [\"node_modules\", \"dist\"]\n}\n"
  },
  {
    "path": "packages/rxjs/src/tsconfig.cjs.json",
    "content": "{\n  \"extends\": \"./tsconfig.base.json\",\n  \"compilerOptions\": {\n    \"module\": \"commonjs\",\n    \"target\": \"ES2022\",\n    \"downlevelIteration\": true,\n    \"outDir\": \"../dist/cjs\"\n  }\n}\n"
  },
  {
    "path": "packages/rxjs/src/tsconfig.cjs.spec.json",
    "content": "{\n  \"extends\": \"./tsconfig.cjs.json\",\n  /**\n   * this is pseudo config for test case's relative path resolution to `../src`, runs\n   * cjs config once more instead of manual copying to utilize incremental build.\n   */\n  \"compilerOptions\": {\n    \"outDir\": \"../dist/src\"\n  }\n}\n"
  },
  {
    "path": "packages/rxjs/src/tsconfig.esm.json",
    "content": "{\n  \"extends\": \"./tsconfig.base.json\",\n  \"compilerOptions\": {\n    \"module\": \"esnext\",\n    \"target\": \"ES2022\",\n    \"outDir\": \"../dist/esm\"\n  }\n}\n"
  },
  {
    "path": "packages/rxjs/src/tsconfig.types.json",
    "content": "{\n  \"extends\": \"./tsconfig.esm.json\",\n  \"compilerOptions\": {\n    \"composite\": true,\n    \"module\": \"es2015\",\n    \"target\": \"ES2022\",\n    \"removeComments\": false,\n    \"declaration\": true,\n    \"declarationMap\": true,\n    \"declarationDir\": \"../dist/types\",\n    \"emitDeclarationOnly\": true\n  }\n}\n"
  },
  {
    "path": "packages/rxjs/src/tsconfig.types.spec.json",
    "content": "{\n  \"extends\": \"./tsconfig.types.json\",\n  \"compilerOptions\": {\n    \"declarationDir\": \"../dist/types_spec\",\n    \"stripInternal\": false\n  }\n}\n"
  },
  {
    "path": "packages/rxjs/src/webSocket/index.ts",
    "content": "export { webSocket as webSocket } from '../internal/observable/dom/webSocket.js';\nexport type { WebSocketSubjectConfig } from '../internal/observable/dom/WebSocketSubject.js';\nexport { WebSocketSubject } from '../internal/observable/dom/WebSocketSubject.js';\n"
  },
  {
    "path": "packages/rxjs/tools/add-license-to-file.js",
    "content": "var fs = require('fs');\n\nfunction addLicenseTextToFile(licenseText, destination) {\n  if (!destination) {\n    throw new Error('destination file path is required as 2nd argument');\n  }\n\n  fs.writeFileSync(\n    destination,\n    `/**\n  @license\n  ${licenseText}\n **/\n${fs.readFileSync(`${destination}`).toString()}\n`\n  );\n}\n\nfunction addLicenseToFile(license, destination) {\n  if (!license) {\n    throw new Error('license path is required as 1st argument');\n  }\n\n  addLicenseTextToFile(fs.readFileSync(license).toString(), destination);\n}\n\nmodule.exports = {\n  addLicenseToFile: addLicenseToFile,\n  addLicenseTextToFile: addLicenseTextToFile,\n};\n"
  },
  {
    "path": "packages/rxjs/tools/generate-alias.js",
    "content": "/**\n * Alias subpath import (`dist/cjs/*`) to top-level path mapping (`rxjs/*`)\n * Previously this was done by placing cjs to top-level package when it's published -\n * Now build uses `dist` as explicit output subpath so we generate top-level alias here instead.\n */\nconst fs = require('fs-extra');\nconst path = require('path');\n\nconst aliasRoot = ['ajax', 'fetch', 'operators', 'testing', 'webSocket'];\n\naliasRoot\n  .map((alias) => path.resolve(__dirname, `../${alias}`))\n  .forEach((alias) => {\n    if (fs.existsSync(alias)) {\n      fs.removeSync(alias);\n    }\n    fs.ensureDirSync(alias);\n  });\n\naliasRoot.forEach((alias) => {\n  const pkgManifest = {\n    name: `rxjs/${alias}`,\n    types: `../dist/types/${alias}/index.d.ts`,\n    main: `../dist/cjs/${alias}/index.js`,\n    module: `../dist/esm/${alias}/index.js`,\n    sideEffects: false,\n  };\n\n  const packagePath = path.resolve(__dirname, `../${alias}/package.json`);\n\n  console.log(`Writing: ${packagePath}`);\n\n  fs.writeJSON(packagePath, pkgManifest, { spaces: 2 });\n});\n"
  },
  {
    "path": "packages/rxjs/tools/subject-benchmark.js",
    "content": "// @ts-check\nconst { Bench } = require('tinybench');\nconst { Subject: SubjectMaster } = require('../dist-master/cjs');\nconst { Subject: SubjectPr } = require('../dist/cjs');\n\nasync function run() {\n  const numIterations = 10_000;\n  const bench = new Bench({ warmupIterations: Math.ceil(numIterations / 20), iterations: numIterations });\n\n  //   bench.add('[master] Creating Subject', () => {\n  //     new SubjectMaster();\n  //   });\n  //   bench.add('[pr] Creating Subject', () => {\n  //     new SubjectPr();\n  //   });\n\n  //   bench.add('[master] 0 subscribed, 1 next', () => {\n  //     const source = new SubjectMaster();\n  //     source.next(1);\n  //   });\n  //   bench.add('[pr] 0 subscribed, 1 next', () => {\n  //     const source = new SubjectPr();\n  //     source.next(1);\n  //   });\n\n  //   bench.add('[master] 0 subscribed, 100 next', () => {\n  //     const source = new SubjectMaster();\n  //     for (let i = 0; i !== 100; ++i) {\n  //       source.next(i);\n  //     }\n  //   });\n  //   bench.add('[pr] 0 subscribed, 100 next', () => {\n  //     const source = new SubjectPr();\n  //     for (let i = 0; i !== 100; ++i) {\n  //       source.next(i);\n  //     }\n  //   });\n\n  //   bench.add('[master] 1 subscribed, 1 next', () => {\n  //     const source = new SubjectMaster();\n  //     const subscription = source.asObservable().subscribe();\n  //     source.next(1);\n  //     subscription.unsubscribe();\n  //   });\n  //   bench.add('[pr] 1 subscribed, 1 next', () => {\n  //     const source = new SubjectPr();\n  //     const subscription = source.asObservable().subscribe();\n  //     source.next(1);\n  //     subscription.unsubscribe();\n  //   });\n\n  //   bench.add('[master] 1 subscribed, 100 next', () => {\n  //     const source = new SubjectMaster();\n  //     const subscription = source.asObservable().subscribe();\n  //     for (let i = 0; i !== 100; ++i) {\n  //       source.next(i);\n  //     }\n  //     subscription.unsubscribe();\n  //   });\n  //   bench.add('[pr] 1 subscribed, 100 next', () => {\n  //     const source = new SubjectPr();\n  //     const subscription = source.asObservable().subscribe();\n  //     for (let i = 0; i !== 100; ++i) {\n  //       source.next(i);\n  //     }\n  //     subscription.unsubscribe();\n  //   });\n\n  //   bench.add('[master] 3 subscribed, 1 next', () => {\n  //     const source = new SubjectMaster();\n  //     const s1 = source.asObservable().subscribe();\n  //     const s2 = source.asObservable().subscribe();\n  //     const s3 = source.asObservable().subscribe();\n  //     source.next(1);\n  //     s1.unsubscribe();\n  //     s2.unsubscribe();\n  //     s3.unsubscribe();\n  //   });\n  //   bench.add('[pr] 3 subscribed, 1 next', () => {\n  //     const source = new SubjectPr();\n  //     const s1 = source.asObservable().subscribe();\n  //     const s2 = source.asObservable().subscribe();\n  //     const s3 = source.asObservable().subscribe();\n  //     source.next(1);\n  //     s1.unsubscribe();\n  //     s2.unsubscribe();\n  //     s3.unsubscribe();\n  //   });\n\n  //   bench.add('[master] 3 subscribed, 100 next', () => {\n  //     const source = new SubjectMaster();\n  //     const s1 = source.asObservable().subscribe();\n  //     const s2 = source.asObservable().subscribe();\n  //     const s3 = source.asObservable().subscribe();\n  //     for (let i = 0; i !== 100; ++i) {\n  //       source.next(i);\n  //     }\n  //     s1.unsubscribe();\n  //     s2.unsubscribe();\n  //     s3.unsubscribe();\n  //   });\n  //   bench.add('[pr] 3 subscribed, 100 next', () => {\n  //     const source = new SubjectPr();\n  //     const s1 = source.asObservable().subscribe();\n  //     const s2 = source.asObservable().subscribe();\n  //     const s3 = source.asObservable().subscribe();\n  //     for (let i = 0; i !== 100; ++i) {\n  //       source.next(i);\n  //     }\n  //     s1.unsubscribe();\n  //     s2.unsubscribe();\n  //     s3.unsubscribe();\n  //   });\n\n  //   bench.add('[master] 10 subscribed, 1 next', () => {\n  //     const source = new SubjectMaster();\n  //     const s = [];\n  //     for (let i = 0; i !== 10; ++i) {\n  //       s.push(source.asObservable().subscribe());\n  //     }\n  //     source.next(1);\n  //     for (const e of s) {\n  //       e.unsubscribe();\n  //     }\n  //   });\n  //   bench.add('[pr] 10 subscribed, 1 next', () => {\n  //     const source = new SubjectPr();\n  //     const s = [];\n  //     for (let i = 0; i !== 10; ++i) {\n  //       s.push(source.asObservable().subscribe());\n  //     }\n  //     source.next(1);\n  //     for (const e of s) {\n  //       e.unsubscribe();\n  //     }\n  //   });\n\n  //   bench.add('[master] 10 subscribed, 100 next', () => {\n  //     const source = new SubjectMaster();\n  //     const s = [];\n  //     for (let i = 0; i !== 10; ++i) {\n  //       s.push(source.asObservable().subscribe());\n  //     }\n  //     for (let i = 0; i !== 100; ++i) {\n  //       source.next(i);\n  //     }\n  //     for (const e of s) {\n  //       e.unsubscribe();\n  //     }\n  //   });\n  //   bench.add('[pr] 10 subscribed, 100 next', () => {\n  //     const source = new SubjectPr();\n  //     const s = [];\n  //     for (let i = 0; i !== 10; ++i) {\n  //       s.push(source.asObservable().subscribe());\n  //     }\n  //     for (let i = 0; i !== 100; ++i) {\n  //       source.next(i);\n  //     }\n  //     for (const e of s) {\n  //       e.unsubscribe();\n  //     }\n  //   });\n\n  //   bench.add('[master] 100 subscribed, 1 next', () => {\n  //     const source = new SubjectMaster();\n  //     const s = [];\n  //     for (let i = 0; i !== 100; ++i) {\n  //       s.push(source.asObservable().subscribe());\n  //     }\n  //     source.next(1);\n  //     for (const e of s) {\n  //       e.unsubscribe();\n  //     }\n  //   });\n  //   bench.add('[pr] 100 subscribed, 1 next', () => {\n  //     const source = new SubjectPr();\n  //     const s = [];\n  //     for (let i = 0; i !== 100; ++i) {\n  //       s.push(source.asObservable().subscribe());\n  //     }\n  //     source.next(1);\n  //     for (const e of s) {\n  //       e.unsubscribe();\n  //     }\n  //   });\n\n  //   bench.add('[master] 100 subscribed, 100 next', () => {\n  //     const source = new SubjectMaster();\n  //     const s = [];\n  //     for (let i = 0; i !== 100; ++i) {\n  //       s.push(source.asObservable().subscribe());\n  //     }\n  //     for (let i = 0; i !== 100; ++i) {\n  //       source.next(i);\n  //     }\n  //     for (const e of s) {\n  //       e.unsubscribe();\n  //     }\n  //   });\n  //   bench.add('[pr] 100 subscribed, 100 next', () => {\n  //     const source = new SubjectPr();\n  //     const s = [];\n  //     for (let i = 0; i !== 100; ++i) {\n  //       s.push(source.asObservable().subscribe());\n  //     }\n  //     for (let i = 0; i !== 100; ++i) {\n  //       source.next(i);\n  //     }\n  //     for (const e of s) {\n  //       e.unsubscribe();\n  //     }\n  //   });\n\n  //   bench.add('[master] 1000 subscribed, 1 next', () => {\n  //     const source = new SubjectMaster();\n  //     const s = [];\n  //     for (let i = 0; i !== 1000; ++i) {\n  //       s.push(source.asObservable().subscribe());\n  //     }\n  //     source.next(1);\n  //     for (const e of s) {\n  //       e.unsubscribe();\n  //     }\n  //   });\n  //   bench.add('[pr] 1000 subscribed, 1 next', () => {\n  //     const source = new SubjectPr();\n  //     const s = [];\n  //     for (let i = 0; i !== 1000; ++i) {\n  //       s.push(source.asObservable().subscribe());\n  //     }\n  //     source.next(1);\n  //     for (const e of s) {\n  //       e.unsubscribe();\n  //     }\n  //   });\n\n  bench.add('[master] 1 subscribed, 10,000 next', () => {\n    const source = new SubjectMaster();\n    const s = [];\n    for (let i = 0; i !== 1; ++i) {\n      s.push(source.asObservable().subscribe());\n    }\n    for (let i = 0; i !== 10000; ++i) {\n      source.next(i);\n    }\n    for (const e of s) {\n      e.unsubscribe();\n    }\n  });\n\n  bench.add('[pr]  1 subscribed, 10,000 next', () => {\n    const source = new SubjectPr();\n    const s = [];\n    for (let i = 0; i !== 1; ++i) {\n      s.push(source.asObservable().subscribe());\n    }\n    for (let i = 0; i !== 10000; ++i) {\n      source.next(i);\n    }\n    for (const e of s) {\n      e.unsubscribe();\n    }\n  });\n\n  await bench.warmup();\n  await bench.run();\n\n  console.table(\n    bench.tasks.map(({ name, result }) => {\n      return {\n        Name: name,\n        Mean: result?.mean,\n        P75: result?.p75,\n        P99: result?.p99,\n        RME: result?.rme,\n      };\n    })\n  );\n}\nrun();\n"
  },
  {
    "path": "packages/rxjs/tsconfig.json",
    "content": "{\n  \"compilerOptions\": {\n    \"incremental\": true,\n    \"removeComments\": true,\n    \"preserveConstEnums\": true,\n    \"sourceMap\": true,\n    \"strict\": true,\n    \"noImplicitReturns\": true,\n    \"moduleResolution\": \"node\",\n    \"stripInternal\": true,\n    \"noEmit\": true,\n    \"lib\": [\"esnext\", \"dom\"],\n    \"target\": \"esnext\",\n    \"baseUrl\": \".\",\n    \"paths\": {\n      \"@rxjs/observable\": [\"../observable/src/index\"],\n      \"rxjs\": [\"./src/index\"],\n      \"rxjs/operators\": [\"./src/operators/index\"],\n      \"rxjs/testing\": [\"./src/testing/index\"],\n      \"rxjs/ajax\": [\"./src/ajax/index\"],\n      \"rxjs/webSocket\": [\"./src/webSocket/index\"],\n      \"rxjs/fetch\": [\"./src/fetch/index\"],\n      \"rxjs/internal/*\": [\"./src/internal/*\"]\n    }\n  }\n}\n"
  },
  {
    "path": "packages/rxjs/tsconfig.mocha.json",
    "content": "{\n  \"extends\": \"./tsconfig.json\",\n  \"compilerOptions\": {\n    \"target\": \"ES2022\",\n    \"lib\": [\"ES2022\"]\n  },\n  \"ts-node\": {\n    \"transpileOnly\": true,\n    \"transpiler\": \"ts-node/transpilers/swc-experimental\"\n  }\n}"
  },
  {
    "path": "packages/rxjs/wallaby.js",
    "content": "module.exports = function (wallaby) {\n  return {\n    files: ['tsconfig.base.json', 'tsconfig.json', 'src/**/*.ts', { pattern: 'spec/helpers/!(*-spec).ts', instrument: false, load: true }],\n\n    tests: ['spec/**/*-spec.ts'],\n\n    testFramework: {\n      type: 'mocha',\n      path: 'mocha',\n    },\n\n    env: {\n      type: 'node',\n    },\n\n    workers: { initial: 2, regular: 1 },\n\n    compilers: {\n      '**/*.ts?(x)': wallaby.compilers.typeScript({\n        module: 'commonjs',\n        target: 'esnext',\n      }),\n    },\n\n    setup: function (w) {\n      if (!global._tsconfigPathsRegistered) {\n        var tsConfigPaths = require('tsconfig-paths');\n        tsConfigPaths.register();\n        global._tsconfigPathsRegistered = true;\n      }\n\n      // Global test helpers\n      global.mocha = require('mocha');\n      global.Suite = global.mocha.Suite;\n      global.Test = global.mocha.Test;\n\n      //delete global context due to avoid issue by reusing process\n      //https://github.com/wallabyjs/public/issues/536\n      if (global.asDiagram) {\n        delete global.asDiagram;\n      }\n\n      var path = require('path');\n      require(path.resolve(w.projectCacheDir, 'spec/helpers/setup'));\n    },\n  };\n};\n"
  },
  {
    "path": "resources/CI-CD/README.md",
    "content": "This folder contains all resources, docs licenses or other information\nrelated to the corporate identity and corporate design of this project.\n"
  },
  {
    "path": "scripts/copy-common-package-files.js",
    "content": "// @ts-check\n\nconst { copyFileSync } = require('fs');\nconst { createProjectGraphAsync, joinPathFragments, workspaceRoot } = require('@nx/devkit');\n\nconst getWorkspacePath = (...pathFragments) => joinPathFragments(workspaceRoot, ...pathFragments);\n\n(async () => {\n  const projectGraph = await createProjectGraphAsync();\n\n  for (const projectConfig of Object.values(projectGraph.nodes)) {\n    const projectRoot = projectConfig.data.root;\n    if (!projectRoot.startsWith('packages')) {\n      continue;\n    }\n    copyFileSync(getWorkspacePath('LICENSE.txt'), getWorkspacePath(projectRoot, `LICENSE.txt`));\n    copyFileSync(getWorkspacePath('CODE_OF_CONDUCT.md'), getWorkspacePath(projectRoot, `CODE_OF_CONDUCT.md`));\n  }\n\n  process.exit(0);\n})();\n"
  },
  {
    "path": "scripts/publish.js",
    "content": "// @ts-check\n\nconst { prerelease, valid } = require('semver');\nconst { releasePublish } = require('nx/src/command-line/release');\n\n/**\n * Maps git branch names to npm dist tags. If master is an alpha/beta release,\n * then it should be mapped to 'next'. Similarly there should be one record for\n * the 'latest' tag.\n */\nconst DIST_TAGS = {\n  'refs/heads/7.x': 'latest',\n  'refs/heads/master': 'next',\n};\n\nif (!Object.values(DIST_TAGS).includes('latest')) {\n  console.error(`Invalid DIST_TAGS:\\n${JSON.stringify(DIST_TAGS, null, 2)}`);\n  throw new Error(\"DIST_TAGS must contain a mapping for 'latest'\");\n}\n\n(async () => {\n  try {\n    let npmDistTag;\n\n    // Publishing was triggered via an GitHub release being created (almost certainly via our `yarn release` script)\n    if (process.env.GITHUB_EVENT_NAME === 'release') {\n      let tag = process.env.GITHUB_REF;\n      if (!tag) {\n        throw new Error('No tag found in environment variable GITHUB_REF');\n      }\n      if (!valid(tag) && /^refs\\/tags\\//.test(tag)) {\n        // It might be a full ref tag name instead of just a version, so try to get the version from the tag\n        tag = tag.split('/').pop();\n      }\n      if (!valid(tag)) {\n        throw new Error(`Git tag '${tag}' pulled from environment variable GITHUB_REF is not a valid semver version`);\n      }\n      if (isPrerelease(tag)) {\n        npmDistTag = 'next';\n      } else {\n        npmDistTag = 'latest';\n      }\n    }\n\n    // Publishing was triggered manually via the GitHub Actions UI\n    if (process.env.GITHUB_EVENT_NAME === 'workflow_dispatch') {\n      const branch = process.env.GITHUB_REF;\n      if (!branch) {\n        throw new Error('No branch found in environment variable GITHUB_REF');\n      }\n\n      npmDistTag = DIST_TAGS[branch];\n\n      if (!npmDistTag) {\n        throw new Error(\n          `Branch '${branch}' found in environment variable GITHUB_REF is not recognized for manual publishing, should be either '7.x' or 'master'`\n        );\n      }\n    }\n\n    if (!npmDistTag) {\n      throw new Error('No npm dist tag could be derived from the current environment');\n    }\n\n    await releasePublish({\n      registry: 'https://registry.npmjs.org',\n      tag: npmDistTag,\n    });\n  } catch (err) {\n    console.error(err);\n    process.exit(1);\n  }\n})();\n\nfunction isPrerelease(version) {\n  // prerelease returns an array of matching prerelease \"components\", or null if the version is not a prerelease\n  return prerelease(version) !== null;\n}\n"
  },
  {
    "path": "scripts/release.js",
    "content": "// @ts-check\n\nconst { execSync } = require('node:child_process');\nconst { releaseChangelog, releaseVersion } = require('nx/src/command-line/release');\n// There are multiple copies of outdated yargs in the workspace, access a known modern one\nconst yargs = require('nx/node_modules/yargs');\n\n(async () => {\n  try {\n    const options = await yargs\n      // @ts-expect-error - don't use the default meaning of version in yargs\n      .version(false)\n      .option('version', {\n        description: 'Explicit version specifier to use, if overriding conventional commits',\n        type: 'string',\n      })\n      .option('dryRun', {\n        alias: 'd',\n        description: 'Whether or not to perform a dry-run of the release process, defaults to true',\n        type: 'boolean',\n        default: true,\n      })\n      .option('verbose', {\n        description: 'Whether or not to enable verbose logging, defaults to false',\n        type: 'boolean',\n        default: false,\n      })\n      .option('gitRemote', {\n        description: 'The name of the git remote to push the release to, defaults to origin',\n        type: 'string',\n      })\n      .parseAsync();\n    if (!options.dryRun) {\n      if (!process.env.GH_TOKEN && !process.env.GITHUB_TOKEN) {\n        throw new Error(`GH_TOKEN or GITHUB_TOKEN environment variable must be set in order to run a real release`);\n      }\n    }\n\n    if (!options.gitRemote) {\n      options.gitRemote = getRemoteFor('git@github.com:ReactiveX/rxjs.git');\n    }\n\n    console.log();\n    console.info(`********* Release Options **********`);\n    console.info(`version   : ${options.version ?? 'use conventional commits'}`);\n    console.info(`dryRun    : ${options.dryRun} ${options.dryRun ? '😅' : '🚨🚨🚨'}`);\n    console.info(`verbose   : ${options.verbose}`);\n    console.info(`gitRemote : ${options.gitRemote}`);\n    console.log();\n\n    // Prepare the packages for publishing\n    execSync('yarn prepare-packages', {\n      stdio: 'inherit',\n      maxBuffer: 1024 * 1024 * 1024, // 1GB\n    });\n\n    const { workspaceVersion, projectsVersionData } = await releaseVersion({\n      specifier: options.version,\n      dryRun: options.dryRun,\n      verbose: options.verbose,\n    });\n\n    // This will create a release on GitHub, which will act as a trigger for the publish.yml workflow\n    await releaseChangelog({\n      versionData: projectsVersionData,\n      version: workspaceVersion,\n      interactive: 'all',\n      gitRemote: options.gitRemote,\n      dryRun: options.dryRun,\n      verbose: options.verbose,\n    });\n\n    if (!options.dryRun) {\n      console.log('Check GitHub: https://github.com/ReactiveX/rxjs/actions/workflows/publish.yml');\n    }\n\n    process.exit(0);\n  } catch (err) {\n    console.error(err);\n    process.exit(1);\n  }\n})();\n\n/**\n * Gets the name of the git remote for the given URL, if\n * the remote is not found an error is thrown.\n * @param {string} url\n * @returns The name of the git remote for the given URL\n */\nfunction getRemoteFor(url) {\n  const stdout = execSync('git remote -v').toString();\n  const lines = stdout.split('\\n');\n  for (const line of lines) {\n    const parts = line.split(/\\s+/);\n    if (parts.length > 1 && parts[1] === url) {\n      return parts[0];\n    }\n  }\n  throw new Error(`Could not find remote for \"${url}\"`);\n}\n"
  }
]